regd.c 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026
  1. /*
  2. * Copyright (c) 2008 Atheros Communications Inc.
  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/kernel.h>
  17. #include <linux/slab.h>
  18. #include "core.h"
  19. #include "hw.h"
  20. #include "regd.h"
  21. #include "regd_common.h"
  22. static int ath9k_regd_chansort(const void *a, const void *b)
  23. {
  24. const struct ath9k_channel *ca = a;
  25. const struct ath9k_channel *cb = b;
  26. return (ca->channel == cb->channel) ?
  27. (ca->channelFlags & CHAN_FLAGS) -
  28. (cb->channelFlags & CHAN_FLAGS) : ca->channel - cb->channel;
  29. }
  30. static void
  31. ath9k_regd_sort(void *a, u32 n, u32 size, ath_hal_cmp_t *cmp)
  32. {
  33. u8 *aa = a;
  34. u8 *ai, *t;
  35. for (ai = aa + size; --n >= 1; ai += size)
  36. for (t = ai; t > aa; t -= size) {
  37. u8 *u = t - size;
  38. if (cmp(u, t) <= 0)
  39. break;
  40. swap(u, t, size);
  41. }
  42. }
  43. static u16 ath9k_regd_get_eepromRD(struct ath_hal *ah)
  44. {
  45. return ah->ah_currentRD & ~WORLDWIDE_ROAMING_FLAG;
  46. }
  47. static bool ath9k_regd_is_chan_bm_zero(u64 *bitmask)
  48. {
  49. int i;
  50. for (i = 0; i < BMLEN; i++) {
  51. if (bitmask[i] != 0)
  52. return false;
  53. }
  54. return true;
  55. }
  56. static bool ath9k_regd_is_eeprom_valid(struct ath_hal *ah)
  57. {
  58. u16 rd = ath9k_regd_get_eepromRD(ah);
  59. int i;
  60. if (rd & COUNTRY_ERD_FLAG) {
  61. u16 cc = rd & ~COUNTRY_ERD_FLAG;
  62. for (i = 0; i < ARRAY_SIZE(allCountries); i++)
  63. if (allCountries[i].countryCode == cc)
  64. return true;
  65. } else {
  66. for (i = 0; i < ARRAY_SIZE(regDomainPairs); i++)
  67. if (regDomainPairs[i].regDmnEnum == rd)
  68. return true;
  69. }
  70. DPRINTF(ah->ah_sc, ATH_DBG_REGULATORY,
  71. "%s: invalid regulatory domain/country code 0x%x\n",
  72. __func__, rd);
  73. return false;
  74. }
  75. static bool ath9k_regd_is_fcc_midband_supported(struct ath_hal *ah)
  76. {
  77. u32 regcap;
  78. regcap = ah->ah_caps.reg_cap;
  79. if (regcap & AR_EEPROM_EEREGCAP_EN_FCC_MIDBAND)
  80. return true;
  81. else
  82. return false;
  83. }
  84. static bool ath9k_regd_is_ccode_valid(struct ath_hal *ah,
  85. u16 cc)
  86. {
  87. u16 rd;
  88. int i;
  89. if (cc == CTRY_DEFAULT)
  90. return true;
  91. if (cc == CTRY_DEBUG)
  92. return true;
  93. rd = ath9k_regd_get_eepromRD(ah);
  94. DPRINTF(ah->ah_sc, ATH_DBG_REGULATORY, "%s: EEPROM regdomain 0x%x\n",
  95. __func__, rd);
  96. if (rd & COUNTRY_ERD_FLAG) {
  97. DPRINTF(ah->ah_sc, ATH_DBG_REGULATORY,
  98. "%s: EEPROM setting is country code %u\n",
  99. __func__, rd & ~COUNTRY_ERD_FLAG);
  100. return cc == (rd & ~COUNTRY_ERD_FLAG);
  101. }
  102. for (i = 0; i < ARRAY_SIZE(allCountries); i++) {
  103. if (cc == allCountries[i].countryCode) {
  104. #ifdef AH_SUPPORT_11D
  105. if ((rd & WORLD_SKU_MASK) == WORLD_SKU_PREFIX)
  106. return true;
  107. #endif
  108. if (allCountries[i].regDmnEnum == rd ||
  109. rd == DEBUG_REG_DMN || rd == NO_ENUMRD)
  110. return true;
  111. }
  112. }
  113. return false;
  114. }
  115. static void
  116. ath9k_regd_get_wmodes_nreg(struct ath_hal *ah,
  117. struct country_code_to_enum_rd *country,
  118. struct regDomain *rd5GHz,
  119. unsigned long *modes_allowed)
  120. {
  121. bitmap_copy(modes_allowed, ah->ah_caps.wireless_modes, ATH9K_MODE_MAX);
  122. if (test_bit(ATH9K_MODE_11G, ah->ah_caps.wireless_modes) &&
  123. (!country->allow11g))
  124. clear_bit(ATH9K_MODE_11G, modes_allowed);
  125. if (test_bit(ATH9K_MODE_11A, ah->ah_caps.wireless_modes) &&
  126. (ath9k_regd_is_chan_bm_zero(rd5GHz->chan11a)))
  127. clear_bit(ATH9K_MODE_11A, modes_allowed);
  128. if (test_bit(ATH9K_MODE_11NG_HT20, ah->ah_caps.wireless_modes)
  129. && (!country->allow11ng20))
  130. clear_bit(ATH9K_MODE_11NG_HT20, modes_allowed);
  131. if (test_bit(ATH9K_MODE_11NA_HT20, ah->ah_caps.wireless_modes)
  132. && (!country->allow11na20))
  133. clear_bit(ATH9K_MODE_11NA_HT20, modes_allowed);
  134. if (test_bit(ATH9K_MODE_11NG_HT40PLUS, ah->ah_caps.wireless_modes) &&
  135. (!country->allow11ng40))
  136. clear_bit(ATH9K_MODE_11NG_HT40PLUS, modes_allowed);
  137. if (test_bit(ATH9K_MODE_11NG_HT40MINUS, ah->ah_caps.wireless_modes) &&
  138. (!country->allow11ng40))
  139. clear_bit(ATH9K_MODE_11NG_HT40MINUS, modes_allowed);
  140. if (test_bit(ATH9K_MODE_11NA_HT40PLUS, ah->ah_caps.wireless_modes) &&
  141. (!country->allow11na40))
  142. clear_bit(ATH9K_MODE_11NA_HT40PLUS, modes_allowed);
  143. if (test_bit(ATH9K_MODE_11NA_HT40MINUS, ah->ah_caps.wireless_modes) &&
  144. (!country->allow11na40))
  145. clear_bit(ATH9K_MODE_11NA_HT40MINUS, modes_allowed);
  146. }
  147. bool ath9k_regd_is_public_safety_sku(struct ath_hal *ah)
  148. {
  149. u16 rd;
  150. rd = ath9k_regd_get_eepromRD(ah);
  151. switch (rd) {
  152. case FCC4_FCCA:
  153. case (CTRY_UNITED_STATES_FCC49 | COUNTRY_ERD_FLAG):
  154. return true;
  155. case DEBUG_REG_DMN:
  156. case NO_ENUMRD:
  157. if (ah->ah_countryCode == CTRY_UNITED_STATES_FCC49)
  158. return true;
  159. break;
  160. }
  161. return false;
  162. }
  163. static struct country_code_to_enum_rd*
  164. ath9k_regd_find_country(u16 countryCode)
  165. {
  166. int i;
  167. for (i = 0; i < ARRAY_SIZE(allCountries); i++) {
  168. if (allCountries[i].countryCode == countryCode)
  169. return &allCountries[i];
  170. }
  171. return NULL;
  172. }
  173. static u16 ath9k_regd_get_default_country(struct ath_hal *ah)
  174. {
  175. u16 rd;
  176. int i;
  177. rd = ath9k_regd_get_eepromRD(ah);
  178. if (rd & COUNTRY_ERD_FLAG) {
  179. struct country_code_to_enum_rd *country = NULL;
  180. u16 cc = rd & ~COUNTRY_ERD_FLAG;
  181. country = ath9k_regd_find_country(cc);
  182. if (country != NULL)
  183. return cc;
  184. }
  185. for (i = 0; i < ARRAY_SIZE(regDomainPairs); i++)
  186. if (regDomainPairs[i].regDmnEnum == rd) {
  187. if (regDomainPairs[i].singleCC != 0)
  188. return regDomainPairs[i].singleCC;
  189. else
  190. i = ARRAY_SIZE(regDomainPairs);
  191. }
  192. return CTRY_DEFAULT;
  193. }
  194. static bool ath9k_regd_is_valid_reg_domain(int regDmn,
  195. struct regDomain *rd)
  196. {
  197. int i;
  198. for (i = 0; i < ARRAY_SIZE(regDomains); i++) {
  199. if (regDomains[i].regDmnEnum == regDmn) {
  200. if (rd != NULL) {
  201. memcpy(rd, &regDomains[i],
  202. sizeof(struct regDomain));
  203. }
  204. return true;
  205. }
  206. }
  207. return false;
  208. }
  209. static bool ath9k_regd_is_valid_reg_domainPair(int regDmnPair)
  210. {
  211. int i;
  212. if (regDmnPair == NO_ENUMRD)
  213. return false;
  214. for (i = 0; i < ARRAY_SIZE(regDomainPairs); i++) {
  215. if (regDomainPairs[i].regDmnEnum == regDmnPair)
  216. return true;
  217. }
  218. return false;
  219. }
  220. static bool
  221. ath9k_regd_get_wmode_regdomain(struct ath_hal *ah, int regDmn,
  222. u16 channelFlag, struct regDomain *rd)
  223. {
  224. int i, found;
  225. u64 flags = NO_REQ;
  226. struct reg_dmn_pair_mapping *regPair = NULL;
  227. int regOrg;
  228. regOrg = regDmn;
  229. if (regDmn == CTRY_DEFAULT) {
  230. u16 rdnum;
  231. rdnum = ath9k_regd_get_eepromRD(ah);
  232. if (!(rdnum & COUNTRY_ERD_FLAG)) {
  233. if (ath9k_regd_is_valid_reg_domain(rdnum, NULL) ||
  234. ath9k_regd_is_valid_reg_domainPair(rdnum)) {
  235. regDmn = rdnum;
  236. }
  237. }
  238. }
  239. if ((regDmn & MULTI_DOMAIN_MASK) == 0) {
  240. for (i = 0, found = 0;
  241. (i < ARRAY_SIZE(regDomainPairs)) && (!found); i++) {
  242. if (regDomainPairs[i].regDmnEnum == regDmn) {
  243. regPair = &regDomainPairs[i];
  244. found = 1;
  245. }
  246. }
  247. if (!found) {
  248. DPRINTF(ah->ah_sc, ATH_DBG_REGULATORY,
  249. "%s: Failed to find reg domain pair %u\n",
  250. __func__, regDmn);
  251. return false;
  252. }
  253. if (!(channelFlag & CHANNEL_2GHZ)) {
  254. regDmn = regPair->regDmn5GHz;
  255. flags = regPair->flags5GHz;
  256. }
  257. if (channelFlag & CHANNEL_2GHZ) {
  258. regDmn = regPair->regDmn2GHz;
  259. flags = regPair->flags2GHz;
  260. }
  261. }
  262. found = ath9k_regd_is_valid_reg_domain(regDmn, rd);
  263. if (!found) {
  264. DPRINTF(ah->ah_sc, ATH_DBG_REGULATORY,
  265. "%s: Failed to find unitary reg domain %u\n",
  266. __func__, regDmn);
  267. return false;
  268. } else {
  269. rd->pscan &= regPair->pscanMask;
  270. if (((regOrg & MULTI_DOMAIN_MASK) == 0) &&
  271. (flags != NO_REQ)) {
  272. rd->flags = flags;
  273. }
  274. rd->flags &= (channelFlag & CHANNEL_2GHZ) ?
  275. REG_DOMAIN_2GHZ_MASK : REG_DOMAIN_5GHZ_MASK;
  276. return true;
  277. }
  278. }
  279. static bool ath9k_regd_is_bit_set(int bit, u64 *bitmask)
  280. {
  281. int byteOffset, bitnum;
  282. u64 val;
  283. byteOffset = bit / 64;
  284. bitnum = bit - byteOffset * 64;
  285. val = ((u64) 1) << bitnum;
  286. if (bitmask[byteOffset] & val)
  287. return true;
  288. else
  289. return false;
  290. }
  291. static void
  292. ath9k_regd_add_reg_classid(u8 *regclassids, u32 maxregids,
  293. u32 *nregids, u8 regclassid)
  294. {
  295. int i;
  296. if (regclassid == 0)
  297. return;
  298. for (i = 0; i < maxregids; i++) {
  299. if (regclassids[i] == regclassid)
  300. return;
  301. if (regclassids[i] == 0)
  302. break;
  303. }
  304. if (i == maxregids)
  305. return;
  306. else {
  307. regclassids[i] = regclassid;
  308. *nregids += 1;
  309. }
  310. return;
  311. }
  312. static bool
  313. ath9k_regd_get_eeprom_reg_ext_bits(struct ath_hal *ah,
  314. enum reg_ext_bitmap bit)
  315. {
  316. return (ah->ah_currentRDExt & (1 << bit)) ? true : false;
  317. }
  318. #ifdef ATH_NF_PER_CHAN
  319. static void ath9k_regd_init_rf_buffer(struct ath9k_channel *ichans,
  320. int nchans)
  321. {
  322. int i, j, next;
  323. for (next = 0; next < nchans; next++) {
  324. for (i = 0; i < NUM_NF_READINGS; i++) {
  325. ichans[next].nfCalHist[i].currIndex = 0;
  326. ichans[next].nfCalHist[i].privNF =
  327. AR_PHY_CCA_MAX_GOOD_VALUE;
  328. ichans[next].nfCalHist[i].invalidNFcount =
  329. AR_PHY_CCA_FILTERWINDOW_LENGTH;
  330. for (j = 0; j < ATH9K_NF_CAL_HIST_MAX; j++) {
  331. ichans[next].nfCalHist[i].nfCalBuffer[j] =
  332. AR_PHY_CCA_MAX_GOOD_VALUE;
  333. }
  334. }
  335. }
  336. }
  337. #endif
  338. static int ath9k_regd_is_chan_present(struct ath_hal *ah,
  339. u16 c)
  340. {
  341. int i;
  342. for (i = 0; i < 150; i++) {
  343. if (!ah->ah_channels[i].channel)
  344. return -1;
  345. else if (ah->ah_channels[i].channel == c)
  346. return i;
  347. }
  348. return -1;
  349. }
  350. static bool
  351. ath9k_regd_add_channel(struct ath_hal *ah,
  352. u16 c,
  353. u16 c_lo,
  354. u16 c_hi,
  355. u16 maxChan,
  356. u8 ctl,
  357. int pos,
  358. struct regDomain rd5GHz,
  359. struct RegDmnFreqBand *fband,
  360. struct regDomain *rd,
  361. const struct cmode *cm,
  362. struct ath9k_channel *ichans,
  363. bool enableExtendedChannels)
  364. {
  365. struct ath9k_channel *chan;
  366. int ret;
  367. u32 channelFlags = 0;
  368. u8 privFlags = 0;
  369. if (!(c_lo <= c && c <= c_hi)) {
  370. DPRINTF(ah->ah_sc, ATH_DBG_REGULATORY,
  371. "%s: c %u out of range [%u..%u]\n",
  372. __func__, c, c_lo, c_hi);
  373. return false;
  374. }
  375. if ((fband->channelBW == CHANNEL_HALF_BW) &&
  376. !(ah->ah_caps.hw_caps & ATH9K_HW_CAP_CHAN_HALFRATE)) {
  377. DPRINTF(ah->ah_sc, ATH_DBG_REGULATORY,
  378. "%s: Skipping %u half rate channel\n",
  379. __func__, c);
  380. return false;
  381. }
  382. if ((fband->channelBW == CHANNEL_QUARTER_BW) &&
  383. !(ah->ah_caps.hw_caps & ATH9K_HW_CAP_CHAN_QUARTERRATE)) {
  384. DPRINTF(ah->ah_sc, ATH_DBG_REGULATORY,
  385. "%s: Skipping %u quarter rate channel\n",
  386. __func__, c);
  387. return false;
  388. }
  389. if (((c + fband->channelSep) / 2) > (maxChan + HALF_MAXCHANBW)) {
  390. DPRINTF(ah->ah_sc, ATH_DBG_REGULATORY,
  391. "%s: c %u > maxChan %u\n",
  392. __func__, c, maxChan);
  393. return false;
  394. }
  395. if ((fband->usePassScan & IS_ECM_CHAN) && !enableExtendedChannels) {
  396. DPRINTF(ah->ah_sc, ATH_DBG_REGULATORY,
  397. "Skipping ecm channel\n");
  398. return false;
  399. }
  400. if ((rd->flags & NO_HOSTAP) && (ah->ah_opmode == ATH9K_M_HOSTAP)) {
  401. DPRINTF(ah->ah_sc, ATH_DBG_REGULATORY,
  402. "Skipping HOSTAP channel\n");
  403. return false;
  404. }
  405. if (IS_HT40_MODE(cm->mode) &&
  406. !(ath9k_regd_get_eeprom_reg_ext_bits(ah, REG_EXT_FCC_DFS_HT40)) &&
  407. (fband->useDfs) &&
  408. (rd->conformanceTestLimit != MKK)) {
  409. DPRINTF(ah->ah_sc, ATH_DBG_REGULATORY,
  410. "Skipping HT40 channel (en_fcc_dfs_ht40 = 0)\n");
  411. return false;
  412. }
  413. if (IS_HT40_MODE(cm->mode) &&
  414. !(ath9k_regd_get_eeprom_reg_ext_bits(ah,
  415. REG_EXT_JAPAN_NONDFS_HT40)) &&
  416. !(fband->useDfs) && (rd->conformanceTestLimit == MKK)) {
  417. DPRINTF(ah->ah_sc, ATH_DBG_REGULATORY,
  418. "Skipping HT40 channel (en_jap_ht40 = 0)\n");
  419. return false;
  420. }
  421. if (IS_HT40_MODE(cm->mode) &&
  422. !(ath9k_regd_get_eeprom_reg_ext_bits(ah, REG_EXT_JAPAN_DFS_HT40)) &&
  423. (fband->useDfs) &&
  424. (rd->conformanceTestLimit == MKK)) {
  425. DPRINTF(ah->ah_sc, ATH_DBG_REGULATORY,
  426. "Skipping HT40 channel (en_jap_dfs_ht40 = 0)\n");
  427. return false;
  428. }
  429. /* Calculate channel flags */
  430. channelFlags = cm->flags;
  431. switch (fband->channelBW) {
  432. case CHANNEL_HALF_BW:
  433. channelFlags |= CHANNEL_HALF;
  434. break;
  435. case CHANNEL_QUARTER_BW:
  436. channelFlags |= CHANNEL_QUARTER;
  437. break;
  438. }
  439. if (fband->usePassScan & rd->pscan)
  440. channelFlags |= CHANNEL_PASSIVE;
  441. else
  442. channelFlags &= ~CHANNEL_PASSIVE;
  443. if (fband->useDfs & rd->dfsMask)
  444. privFlags = CHANNEL_DFS;
  445. else
  446. privFlags = 0;
  447. if (rd->flags & LIMIT_FRAME_4MS)
  448. privFlags |= CHANNEL_4MS_LIMIT;
  449. if (privFlags & CHANNEL_DFS)
  450. privFlags |= CHANNEL_DISALLOW_ADHOC;
  451. if (rd->flags & ADHOC_PER_11D)
  452. privFlags |= CHANNEL_PER_11D_ADHOC;
  453. if (channelFlags & CHANNEL_PASSIVE) {
  454. if ((c < 2412) || (c > 2462)) {
  455. if (rd5GHz.regDmnEnum == MKK1 ||
  456. rd5GHz.regDmnEnum == MKK2) {
  457. u32 regcap = ah->ah_caps.reg_cap;
  458. if (!(regcap &
  459. (AR_EEPROM_EEREGCAP_EN_KK_U1_EVEN |
  460. AR_EEPROM_EEREGCAP_EN_KK_U2 |
  461. AR_EEPROM_EEREGCAP_EN_KK_MIDBAND)) &&
  462. isUNII1OddChan(c)) {
  463. channelFlags &= ~CHANNEL_PASSIVE;
  464. } else {
  465. privFlags |= CHANNEL_DISALLOW_ADHOC;
  466. }
  467. } else {
  468. privFlags |= CHANNEL_DISALLOW_ADHOC;
  469. }
  470. }
  471. }
  472. if ((cm->mode == ATH9K_MODE_11A) ||
  473. (cm->mode == ATH9K_MODE_11NA_HT20) ||
  474. (cm->mode == ATH9K_MODE_11NA_HT40PLUS) ||
  475. (cm->mode == ATH9K_MODE_11NA_HT40MINUS)) {
  476. if (rd->flags & (ADHOC_NO_11A | DISALLOW_ADHOC_11A))
  477. privFlags |= CHANNEL_DISALLOW_ADHOC;
  478. }
  479. /* Fill in channel details */
  480. ret = ath9k_regd_is_chan_present(ah, c);
  481. if (ret == -1) {
  482. chan = &ah->ah_channels[pos];
  483. chan->channel = c;
  484. chan->maxRegTxPower = fband->powerDfs;
  485. chan->antennaMax = fband->antennaMax;
  486. chan->regDmnFlags = rd->flags;
  487. chan->maxTxPower = AR5416_MAX_RATE_POWER;
  488. chan->minTxPower = AR5416_MAX_RATE_POWER;
  489. chan->channelFlags = channelFlags;
  490. chan->privFlags = privFlags;
  491. } else {
  492. chan = &ah->ah_channels[ret];
  493. chan->channelFlags |= channelFlags;
  494. chan->privFlags |= privFlags;
  495. }
  496. /* Set CTLs */
  497. if ((cm->flags & CHANNEL_ALL) == CHANNEL_A)
  498. chan->conformanceTestLimit[0] = ctl;
  499. else if ((cm->flags & CHANNEL_ALL) == CHANNEL_B)
  500. chan->conformanceTestLimit[1] = ctl;
  501. else if ((cm->flags & CHANNEL_ALL) == CHANNEL_G)
  502. chan->conformanceTestLimit[2] = ctl;
  503. return (ret == -1) ? true : false;
  504. }
  505. static bool ath9k_regd_japan_check(struct ath_hal *ah,
  506. int b,
  507. struct regDomain *rd5GHz)
  508. {
  509. bool skipband = false;
  510. int i;
  511. u32 regcap;
  512. for (i = 0; i < ARRAY_SIZE(j_bandcheck); i++) {
  513. if (j_bandcheck[i].freqbandbit == b) {
  514. regcap = ah->ah_caps.reg_cap;
  515. if ((j_bandcheck[i].eepromflagtocheck & regcap) == 0) {
  516. skipband = true;
  517. } else if ((regcap & AR_EEPROM_EEREGCAP_EN_KK_U2) ||
  518. (regcap & AR_EEPROM_EEREGCAP_EN_KK_MIDBAND)) {
  519. rd5GHz->dfsMask |= DFS_MKK4;
  520. rd5GHz->pscan |= PSCAN_MKK3;
  521. }
  522. break;
  523. }
  524. }
  525. DPRINTF(ah->ah_sc, ATH_DBG_REGULATORY,
  526. "%s: Skipping %d freq band\n",
  527. __func__, j_bandcheck[i].freqbandbit);
  528. return skipband;
  529. }
  530. bool
  531. ath9k_regd_init_channels(struct ath_hal *ah,
  532. u32 maxchans,
  533. u32 *nchans, u8 *regclassids,
  534. u32 maxregids, u32 *nregids, u16 cc,
  535. bool enableOutdoor,
  536. bool enableExtendedChannels)
  537. {
  538. u16 maxChan = 7000;
  539. struct country_code_to_enum_rd *country = NULL;
  540. struct regDomain rd5GHz, rd2GHz;
  541. const struct cmode *cm;
  542. struct ath9k_channel *ichans = &ah->ah_channels[0];
  543. int next = 0, b;
  544. u8 ctl;
  545. int regdmn;
  546. u16 chanSep;
  547. unsigned long *modes_avail;
  548. DECLARE_BITMAP(modes_allowed, ATH9K_MODE_MAX);
  549. DPRINTF(ah->ah_sc, ATH_DBG_REGULATORY, "%s: cc %u %s %s\n",
  550. __func__, cc,
  551. enableOutdoor ? "Enable outdoor" : "",
  552. enableExtendedChannels ? "Enable ecm" : "");
  553. if (!ath9k_regd_is_ccode_valid(ah, cc)) {
  554. DPRINTF(ah->ah_sc, ATH_DBG_REGULATORY,
  555. "%s: invalid country code %d\n", __func__, cc);
  556. return false;
  557. }
  558. if (!ath9k_regd_is_eeprom_valid(ah)) {
  559. DPRINTF(ah->ah_sc, ATH_DBG_REGULATORY,
  560. "%s: invalid EEPROM contents\n", __func__);
  561. return false;
  562. }
  563. ah->ah_countryCode = ath9k_regd_get_default_country(ah);
  564. if (ah->ah_countryCode == CTRY_DEFAULT) {
  565. ah->ah_countryCode = cc & COUNTRY_CODE_MASK;
  566. if ((ah->ah_countryCode == CTRY_DEFAULT) &&
  567. (ath9k_regd_get_eepromRD(ah) == CTRY_DEFAULT)) {
  568. ah->ah_countryCode = CTRY_UNITED_STATES;
  569. }
  570. }
  571. #ifdef AH_SUPPORT_11D
  572. if (ah->ah_countryCode == CTRY_DEFAULT) {
  573. regdmn = ath9k_regd_get_eepromRD(ah);
  574. country = NULL;
  575. } else {
  576. #endif
  577. country = ath9k_regd_find_country(ah->ah_countryCode);
  578. if (country == NULL) {
  579. DPRINTF(ah->ah_sc, ATH_DBG_REGULATORY,
  580. "Country is NULL!!!!, cc= %d\n",
  581. ah->ah_countryCode);
  582. return false;
  583. } else {
  584. regdmn = country->regDmnEnum;
  585. #ifdef AH_SUPPORT_11D
  586. if (((ath9k_regd_get_eepromRD(ah) &
  587. WORLD_SKU_MASK) == WORLD_SKU_PREFIX) &&
  588. (cc == CTRY_UNITED_STATES)) {
  589. if (!isWwrSKU_NoMidband(ah)
  590. && ath9k_regd_is_fcc_midband_supported(ah))
  591. regdmn = FCC3_FCCA;
  592. else
  593. regdmn = FCC1_FCCA;
  594. }
  595. #endif
  596. }
  597. #ifdef AH_SUPPORT_11D
  598. }
  599. #endif
  600. if (!ath9k_regd_get_wmode_regdomain(ah,
  601. regdmn,
  602. ~CHANNEL_2GHZ,
  603. &rd5GHz)) {
  604. DPRINTF(ah->ah_sc, ATH_DBG_REGULATORY,
  605. "%s: couldn't find unitary "
  606. "5GHz reg domain for country %u\n",
  607. __func__, ah->ah_countryCode);
  608. return false;
  609. }
  610. if (!ath9k_regd_get_wmode_regdomain(ah,
  611. regdmn,
  612. CHANNEL_2GHZ,
  613. &rd2GHz)) {
  614. DPRINTF(ah->ah_sc, ATH_DBG_REGULATORY,
  615. "%s: couldn't find unitary 2GHz "
  616. "reg domain for country %u\n",
  617. __func__, ah->ah_countryCode);
  618. return false;
  619. }
  620. if (!isWwrSKU(ah) && ((rd5GHz.regDmnEnum == FCC1) ||
  621. (rd5GHz.regDmnEnum == FCC2))) {
  622. if (ath9k_regd_is_fcc_midband_supported(ah)) {
  623. if (!ath9k_regd_get_wmode_regdomain(ah,
  624. FCC3_FCCA,
  625. ~CHANNEL_2GHZ,
  626. &rd5GHz)) {
  627. DPRINTF(ah->ah_sc, ATH_DBG_REGULATORY,
  628. "%s: couldn't find unitary 5GHz "
  629. "reg domain for country %u\n",
  630. __func__, ah->ah_countryCode);
  631. return false;
  632. }
  633. }
  634. }
  635. if (country == NULL) {
  636. modes_avail = ah->ah_caps.wireless_modes;
  637. } else {
  638. ath9k_regd_get_wmodes_nreg(ah, country, &rd5GHz, modes_allowed);
  639. modes_avail = modes_allowed;
  640. if (!enableOutdoor)
  641. maxChan = country->outdoorChanStart;
  642. }
  643. next = 0;
  644. if (maxchans > ARRAY_SIZE(ah->ah_channels))
  645. maxchans = ARRAY_SIZE(ah->ah_channels);
  646. for (cm = modes; cm < &modes[ARRAY_SIZE(modes)]; cm++) {
  647. u16 c, c_hi, c_lo;
  648. u64 *channelBM = NULL;
  649. struct regDomain *rd = NULL;
  650. struct RegDmnFreqBand *fband = NULL, *freqs;
  651. int8_t low_adj = 0, hi_adj = 0;
  652. if (!test_bit(cm->mode, modes_avail)) {
  653. DPRINTF(ah->ah_sc, ATH_DBG_REGULATORY,
  654. "%s: !avail mode %d flags 0x%x\n",
  655. __func__, cm->mode, cm->flags);
  656. continue;
  657. }
  658. if (!ath9k_get_channel_edges(ah, cm->flags, &c_lo, &c_hi)) {
  659. DPRINTF(ah->ah_sc, ATH_DBG_REGULATORY,
  660. "%s: channels 0x%x not supported "
  661. "by hardware\n",
  662. __func__, cm->flags);
  663. continue;
  664. }
  665. switch (cm->mode) {
  666. case ATH9K_MODE_11A:
  667. case ATH9K_MODE_11NA_HT20:
  668. case ATH9K_MODE_11NA_HT40PLUS:
  669. case ATH9K_MODE_11NA_HT40MINUS:
  670. rd = &rd5GHz;
  671. channelBM = rd->chan11a;
  672. freqs = &regDmn5GhzFreq[0];
  673. ctl = rd->conformanceTestLimit;
  674. break;
  675. case ATH9K_MODE_11B:
  676. rd = &rd2GHz;
  677. channelBM = rd->chan11b;
  678. freqs = &regDmn2GhzFreq[0];
  679. ctl = rd->conformanceTestLimit | CTL_11B;
  680. break;
  681. case ATH9K_MODE_11G:
  682. case ATH9K_MODE_11NG_HT20:
  683. case ATH9K_MODE_11NG_HT40PLUS:
  684. case ATH9K_MODE_11NG_HT40MINUS:
  685. rd = &rd2GHz;
  686. channelBM = rd->chan11g;
  687. freqs = &regDmn2Ghz11gFreq[0];
  688. ctl = rd->conformanceTestLimit | CTL_11G;
  689. break;
  690. default:
  691. DPRINTF(ah->ah_sc, ATH_DBG_REGULATORY,
  692. "%s: Unknown HAL mode 0x%x\n", __func__,
  693. cm->mode);
  694. continue;
  695. }
  696. if (ath9k_regd_is_chan_bm_zero(channelBM))
  697. continue;
  698. if ((cm->mode == ATH9K_MODE_11NA_HT40PLUS) ||
  699. (cm->mode == ATH9K_MODE_11NG_HT40PLUS)) {
  700. hi_adj = -20;
  701. }
  702. if ((cm->mode == ATH9K_MODE_11NA_HT40MINUS) ||
  703. (cm->mode == ATH9K_MODE_11NG_HT40MINUS)) {
  704. low_adj = 20;
  705. }
  706. /* XXX: Add a helper here instead */
  707. for (b = 0; b < 64 * BMLEN; b++) {
  708. if (ath9k_regd_is_bit_set(b, channelBM)) {
  709. fband = &freqs[b];
  710. if (rd5GHz.regDmnEnum == MKK1
  711. || rd5GHz.regDmnEnum == MKK2) {
  712. if (ath9k_regd_japan_check(ah,
  713. b,
  714. &rd5GHz))
  715. continue;
  716. }
  717. ath9k_regd_add_reg_classid(regclassids,
  718. maxregids,
  719. nregids,
  720. fband->
  721. regClassId);
  722. if (IS_HT40_MODE(cm->mode) && (rd == &rd5GHz)) {
  723. chanSep = 40;
  724. if (fband->lowChannel == 5280)
  725. low_adj += 20;
  726. if (fband->lowChannel == 5170)
  727. continue;
  728. } else
  729. chanSep = fband->channelSep;
  730. for (c = fband->lowChannel + low_adj;
  731. ((c <= (fband->highChannel + hi_adj)) &&
  732. (c >= (fband->lowChannel + low_adj)));
  733. c += chanSep) {
  734. if (next >= maxchans) {
  735. DPRINTF(ah->ah_sc,
  736. ATH_DBG_REGULATORY,
  737. "%s: too many channels "
  738. "for channel table\n",
  739. __func__);
  740. goto done;
  741. }
  742. if (ath9k_regd_add_channel(ah,
  743. c, c_lo, c_hi,
  744. maxChan, ctl,
  745. next,
  746. rd5GHz,
  747. fband, rd, cm,
  748. ichans,
  749. enableExtendedChannels))
  750. next++;
  751. }
  752. if (IS_HT40_MODE(cm->mode) &&
  753. (fband->lowChannel == 5280)) {
  754. low_adj -= 20;
  755. }
  756. }
  757. }
  758. }
  759. done:
  760. if (next != 0) {
  761. int i;
  762. if (next > ARRAY_SIZE(ah->ah_channels)) {
  763. DPRINTF(ah->ah_sc, ATH_DBG_REGULATORY,
  764. "%s: too many channels %u; truncating to %u\n",
  765. __func__, next,
  766. (int) ARRAY_SIZE(ah->ah_channels));
  767. next = ARRAY_SIZE(ah->ah_channels);
  768. }
  769. #ifdef ATH_NF_PER_CHAN
  770. ath9k_regd_init_rf_buffer(ichans, next);
  771. #endif
  772. ath9k_regd_sort(ichans, next,
  773. sizeof(struct ath9k_channel),
  774. ath9k_regd_chansort);
  775. ah->ah_nchan = next;
  776. DPRINTF(ah->ah_sc, ATH_DBG_REGULATORY, "Channel list:\n");
  777. for (i = 0; i < next; i++) {
  778. DPRINTF(ah->ah_sc, ATH_DBG_REGULATORY,
  779. "chan: %d flags: 0x%x\n",
  780. ah->ah_channels[i].channel,
  781. ah->ah_channels[i].channelFlags);
  782. }
  783. }
  784. *nchans = next;
  785. ah->ah_countryCode = ah->ah_countryCode;
  786. ah->ah_currentRDInUse = regdmn;
  787. ah->ah_currentRD5G = rd5GHz.regDmnEnum;
  788. ah->ah_currentRD2G = rd2GHz.regDmnEnum;
  789. if (country == NULL) {
  790. ah->ah_iso[0] = 0;
  791. ah->ah_iso[1] = 0;
  792. } else {
  793. ah->ah_iso[0] = country->isoName[0];
  794. ah->ah_iso[1] = country->isoName[1];
  795. }
  796. return next != 0;
  797. }
  798. struct ath9k_channel*
  799. ath9k_regd_check_channel(struct ath_hal *ah,
  800. const struct ath9k_channel *c)
  801. {
  802. struct ath9k_channel *base, *cc;
  803. int flags = c->channelFlags & CHAN_FLAGS;
  804. int n, lim;
  805. DPRINTF(ah->ah_sc, ATH_DBG_REGULATORY,
  806. "%s: channel %u/0x%x (0x%x) requested\n", __func__,
  807. c->channel, c->channelFlags, flags);
  808. cc = ah->ah_curchan;
  809. if (cc != NULL && cc->channel == c->channel &&
  810. (cc->channelFlags & CHAN_FLAGS) == flags) {
  811. if ((cc->privFlags & CHANNEL_INTERFERENCE) &&
  812. (cc->privFlags & CHANNEL_DFS))
  813. return NULL;
  814. else
  815. return cc;
  816. }
  817. base = ah->ah_channels;
  818. n = ah->ah_nchan;
  819. for (lim = n; lim != 0; lim >>= 1) {
  820. int d;
  821. cc = &base[lim >> 1];
  822. d = c->channel - cc->channel;
  823. if (d == 0) {
  824. if ((cc->channelFlags & CHAN_FLAGS) == flags) {
  825. if ((cc->privFlags & CHANNEL_INTERFERENCE) &&
  826. (cc->privFlags & CHANNEL_DFS))
  827. return NULL;
  828. else
  829. return cc;
  830. }
  831. d = flags - (cc->channelFlags & CHAN_FLAGS);
  832. }
  833. DPRINTF(ah->ah_sc, ATH_DBG_REGULATORY,
  834. "%s: channel %u/0x%x d %d\n", __func__,
  835. cc->channel, cc->channelFlags, d);
  836. if (d > 0) {
  837. base = cc + 1;
  838. lim--;
  839. }
  840. }
  841. DPRINTF(ah->ah_sc, ATH_DBG_REGULATORY, "%s: no match for %u/0x%x\n",
  842. __func__, c->channel, c->channelFlags);
  843. return NULL;
  844. }
  845. u32
  846. ath9k_regd_get_antenna_allowed(struct ath_hal *ah,
  847. struct ath9k_channel *chan)
  848. {
  849. struct ath9k_channel *ichan = NULL;
  850. ichan = ath9k_regd_check_channel(ah, chan);
  851. if (!ichan)
  852. return 0;
  853. return ichan->antennaMax;
  854. }
  855. u32 ath9k_regd_get_ctl(struct ath_hal *ah, struct ath9k_channel *chan)
  856. {
  857. u32 ctl = NO_CTL;
  858. struct ath9k_channel *ichan;
  859. if (ah->ah_countryCode == CTRY_DEFAULT && isWwrSKU(ah)) {
  860. if (IS_CHAN_B(chan))
  861. ctl = SD_NO_CTL | CTL_11B;
  862. else if (IS_CHAN_G(chan))
  863. ctl = SD_NO_CTL | CTL_11G;
  864. else
  865. ctl = SD_NO_CTL | CTL_11A;
  866. } else {
  867. ichan = ath9k_regd_check_channel(ah, chan);
  868. if (ichan != NULL) {
  869. /* FIXME */
  870. if (IS_CHAN_A(ichan))
  871. ctl = ichan->conformanceTestLimit[0];
  872. else if (IS_CHAN_B(ichan))
  873. ctl = ichan->conformanceTestLimit[1];
  874. else if (IS_CHAN_G(ichan))
  875. ctl = ichan->conformanceTestLimit[2];
  876. if (IS_CHAN_G(chan) && (ctl & 0xf) == CTL_11B)
  877. ctl = (ctl & ~0xf) | CTL_11G;
  878. }
  879. }
  880. return ctl;
  881. }
  882. void ath9k_regd_get_current_country(struct ath_hal *ah,
  883. struct ath9k_country_entry *ctry)
  884. {
  885. u16 rd = ath9k_regd_get_eepromRD(ah);
  886. ctry->isMultidomain = false;
  887. if (rd == CTRY_DEFAULT)
  888. ctry->isMultidomain = true;
  889. else if (!(rd & COUNTRY_ERD_FLAG))
  890. ctry->isMultidomain = isWwrSKU(ah);
  891. ctry->countryCode = ah->ah_countryCode;
  892. ctry->regDmnEnum = ah->ah_currentRD;
  893. ctry->regDmn5G = ah->ah_currentRD5G;
  894. ctry->regDmn2G = ah->ah_currentRD2G;
  895. ctry->iso[0] = ah->ah_iso[0];
  896. ctry->iso[1] = ah->ah_iso[1];
  897. ctry->iso[2] = ah->ah_iso[2];
  898. }