wifi_regd.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424
  1. /******************************************************************************
  2. *
  3. * Copyright(c) 2009-2010 - 2017 Realtek Corporation.
  4. *
  5. * This program is free software; you can redistribute it and/or modify it
  6. * under the terms of version 2 of the GNU General Public License as
  7. * published by the Free Software Foundation.
  8. *
  9. * This program is distributed in the hope that it will be useful, but WITHOUT
  10. * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11. * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
  12. * more details.
  13. *
  14. *****************************************************************************/
  15. #include <drv_types.h>
  16. #ifdef CONFIG_IOCTL_CFG80211
  17. #include <rtw_wifi_regd.h>
  18. static struct country_code_to_enum_rd allCountries[] = {
  19. {COUNTRY_CODE_USER, "RD"},
  20. };
  21. /*
  22. * REG_RULE(freq start, freq end, bandwidth, max gain, eirp, reg_flags)
  23. */
  24. /*
  25. *Only these channels all allow active
  26. *scan on all world regulatory domains
  27. */
  28. /* 2G chan 01 - chan 11 */
  29. #define RTW_2GHZ_CH01_11 \
  30. REG_RULE(2412-10, 2462+10, 40, 0, 20, 0)
  31. /*
  32. *We enable active scan on these a case
  33. *by case basis by regulatory domain
  34. */
  35. /* 2G chan 12 - chan 13, PASSIV SCAN */
  36. #define RTW_2GHZ_CH12_13 \
  37. REG_RULE(2467-10, 2472+10, 40, 0, 20, \
  38. NL80211_RRF_PASSIVE_SCAN)
  39. /* 2G chan 14, PASSIVS SCAN, NO OFDM (B only) */
  40. #define RTW_2GHZ_CH14 \
  41. REG_RULE(2484-10, 2484+10, 40, 0, 20, \
  42. NL80211_RRF_PASSIVE_SCAN | NL80211_RRF_NO_OFDM)
  43. /* 5G chan 36 - chan 64 */
  44. #define RTW_5GHZ_5150_5350 \
  45. REG_RULE(5150-10, 5350+10, 40, 0, 30, \
  46. NL80211_RRF_PASSIVE_SCAN | NL80211_RRF_NO_IBSS)
  47. /* 5G chan 100 - chan 165 */
  48. #define RTW_5GHZ_5470_5850 \
  49. REG_RULE(5470-10, 5850+10, 40, 0, 30, \
  50. NL80211_RRF_PASSIVE_SCAN | NL80211_RRF_NO_IBSS)
  51. /* 5G chan 149 - chan 165 */
  52. #define RTW_5GHZ_5725_5850 \
  53. REG_RULE(5725-10, 5850+10, 40, 0, 30, \
  54. NL80211_RRF_PASSIVE_SCAN | NL80211_RRF_NO_IBSS)
  55. /* 5G chan 36 - chan 165 */
  56. #define RTW_5GHZ_5150_5850 \
  57. REG_RULE(5150-10, 5850+10, 40, 0, 30, \
  58. NL80211_RRF_PASSIVE_SCAN | NL80211_RRF_NO_IBSS)
  59. static const struct ieee80211_regdomain rtw_regdom_rd = {
  60. .n_reg_rules = 3,
  61. .alpha2 = "99",
  62. .reg_rules = {
  63. RTW_2GHZ_CH01_11,
  64. RTW_2GHZ_CH12_13,
  65. RTW_5GHZ_5150_5850,
  66. }
  67. };
  68. static const struct ieee80211_regdomain rtw_regdom_11 = {
  69. .n_reg_rules = 1,
  70. .alpha2 = "99",
  71. .reg_rules = {
  72. RTW_2GHZ_CH01_11,
  73. }
  74. };
  75. static const struct ieee80211_regdomain rtw_regdom_12_13 = {
  76. .n_reg_rules = 2,
  77. .alpha2 = "99",
  78. .reg_rules = {
  79. RTW_2GHZ_CH01_11,
  80. RTW_2GHZ_CH12_13,
  81. }
  82. };
  83. static const struct ieee80211_regdomain rtw_regdom_no_midband = {
  84. .n_reg_rules = 3,
  85. .alpha2 = "99",
  86. .reg_rules = {
  87. RTW_2GHZ_CH01_11,
  88. RTW_5GHZ_5150_5350,
  89. RTW_5GHZ_5725_5850,
  90. }
  91. };
  92. static const struct ieee80211_regdomain rtw_regdom_60_64 = {
  93. .n_reg_rules = 3,
  94. .alpha2 = "99",
  95. .reg_rules = {
  96. RTW_2GHZ_CH01_11,
  97. RTW_2GHZ_CH12_13,
  98. RTW_5GHZ_5725_5850,
  99. }
  100. };
  101. static const struct ieee80211_regdomain rtw_regdom_14_60_64 = {
  102. .n_reg_rules = 4,
  103. .alpha2 = "99",
  104. .reg_rules = {
  105. RTW_2GHZ_CH01_11,
  106. RTW_2GHZ_CH12_13,
  107. RTW_2GHZ_CH14,
  108. RTW_5GHZ_5725_5850,
  109. }
  110. };
  111. static const struct ieee80211_regdomain rtw_regdom_14 = {
  112. .n_reg_rules = 3,
  113. .alpha2 = "99",
  114. .reg_rules = {
  115. RTW_2GHZ_CH01_11,
  116. RTW_2GHZ_CH12_13,
  117. RTW_2GHZ_CH14,
  118. }
  119. };
  120. #if 0
  121. static struct rtw_regulatory *rtw_regd;
  122. #endif
  123. #if 0 /* not_yet */
  124. static void _rtw_reg_apply_beaconing_flags(struct wiphy *wiphy,
  125. enum nl80211_reg_initiator initiator)
  126. {
  127. enum nl80211_band band;
  128. struct ieee80211_supported_band *sband;
  129. const struct ieee80211_reg_rule *reg_rule;
  130. struct ieee80211_channel *ch;
  131. unsigned int i;
  132. u32 bandwidth = 0;
  133. int r;
  134. for (band = 0; band < NUM_NL80211_BANDS; band++) {
  135. if (!wiphy->bands[band])
  136. continue;
  137. sband = wiphy->bands[band];
  138. for (i = 0; i < sband->n_channels; i++) {
  139. ch = &sband->channels[i];
  140. if (rtw_is_dfs_ch(ch->hw_value) ||
  141. (ch->flags & IEEE80211_CHAN_RADAR))
  142. continue;
  143. if (initiator == NL80211_REGDOM_SET_BY_COUNTRY_IE) {
  144. r = freq_reg_info(wiphy, ch->center_freq,
  145. bandwidth, &reg_rule);
  146. if (r)
  147. continue;
  148. /*
  149. *If 11d had a rule for this channel ensure
  150. *we enable adhoc/beaconing if it allows us to
  151. *use it. Note that we would have disabled it
  152. *by applying our static world regdomain by
  153. *default during init, prior to calling our
  154. *regulatory_hint().
  155. */
  156. if (!(reg_rule->flags & NL80211_RRF_NO_IBSS))
  157. ch->flags &= ~IEEE80211_CHAN_NO_IBSS;
  158. if (!
  159. (reg_rule->flags &
  160. NL80211_RRF_PASSIVE_SCAN))
  161. ch->flags &=
  162. ~IEEE80211_CHAN_PASSIVE_SCAN;
  163. } else {
  164. if (ch->beacon_found)
  165. ch->flags &= ~(IEEE80211_CHAN_NO_IBSS |
  166. IEEE80211_CHAN_PASSIVE_SCAN);
  167. }
  168. }
  169. }
  170. }
  171. /* Allows active scan scan on Ch 12 and 13 */
  172. static void _rtw_reg_apply_active_scan_flags(struct wiphy *wiphy,
  173. enum nl80211_reg_initiator
  174. initiator)
  175. {
  176. struct ieee80211_supported_band *sband;
  177. struct ieee80211_channel *ch;
  178. const struct ieee80211_reg_rule *reg_rule;
  179. u32 bandwidth = 0;
  180. int r;
  181. if (!wiphy->bands[NL80211_BAND_2GHZ])
  182. return;
  183. sband = wiphy->bands[NL80211_BAND_2GHZ];
  184. /*
  185. * If no country IE has been received always enable active scan
  186. * on these channels. This is only done for specific regulatory SKUs
  187. */
  188. if (initiator != NL80211_REGDOM_SET_BY_COUNTRY_IE) {
  189. ch = &sband->channels[11]; /* CH 12 */
  190. if (ch->flags & IEEE80211_CHAN_PASSIVE_SCAN)
  191. ch->flags &= ~IEEE80211_CHAN_PASSIVE_SCAN;
  192. ch = &sband->channels[12]; /* CH 13 */
  193. if (ch->flags & IEEE80211_CHAN_PASSIVE_SCAN)
  194. ch->flags &= ~IEEE80211_CHAN_PASSIVE_SCAN;
  195. return;
  196. }
  197. /*
  198. * If a country IE has been received check its rule for this
  199. * channel first before enabling active scan. The passive scan
  200. * would have been enforced by the initial processing of our
  201. * custom regulatory domain.
  202. */
  203. ch = &sband->channels[11]; /* CH 12 */
  204. r = freq_reg_info(wiphy, ch->center_freq, bandwidth, &reg_rule);
  205. if (!r) {
  206. if (!(reg_rule->flags & NL80211_RRF_PASSIVE_SCAN))
  207. if (ch->flags & IEEE80211_CHAN_PASSIVE_SCAN)
  208. ch->flags &= ~IEEE80211_CHAN_PASSIVE_SCAN;
  209. }
  210. ch = &sband->channels[12]; /* CH 13 */
  211. r = freq_reg_info(wiphy, ch->center_freq, bandwidth, &reg_rule);
  212. if (!r) {
  213. if (!(reg_rule->flags & NL80211_RRF_PASSIVE_SCAN))
  214. if (ch->flags & IEEE80211_CHAN_PASSIVE_SCAN)
  215. ch->flags &= ~IEEE80211_CHAN_PASSIVE_SCAN;
  216. }
  217. }
  218. #endif
  219. void rtw_regd_apply_flags(struct wiphy *wiphy)
  220. {
  221. struct dvobj_priv *dvobj = wiphy_to_dvobj(wiphy);
  222. struct rf_ctl_t *rfctl = dvobj_to_rfctl(dvobj);
  223. RT_CHANNEL_INFO *channel_set = rfctl->channel_set;
  224. u8 max_chan_nums = rfctl->max_chan_nums;
  225. struct ieee80211_supported_band *sband;
  226. struct ieee80211_channel *ch;
  227. unsigned int i, j;
  228. u16 channel;
  229. u32 freq;
  230. /* all channels disable */
  231. for (i = 0; i < NUM_NL80211_BANDS; i++) {
  232. sband = wiphy->bands[i];
  233. if (sband) {
  234. for (j = 0; j < sband->n_channels; j++) {
  235. ch = &sband->channels[j];
  236. if (ch)
  237. ch->flags = IEEE80211_CHAN_DISABLED;
  238. }
  239. }
  240. }
  241. /* channels apply by channel plans. */
  242. for (i = 0; i < max_chan_nums; i++) {
  243. channel = channel_set[i].ChannelNum;
  244. freq = rtw_ch2freq(channel);
  245. ch = ieee80211_get_channel(wiphy, freq);
  246. if (!ch)
  247. continue;
  248. if (channel_set[i].ScanType == SCAN_PASSIVE
  249. #if defined(CONFIG_DFS_MASTER)
  250. && rtw_odm_dfs_domain_unknown(dvobj)
  251. #endif
  252. ) {
  253. #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 14, 0))
  254. ch->flags = (IEEE80211_CHAN_NO_IBSS | IEEE80211_CHAN_PASSIVE_SCAN);
  255. #else
  256. ch->flags = IEEE80211_CHAN_NO_IR;
  257. #endif
  258. } else
  259. ch->flags = 0;
  260. #ifdef CONFIG_DFS
  261. if (rtw_is_dfs_ch(ch->hw_value)
  262. #if defined(CONFIG_DFS_MASTER)
  263. && rtw_odm_dfs_domain_unknown(dvobj)
  264. #endif
  265. ) {
  266. ch->flags |= IEEE80211_CHAN_RADAR;
  267. #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 14, 0))
  268. ch->flags |= (IEEE80211_CHAN_NO_IBSS | IEEE80211_CHAN_PASSIVE_SCAN);
  269. #else
  270. ch->flags |= IEEE80211_CHAN_NO_IR;
  271. #endif
  272. }
  273. #endif /* CONFIG_DFS */
  274. }
  275. }
  276. static const struct ieee80211_regdomain *_rtw_regdomain_select(struct
  277. rtw_regulatory
  278. *reg)
  279. {
  280. #if 0
  281. switch (reg->country_code) {
  282. case COUNTRY_CODE_USER:
  283. default:
  284. return &rtw_regdom_rd;
  285. }
  286. #else
  287. return &rtw_regdom_rd;
  288. #endif
  289. }
  290. static void rtw_reg_notifier(struct wiphy *wiphy, struct regulatory_request *request)
  291. {
  292. switch (request->initiator) {
  293. case NL80211_REGDOM_SET_BY_DRIVER:
  294. RTW_INFO("%s: %s\n", __func__, "NL80211_REGDOM_SET_BY_DRIVER");
  295. break;
  296. case NL80211_REGDOM_SET_BY_CORE:
  297. RTW_INFO("%s: %s\n", __func__, "NL80211_REGDOM_SET_BY_CORE");
  298. break;
  299. case NL80211_REGDOM_SET_BY_USER:
  300. RTW_INFO("%s: %s alpha2:%c%c\n", __func__, "NL80211_REGDOM_SET_BY_USER"
  301. , request->alpha2[0], request->alpha2[1]);
  302. rtw_set_country(wiphy_to_adapter(wiphy), request->alpha2);
  303. break;
  304. case NL80211_REGDOM_SET_BY_COUNTRY_IE:
  305. RTW_INFO("%s: %s\n", __func__, "NL80211_REGDOM_SET_BY_COUNTRY_IE");
  306. break;
  307. }
  308. rtw_regd_apply_flags(wiphy);
  309. }
  310. #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 9, 0))
  311. static int rtw_reg_notifier_return(struct wiphy *wiphy, struct regulatory_request *request)
  312. {
  313. rtw_reg_notifier(wiphy, request);
  314. return 0;
  315. }
  316. #endif
  317. static void _rtw_regd_init_wiphy(struct rtw_regulatory *reg, struct wiphy *wiphy)
  318. {
  319. const struct ieee80211_regdomain *regd;
  320. #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 9, 0))
  321. wiphy->reg_notifier = rtw_reg_notifier_return;
  322. #else
  323. wiphy->reg_notifier = rtw_reg_notifier;
  324. #endif
  325. #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 14, 0))
  326. wiphy->flags |= WIPHY_FLAG_CUSTOM_REGULATORY;
  327. wiphy->flags &= ~WIPHY_FLAG_STRICT_REGULATORY;
  328. wiphy->flags &= ~WIPHY_FLAG_DISABLE_BEACON_HINTS;
  329. #else
  330. wiphy->regulatory_flags |= REGULATORY_CUSTOM_REG;
  331. wiphy->regulatory_flags &= ~REGULATORY_STRICT_REG;
  332. wiphy->regulatory_flags &= ~REGULATORY_DISABLE_BEACON_HINTS;
  333. #endif
  334. regd = _rtw_regdomain_select(reg);
  335. wiphy_apply_custom_regulatory(wiphy, regd);
  336. rtw_regd_apply_flags(wiphy);
  337. }
  338. static struct country_code_to_enum_rd *_rtw_regd_find_country(u16 countrycode)
  339. {
  340. int i;
  341. for (i = 0; i < ARRAY_SIZE(allCountries); i++) {
  342. if (allCountries[i].countrycode == countrycode)
  343. return &allCountries[i];
  344. }
  345. return NULL;
  346. }
  347. int rtw_regd_init(struct wiphy *wiphy)
  348. {
  349. #if 0
  350. if (rtw_regd == NULL) {
  351. rtw_regd = (struct rtw_regulatory *)
  352. rtw_malloc(sizeof(struct rtw_regulatory));
  353. rtw_regd->alpha2[0] = '9';
  354. rtw_regd->alpha2[1] = '9';
  355. rtw_regd->country_code = COUNTRY_CODE_USER;
  356. }
  357. RTW_INFO("%s: Country alpha2 being used: %c%c\n",
  358. __func__, rtw_regd->alpha2[0], rtw_regd->alpha2[1]);
  359. #endif
  360. _rtw_regd_init_wiphy(NULL, wiphy);
  361. return 0;
  362. }
  363. #endif /* CONFIG_IOCTL_CFG80211 */