wifi_regd.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544
  1. /******************************************************************************
  2. *
  3. * Copyright(c) 2009-2010 Realtek Corporation.
  4. *
  5. *****************************************************************************/
  6. #include <drv_types.h>
  7. #ifdef CONFIG_IOCTL_CFG80211
  8. #include <rtw_wifi_regd.h>
  9. static struct country_code_to_enum_rd allCountries[] = {
  10. {COUNTRY_CODE_USER, "RD"},
  11. };
  12. /*
  13. * REG_RULE(freq start, freq end, bandwidth, max gain, eirp, reg_flags)
  14. */
  15. /*
  16. *Only these channels all allow active
  17. *scan on all world regulatory domains
  18. */
  19. /* 2G chan 01 - chan 11 */
  20. #define RTW_2GHZ_CH01_11 \
  21. REG_RULE(2412-10, 2462+10, 40, 0, 20, 0)
  22. /*
  23. *We enable active scan on these a case
  24. *by case basis by regulatory domain
  25. */
  26. /* 2G chan 12 - chan 13, PASSIV SCAN */
  27. #define RTW_2GHZ_CH12_13 \
  28. REG_RULE(2467-10, 2472+10, 40, 0, 20, \
  29. NL80211_RRF_PASSIVE_SCAN)
  30. /* 2G chan 14, PASSIVS SCAN, NO OFDM (B only) */
  31. #define RTW_2GHZ_CH14 \
  32. REG_RULE(2484-10, 2484+10, 40, 0, 20, \
  33. NL80211_RRF_PASSIVE_SCAN | NL80211_RRF_NO_OFDM)
  34. /* 5G chan 36 - chan 64 */
  35. #define RTW_5GHZ_5150_5350 \
  36. REG_RULE(5150-10, 5350+10, 40, 0, 30, \
  37. NL80211_RRF_PASSIVE_SCAN | NL80211_RRF_NO_IBSS)
  38. /* 5G chan 100 - chan 165 */
  39. #define RTW_5GHZ_5470_5850 \
  40. REG_RULE(5470-10, 5850+10, 40, 0, 30, \
  41. NL80211_RRF_PASSIVE_SCAN | NL80211_RRF_NO_IBSS)
  42. /* 5G chan 149 - chan 165 */
  43. #define RTW_5GHZ_5725_5850 \
  44. REG_RULE(5725-10, 5850+10, 40, 0, 30, \
  45. NL80211_RRF_PASSIVE_SCAN | NL80211_RRF_NO_IBSS)
  46. /* 5G chan 36 - chan 165 */
  47. #define RTW_5GHZ_5150_5850 \
  48. REG_RULE(5150-10, 5850+10, 40, 0, 30, \
  49. NL80211_RRF_PASSIVE_SCAN | NL80211_RRF_NO_IBSS)
  50. static const struct ieee80211_regdomain rtw_regdom_rd = {
  51. .n_reg_rules = 3,
  52. .alpha2 = "99",
  53. .reg_rules = {
  54. RTW_2GHZ_CH01_11,
  55. RTW_2GHZ_CH12_13,
  56. RTW_5GHZ_5150_5850,
  57. }
  58. };
  59. static const struct ieee80211_regdomain rtw_regdom_11 = {
  60. .n_reg_rules = 1,
  61. .alpha2 = "99",
  62. .reg_rules = {
  63. RTW_2GHZ_CH01_11,
  64. }
  65. };
  66. static const struct ieee80211_regdomain rtw_regdom_12_13 = {
  67. .n_reg_rules = 2,
  68. .alpha2 = "99",
  69. .reg_rules = {
  70. RTW_2GHZ_CH01_11,
  71. RTW_2GHZ_CH12_13,
  72. }
  73. };
  74. static const struct ieee80211_regdomain rtw_regdom_no_midband = {
  75. .n_reg_rules = 3,
  76. .alpha2 = "99",
  77. .reg_rules = {
  78. RTW_2GHZ_CH01_11,
  79. RTW_5GHZ_5150_5350,
  80. RTW_5GHZ_5725_5850,
  81. }
  82. };
  83. static const struct ieee80211_regdomain rtw_regdom_60_64 = {
  84. .n_reg_rules = 3,
  85. .alpha2 = "99",
  86. .reg_rules = {
  87. RTW_2GHZ_CH01_11,
  88. RTW_2GHZ_CH12_13,
  89. RTW_5GHZ_5725_5850,
  90. }
  91. };
  92. static const struct ieee80211_regdomain rtw_regdom_14_60_64 = {
  93. .n_reg_rules = 4,
  94. .alpha2 = "99",
  95. .reg_rules = {
  96. RTW_2GHZ_CH01_11,
  97. RTW_2GHZ_CH12_13,
  98. RTW_2GHZ_CH14,
  99. RTW_5GHZ_5725_5850,
  100. }
  101. };
  102. static const struct ieee80211_regdomain rtw_regdom_14 = {
  103. .n_reg_rules = 3,
  104. .alpha2 = "99",
  105. .reg_rules = {
  106. RTW_2GHZ_CH01_11,
  107. RTW_2GHZ_CH12_13,
  108. RTW_2GHZ_CH14,
  109. }
  110. };
  111. #if 0
  112. static struct rtw_regulatory *rtw_regd;
  113. #endif
  114. #if 0 /* not_yet */
  115. static void _rtw_reg_apply_beaconing_flags(struct wiphy *wiphy,
  116. enum nl80211_reg_initiator initiator)
  117. {
  118. enum nl80211_band band;
  119. struct ieee80211_supported_band *sband;
  120. const struct ieee80211_reg_rule *reg_rule;
  121. struct ieee80211_channel *ch;
  122. unsigned int i;
  123. u32 bandwidth = 0;
  124. int r;
  125. for (band = 0; band < IEEE80211_NUM_BANDS; band++) {
  126. if (!wiphy->bands[band])
  127. continue;
  128. sband = wiphy->bands[band];
  129. for (i = 0; i < sband->n_channels; i++) {
  130. ch = &sband->channels[i];
  131. if (rtw_is_dfs_ch(ch->hw_value) ||
  132. (ch->flags & IEEE80211_CHAN_RADAR))
  133. continue;
  134. if (initiator == NL80211_REGDOM_SET_BY_COUNTRY_IE) {
  135. r = freq_reg_info(wiphy, ch->center_freq,
  136. bandwidth, &reg_rule);
  137. if (r)
  138. continue;
  139. /*
  140. *If 11d had a rule for this channel ensure
  141. *we enable adhoc/beaconing if it allows us to
  142. *use it. Note that we would have disabled it
  143. *by applying our static world regdomain by
  144. *default during init, prior to calling our
  145. *regulatory_hint().
  146. */
  147. if (!(reg_rule->flags & NL80211_RRF_NO_IBSS))
  148. ch->flags &= ~IEEE80211_CHAN_NO_IBSS;
  149. if (!
  150. (reg_rule->flags &
  151. NL80211_RRF_PASSIVE_SCAN))
  152. ch->flags &=
  153. ~IEEE80211_CHAN_PASSIVE_SCAN;
  154. } else {
  155. if (ch->beacon_found)
  156. ch->flags &= ~(IEEE80211_CHAN_NO_IBSS |
  157. IEEE80211_CHAN_PASSIVE_SCAN);
  158. }
  159. }
  160. }
  161. }
  162. /* Allows active scan scan on Ch 12 and 13 */
  163. static void _rtw_reg_apply_active_scan_flags(struct wiphy *wiphy,
  164. enum nl80211_reg_initiator
  165. initiator)
  166. {
  167. struct ieee80211_supported_band *sband;
  168. struct ieee80211_channel *ch;
  169. const struct ieee80211_reg_rule *reg_rule;
  170. u32 bandwidth = 0;
  171. int r;
  172. if (!wiphy->bands[NL80211_BAND_2GHZ])
  173. return;
  174. sband = wiphy->bands[NL80211_BAND_2GHZ];
  175. /*
  176. * If no country IE has been received always enable active scan
  177. * on these channels. This is only done for specific regulatory SKUs
  178. */
  179. if (initiator != NL80211_REGDOM_SET_BY_COUNTRY_IE) {
  180. ch = &sband->channels[11]; /* CH 12 */
  181. if (ch->flags & IEEE80211_CHAN_PASSIVE_SCAN)
  182. ch->flags &= ~IEEE80211_CHAN_PASSIVE_SCAN;
  183. ch = &sband->channels[12]; /* CH 13 */
  184. if (ch->flags & IEEE80211_CHAN_PASSIVE_SCAN)
  185. ch->flags &= ~IEEE80211_CHAN_PASSIVE_SCAN;
  186. return;
  187. }
  188. /*
  189. * If a country IE has been received check its rule for this
  190. * channel first before enabling active scan. The passive scan
  191. * would have been enforced by the initial processing of our
  192. * custom regulatory domain.
  193. */
  194. ch = &sband->channels[11]; /* CH 12 */
  195. r = freq_reg_info(wiphy, ch->center_freq, bandwidth, &reg_rule);
  196. if (!r) {
  197. if (!(reg_rule->flags & NL80211_RRF_PASSIVE_SCAN))
  198. if (ch->flags & IEEE80211_CHAN_PASSIVE_SCAN)
  199. ch->flags &= ~IEEE80211_CHAN_PASSIVE_SCAN;
  200. }
  201. ch = &sband->channels[12]; /* CH 13 */
  202. r = freq_reg_info(wiphy, ch->center_freq, bandwidth, &reg_rule);
  203. if (!r) {
  204. if (!(reg_rule->flags & NL80211_RRF_PASSIVE_SCAN))
  205. if (ch->flags & IEEE80211_CHAN_PASSIVE_SCAN)
  206. ch->flags &= ~IEEE80211_CHAN_PASSIVE_SCAN;
  207. }
  208. }
  209. #endif
  210. /*
  211. * Always apply Radar/DFS rules on
  212. * freq range 5260 MHz - 5700 MHz
  213. */
  214. static void _rtw_reg_apply_radar_flags(struct wiphy *wiphy)
  215. {
  216. struct ieee80211_supported_band *sband;
  217. struct ieee80211_channel *ch;
  218. unsigned int i;
  219. if (!wiphy->bands[NL80211_BAND_5GHZ])
  220. return;
  221. sband = wiphy->bands[NL80211_BAND_5GHZ];
  222. for (i = 0; i < sband->n_channels; i++) {
  223. ch = &sband->channels[i];
  224. if (!rtw_is_dfs_ch(ch->hw_value))
  225. continue;
  226. #ifdef CONFIG_DFS
  227. if (!(ch->flags & IEEE80211_CHAN_DISABLED)
  228. #if defined(CONFIG_DFS_MASTER)
  229. && rtw_odm_dfs_domain_unknown(wiphy_to_adapter(wiphy))
  230. #endif
  231. ) {
  232. ch->flags |= IEEE80211_CHAN_RADAR;
  233. #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 14, 0))
  234. ch->flags |= (IEEE80211_CHAN_NO_IBSS | IEEE80211_CHAN_PASSIVE_SCAN);
  235. #else
  236. ch->flags |= IEEE80211_CHAN_NO_IR;
  237. #endif
  238. }
  239. #endif /* CONFIG_DFS */
  240. #if 0
  241. /*
  242. * We always enable radar detection/DFS on this
  243. * frequency range. Additionally we also apply on
  244. * this frequency range:
  245. * - If STA mode does not yet have DFS supports disable
  246. * active scanning
  247. * - If adhoc mode does not support DFS yet then disable
  248. * adhoc in the frequency.
  249. * - If AP mode does not yet support radar detection/DFS
  250. * do not allow AP mode
  251. */
  252. if (!(ch->flags & IEEE80211_CHAN_DISABLED))
  253. ch->flags |= IEEE80211_CHAN_RADAR |
  254. IEEE80211_CHAN_NO_IBSS |
  255. IEEE80211_CHAN_PASSIVE_SCAN;
  256. #endif
  257. }
  258. }
  259. static void _rtw_reg_apply_flags(struct wiphy *wiphy)
  260. {
  261. #if 1 /* by channel plan */
  262. _adapter *padapter = wiphy_to_adapter(wiphy);
  263. u8 channel_plan = padapter->mlmepriv.ChannelPlan;
  264. struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
  265. RT_CHANNEL_INFO *channel_set = pmlmeext->channel_set;
  266. u8 max_chan_nums = pmlmeext->max_chan_nums;
  267. struct ieee80211_supported_band *sband;
  268. struct ieee80211_channel *ch;
  269. unsigned int i, j;
  270. u16 channel;
  271. u32 freq;
  272. /* all channels disable */
  273. for (i = 0; i < NUM_NL80211_BANDS; i++) {
  274. sband = wiphy->bands[i];
  275. if (sband) {
  276. for (j = 0; j < sband->n_channels; j++) {
  277. ch = &sband->channels[j];
  278. if (ch)
  279. ch->flags = IEEE80211_CHAN_DISABLED;
  280. }
  281. }
  282. }
  283. /* channels apply by channel plans. */
  284. for (i = 0; i < max_chan_nums; i++) {
  285. channel = channel_set[i].ChannelNum;
  286. freq = rtw_ch2freq(channel);
  287. ch = ieee80211_get_channel(wiphy, freq);
  288. if (ch) {
  289. if (channel_set[i].ScanType == SCAN_PASSIVE
  290. #if defined(CONFIG_DFS_MASTER)
  291. && rtw_odm_dfs_domain_unknown(wiphy_to_adapter(wiphy))
  292. #endif
  293. ) {
  294. #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 14, 0))
  295. ch->flags = (IEEE80211_CHAN_NO_IBSS | IEEE80211_CHAN_PASSIVE_SCAN);
  296. #else
  297. ch->flags = IEEE80211_CHAN_NO_IR;
  298. #endif
  299. } else
  300. ch->flags = 0;
  301. }
  302. }
  303. #else
  304. struct ieee80211_supported_band *sband;
  305. struct ieee80211_channel *ch;
  306. unsigned int i, j;
  307. u16 channels[37] = {
  308. 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 36, 40, 44, 48, 52, 56,
  309. 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140,
  310. 149, 153,
  311. 157, 161, 165
  312. };
  313. u16 channel;
  314. u32 freq;
  315. for (i = 0; i < NUM_NL80211_BANDS; i++) {
  316. sband = wiphy->bands[i];
  317. if (sband)
  318. for (j = 0; j < sband->n_channels; j++) {
  319. ch = &sband->channels[j];
  320. if (ch)
  321. ch->flags = IEEE80211_CHAN_DISABLED;
  322. }
  323. }
  324. for (i = 0; i < 37; i++) {
  325. channel = channels[i];
  326. freq = rtw_ch2freq(channel);
  327. ch = ieee80211_get_channel(wiphy, freq);
  328. if (ch) {
  329. if (channel <= 11)
  330. ch->flags = 0;
  331. else
  332. ch->flags = 0; /* IEEE80211_CHAN_PASSIVE_SCAN; */
  333. }
  334. /* printk("%s: freq %d(%d) flag 0x%02X\n", __func__, freq, channel, ch->flags); */
  335. }
  336. #endif
  337. }
  338. static void _rtw_reg_apply_world_flags(struct wiphy *wiphy,
  339. enum nl80211_reg_initiator initiator,
  340. struct rtw_regulatory *reg)
  341. {
  342. /* _rtw_reg_apply_beaconing_flags(wiphy, initiator); */
  343. /* _rtw_reg_apply_active_scan_flags(wiphy, initiator); */
  344. return;
  345. }
  346. static int _rtw_reg_notifier_apply(struct wiphy *wiphy,
  347. struct regulatory_request *request,
  348. struct rtw_regulatory *reg)
  349. {
  350. /* Hard code flags */
  351. _rtw_reg_apply_flags(wiphy);
  352. /* We always apply this */
  353. _rtw_reg_apply_radar_flags(wiphy);
  354. switch (request->initiator) {
  355. case NL80211_REGDOM_SET_BY_DRIVER:
  356. RTW_INFO("%s: %s\n", __func__, "NL80211_REGDOM_SET_BY_DRIVER");
  357. _rtw_reg_apply_world_flags(wiphy, NL80211_REGDOM_SET_BY_DRIVER,
  358. reg);
  359. break;
  360. case NL80211_REGDOM_SET_BY_CORE:
  361. RTW_INFO("%s: %s\n", __func__,
  362. "NL80211_REGDOM_SET_BY_CORE to DRV");
  363. _rtw_reg_apply_world_flags(wiphy, NL80211_REGDOM_SET_BY_DRIVER,
  364. reg);
  365. break;
  366. case NL80211_REGDOM_SET_BY_USER:
  367. RTW_INFO("%s: %s\n", __func__,
  368. "NL80211_REGDOM_SET_BY_USER to DRV");
  369. _rtw_reg_apply_world_flags(wiphy, NL80211_REGDOM_SET_BY_DRIVER,
  370. reg);
  371. break;
  372. case NL80211_REGDOM_SET_BY_COUNTRY_IE:
  373. RTW_INFO("%s: %s\n", __func__,
  374. "NL80211_REGDOM_SET_BY_COUNTRY_IE");
  375. _rtw_reg_apply_world_flags(wiphy, request->initiator, reg);
  376. break;
  377. }
  378. return 0;
  379. }
  380. static const struct ieee80211_regdomain *_rtw_regdomain_select(struct
  381. rtw_regulatory
  382. *reg)
  383. {
  384. #if 0
  385. switch (reg->country_code) {
  386. case COUNTRY_CODE_USER:
  387. default:
  388. return &rtw_regdom_rd;
  389. }
  390. #else
  391. return &rtw_regdom_rd;
  392. #endif
  393. }
  394. void _rtw_reg_notifier(struct wiphy *wiphy, struct regulatory_request *request)
  395. {
  396. struct rtw_regulatory *reg = NULL;
  397. RTW_INFO("%s\n", __func__);
  398. _rtw_reg_notifier_apply(wiphy, request, reg);
  399. }
  400. #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 9, 0))
  401. int rtw_reg_notifier(struct wiphy *wiphy, struct regulatory_request *request)
  402. #else
  403. void rtw_reg_notifier(struct wiphy *wiphy, struct regulatory_request *request)
  404. #endif
  405. {
  406. _rtw_reg_notifier(wiphy, request);
  407. #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 9, 0))
  408. return 0;
  409. #endif
  410. }
  411. void rtw_reg_notify_by_driver(_adapter *adapter)
  412. {
  413. if ((adapter->rtw_wdev != NULL) && (adapter->rtw_wdev->wiphy)) {
  414. struct regulatory_request request;
  415. request.initiator = NL80211_REGDOM_SET_BY_DRIVER;
  416. rtw_reg_notifier(adapter->rtw_wdev->wiphy, &request);
  417. }
  418. }
  419. static void _rtw_regd_init_wiphy(struct rtw_regulatory *reg, struct wiphy *wiphy)
  420. {
  421. const struct ieee80211_regdomain *regd;
  422. wiphy->reg_notifier = rtw_reg_notifier;
  423. #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 14, 0))
  424. wiphy->flags |= WIPHY_FLAG_CUSTOM_REGULATORY;
  425. wiphy->flags &= ~WIPHY_FLAG_STRICT_REGULATORY;
  426. wiphy->flags &= ~WIPHY_FLAG_DISABLE_BEACON_HINTS;
  427. #else
  428. wiphy->regulatory_flags |= REGULATORY_CUSTOM_REG;
  429. wiphy->regulatory_flags &= ~REGULATORY_STRICT_REG;
  430. wiphy->regulatory_flags &= ~REGULATORY_DISABLE_BEACON_HINTS;
  431. #endif
  432. regd = _rtw_regdomain_select(reg);
  433. wiphy_apply_custom_regulatory(wiphy, regd);
  434. /* Hard code flags */
  435. _rtw_reg_apply_flags(wiphy);
  436. _rtw_reg_apply_radar_flags(wiphy);
  437. _rtw_reg_apply_world_flags(wiphy, NL80211_REGDOM_SET_BY_DRIVER, reg);
  438. }
  439. static struct country_code_to_enum_rd *_rtw_regd_find_country(u16 countrycode)
  440. {
  441. int i;
  442. for (i = 0; i < ARRAY_SIZE(allCountries); i++) {
  443. if (allCountries[i].countrycode == countrycode)
  444. return &allCountries[i];
  445. }
  446. return NULL;
  447. }
  448. int rtw_regd_init(_adapter *padapter)
  449. {
  450. struct wiphy *wiphy = padapter->rtw_wdev->wiphy;
  451. #if 0
  452. if (rtw_regd == NULL) {
  453. rtw_regd = (struct rtw_regulatory *)
  454. rtw_malloc(sizeof(struct rtw_regulatory));
  455. rtw_regd->alpha2[0] = '9';
  456. rtw_regd->alpha2[1] = '9';
  457. rtw_regd->country_code = COUNTRY_CODE_USER;
  458. }
  459. RTW_INFO("%s: Country alpha2 being used: %c%c\n",
  460. __func__, rtw_regd->alpha2[0], rtw_regd->alpha2[1]);
  461. #endif
  462. _rtw_regd_init_wiphy(NULL, wiphy);
  463. return 0;
  464. }
  465. #endif /* CONFIG_IOCTL_CFG80211 */