mt76x2_dfs.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506
  1. /*
  2. * Copyright (C) 2016 Lorenzo Bianconi <lorenzo.bianconi83@gmail.com>
  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 "mt76x2.h"
  17. #define RADAR_SPEC(m, len, el, eh, wl, wh, \
  18. w_tolerance, tl, th, t_tolerance, \
  19. bl, bh, event_exp, power_jmp) \
  20. { \
  21. .mode = m, \
  22. .avg_len = len, \
  23. .e_low = el, \
  24. .e_high = eh, \
  25. .w_low = wl, \
  26. .w_high = wh, \
  27. .w_margin = w_tolerance, \
  28. .t_low = tl, \
  29. .t_high = th, \
  30. .t_margin = t_tolerance, \
  31. .b_low = bl, \
  32. .b_high = bh, \
  33. .event_expiration = event_exp, \
  34. .pwr_jmp = power_jmp \
  35. }
  36. static const struct mt76x2_radar_specs etsi_radar_specs[] = {
  37. /* 20MHz */
  38. RADAR_SPEC(0, 8, 2, 15, 106, 150, 10, 4900, 100096, 10, 0,
  39. 0x7fffffff, 0x155cc0, 0x19cc),
  40. RADAR_SPEC(0, 40, 4, 59, 96, 380, 150, 4900, 100096, 40, 0,
  41. 0x7fffffff, 0x155cc0, 0x19cc),
  42. RADAR_SPEC(3, 60, 20, 46, 300, 640, 80, 4900, 10100, 80, 0,
  43. 0x7fffffff, 0x155cc0, 0x19dd),
  44. RADAR_SPEC(8, 8, 2, 9, 106, 150, 32, 4900, 296704, 32, 0,
  45. 0x7fffffff, 0x2191c0, 0x15cc),
  46. /* 40MHz */
  47. RADAR_SPEC(0, 8, 2, 15, 106, 150, 10, 4900, 100096, 10, 0,
  48. 0x7fffffff, 0x155cc0, 0x19cc),
  49. RADAR_SPEC(0, 40, 4, 59, 96, 380, 150, 4900, 100096, 40, 0,
  50. 0x7fffffff, 0x155cc0, 0x19cc),
  51. RADAR_SPEC(3, 60, 20, 46, 300, 640, 80, 4900, 10100, 80, 0,
  52. 0x7fffffff, 0x155cc0, 0x19dd),
  53. RADAR_SPEC(8, 8, 2, 9, 106, 150, 32, 4900, 296704, 32, 0,
  54. 0x7fffffff, 0x2191c0, 0x15cc),
  55. /* 80MHz */
  56. RADAR_SPEC(0, 8, 2, 15, 106, 150, 10, 4900, 100096, 10, 0,
  57. 0x7fffffff, 0x155cc0, 0x19cc),
  58. RADAR_SPEC(0, 40, 4, 59, 96, 380, 150, 4900, 100096, 40, 0,
  59. 0x7fffffff, 0x155cc0, 0x19cc),
  60. RADAR_SPEC(3, 60, 20, 46, 300, 640, 80, 4900, 10100, 80, 0,
  61. 0x7fffffff, 0x155cc0, 0x19dd),
  62. RADAR_SPEC(8, 8, 2, 9, 106, 150, 32, 4900, 296704, 32, 0,
  63. 0x7fffffff, 0x2191c0, 0x15cc)
  64. };
  65. static const struct mt76x2_radar_specs fcc_radar_specs[] = {
  66. /* 20MHz */
  67. RADAR_SPEC(0, 8, 2, 12, 106, 150, 5, 2900, 80100, 5, 0,
  68. 0x7fffffff, 0xfe808, 0x13dc),
  69. RADAR_SPEC(0, 8, 2, 7, 106, 140, 5, 27600, 27900, 5, 0,
  70. 0x7fffffff, 0xfe808, 0x19dd),
  71. RADAR_SPEC(0, 40, 4, 54, 96, 480, 150, 2900, 80100, 40, 0,
  72. 0x7fffffff, 0xfe808, 0x12cc),
  73. RADAR_SPEC(2, 60, 15, 63, 640, 2080, 32, 19600, 40200, 32, 0,
  74. 0x3938700, 0x57bcf00, 0x1289),
  75. /* 40MHz */
  76. RADAR_SPEC(0, 8, 2, 12, 106, 150, 5, 2900, 80100, 5, 0,
  77. 0x7fffffff, 0xfe808, 0x13dc),
  78. RADAR_SPEC(0, 8, 2, 7, 106, 140, 5, 27600, 27900, 5, 0,
  79. 0x7fffffff, 0xfe808, 0x19dd),
  80. RADAR_SPEC(0, 40, 4, 54, 96, 480, 150, 2900, 80100, 40, 0,
  81. 0x7fffffff, 0xfe808, 0x12cc),
  82. RADAR_SPEC(2, 60, 15, 63, 640, 2080, 32, 19600, 40200, 32, 0,
  83. 0x3938700, 0x57bcf00, 0x1289),
  84. /* 80MHz */
  85. RADAR_SPEC(0, 8, 2, 14, 106, 150, 15, 2900, 80100, 15, 0,
  86. 0x7fffffff, 0xfe808, 0x16cc),
  87. RADAR_SPEC(0, 8, 2, 7, 106, 140, 5, 27600, 27900, 5, 0,
  88. 0x7fffffff, 0xfe808, 0x19dd),
  89. RADAR_SPEC(0, 40, 4, 54, 96, 480, 150, 2900, 80100, 40, 0,
  90. 0x7fffffff, 0xfe808, 0x12cc),
  91. RADAR_SPEC(2, 60, 15, 63, 640, 2080, 32, 19600, 40200, 32, 0,
  92. 0x3938700, 0x57bcf00, 0x1289)
  93. };
  94. static const struct mt76x2_radar_specs jp_w56_radar_specs[] = {
  95. /* 20MHz */
  96. RADAR_SPEC(0, 8, 2, 7, 106, 150, 5, 2900, 80100, 5, 0,
  97. 0x7fffffff, 0x14c080, 0x13dc),
  98. RADAR_SPEC(0, 8, 2, 7, 106, 140, 5, 27600, 27900, 5, 0,
  99. 0x7fffffff, 0x14c080, 0x19dd),
  100. RADAR_SPEC(0, 40, 4, 44, 96, 480, 150, 2900, 80100, 40, 0,
  101. 0x7fffffff, 0x14c080, 0x12cc),
  102. RADAR_SPEC(2, 60, 15, 48, 940, 2080, 32, 19600, 40200, 32, 0,
  103. 0x3938700, 0X57bcf00, 0x1289),
  104. /* 40MHz */
  105. RADAR_SPEC(0, 8, 2, 7, 106, 150, 5, 2900, 80100, 5, 0,
  106. 0x7fffffff, 0x14c080, 0x13dc),
  107. RADAR_SPEC(0, 8, 2, 7, 106, 140, 5, 27600, 27900, 5, 0,
  108. 0x7fffffff, 0x14c080, 0x19dd),
  109. RADAR_SPEC(0, 40, 4, 44, 96, 480, 150, 2900, 80100, 40, 0,
  110. 0x7fffffff, 0x14c080, 0x12cc),
  111. RADAR_SPEC(2, 60, 15, 48, 940, 2080, 32, 19600, 40200, 32, 0,
  112. 0x3938700, 0X57bcf00, 0x1289),
  113. /* 80MHz */
  114. RADAR_SPEC(0, 8, 2, 9, 106, 150, 15, 2900, 80100, 15, 0,
  115. 0x7fffffff, 0x14c080, 0x16cc),
  116. RADAR_SPEC(0, 8, 2, 7, 106, 140, 5, 27600, 27900, 5, 0,
  117. 0x7fffffff, 0x14c080, 0x19dd),
  118. RADAR_SPEC(0, 40, 4, 44, 96, 480, 150, 2900, 80100, 40, 0,
  119. 0x7fffffff, 0x14c080, 0x12cc),
  120. RADAR_SPEC(2, 60, 15, 48, 940, 2080, 32, 19600, 40200, 32, 0,
  121. 0x3938700, 0X57bcf00, 0x1289)
  122. };
  123. static const struct mt76x2_radar_specs jp_w53_radar_specs[] = {
  124. /* 20MHz */
  125. RADAR_SPEC(0, 8, 2, 9, 106, 150, 20, 28400, 77000, 20, 0,
  126. 0x7fffffff, 0x14c080, 0x16cc),
  127. { 0 },
  128. RADAR_SPEC(0, 40, 4, 44, 96, 200, 150, 28400, 77000, 60, 0,
  129. 0x7fffffff, 0x14c080, 0x16cc),
  130. { 0 },
  131. /* 40MHz */
  132. RADAR_SPEC(0, 8, 2, 9, 106, 150, 20, 28400, 77000, 20, 0,
  133. 0x7fffffff, 0x14c080, 0x16cc),
  134. { 0 },
  135. RADAR_SPEC(0, 40, 4, 44, 96, 200, 150, 28400, 77000, 60, 0,
  136. 0x7fffffff, 0x14c080, 0x16cc),
  137. { 0 },
  138. /* 80MHz */
  139. RADAR_SPEC(0, 8, 2, 9, 106, 150, 20, 28400, 77000, 20, 0,
  140. 0x7fffffff, 0x14c080, 0x16cc),
  141. { 0 },
  142. RADAR_SPEC(0, 40, 4, 44, 96, 200, 150, 28400, 77000, 60, 0,
  143. 0x7fffffff, 0x14c080, 0x16cc),
  144. { 0 }
  145. };
  146. static void mt76x2_dfs_set_capture_mode_ctrl(struct mt76x2_dev *dev,
  147. u8 enable)
  148. {
  149. u32 data;
  150. data = (1 << 1) | enable;
  151. mt76_wr(dev, MT_BBP(DFS, 36), data);
  152. }
  153. static bool mt76x2_dfs_check_chirp(struct mt76x2_dev *dev)
  154. {
  155. bool ret = false;
  156. u32 current_ts, delta_ts;
  157. struct mt76x2_dfs_pattern_detector *dfs_pd = &dev->dfs_pd;
  158. current_ts = mt76_rr(dev, MT_PBF_LIFE_TIMER);
  159. delta_ts = current_ts - dfs_pd->chirp_pulse_ts;
  160. dfs_pd->chirp_pulse_ts = current_ts;
  161. /* 12 sec */
  162. if (delta_ts <= (12 * (1 << 20))) {
  163. if (++dfs_pd->chirp_pulse_cnt > 8)
  164. ret = true;
  165. } else {
  166. dfs_pd->chirp_pulse_cnt = 1;
  167. }
  168. return ret;
  169. }
  170. static void mt76x2_dfs_get_hw_pulse(struct mt76x2_dev *dev,
  171. struct mt76x2_dfs_hw_pulse *pulse)
  172. {
  173. u32 data;
  174. /* select channel */
  175. data = (MT_DFS_CH_EN << 16) | pulse->engine;
  176. mt76_wr(dev, MT_BBP(DFS, 0), data);
  177. /* reported period */
  178. pulse->period = mt76_rr(dev, MT_BBP(DFS, 19));
  179. /* reported width */
  180. pulse->w1 = mt76_rr(dev, MT_BBP(DFS, 20));
  181. pulse->w2 = mt76_rr(dev, MT_BBP(DFS, 23));
  182. /* reported burst number */
  183. pulse->burst = mt76_rr(dev, MT_BBP(DFS, 22));
  184. }
  185. static bool mt76x2_dfs_check_hw_pulse(struct mt76x2_dev *dev,
  186. struct mt76x2_dfs_hw_pulse *pulse)
  187. {
  188. bool ret = false;
  189. if (!pulse->period || !pulse->w1)
  190. return false;
  191. switch (dev->dfs_pd.region) {
  192. case NL80211_DFS_FCC:
  193. if (pulse->engine > 3)
  194. break;
  195. if (pulse->engine == 3) {
  196. ret = mt76x2_dfs_check_chirp(dev);
  197. break;
  198. }
  199. /* check short pulse*/
  200. if (pulse->w1 < 120)
  201. ret = (pulse->period >= 2900 &&
  202. (pulse->period <= 4700 ||
  203. pulse->period >= 6400) &&
  204. (pulse->period <= 6800 ||
  205. pulse->period >= 10200) &&
  206. pulse->period <= 61600);
  207. else if (pulse->w1 < 130) /* 120 - 130 */
  208. ret = (pulse->period >= 2900 &&
  209. pulse->period <= 61600);
  210. else
  211. ret = (pulse->period >= 3500 &&
  212. pulse->period <= 10100);
  213. break;
  214. case NL80211_DFS_ETSI:
  215. if (pulse->engine >= 3)
  216. break;
  217. ret = (pulse->period >= 4900 &&
  218. (pulse->period <= 10200 ||
  219. pulse->period >= 12400) &&
  220. pulse->period <= 100100);
  221. break;
  222. case NL80211_DFS_JP:
  223. if (dev->mt76.chandef.chan->center_freq >= 5250 &&
  224. dev->mt76.chandef.chan->center_freq <= 5350) {
  225. /* JPW53 */
  226. if (pulse->w1 <= 130)
  227. ret = (pulse->period >= 28360 &&
  228. (pulse->period <= 28700 ||
  229. pulse->period >= 76900) &&
  230. pulse->period <= 76940);
  231. break;
  232. }
  233. if (pulse->engine > 3)
  234. break;
  235. if (pulse->engine == 3) {
  236. ret = mt76x2_dfs_check_chirp(dev);
  237. break;
  238. }
  239. /* check short pulse*/
  240. if (pulse->w1 < 120)
  241. ret = (pulse->period >= 2900 &&
  242. (pulse->period <= 4700 ||
  243. pulse->period >= 6400) &&
  244. (pulse->period <= 6800 ||
  245. pulse->period >= 27560) &&
  246. (pulse->period <= 27960 ||
  247. pulse->period >= 28360) &&
  248. (pulse->period <= 28700 ||
  249. pulse->period >= 79900) &&
  250. pulse->period <= 80100);
  251. else if (pulse->w1 < 130) /* 120 - 130 */
  252. ret = (pulse->period >= 2900 &&
  253. (pulse->period <= 10100 ||
  254. pulse->period >= 27560) &&
  255. (pulse->period <= 27960 ||
  256. pulse->period >= 28360) &&
  257. (pulse->period <= 28700 ||
  258. pulse->period >= 79900) &&
  259. pulse->period <= 80100);
  260. else
  261. ret = (pulse->period >= 3900 &&
  262. pulse->period <= 10100);
  263. break;
  264. case NL80211_DFS_UNSET:
  265. default:
  266. return false;
  267. }
  268. return ret;
  269. }
  270. static void mt76x2_dfs_tasklet(unsigned long arg)
  271. {
  272. struct mt76x2_dev *dev = (struct mt76x2_dev *)arg;
  273. struct mt76x2_dfs_pattern_detector *dfs_pd = &dev->dfs_pd;
  274. u32 engine_mask;
  275. int i;
  276. if (test_bit(MT76_SCANNING, &dev->mt76.state))
  277. goto out;
  278. engine_mask = mt76_rr(dev, MT_BBP(DFS, 1));
  279. if (!(engine_mask & 0xf))
  280. goto out;
  281. for (i = 0; i < MT_DFS_NUM_ENGINES; i++) {
  282. struct mt76x2_dfs_hw_pulse pulse;
  283. if (!(engine_mask & (1 << i)))
  284. continue;
  285. pulse.engine = i;
  286. mt76x2_dfs_get_hw_pulse(dev, &pulse);
  287. if (!mt76x2_dfs_check_hw_pulse(dev, &pulse)) {
  288. dfs_pd->stats[i].hw_pulse_discarded++;
  289. continue;
  290. }
  291. /* hw detector rx radar pattern */
  292. dfs_pd->stats[i].hw_pattern++;
  293. ieee80211_radar_detected(dev->mt76.hw);
  294. /* reset hw detector */
  295. mt76_wr(dev, MT_BBP(DFS, 1), 0xf);
  296. return;
  297. }
  298. /* reset hw detector */
  299. mt76_wr(dev, MT_BBP(DFS, 1), 0xf);
  300. out:
  301. mt76x2_irq_enable(dev, MT_INT_GPTIMER);
  302. }
  303. static void mt76x2_dfs_set_bbp_params(struct mt76x2_dev *dev)
  304. {
  305. u32 data;
  306. u8 i, shift;
  307. const struct mt76x2_radar_specs *radar_specs;
  308. switch (dev->mt76.chandef.width) {
  309. case NL80211_CHAN_WIDTH_40:
  310. shift = MT_DFS_NUM_ENGINES;
  311. break;
  312. case NL80211_CHAN_WIDTH_80:
  313. shift = 2 * MT_DFS_NUM_ENGINES;
  314. break;
  315. default:
  316. shift = 0;
  317. break;
  318. }
  319. switch (dev->dfs_pd.region) {
  320. case NL80211_DFS_FCC:
  321. radar_specs = &fcc_radar_specs[shift];
  322. break;
  323. case NL80211_DFS_ETSI:
  324. radar_specs = &etsi_radar_specs[shift];
  325. break;
  326. case NL80211_DFS_JP:
  327. if (dev->mt76.chandef.chan->center_freq >= 5250 &&
  328. dev->mt76.chandef.chan->center_freq <= 5350)
  329. radar_specs = &jp_w53_radar_specs[shift];
  330. else
  331. radar_specs = &jp_w56_radar_specs[shift];
  332. break;
  333. case NL80211_DFS_UNSET:
  334. default:
  335. return;
  336. }
  337. data = (MT_DFS_VGA_MASK << 16) |
  338. (MT_DFS_PWR_GAIN_OFFSET << 12) |
  339. (MT_DFS_PWR_DOWN_TIME << 8) |
  340. (MT_DFS_SYM_ROUND << 4) |
  341. (MT_DFS_DELTA_DELAY & 0xf);
  342. mt76_wr(dev, MT_BBP(DFS, 2), data);
  343. data = (MT_DFS_RX_PE_MASK << 16) | MT_DFS_PKT_END_MASK;
  344. mt76_wr(dev, MT_BBP(DFS, 3), data);
  345. for (i = 0; i < MT_DFS_NUM_ENGINES; i++) {
  346. /* configure engine */
  347. mt76_wr(dev, MT_BBP(DFS, 0), i);
  348. /* detection mode + avg_len */
  349. data = ((radar_specs[i].avg_len & 0x1ff) << 16) |
  350. (radar_specs[i].mode & 0xf);
  351. mt76_wr(dev, MT_BBP(DFS, 4), data);
  352. /* dfs energy */
  353. data = ((radar_specs[i].e_high & 0x0fff) << 16) |
  354. (radar_specs[i].e_low & 0x0fff);
  355. mt76_wr(dev, MT_BBP(DFS, 5), data);
  356. /* dfs period */
  357. mt76_wr(dev, MT_BBP(DFS, 7), radar_specs[i].t_low);
  358. mt76_wr(dev, MT_BBP(DFS, 9), radar_specs[i].t_high);
  359. /* dfs burst */
  360. mt76_wr(dev, MT_BBP(DFS, 11), radar_specs[i].b_low);
  361. mt76_wr(dev, MT_BBP(DFS, 13), radar_specs[i].b_high);
  362. /* dfs width */
  363. data = ((radar_specs[i].w_high & 0x0fff) << 16) |
  364. (radar_specs[i].w_low & 0x0fff);
  365. mt76_wr(dev, MT_BBP(DFS, 14), data);
  366. /* dfs margins */
  367. data = (radar_specs[i].w_margin << 16) |
  368. radar_specs[i].t_margin;
  369. mt76_wr(dev, MT_BBP(DFS, 15), data);
  370. /* dfs event expiration */
  371. mt76_wr(dev, MT_BBP(DFS, 17), radar_specs[i].event_expiration);
  372. /* dfs pwr adj */
  373. mt76_wr(dev, MT_BBP(DFS, 30), radar_specs[i].pwr_jmp);
  374. }
  375. /* reset status */
  376. mt76_wr(dev, MT_BBP(DFS, 1), 0xf);
  377. mt76_wr(dev, MT_BBP(DFS, 36), 0x3);
  378. /* enable detection*/
  379. mt76_wr(dev, MT_BBP(DFS, 0), MT_DFS_CH_EN << 16);
  380. mt76_wr(dev, 0x212c, 0x0c350001);
  381. }
  382. void mt76x2_dfs_adjust_agc(struct mt76x2_dev *dev)
  383. {
  384. u32 agc_r8, agc_r4, val_r8, val_r4, dfs_r31;
  385. agc_r8 = mt76_rr(dev, MT_BBP(AGC, 8));
  386. agc_r4 = mt76_rr(dev, MT_BBP(AGC, 4));
  387. val_r8 = (agc_r8 & 0x00007e00) >> 9;
  388. val_r4 = agc_r4 & ~0x1f000000;
  389. val_r4 += (((val_r8 + 1) >> 1) << 24);
  390. mt76_wr(dev, MT_BBP(AGC, 4), val_r4);
  391. dfs_r31 = FIELD_GET(MT_BBP_AGC_LNA_HIGH_GAIN, val_r4);
  392. dfs_r31 += val_r8;
  393. dfs_r31 -= (agc_r8 & 0x00000038) >> 3;
  394. dfs_r31 = (dfs_r31 << 16) | 0x00000307;
  395. mt76_wr(dev, MT_BBP(DFS, 31), dfs_r31);
  396. mt76_wr(dev, MT_BBP(DFS, 32), 0x00040071);
  397. }
  398. void mt76x2_dfs_init_params(struct mt76x2_dev *dev)
  399. {
  400. struct cfg80211_chan_def *chandef = &dev->mt76.chandef;
  401. if ((chandef->chan->flags & IEEE80211_CHAN_RADAR) &&
  402. dev->dfs_pd.region != NL80211_DFS_UNSET) {
  403. mt76x2_dfs_set_bbp_params(dev);
  404. /* enable debug mode */
  405. mt76x2_dfs_set_capture_mode_ctrl(dev, true);
  406. mt76x2_irq_enable(dev, MT_INT_GPTIMER);
  407. mt76_rmw_field(dev, MT_INT_TIMER_EN,
  408. MT_INT_TIMER_EN_GP_TIMER_EN, 1);
  409. } else {
  410. /* disable hw detector */
  411. mt76_wr(dev, MT_BBP(DFS, 0), 0);
  412. /* clear detector status */
  413. mt76_wr(dev, MT_BBP(DFS, 1), 0xf);
  414. mt76_wr(dev, 0x212c, 0);
  415. mt76x2_irq_disable(dev, MT_INT_GPTIMER);
  416. mt76_rmw_field(dev, MT_INT_TIMER_EN,
  417. MT_INT_TIMER_EN_GP_TIMER_EN, 0);
  418. }
  419. }
  420. void mt76x2_dfs_init_detector(struct mt76x2_dev *dev)
  421. {
  422. struct mt76x2_dfs_pattern_detector *dfs_pd = &dev->dfs_pd;
  423. dfs_pd->region = NL80211_DFS_UNSET;
  424. tasklet_init(&dfs_pd->dfs_tasklet, mt76x2_dfs_tasklet,
  425. (unsigned long)dev);
  426. }
  427. void mt76x2_dfs_set_domain(struct mt76x2_dev *dev,
  428. enum nl80211_dfs_regions region)
  429. {
  430. struct mt76x2_dfs_pattern_detector *dfs_pd = &dev->dfs_pd;
  431. if (dfs_pd->region != region) {
  432. tasklet_disable(&dfs_pd->dfs_tasklet);
  433. dfs_pd->region = region;
  434. mt76x2_dfs_init_params(dev);
  435. tasklet_enable(&dfs_pd->dfs_tasklet);
  436. }
  437. }