dfs_pattern_detector.c 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300
  1. /*
  2. * Copyright (c) 2012 Neratec Solutions AG
  3. *
  4. * Permission to use, copy, modify, and/or distribute this software for any
  5. * purpose with or without fee is hereby granted, provided that the above
  6. * copyright notice and this permission notice appear in all copies.
  7. *
  8. * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
  9. * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
  10. * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
  11. * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  12. * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
  13. * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  14. * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  15. */
  16. #include <linux/slab.h>
  17. #include <linux/export.h>
  18. #include "dfs_pattern_detector.h"
  19. #include "dfs_pri_detector.h"
  20. /*
  21. * tolerated deviation of radar time stamp in usecs on both sides
  22. * TODO: this might need to be HW-dependent
  23. */
  24. #define PRI_TOLERANCE 16
  25. /**
  26. * struct radar_types - contains array of patterns defined for one DFS domain
  27. * @domain: DFS regulatory domain
  28. * @num_radar_types: number of radar types to follow
  29. * @radar_types: radar types array
  30. */
  31. struct radar_types {
  32. enum nl80211_dfs_regions region;
  33. u32 num_radar_types;
  34. const struct radar_detector_specs *radar_types;
  35. };
  36. /* percentage on ppb threshold to trigger detection */
  37. #define MIN_PPB_THRESH 50
  38. #define PPB_THRESH(PPB) ((PPB * MIN_PPB_THRESH + 50) / 100)
  39. #define PRF2PRI(PRF) ((1000000 + PRF / 2) / PRF)
  40. #define ETSI_PATTERN(ID, WMIN, WMAX, PMIN, PMAX, PRF, PPB) \
  41. { \
  42. ID, WMIN, WMAX, (PRF2PRI(PMAX) - PRI_TOLERANCE), \
  43. (PRF2PRI(PMIN) * PRF + PRI_TOLERANCE), PRF, PPB * PRF, \
  44. PPB_THRESH(PPB), PRI_TOLERANCE, \
  45. }
  46. /* radar types as defined by ETSI EN-301-893 v1.5.1 */
  47. static const struct radar_detector_specs etsi_radar_ref_types_v15[] = {
  48. ETSI_PATTERN(0, 0, 1, 700, 700, 1, 18),
  49. ETSI_PATTERN(1, 0, 5, 200, 1000, 1, 10),
  50. ETSI_PATTERN(2, 0, 15, 200, 1600, 1, 15),
  51. ETSI_PATTERN(3, 0, 15, 2300, 4000, 1, 25),
  52. ETSI_PATTERN(4, 20, 30, 2000, 4000, 1, 20),
  53. ETSI_PATTERN(5, 0, 2, 300, 400, 3, 10),
  54. ETSI_PATTERN(6, 0, 2, 400, 1200, 3, 15),
  55. };
  56. static const struct radar_types etsi_radar_types_v15 = {
  57. .region = NL80211_DFS_ETSI,
  58. .num_radar_types = ARRAY_SIZE(etsi_radar_ref_types_v15),
  59. .radar_types = etsi_radar_ref_types_v15,
  60. };
  61. /* for now, we support ETSI radar types, FCC and JP are TODO */
  62. static const struct radar_types *dfs_domains[] = {
  63. &etsi_radar_types_v15,
  64. };
  65. /**
  66. * get_dfs_domain_radar_types() - get radar types for a given DFS domain
  67. * @param domain DFS domain
  68. * @return radar_types ptr on success, NULL if DFS domain is not supported
  69. */
  70. static const struct radar_types *
  71. get_dfs_domain_radar_types(enum nl80211_dfs_regions region)
  72. {
  73. u32 i;
  74. for (i = 0; i < ARRAY_SIZE(dfs_domains); i++) {
  75. if (dfs_domains[i]->region == region)
  76. return dfs_domains[i];
  77. }
  78. return NULL;
  79. }
  80. /**
  81. * struct channel_detector - detector elements for a DFS channel
  82. * @head: list_head
  83. * @freq: frequency for this channel detector in MHz
  84. * @detectors: array of dynamically created detector elements for this freq
  85. *
  86. * Channel detectors are required to provide multi-channel DFS detection, e.g.
  87. * to support off-channel scanning. A pattern detector has a list of channels
  88. * radar pulses have been reported for in the past.
  89. */
  90. struct channel_detector {
  91. struct list_head head;
  92. u16 freq;
  93. struct pri_detector **detectors;
  94. };
  95. /* channel_detector_reset() - reset detector lines for a given channel */
  96. static void channel_detector_reset(struct dfs_pattern_detector *dpd,
  97. struct channel_detector *cd)
  98. {
  99. u32 i;
  100. if (cd == NULL)
  101. return;
  102. for (i = 0; i < dpd->num_radar_types; i++)
  103. cd->detectors[i]->reset(cd->detectors[i], dpd->last_pulse_ts);
  104. }
  105. /* channel_detector_exit() - destructor */
  106. static void channel_detector_exit(struct dfs_pattern_detector *dpd,
  107. struct channel_detector *cd)
  108. {
  109. u32 i;
  110. if (cd == NULL)
  111. return;
  112. list_del(&cd->head);
  113. for (i = 0; i < dpd->num_radar_types; i++) {
  114. struct pri_detector *de = cd->detectors[i];
  115. if (de != NULL)
  116. de->exit(de);
  117. }
  118. kfree(cd->detectors);
  119. kfree(cd);
  120. }
  121. static struct channel_detector *
  122. channel_detector_create(struct dfs_pattern_detector *dpd, u16 freq)
  123. {
  124. u32 sz, i;
  125. struct channel_detector *cd;
  126. cd = kmalloc(sizeof(*cd), GFP_KERNEL);
  127. if (cd == NULL)
  128. goto fail;
  129. INIT_LIST_HEAD(&cd->head);
  130. cd->freq = freq;
  131. sz = sizeof(cd->detectors) * dpd->num_radar_types;
  132. cd->detectors = kzalloc(sz, GFP_KERNEL);
  133. if (cd->detectors == NULL)
  134. goto fail;
  135. for (i = 0; i < dpd->num_radar_types; i++) {
  136. const struct radar_detector_specs *rs = &dpd->radar_spec[i];
  137. struct pri_detector *de = pri_detector_init(rs);
  138. if (de == NULL)
  139. goto fail;
  140. cd->detectors[i] = de;
  141. }
  142. list_add(&cd->head, &dpd->channel_detectors);
  143. return cd;
  144. fail:
  145. pr_err("failed to allocate channel_detector for freq=%d\n", freq);
  146. channel_detector_exit(dpd, cd);
  147. return NULL;
  148. }
  149. /**
  150. * channel_detector_get() - get channel detector for given frequency
  151. * @param dpd instance pointer
  152. * @param freq frequency in MHz
  153. * @return pointer to channel detector on success, NULL otherwise
  154. *
  155. * Return existing channel detector for the given frequency or return a
  156. * newly create one.
  157. */
  158. static struct channel_detector *
  159. channel_detector_get(struct dfs_pattern_detector *dpd, u16 freq)
  160. {
  161. struct channel_detector *cd;
  162. list_for_each_entry(cd, &dpd->channel_detectors, head) {
  163. if (cd->freq == freq)
  164. return cd;
  165. }
  166. return channel_detector_create(dpd, freq);
  167. }
  168. /*
  169. * DFS Pattern Detector
  170. */
  171. /* dpd_reset(): reset all channel detectors */
  172. static void dpd_reset(struct dfs_pattern_detector *dpd)
  173. {
  174. struct channel_detector *cd;
  175. if (!list_empty(&dpd->channel_detectors))
  176. list_for_each_entry(cd, &dpd->channel_detectors, head)
  177. channel_detector_reset(dpd, cd);
  178. }
  179. static void dpd_exit(struct dfs_pattern_detector *dpd)
  180. {
  181. struct channel_detector *cd, *cd0;
  182. if (!list_empty(&dpd->channel_detectors))
  183. list_for_each_entry_safe(cd, cd0, &dpd->channel_detectors, head)
  184. channel_detector_exit(dpd, cd);
  185. kfree(dpd);
  186. }
  187. static bool
  188. dpd_add_pulse(struct dfs_pattern_detector *dpd, struct pulse_event *event)
  189. {
  190. u32 i;
  191. bool ts_wraparound;
  192. struct channel_detector *cd;
  193. if (dpd->region == NL80211_DFS_UNSET) {
  194. /*
  195. * pulses received for a non-supported or un-initialized
  196. * domain are treated as detected radars
  197. */
  198. return true;
  199. }
  200. cd = channel_detector_get(dpd, event->freq);
  201. if (cd == NULL)
  202. return false;
  203. ts_wraparound = (event->ts < dpd->last_pulse_ts);
  204. dpd->last_pulse_ts = event->ts;
  205. if (ts_wraparound) {
  206. /*
  207. * reset detector on time stamp wraparound
  208. * with monotonic time stamps, this should never happen
  209. */
  210. pr_warn("DFS: time stamp wraparound detected, resetting\n");
  211. dpd_reset(dpd);
  212. }
  213. /* do type individual pattern matching */
  214. for (i = 0; i < dpd->num_radar_types; i++) {
  215. if (cd->detectors[i]->add_pulse(cd->detectors[i], event) != 0) {
  216. channel_detector_reset(dpd, cd);
  217. return true;
  218. }
  219. }
  220. return false;
  221. }
  222. static bool dpd_set_domain(struct dfs_pattern_detector *dpd,
  223. enum nl80211_dfs_regions region)
  224. {
  225. const struct radar_types *rt;
  226. struct channel_detector *cd, *cd0;
  227. if (dpd->region == region)
  228. return true;
  229. dpd->region = NL80211_DFS_UNSET;
  230. rt = get_dfs_domain_radar_types(region);
  231. if (rt == NULL)
  232. return false;
  233. /* delete all channel detectors for previous DFS domain */
  234. if (!list_empty(&dpd->channel_detectors))
  235. list_for_each_entry_safe(cd, cd0, &dpd->channel_detectors, head)
  236. channel_detector_exit(dpd, cd);
  237. dpd->radar_spec = rt->radar_types;
  238. dpd->num_radar_types = rt->num_radar_types;
  239. dpd->region = region;
  240. return true;
  241. }
  242. static struct dfs_pattern_detector default_dpd = {
  243. .exit = dpd_exit,
  244. .set_domain = dpd_set_domain,
  245. .add_pulse = dpd_add_pulse,
  246. .region = NL80211_DFS_UNSET,
  247. };
  248. struct dfs_pattern_detector *
  249. dfs_pattern_detector_init(enum nl80211_dfs_regions region)
  250. {
  251. struct dfs_pattern_detector *dpd;
  252. dpd = kmalloc(sizeof(*dpd), GFP_KERNEL);
  253. if (dpd == NULL) {
  254. pr_err("allocation of dfs_pattern_detector failed\n");
  255. return NULL;
  256. }
  257. *dpd = default_dpd;
  258. INIT_LIST_HEAD(&dpd->channel_detectors);
  259. if (dpd->set_domain(dpd, region))
  260. return dpd;
  261. pr_err("Could not set DFS domain to %d. ", region);
  262. return NULL;
  263. }
  264. EXPORT_SYMBOL(dfs_pattern_detector_init);