channel.c 43 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474
  1. /*
  2. * Copyright (c) 2010 Broadcom Corporation
  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 ANY
  11. * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  12. * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
  13. * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
  14. * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  15. */
  16. #include <linux/types.h>
  17. #include <net/mac80211.h>
  18. #include <defs.h>
  19. #include "pub.h"
  20. #include "phy/phy_hal.h"
  21. #include "main.h"
  22. #include "stf.h"
  23. #include "channel.h"
  24. /* QDB() macro takes a dB value and converts to a quarter dB value */
  25. #define QDB(n) ((n) * BRCMS_TXPWR_DB_FACTOR)
  26. #define LOCALE_CHAN_01_11 (1<<0)
  27. #define LOCALE_CHAN_12_13 (1<<1)
  28. #define LOCALE_CHAN_14 (1<<2)
  29. #define LOCALE_SET_5G_LOW_JP1 (1<<3) /* 34-48, step 2 */
  30. #define LOCALE_SET_5G_LOW_JP2 (1<<4) /* 34-46, step 4 */
  31. #define LOCALE_SET_5G_LOW1 (1<<5) /* 36-48, step 4 */
  32. #define LOCALE_SET_5G_LOW2 (1<<6) /* 52 */
  33. #define LOCALE_SET_5G_LOW3 (1<<7) /* 56-64, step 4 */
  34. #define LOCALE_SET_5G_MID1 (1<<8) /* 100-116, step 4 */
  35. #define LOCALE_SET_5G_MID2 (1<<9) /* 120-124, step 4 */
  36. #define LOCALE_SET_5G_MID3 (1<<10) /* 128 */
  37. #define LOCALE_SET_5G_HIGH1 (1<<11) /* 132-140, step 4 */
  38. #define LOCALE_SET_5G_HIGH2 (1<<12) /* 149-161, step 4 */
  39. #define LOCALE_SET_5G_HIGH3 (1<<13) /* 165 */
  40. #define LOCALE_CHAN_52_140_ALL (1<<14)
  41. #define LOCALE_SET_5G_HIGH4 (1<<15) /* 184-216 */
  42. #define LOCALE_CHAN_36_64 (LOCALE_SET_5G_LOW1 | \
  43. LOCALE_SET_5G_LOW2 | \
  44. LOCALE_SET_5G_LOW3)
  45. #define LOCALE_CHAN_52_64 (LOCALE_SET_5G_LOW2 | LOCALE_SET_5G_LOW3)
  46. #define LOCALE_CHAN_100_124 (LOCALE_SET_5G_MID1 | LOCALE_SET_5G_MID2)
  47. #define LOCALE_CHAN_100_140 (LOCALE_SET_5G_MID1 | LOCALE_SET_5G_MID2 | \
  48. LOCALE_SET_5G_MID3 | LOCALE_SET_5G_HIGH1)
  49. #define LOCALE_CHAN_149_165 (LOCALE_SET_5G_HIGH2 | LOCALE_SET_5G_HIGH3)
  50. #define LOCALE_CHAN_184_216 LOCALE_SET_5G_HIGH4
  51. #define LOCALE_CHAN_01_14 (LOCALE_CHAN_01_11 | \
  52. LOCALE_CHAN_12_13 | \
  53. LOCALE_CHAN_14)
  54. #define LOCALE_RADAR_SET_NONE 0
  55. #define LOCALE_RADAR_SET_1 1
  56. #define LOCALE_RESTRICTED_NONE 0
  57. #define LOCALE_RESTRICTED_SET_2G_SHORT 1
  58. #define LOCALE_RESTRICTED_CHAN_165 2
  59. #define LOCALE_CHAN_ALL_5G 3
  60. #define LOCALE_RESTRICTED_JAPAN_LEGACY 4
  61. #define LOCALE_RESTRICTED_11D_2G 5
  62. #define LOCALE_RESTRICTED_11D_5G 6
  63. #define LOCALE_RESTRICTED_LOW_HI 7
  64. #define LOCALE_RESTRICTED_12_13_14 8
  65. #define LOCALE_2G_IDX_i 0
  66. #define LOCALE_5G_IDX_11 0
  67. #define LOCALE_MIMO_IDX_bn 0
  68. #define LOCALE_MIMO_IDX_11n 0
  69. /* max of BAND_5G_PWR_LVLS and 6 for 2.4 GHz */
  70. #define BRCMS_MAXPWR_TBL_SIZE 6
  71. /* max of BAND_5G_PWR_LVLS and 14 for 2.4 GHz */
  72. #define BRCMS_MAXPWR_MIMO_TBL_SIZE 14
  73. /* power level in group of 2.4GHz band channels:
  74. * maxpwr[0] - CCK channels [1]
  75. * maxpwr[1] - CCK channels [2-10]
  76. * maxpwr[2] - CCK channels [11-14]
  77. * maxpwr[3] - OFDM channels [1]
  78. * maxpwr[4] - OFDM channels [2-10]
  79. * maxpwr[5] - OFDM channels [11-14]
  80. */
  81. /* maxpwr mapping to 5GHz band channels:
  82. * maxpwr[0] - channels [34-48]
  83. * maxpwr[1] - channels [52-60]
  84. * maxpwr[2] - channels [62-64]
  85. * maxpwr[3] - channels [100-140]
  86. * maxpwr[4] - channels [149-165]
  87. */
  88. #define BAND_5G_PWR_LVLS 5 /* 5 power levels for 5G */
  89. #define LC(id) LOCALE_MIMO_IDX_ ## id
  90. #define LC_2G(id) LOCALE_2G_IDX_ ## id
  91. #define LC_5G(id) LOCALE_5G_IDX_ ## id
  92. #define LOCALES(band2, band5, mimo2, mimo5) \
  93. {LC_2G(band2), LC_5G(band5), LC(mimo2), LC(mimo5)}
  94. /* macro to get 2.4 GHz channel group index for tx power */
  95. #define CHANNEL_POWER_IDX_2G_CCK(c) (((c) < 2) ? 0 : (((c) < 11) ? 1 : 2))
  96. #define CHANNEL_POWER_IDX_2G_OFDM(c) (((c) < 2) ? 3 : (((c) < 11) ? 4 : 5))
  97. /* macro to get 5 GHz channel group index for tx power */
  98. #define CHANNEL_POWER_IDX_5G(c) (((c) < 52) ? 0 : \
  99. (((c) < 62) ? 1 : \
  100. (((c) < 100) ? 2 : \
  101. (((c) < 149) ? 3 : 4))))
  102. #define ISDFS_EU(fl) (((fl) & BRCMS_DFS_EU) == BRCMS_DFS_EU)
  103. struct brcms_cm_band {
  104. /* struct locale_info flags */
  105. u8 locale_flags;
  106. /* List of valid channels in the country */
  107. struct brcms_chanvec valid_channels;
  108. /* List of restricted use channels */
  109. const struct brcms_chanvec *restricted_channels;
  110. /* List of radar sensitive channels */
  111. const struct brcms_chanvec *radar_channels;
  112. u8 PAD[8];
  113. };
  114. /* locale per-channel tx power limits for MIMO frames
  115. * maxpwr arrays are index by channel for 2.4 GHz limits, and
  116. * by sub-band for 5 GHz limits using CHANNEL_POWER_IDX_5G(channel)
  117. */
  118. struct locale_mimo_info {
  119. /* tx 20 MHz power limits, qdBm units */
  120. s8 maxpwr20[BRCMS_MAXPWR_MIMO_TBL_SIZE];
  121. /* tx 40 MHz power limits, qdBm units */
  122. s8 maxpwr40[BRCMS_MAXPWR_MIMO_TBL_SIZE];
  123. u8 flags;
  124. };
  125. /* Country names and abbreviations with locale defined from ISO 3166 */
  126. struct country_info {
  127. const u8 locale_2G; /* 2.4G band locale */
  128. const u8 locale_5G; /* 5G band locale */
  129. const u8 locale_mimo_2G; /* 2.4G mimo info */
  130. const u8 locale_mimo_5G; /* 5G mimo info */
  131. };
  132. struct brcms_cm_info {
  133. struct brcms_pub *pub;
  134. struct brcms_c_info *wlc;
  135. char srom_ccode[BRCM_CNTRY_BUF_SZ]; /* Country Code in SROM */
  136. uint srom_regrev; /* Regulatory Rev for the SROM ccode */
  137. const struct country_info *country; /* current country def */
  138. char ccode[BRCM_CNTRY_BUF_SZ]; /* current internal Country Code */
  139. uint regrev; /* current Regulatory Revision */
  140. char country_abbrev[BRCM_CNTRY_BUF_SZ]; /* current advertised ccode */
  141. /* per-band state (one per phy/radio) */
  142. struct brcms_cm_band bandstate[MAXBANDS];
  143. /* quiet channels currently for radar sensitivity or 11h support */
  144. /* channels on which we cannot transmit */
  145. struct brcms_chanvec quiet_channels;
  146. };
  147. /* locale channel and power info. */
  148. struct locale_info {
  149. u32 valid_channels;
  150. /* List of radar sensitive channels */
  151. u8 radar_channels;
  152. /* List of channels used only if APs are detected */
  153. u8 restricted_channels;
  154. /* Max tx pwr in qdBm for each sub-band */
  155. s8 maxpwr[BRCMS_MAXPWR_TBL_SIZE];
  156. /* Country IE advertised max tx pwr in dBm per sub-band */
  157. s8 pub_maxpwr[BAND_5G_PWR_LVLS];
  158. u8 flags;
  159. };
  160. /* Regulatory Matrix Spreadsheet (CLM) MIMO v3.7.9 */
  161. /*
  162. * Some common channel sets
  163. */
  164. /* No channels */
  165. static const struct brcms_chanvec chanvec_none = {
  166. {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  167. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  168. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  169. 0x00, 0x00, 0x00, 0x00}
  170. };
  171. /* All 2.4 GHz HW channels */
  172. static const struct brcms_chanvec chanvec_all_2G = {
  173. {0xfe, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  174. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  175. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  176. 0x00, 0x00, 0x00, 0x00}
  177. };
  178. /* All 5 GHz HW channels */
  179. static const struct brcms_chanvec chanvec_all_5G = {
  180. {0x00, 0x00, 0x00, 0x00, 0x54, 0x55, 0x11, 0x11,
  181. 0x01, 0x00, 0x00, 0x00, 0x10, 0x11, 0x11, 0x11,
  182. 0x11, 0x11, 0x20, 0x22, 0x22, 0x00, 0x00, 0x11,
  183. 0x11, 0x11, 0x11, 0x01}
  184. };
  185. /*
  186. * Radar channel sets
  187. */
  188. /* Channels 52 - 64, 100 - 140 */
  189. static const struct brcms_chanvec radar_set1 = {
  190. {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x11, /* 52 - 60 */
  191. 0x01, 0x00, 0x00, 0x00, 0x10, 0x11, 0x11, 0x11, /* 64, 100 - 124 */
  192. 0x11, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 128 - 140 */
  193. 0x00, 0x00, 0x00, 0x00}
  194. };
  195. /*
  196. * Restricted channel sets
  197. */
  198. /* Channels 34, 38, 42, 46 */
  199. static const struct brcms_chanvec restricted_set_japan_legacy = {
  200. {0x00, 0x00, 0x00, 0x00, 0x44, 0x44, 0x00, 0x00,
  201. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  202. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  203. 0x00, 0x00, 0x00, 0x00}
  204. };
  205. /* Channels 12, 13 */
  206. static const struct brcms_chanvec restricted_set_2g_short = {
  207. {0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  208. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  209. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  210. 0x00, 0x00, 0x00, 0x00}
  211. };
  212. /* Channel 165 */
  213. static const struct brcms_chanvec restricted_chan_165 = {
  214. {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  215. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  216. 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
  217. 0x00, 0x00, 0x00, 0x00}
  218. };
  219. /* Channels 36 - 48 & 149 - 165 */
  220. static const struct brcms_chanvec restricted_low_hi = {
  221. {0x00, 0x00, 0x00, 0x00, 0x10, 0x11, 0x01, 0x00,
  222. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  223. 0x00, 0x00, 0x20, 0x22, 0x22, 0x00, 0x00, 0x00,
  224. 0x00, 0x00, 0x00, 0x00}
  225. };
  226. /* Channels 12 - 14 */
  227. static const struct brcms_chanvec restricted_set_12_13_14 = {
  228. {0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  229. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  230. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  231. 0x00, 0x00, 0x00, 0x00}
  232. };
  233. /* global memory to provide working buffer for expanded locale */
  234. static const struct brcms_chanvec *g_table_radar_set[] = {
  235. &chanvec_none,
  236. &radar_set1
  237. };
  238. static const struct brcms_chanvec *g_table_restricted_chan[] = {
  239. &chanvec_none, /* restricted_set_none */
  240. &restricted_set_2g_short,
  241. &restricted_chan_165,
  242. &chanvec_all_5G,
  243. &restricted_set_japan_legacy,
  244. &chanvec_all_2G, /* restricted_set_11d_2G */
  245. &chanvec_all_5G, /* restricted_set_11d_5G */
  246. &restricted_low_hi,
  247. &restricted_set_12_13_14
  248. };
  249. static const struct brcms_chanvec locale_2g_01_11 = {
  250. {0xfe, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  251. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  252. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  253. 0x00, 0x00, 0x00, 0x00}
  254. };
  255. static const struct brcms_chanvec locale_2g_12_13 = {
  256. {0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  257. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  258. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  259. 0x00, 0x00, 0x00, 0x00}
  260. };
  261. static const struct brcms_chanvec locale_2g_14 = {
  262. {0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  263. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  264. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  265. 0x00, 0x00, 0x00, 0x00}
  266. };
  267. static const struct brcms_chanvec locale_5g_LOW_JP1 = {
  268. {0x00, 0x00, 0x00, 0x00, 0x54, 0x55, 0x01, 0x00,
  269. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  270. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  271. 0x00, 0x00, 0x00, 0x00}
  272. };
  273. static const struct brcms_chanvec locale_5g_LOW_JP2 = {
  274. {0x00, 0x00, 0x00, 0x00, 0x44, 0x44, 0x00, 0x00,
  275. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  276. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  277. 0x00, 0x00, 0x00, 0x00}
  278. };
  279. static const struct brcms_chanvec locale_5g_LOW1 = {
  280. {0x00, 0x00, 0x00, 0x00, 0x10, 0x11, 0x01, 0x00,
  281. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  282. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  283. 0x00, 0x00, 0x00, 0x00}
  284. };
  285. static const struct brcms_chanvec locale_5g_LOW2 = {
  286. {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00,
  287. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  288. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  289. 0x00, 0x00, 0x00, 0x00}
  290. };
  291. static const struct brcms_chanvec locale_5g_LOW3 = {
  292. {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11,
  293. 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  294. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  295. 0x00, 0x00, 0x00, 0x00}
  296. };
  297. static const struct brcms_chanvec locale_5g_MID1 = {
  298. {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  299. 0x00, 0x00, 0x00, 0x00, 0x10, 0x11, 0x11, 0x00,
  300. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  301. 0x00, 0x00, 0x00, 0x00}
  302. };
  303. static const struct brcms_chanvec locale_5g_MID2 = {
  304. {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  305. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11,
  306. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  307. 0x00, 0x00, 0x00, 0x00}
  308. };
  309. static const struct brcms_chanvec locale_5g_MID3 = {
  310. {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  311. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  312. 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  313. 0x00, 0x00, 0x00, 0x00}
  314. };
  315. static const struct brcms_chanvec locale_5g_HIGH1 = {
  316. {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  317. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  318. 0x10, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  319. 0x00, 0x00, 0x00, 0x00}
  320. };
  321. static const struct brcms_chanvec locale_5g_HIGH2 = {
  322. {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  323. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  324. 0x00, 0x00, 0x20, 0x22, 0x02, 0x00, 0x00, 0x00,
  325. 0x00, 0x00, 0x00, 0x00}
  326. };
  327. static const struct brcms_chanvec locale_5g_HIGH3 = {
  328. {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  329. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  330. 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
  331. 0x00, 0x00, 0x00, 0x00}
  332. };
  333. static const struct brcms_chanvec locale_5g_52_140_ALL = {
  334. {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x11,
  335. 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
  336. 0x11, 0x11, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
  337. 0x00, 0x00, 0x00, 0x00}
  338. };
  339. static const struct brcms_chanvec locale_5g_HIGH4 = {
  340. {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  341. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  342. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11,
  343. 0x11, 0x11, 0x11, 0x11}
  344. };
  345. static const struct brcms_chanvec *g_table_locale_base[] = {
  346. &locale_2g_01_11,
  347. &locale_2g_12_13,
  348. &locale_2g_14,
  349. &locale_5g_LOW_JP1,
  350. &locale_5g_LOW_JP2,
  351. &locale_5g_LOW1,
  352. &locale_5g_LOW2,
  353. &locale_5g_LOW3,
  354. &locale_5g_MID1,
  355. &locale_5g_MID2,
  356. &locale_5g_MID3,
  357. &locale_5g_HIGH1,
  358. &locale_5g_HIGH2,
  359. &locale_5g_HIGH3,
  360. &locale_5g_52_140_ALL,
  361. &locale_5g_HIGH4
  362. };
  363. static void brcms_c_locale_add_channels(struct brcms_chanvec *target,
  364. const struct brcms_chanvec *channels)
  365. {
  366. u8 i;
  367. for (i = 0; i < sizeof(struct brcms_chanvec); i++)
  368. target->vec[i] |= channels->vec[i];
  369. }
  370. static void brcms_c_locale_get_channels(const struct locale_info *locale,
  371. struct brcms_chanvec *channels)
  372. {
  373. u8 i;
  374. memset(channels, 0, sizeof(struct brcms_chanvec));
  375. for (i = 0; i < ARRAY_SIZE(g_table_locale_base); i++) {
  376. if (locale->valid_channels & (1 << i))
  377. brcms_c_locale_add_channels(channels,
  378. g_table_locale_base[i]);
  379. }
  380. }
  381. /*
  382. * Locale Definitions - 2.4 GHz
  383. */
  384. static const struct locale_info locale_i = { /* locale i. channel 1 - 13 */
  385. LOCALE_CHAN_01_11 | LOCALE_CHAN_12_13,
  386. LOCALE_RADAR_SET_NONE,
  387. LOCALE_RESTRICTED_SET_2G_SHORT,
  388. {QDB(19), QDB(19), QDB(19),
  389. QDB(19), QDB(19), QDB(19)},
  390. {20, 20, 20, 0},
  391. BRCMS_EIRP
  392. };
  393. /*
  394. * Locale Definitions - 5 GHz
  395. */
  396. static const struct locale_info locale_11 = {
  397. /* locale 11. channel 36 - 48, 52 - 64, 100 - 140, 149 - 165 */
  398. LOCALE_CHAN_36_64 | LOCALE_CHAN_100_140 | LOCALE_CHAN_149_165,
  399. LOCALE_RADAR_SET_1,
  400. LOCALE_RESTRICTED_NONE,
  401. {QDB(21), QDB(21), QDB(21), QDB(21), QDB(21)},
  402. {23, 23, 23, 30, 30},
  403. BRCMS_EIRP | BRCMS_DFS_EU
  404. };
  405. static const struct locale_info *g_locale_2g_table[] = {
  406. &locale_i
  407. };
  408. static const struct locale_info *g_locale_5g_table[] = {
  409. &locale_11
  410. };
  411. /*
  412. * MIMO Locale Definitions - 2.4 GHz
  413. */
  414. static const struct locale_mimo_info locale_bn = {
  415. {QDB(13), QDB(13), QDB(13), QDB(13), QDB(13),
  416. QDB(13), QDB(13), QDB(13), QDB(13), QDB(13),
  417. QDB(13), QDB(13), QDB(13)},
  418. {0, 0, QDB(13), QDB(13), QDB(13),
  419. QDB(13), QDB(13), QDB(13), QDB(13), QDB(13),
  420. QDB(13), 0, 0},
  421. 0
  422. };
  423. static const struct locale_mimo_info *g_mimo_2g_table[] = {
  424. &locale_bn
  425. };
  426. /*
  427. * MIMO Locale Definitions - 5 GHz
  428. */
  429. static const struct locale_mimo_info locale_11n = {
  430. { /* 12.5 dBm */ 50, 50, 50, QDB(15), QDB(15)},
  431. {QDB(14), QDB(15), QDB(15), QDB(15), QDB(15)},
  432. 0
  433. };
  434. static const struct locale_mimo_info *g_mimo_5g_table[] = {
  435. &locale_11n
  436. };
  437. static const struct {
  438. char abbrev[BRCM_CNTRY_BUF_SZ]; /* country abbreviation */
  439. struct country_info country;
  440. } cntry_locales[] = {
  441. {
  442. "X2", LOCALES(i, 11, bn, 11n)}, /* Worldwide RoW 2 */
  443. };
  444. #ifdef SUPPORT_40MHZ
  445. /* 20MHz channel info for 40MHz pairing support */
  446. struct chan20_info {
  447. u8 sb;
  448. u8 adj_sbs;
  449. };
  450. /* indicates adjacent channels that are allowed for a 40 Mhz channel and
  451. * those that permitted by the HT
  452. */
  453. struct chan20_info chan20_info[] = {
  454. /* 11b/11g */
  455. /* 0 */ {1, (CH_UPPER_SB | CH_EWA_VALID)},
  456. /* 1 */ {2, (CH_UPPER_SB | CH_EWA_VALID)},
  457. /* 2 */ {3, (CH_UPPER_SB | CH_EWA_VALID)},
  458. /* 3 */ {4, (CH_UPPER_SB | CH_EWA_VALID)},
  459. /* 4 */ {5, (CH_UPPER_SB | CH_LOWER_SB | CH_EWA_VALID)},
  460. /* 5 */ {6, (CH_UPPER_SB | CH_LOWER_SB | CH_EWA_VALID)},
  461. /* 6 */ {7, (CH_UPPER_SB | CH_LOWER_SB | CH_EWA_VALID)},
  462. /* 7 */ {8, (CH_UPPER_SB | CH_LOWER_SB | CH_EWA_VALID)},
  463. /* 8 */ {9, (CH_UPPER_SB | CH_LOWER_SB | CH_EWA_VALID)},
  464. /* 9 */ {10, (CH_LOWER_SB | CH_EWA_VALID)},
  465. /* 10 */ {11, (CH_LOWER_SB | CH_EWA_VALID)},
  466. /* 11 */ {12, (CH_LOWER_SB)},
  467. /* 12 */ {13, (CH_LOWER_SB)},
  468. /* 13 */ {14, (CH_LOWER_SB)},
  469. /* 11a japan high */
  470. /* 14 */ {34, (CH_UPPER_SB)},
  471. /* 15 */ {38, (CH_LOWER_SB)},
  472. /* 16 */ {42, (CH_LOWER_SB)},
  473. /* 17 */ {46, (CH_LOWER_SB)},
  474. /* 11a usa low */
  475. /* 18 */ {36, (CH_UPPER_SB | CH_EWA_VALID)},
  476. /* 19 */ {40, (CH_LOWER_SB | CH_EWA_VALID)},
  477. /* 20 */ {44, (CH_UPPER_SB | CH_EWA_VALID)},
  478. /* 21 */ {48, (CH_LOWER_SB | CH_EWA_VALID)},
  479. /* 22 */ {52, (CH_UPPER_SB | CH_EWA_VALID)},
  480. /* 23 */ {56, (CH_LOWER_SB | CH_EWA_VALID)},
  481. /* 24 */ {60, (CH_UPPER_SB | CH_EWA_VALID)},
  482. /* 25 */ {64, (CH_LOWER_SB | CH_EWA_VALID)},
  483. /* 11a Europe */
  484. /* 26 */ {100, (CH_UPPER_SB | CH_EWA_VALID)},
  485. /* 27 */ {104, (CH_LOWER_SB | CH_EWA_VALID)},
  486. /* 28 */ {108, (CH_UPPER_SB | CH_EWA_VALID)},
  487. /* 29 */ {112, (CH_LOWER_SB | CH_EWA_VALID)},
  488. /* 30 */ {116, (CH_UPPER_SB | CH_EWA_VALID)},
  489. /* 31 */ {120, (CH_LOWER_SB | CH_EWA_VALID)},
  490. /* 32 */ {124, (CH_UPPER_SB | CH_EWA_VALID)},
  491. /* 33 */ {128, (CH_LOWER_SB | CH_EWA_VALID)},
  492. /* 34 */ {132, (CH_UPPER_SB | CH_EWA_VALID)},
  493. /* 35 */ {136, (CH_LOWER_SB | CH_EWA_VALID)},
  494. /* 36 */ {140, (CH_LOWER_SB)},
  495. /* 11a usa high, ref5 only */
  496. /* The 0x80 bit in pdiv means these are REF5, other entries are REF20 */
  497. /* 37 */ {149, (CH_UPPER_SB | CH_EWA_VALID)},
  498. /* 38 */ {153, (CH_LOWER_SB | CH_EWA_VALID)},
  499. /* 39 */ {157, (CH_UPPER_SB | CH_EWA_VALID)},
  500. /* 40 */ {161, (CH_LOWER_SB | CH_EWA_VALID)},
  501. /* 41 */ {165, (CH_LOWER_SB)},
  502. /* 11a japan */
  503. /* 42 */ {184, (CH_UPPER_SB)},
  504. /* 43 */ {188, (CH_LOWER_SB)},
  505. /* 44 */ {192, (CH_UPPER_SB)},
  506. /* 45 */ {196, (CH_LOWER_SB)},
  507. /* 46 */ {200, (CH_UPPER_SB)},
  508. /* 47 */ {204, (CH_LOWER_SB)},
  509. /* 48 */ {208, (CH_UPPER_SB)},
  510. /* 49 */ {212, (CH_LOWER_SB)},
  511. /* 50 */ {216, (CH_LOWER_SB)}
  512. };
  513. #endif /* SUPPORT_40MHZ */
  514. static const struct locale_info *brcms_c_get_locale_2g(u8 locale_idx)
  515. {
  516. if (locale_idx >= ARRAY_SIZE(g_locale_2g_table))
  517. return NULL; /* error condition */
  518. return g_locale_2g_table[locale_idx];
  519. }
  520. static const struct locale_info *brcms_c_get_locale_5g(u8 locale_idx)
  521. {
  522. if (locale_idx >= ARRAY_SIZE(g_locale_5g_table))
  523. return NULL; /* error condition */
  524. return g_locale_5g_table[locale_idx];
  525. }
  526. static const struct locale_mimo_info *brcms_c_get_mimo_2g(u8 locale_idx)
  527. {
  528. if (locale_idx >= ARRAY_SIZE(g_mimo_2g_table))
  529. return NULL;
  530. return g_mimo_2g_table[locale_idx];
  531. }
  532. static const struct locale_mimo_info *brcms_c_get_mimo_5g(u8 locale_idx)
  533. {
  534. if (locale_idx >= ARRAY_SIZE(g_mimo_5g_table))
  535. return NULL;
  536. return g_mimo_5g_table[locale_idx];
  537. }
  538. static int
  539. brcms_c_country_aggregate_map(struct brcms_cm_info *wlc_cm, const char *ccode,
  540. char *mapped_ccode, uint *mapped_regrev)
  541. {
  542. return false;
  543. }
  544. /* Lookup a country info structure from a null terminated country
  545. * abbreviation and regrev directly with no translation.
  546. */
  547. static const struct country_info *
  548. brcms_c_country_lookup_direct(const char *ccode, uint regrev)
  549. {
  550. uint size, i;
  551. /* Should just return 0 for single locale driver. */
  552. /* Keep it this way in case we add more locales. (for now anyway) */
  553. /*
  554. * all other country def arrays are for regrev == 0, so if
  555. * regrev is non-zero, fail
  556. */
  557. if (regrev > 0)
  558. return NULL;
  559. /* find matched table entry from country code */
  560. size = ARRAY_SIZE(cntry_locales);
  561. for (i = 0; i < size; i++) {
  562. if (strcmp(ccode, cntry_locales[i].abbrev) == 0)
  563. return &cntry_locales[i].country;
  564. }
  565. return NULL;
  566. }
  567. static const struct country_info *
  568. brcms_c_countrycode_map(struct brcms_cm_info *wlc_cm, const char *ccode,
  569. char *mapped_ccode, uint *mapped_regrev)
  570. {
  571. struct brcms_c_info *wlc = wlc_cm->wlc;
  572. const struct country_info *country;
  573. uint srom_regrev = wlc_cm->srom_regrev;
  574. const char *srom_ccode = wlc_cm->srom_ccode;
  575. int mapped;
  576. /* check for currently supported ccode size */
  577. if (strlen(ccode) > (BRCM_CNTRY_BUF_SZ - 1)) {
  578. wiphy_err(wlc->wiphy, "wl%d: %s: ccode \"%s\" too long for "
  579. "match\n", wlc->pub->unit, __func__, ccode);
  580. return NULL;
  581. }
  582. /* default mapping is the given ccode and regrev 0 */
  583. strncpy(mapped_ccode, ccode, BRCM_CNTRY_BUF_SZ);
  584. *mapped_regrev = 0;
  585. /* If the desired country code matches the srom country code,
  586. * then the mapped country is the srom regulatory rev.
  587. * Otherwise look for an aggregate mapping.
  588. */
  589. if (!strcmp(srom_ccode, ccode)) {
  590. *mapped_regrev = srom_regrev;
  591. mapped = 0;
  592. wiphy_err(wlc->wiphy, "srom_code == ccode %s\n", __func__);
  593. } else {
  594. mapped =
  595. brcms_c_country_aggregate_map(wlc_cm, ccode, mapped_ccode,
  596. mapped_regrev);
  597. }
  598. /* find the matching built-in country definition */
  599. country = brcms_c_country_lookup_direct(mapped_ccode, *mapped_regrev);
  600. /* if there is not an exact rev match, default to rev zero */
  601. if (country == NULL && *mapped_regrev != 0) {
  602. *mapped_regrev = 0;
  603. country =
  604. brcms_c_country_lookup_direct(mapped_ccode, *mapped_regrev);
  605. }
  606. return country;
  607. }
  608. /* Lookup a country info structure from a null terminated country code
  609. * The lookup is case sensitive.
  610. */
  611. static const struct country_info *
  612. brcms_c_country_lookup(struct brcms_c_info *wlc, const char *ccode)
  613. {
  614. const struct country_info *country;
  615. char mapped_ccode[BRCM_CNTRY_BUF_SZ];
  616. uint mapped_regrev;
  617. /*
  618. * map the country code to a built-in country code, regrev, and
  619. * country_info struct
  620. */
  621. country = brcms_c_countrycode_map(wlc->cmi, ccode, mapped_ccode,
  622. &mapped_regrev);
  623. return country;
  624. }
  625. /*
  626. * reset the quiet channels vector to the union
  627. * of the restricted and radar channel sets
  628. */
  629. static void brcms_c_quiet_channels_reset(struct brcms_cm_info *wlc_cm)
  630. {
  631. struct brcms_c_info *wlc = wlc_cm->wlc;
  632. uint i, j;
  633. struct brcms_band *band;
  634. const struct brcms_chanvec *chanvec;
  635. memset(&wlc_cm->quiet_channels, 0, sizeof(struct brcms_chanvec));
  636. band = wlc->band;
  637. for (i = 0; i < wlc->pub->_nbands;
  638. i++, band = wlc->bandstate[OTHERBANDUNIT(wlc)]) {
  639. /* initialize quiet channels for restricted channels */
  640. chanvec = wlc_cm->bandstate[band->bandunit].restricted_channels;
  641. for (j = 0; j < sizeof(struct brcms_chanvec); j++)
  642. wlc_cm->quiet_channels.vec[j] |= chanvec->vec[j];
  643. }
  644. }
  645. /* Is the channel valid for the current locale and current band? */
  646. static bool brcms_c_valid_channel20(struct brcms_cm_info *wlc_cm, uint val)
  647. {
  648. struct brcms_c_info *wlc = wlc_cm->wlc;
  649. return ((val < MAXCHANNEL) &&
  650. isset(wlc_cm->bandstate[wlc->band->bandunit].valid_channels.vec,
  651. val));
  652. }
  653. /* Is the channel valid for the current locale and specified band? */
  654. static bool brcms_c_valid_channel20_in_band(struct brcms_cm_info *wlc_cm,
  655. uint bandunit, uint val)
  656. {
  657. return ((val < MAXCHANNEL)
  658. && isset(wlc_cm->bandstate[bandunit].valid_channels.vec, val));
  659. }
  660. /* Is the channel valid for the current locale? (but don't consider channels not
  661. * available due to bandlocking)
  662. */
  663. static bool brcms_c_valid_channel20_db(struct brcms_cm_info *wlc_cm, uint val)
  664. {
  665. struct brcms_c_info *wlc = wlc_cm->wlc;
  666. return brcms_c_valid_channel20(wlc->cmi, val) ||
  667. (!wlc->bandlocked
  668. && brcms_c_valid_channel20_in_band(wlc->cmi,
  669. OTHERBANDUNIT(wlc), val));
  670. }
  671. /* JP, J1 - J10 are Japan ccodes */
  672. static bool brcms_c_japan_ccode(const char *ccode)
  673. {
  674. return (ccode[0] == 'J' &&
  675. (ccode[1] == 'P' || (ccode[1] >= '1' && ccode[1] <= '9')));
  676. }
  677. /* Returns true if currently set country is Japan or variant */
  678. static bool brcms_c_japan(struct brcms_c_info *wlc)
  679. {
  680. return brcms_c_japan_ccode(wlc->cmi->country_abbrev);
  681. }
  682. static void
  683. brcms_c_channel_min_txpower_limits_with_local_constraint(
  684. struct brcms_cm_info *wlc_cm, struct txpwr_limits *txpwr,
  685. u8 local_constraint_qdbm)
  686. {
  687. int j;
  688. /* CCK Rates */
  689. for (j = 0; j < WL_TX_POWER_CCK_NUM; j++)
  690. txpwr->cck[j] = min(txpwr->cck[j], local_constraint_qdbm);
  691. /* 20 MHz Legacy OFDM SISO */
  692. for (j = 0; j < WL_TX_POWER_OFDM_NUM; j++)
  693. txpwr->ofdm[j] = min(txpwr->ofdm[j], local_constraint_qdbm);
  694. /* 20 MHz Legacy OFDM CDD */
  695. for (j = 0; j < BRCMS_NUM_RATES_OFDM; j++)
  696. txpwr->ofdm_cdd[j] =
  697. min(txpwr->ofdm_cdd[j], local_constraint_qdbm);
  698. /* 40 MHz Legacy OFDM SISO */
  699. for (j = 0; j < BRCMS_NUM_RATES_OFDM; j++)
  700. txpwr->ofdm_40_siso[j] =
  701. min(txpwr->ofdm_40_siso[j], local_constraint_qdbm);
  702. /* 40 MHz Legacy OFDM CDD */
  703. for (j = 0; j < BRCMS_NUM_RATES_OFDM; j++)
  704. txpwr->ofdm_40_cdd[j] =
  705. min(txpwr->ofdm_40_cdd[j], local_constraint_qdbm);
  706. /* 20MHz MCS 0-7 SISO */
  707. for (j = 0; j < BRCMS_NUM_RATES_MCS_1_STREAM; j++)
  708. txpwr->mcs_20_siso[j] =
  709. min(txpwr->mcs_20_siso[j], local_constraint_qdbm);
  710. /* 20MHz MCS 0-7 CDD */
  711. for (j = 0; j < BRCMS_NUM_RATES_MCS_1_STREAM; j++)
  712. txpwr->mcs_20_cdd[j] =
  713. min(txpwr->mcs_20_cdd[j], local_constraint_qdbm);
  714. /* 20MHz MCS 0-7 STBC */
  715. for (j = 0; j < BRCMS_NUM_RATES_MCS_1_STREAM; j++)
  716. txpwr->mcs_20_stbc[j] =
  717. min(txpwr->mcs_20_stbc[j], local_constraint_qdbm);
  718. /* 20MHz MCS 8-15 MIMO */
  719. for (j = 0; j < BRCMS_NUM_RATES_MCS_2_STREAM; j++)
  720. txpwr->mcs_20_mimo[j] =
  721. min(txpwr->mcs_20_mimo[j], local_constraint_qdbm);
  722. /* 40MHz MCS 0-7 SISO */
  723. for (j = 0; j < BRCMS_NUM_RATES_MCS_1_STREAM; j++)
  724. txpwr->mcs_40_siso[j] =
  725. min(txpwr->mcs_40_siso[j], local_constraint_qdbm);
  726. /* 40MHz MCS 0-7 CDD */
  727. for (j = 0; j < BRCMS_NUM_RATES_MCS_1_STREAM; j++)
  728. txpwr->mcs_40_cdd[j] =
  729. min(txpwr->mcs_40_cdd[j], local_constraint_qdbm);
  730. /* 40MHz MCS 0-7 STBC */
  731. for (j = 0; j < BRCMS_NUM_RATES_MCS_1_STREAM; j++)
  732. txpwr->mcs_40_stbc[j] =
  733. min(txpwr->mcs_40_stbc[j], local_constraint_qdbm);
  734. /* 40MHz MCS 8-15 MIMO */
  735. for (j = 0; j < BRCMS_NUM_RATES_MCS_2_STREAM; j++)
  736. txpwr->mcs_40_mimo[j] =
  737. min(txpwr->mcs_40_mimo[j], local_constraint_qdbm);
  738. /* 40MHz MCS 32 */
  739. txpwr->mcs32 = min(txpwr->mcs32, local_constraint_qdbm);
  740. }
  741. /* Update the radio state (enable/disable) and tx power targets
  742. * based on a new set of channel/regulatory information
  743. */
  744. static void brcms_c_channels_commit(struct brcms_cm_info *wlc_cm)
  745. {
  746. struct brcms_c_info *wlc = wlc_cm->wlc;
  747. uint chan;
  748. struct txpwr_limits txpwr;
  749. /* search for the existence of any valid channel */
  750. for (chan = 0; chan < MAXCHANNEL; chan++) {
  751. if (brcms_c_valid_channel20_db(wlc->cmi, chan))
  752. break;
  753. }
  754. if (chan == MAXCHANNEL)
  755. chan = INVCHANNEL;
  756. /*
  757. * based on the channel search above, set or
  758. * clear WL_RADIO_COUNTRY_DISABLE.
  759. */
  760. if (chan == INVCHANNEL) {
  761. /*
  762. * country/locale with no valid channels, set
  763. * the radio disable bit
  764. */
  765. mboolset(wlc->pub->radio_disabled, WL_RADIO_COUNTRY_DISABLE);
  766. wiphy_err(wlc->wiphy, "wl%d: %s: no valid channel for \"%s\" "
  767. "nbands %d bandlocked %d\n", wlc->pub->unit,
  768. __func__, wlc_cm->country_abbrev, wlc->pub->_nbands,
  769. wlc->bandlocked);
  770. } else if (mboolisset(wlc->pub->radio_disabled,
  771. WL_RADIO_COUNTRY_DISABLE)) {
  772. /*
  773. * country/locale with valid channel, clear
  774. * the radio disable bit
  775. */
  776. mboolclr(wlc->pub->radio_disabled, WL_RADIO_COUNTRY_DISABLE);
  777. }
  778. /*
  779. * Now that the country abbreviation is set, if the radio supports 2G,
  780. * then set channel 14 restrictions based on the new locale.
  781. */
  782. if (wlc->pub->_nbands > 1 || wlc->band->bandtype == BRCM_BAND_2G)
  783. wlc_phy_chanspec_ch14_widefilter_set(wlc->band->pi,
  784. brcms_c_japan(wlc) ? true :
  785. false);
  786. if (wlc->pub->up && chan != INVCHANNEL) {
  787. brcms_c_channel_reg_limits(wlc_cm, wlc->chanspec, &txpwr);
  788. brcms_c_channel_min_txpower_limits_with_local_constraint(wlc_cm,
  789. &txpwr, BRCMS_TXPWR_MAX);
  790. wlc_phy_txpower_limit_set(wlc->band->pi, &txpwr, wlc->chanspec);
  791. }
  792. }
  793. static int
  794. brcms_c_channels_init(struct brcms_cm_info *wlc_cm,
  795. const struct country_info *country)
  796. {
  797. struct brcms_c_info *wlc = wlc_cm->wlc;
  798. uint i, j;
  799. struct brcms_band *band;
  800. const struct locale_info *li;
  801. struct brcms_chanvec sup_chan;
  802. const struct locale_mimo_info *li_mimo;
  803. band = wlc->band;
  804. for (i = 0; i < wlc->pub->_nbands;
  805. i++, band = wlc->bandstate[OTHERBANDUNIT(wlc)]) {
  806. li = (band->bandtype == BRCM_BAND_5G) ?
  807. brcms_c_get_locale_5g(country->locale_5G) :
  808. brcms_c_get_locale_2g(country->locale_2G);
  809. wlc_cm->bandstate[band->bandunit].locale_flags = li->flags;
  810. li_mimo = (band->bandtype == BRCM_BAND_5G) ?
  811. brcms_c_get_mimo_5g(country->locale_mimo_5G) :
  812. brcms_c_get_mimo_2g(country->locale_mimo_2G);
  813. /* merge the mimo non-mimo locale flags */
  814. wlc_cm->bandstate[band->bandunit].locale_flags |=
  815. li_mimo->flags;
  816. wlc_cm->bandstate[band->bandunit].restricted_channels =
  817. g_table_restricted_chan[li->restricted_channels];
  818. wlc_cm->bandstate[band->bandunit].radar_channels =
  819. g_table_radar_set[li->radar_channels];
  820. /*
  821. * set the channel availability, masking out the channels
  822. * that may not be supported on this phy.
  823. */
  824. wlc_phy_chanspec_band_validch(band->pi, band->bandtype,
  825. &sup_chan);
  826. brcms_c_locale_get_channels(li,
  827. &wlc_cm->bandstate[band->bandunit].
  828. valid_channels);
  829. for (j = 0; j < sizeof(struct brcms_chanvec); j++)
  830. wlc_cm->bandstate[band->bandunit].valid_channels.
  831. vec[j] &= sup_chan.vec[j];
  832. }
  833. brcms_c_quiet_channels_reset(wlc_cm);
  834. brcms_c_channels_commit(wlc_cm);
  835. return 0;
  836. }
  837. /*
  838. * set the driver's current country and regulatory information
  839. * using a country code as the source. Look up built in country
  840. * information found with the country code.
  841. */
  842. static void
  843. brcms_c_set_country_common(struct brcms_cm_info *wlc_cm,
  844. const char *country_abbrev,
  845. const char *ccode, uint regrev,
  846. const struct country_info *country)
  847. {
  848. const struct locale_info *locale;
  849. struct brcms_c_info *wlc = wlc_cm->wlc;
  850. char prev_country_abbrev[BRCM_CNTRY_BUF_SZ];
  851. /* save current country state */
  852. wlc_cm->country = country;
  853. memset(&prev_country_abbrev, 0, BRCM_CNTRY_BUF_SZ);
  854. strncpy(prev_country_abbrev, wlc_cm->country_abbrev,
  855. BRCM_CNTRY_BUF_SZ - 1);
  856. strncpy(wlc_cm->country_abbrev, country_abbrev, BRCM_CNTRY_BUF_SZ - 1);
  857. strncpy(wlc_cm->ccode, ccode, BRCM_CNTRY_BUF_SZ - 1);
  858. wlc_cm->regrev = regrev;
  859. if ((wlc->pub->_n_enab & SUPPORT_11N) !=
  860. wlc->protection->nmode_user)
  861. brcms_c_set_nmode(wlc);
  862. brcms_c_stf_ss_update(wlc, wlc->bandstate[BAND_2G_INDEX]);
  863. brcms_c_stf_ss_update(wlc, wlc->bandstate[BAND_5G_INDEX]);
  864. /* set or restore gmode as required by regulatory */
  865. locale = brcms_c_get_locale_2g(country->locale_2G);
  866. if (locale && (locale->flags & BRCMS_NO_OFDM))
  867. brcms_c_set_gmode(wlc, GMODE_LEGACY_B, false);
  868. else
  869. brcms_c_set_gmode(wlc, wlc->protection->gmode_user, false);
  870. brcms_c_channels_init(wlc_cm, country);
  871. return;
  872. }
  873. static int
  874. brcms_c_set_countrycode_rev(struct brcms_cm_info *wlc_cm,
  875. const char *country_abbrev,
  876. const char *ccode, int regrev)
  877. {
  878. const struct country_info *country;
  879. char mapped_ccode[BRCM_CNTRY_BUF_SZ];
  880. uint mapped_regrev;
  881. /* if regrev is -1, lookup the mapped country code,
  882. * otherwise use the ccode and regrev directly
  883. */
  884. if (regrev == -1) {
  885. /*
  886. * map the country code to a built-in country
  887. * code, regrev, and country_info
  888. */
  889. country =
  890. brcms_c_countrycode_map(wlc_cm, ccode, mapped_ccode,
  891. &mapped_regrev);
  892. } else {
  893. /* find the matching built-in country definition */
  894. country = brcms_c_country_lookup_direct(ccode, regrev);
  895. strncpy(mapped_ccode, ccode, BRCM_CNTRY_BUF_SZ);
  896. mapped_regrev = regrev;
  897. }
  898. if (country == NULL)
  899. return -EINVAL;
  900. /* set the driver state for the country */
  901. brcms_c_set_country_common(wlc_cm, country_abbrev, mapped_ccode,
  902. mapped_regrev, country);
  903. return 0;
  904. }
  905. /*
  906. * set the driver's current country and regulatory information using
  907. * a country code as the source. Lookup built in country information
  908. * found with the country code.
  909. */
  910. static int
  911. brcms_c_set_countrycode(struct brcms_cm_info *wlc_cm, const char *ccode)
  912. {
  913. char country_abbrev[BRCM_CNTRY_BUF_SZ];
  914. strncpy(country_abbrev, ccode, BRCM_CNTRY_BUF_SZ);
  915. return brcms_c_set_countrycode_rev(wlc_cm, country_abbrev, ccode, -1);
  916. }
  917. struct brcms_cm_info *brcms_c_channel_mgr_attach(struct brcms_c_info *wlc)
  918. {
  919. struct brcms_cm_info *wlc_cm;
  920. char country_abbrev[BRCM_CNTRY_BUF_SZ];
  921. const struct country_info *country;
  922. struct brcms_pub *pub = wlc->pub;
  923. char *ccode;
  924. BCMMSG(wlc->wiphy, "wl%d\n", wlc->pub->unit);
  925. wlc_cm = kzalloc(sizeof(struct brcms_cm_info), GFP_ATOMIC);
  926. if (wlc_cm == NULL)
  927. return NULL;
  928. wlc_cm->pub = pub;
  929. wlc_cm->wlc = wlc;
  930. wlc->cmi = wlc_cm;
  931. /* store the country code for passing up as a regulatory hint */
  932. ccode = getvar(wlc->hw->sih, BRCMS_SROM_CCODE);
  933. if (ccode)
  934. strncpy(wlc->pub->srom_ccode, ccode, BRCM_CNTRY_BUF_SZ - 1);
  935. /*
  936. * internal country information which must match
  937. * regulatory constraints in firmware
  938. */
  939. memset(country_abbrev, 0, BRCM_CNTRY_BUF_SZ);
  940. strncpy(country_abbrev, "X2", sizeof(country_abbrev) - 1);
  941. country = brcms_c_country_lookup(wlc, country_abbrev);
  942. /* save default country for exiting 11d regulatory mode */
  943. strncpy(wlc->country_default, country_abbrev, BRCM_CNTRY_BUF_SZ - 1);
  944. /* initialize autocountry_default to driver default */
  945. strncpy(wlc->autocountry_default, "X2", BRCM_CNTRY_BUF_SZ - 1);
  946. brcms_c_set_countrycode(wlc_cm, country_abbrev);
  947. return wlc_cm;
  948. }
  949. void brcms_c_channel_mgr_detach(struct brcms_cm_info *wlc_cm)
  950. {
  951. kfree(wlc_cm);
  952. }
  953. u8
  954. brcms_c_channel_locale_flags_in_band(struct brcms_cm_info *wlc_cm,
  955. uint bandunit)
  956. {
  957. return wlc_cm->bandstate[bandunit].locale_flags;
  958. }
  959. static bool
  960. brcms_c_quiet_chanspec(struct brcms_cm_info *wlc_cm, u16 chspec)
  961. {
  962. return (wlc_cm->wlc->pub->_n_enab & SUPPORT_11N) &&
  963. CHSPEC_IS40(chspec) ?
  964. (isset(wlc_cm->quiet_channels.vec,
  965. lower_20_sb(CHSPEC_CHANNEL(chspec))) ||
  966. isset(wlc_cm->quiet_channels.vec,
  967. upper_20_sb(CHSPEC_CHANNEL(chspec)))) :
  968. isset(wlc_cm->quiet_channels.vec, CHSPEC_CHANNEL(chspec));
  969. }
  970. void
  971. brcms_c_channel_set_chanspec(struct brcms_cm_info *wlc_cm, u16 chanspec,
  972. u8 local_constraint_qdbm)
  973. {
  974. struct brcms_c_info *wlc = wlc_cm->wlc;
  975. struct txpwr_limits txpwr;
  976. brcms_c_channel_reg_limits(wlc_cm, chanspec, &txpwr);
  977. brcms_c_channel_min_txpower_limits_with_local_constraint(
  978. wlc_cm, &txpwr, local_constraint_qdbm
  979. );
  980. brcms_b_set_chanspec(wlc->hw, chanspec,
  981. (brcms_c_quiet_chanspec(wlc_cm, chanspec) != 0),
  982. &txpwr);
  983. }
  984. void
  985. brcms_c_channel_reg_limits(struct brcms_cm_info *wlc_cm, u16 chanspec,
  986. struct txpwr_limits *txpwr)
  987. {
  988. struct brcms_c_info *wlc = wlc_cm->wlc;
  989. uint i;
  990. uint chan;
  991. int maxpwr;
  992. int delta;
  993. const struct country_info *country;
  994. struct brcms_band *band;
  995. const struct locale_info *li;
  996. int conducted_max = BRCMS_TXPWR_MAX;
  997. int conducted_ofdm_max = BRCMS_TXPWR_MAX;
  998. const struct locale_mimo_info *li_mimo;
  999. int maxpwr20, maxpwr40;
  1000. int maxpwr_idx;
  1001. uint j;
  1002. memset(txpwr, 0, sizeof(struct txpwr_limits));
  1003. if (!brcms_c_valid_chanspec_db(wlc_cm, chanspec)) {
  1004. country = brcms_c_country_lookup(wlc, wlc->autocountry_default);
  1005. if (country == NULL)
  1006. return;
  1007. } else {
  1008. country = wlc_cm->country;
  1009. }
  1010. chan = CHSPEC_CHANNEL(chanspec);
  1011. band = wlc->bandstate[chspec_bandunit(chanspec)];
  1012. li = (band->bandtype == BRCM_BAND_5G) ?
  1013. brcms_c_get_locale_5g(country->locale_5G) :
  1014. brcms_c_get_locale_2g(country->locale_2G);
  1015. li_mimo = (band->bandtype == BRCM_BAND_5G) ?
  1016. brcms_c_get_mimo_5g(country->locale_mimo_5G) :
  1017. brcms_c_get_mimo_2g(country->locale_mimo_2G);
  1018. if (li->flags & BRCMS_EIRP) {
  1019. delta = band->antgain;
  1020. } else {
  1021. delta = 0;
  1022. if (band->antgain > QDB(6))
  1023. delta = band->antgain - QDB(6); /* Excess over 6 dB */
  1024. }
  1025. if (li == &locale_i) {
  1026. conducted_max = QDB(22);
  1027. conducted_ofdm_max = QDB(22);
  1028. }
  1029. /* CCK txpwr limits for 2.4G band */
  1030. if (band->bandtype == BRCM_BAND_2G) {
  1031. maxpwr = li->maxpwr[CHANNEL_POWER_IDX_2G_CCK(chan)];
  1032. maxpwr = maxpwr - delta;
  1033. maxpwr = max(maxpwr, 0);
  1034. maxpwr = min(maxpwr, conducted_max);
  1035. for (i = 0; i < BRCMS_NUM_RATES_CCK; i++)
  1036. txpwr->cck[i] = (u8) maxpwr;
  1037. }
  1038. /* OFDM txpwr limits for 2.4G or 5G bands */
  1039. if (band->bandtype == BRCM_BAND_2G)
  1040. maxpwr = li->maxpwr[CHANNEL_POWER_IDX_2G_OFDM(chan)];
  1041. else
  1042. maxpwr = li->maxpwr[CHANNEL_POWER_IDX_5G(chan)];
  1043. maxpwr = maxpwr - delta;
  1044. maxpwr = max(maxpwr, 0);
  1045. maxpwr = min(maxpwr, conducted_ofdm_max);
  1046. /* Keep OFDM lmit below CCK limit */
  1047. if (band->bandtype == BRCM_BAND_2G)
  1048. maxpwr = min_t(int, maxpwr, txpwr->cck[0]);
  1049. for (i = 0; i < BRCMS_NUM_RATES_OFDM; i++)
  1050. txpwr->ofdm[i] = (u8) maxpwr;
  1051. for (i = 0; i < BRCMS_NUM_RATES_OFDM; i++) {
  1052. /*
  1053. * OFDM 40 MHz SISO has the same power as the corresponding
  1054. * MCS0-7 rate unless overriden by the locale specific code.
  1055. * We set this value to 0 as a flag (presumably 0 dBm isn't
  1056. * a possibility) and then copy the MCS0-7 value to the 40 MHz
  1057. * value if it wasn't explicitly set.
  1058. */
  1059. txpwr->ofdm_40_siso[i] = 0;
  1060. txpwr->ofdm_cdd[i] = (u8) maxpwr;
  1061. txpwr->ofdm_40_cdd[i] = 0;
  1062. }
  1063. /* MIMO/HT specific limits */
  1064. if (li_mimo->flags & BRCMS_EIRP) {
  1065. delta = band->antgain;
  1066. } else {
  1067. delta = 0;
  1068. if (band->antgain > QDB(6))
  1069. delta = band->antgain - QDB(6); /* Excess over 6 dB */
  1070. }
  1071. if (band->bandtype == BRCM_BAND_2G)
  1072. maxpwr_idx = (chan - 1);
  1073. else
  1074. maxpwr_idx = CHANNEL_POWER_IDX_5G(chan);
  1075. maxpwr20 = li_mimo->maxpwr20[maxpwr_idx];
  1076. maxpwr40 = li_mimo->maxpwr40[maxpwr_idx];
  1077. maxpwr20 = maxpwr20 - delta;
  1078. maxpwr20 = max(maxpwr20, 0);
  1079. maxpwr40 = maxpwr40 - delta;
  1080. maxpwr40 = max(maxpwr40, 0);
  1081. /* Fill in the MCS 0-7 (SISO) rates */
  1082. for (i = 0; i < BRCMS_NUM_RATES_MCS_1_STREAM; i++) {
  1083. /*
  1084. * 20 MHz has the same power as the corresponding OFDM rate
  1085. * unless overriden by the locale specific code.
  1086. */
  1087. txpwr->mcs_20_siso[i] = txpwr->ofdm[i];
  1088. txpwr->mcs_40_siso[i] = 0;
  1089. }
  1090. /* Fill in the MCS 0-7 CDD rates */
  1091. for (i = 0; i < BRCMS_NUM_RATES_MCS_1_STREAM; i++) {
  1092. txpwr->mcs_20_cdd[i] = (u8) maxpwr20;
  1093. txpwr->mcs_40_cdd[i] = (u8) maxpwr40;
  1094. }
  1095. /*
  1096. * These locales have SISO expressed in the
  1097. * table and override CDD later
  1098. */
  1099. if (li_mimo == &locale_bn) {
  1100. if (li_mimo == &locale_bn) {
  1101. maxpwr20 = QDB(16);
  1102. maxpwr40 = 0;
  1103. if (chan >= 3 && chan <= 11)
  1104. maxpwr40 = QDB(16);
  1105. }
  1106. for (i = 0; i < BRCMS_NUM_RATES_MCS_1_STREAM; i++) {
  1107. txpwr->mcs_20_siso[i] = (u8) maxpwr20;
  1108. txpwr->mcs_40_siso[i] = (u8) maxpwr40;
  1109. }
  1110. }
  1111. /* Fill in the MCS 0-7 STBC rates */
  1112. for (i = 0; i < BRCMS_NUM_RATES_MCS_1_STREAM; i++) {
  1113. txpwr->mcs_20_stbc[i] = 0;
  1114. txpwr->mcs_40_stbc[i] = 0;
  1115. }
  1116. /* Fill in the MCS 8-15 SDM rates */
  1117. for (i = 0; i < BRCMS_NUM_RATES_MCS_2_STREAM; i++) {
  1118. txpwr->mcs_20_mimo[i] = (u8) maxpwr20;
  1119. txpwr->mcs_40_mimo[i] = (u8) maxpwr40;
  1120. }
  1121. /* Fill in MCS32 */
  1122. txpwr->mcs32 = (u8) maxpwr40;
  1123. for (i = 0, j = 0; i < BRCMS_NUM_RATES_OFDM; i++, j++) {
  1124. if (txpwr->ofdm_40_cdd[i] == 0)
  1125. txpwr->ofdm_40_cdd[i] = txpwr->mcs_40_cdd[j];
  1126. if (i == 0) {
  1127. i = i + 1;
  1128. if (txpwr->ofdm_40_cdd[i] == 0)
  1129. txpwr->ofdm_40_cdd[i] = txpwr->mcs_40_cdd[j];
  1130. }
  1131. }
  1132. /*
  1133. * Copy the 40 MHZ MCS 0-7 CDD value to the 40 MHZ MCS 0-7 SISO
  1134. * value if it wasn't provided explicitly.
  1135. */
  1136. for (i = 0; i < BRCMS_NUM_RATES_MCS_1_STREAM; i++) {
  1137. if (txpwr->mcs_40_siso[i] == 0)
  1138. txpwr->mcs_40_siso[i] = txpwr->mcs_40_cdd[i];
  1139. }
  1140. for (i = 0, j = 0; i < BRCMS_NUM_RATES_OFDM; i++, j++) {
  1141. if (txpwr->ofdm_40_siso[i] == 0)
  1142. txpwr->ofdm_40_siso[i] = txpwr->mcs_40_siso[j];
  1143. if (i == 0) {
  1144. i = i + 1;
  1145. if (txpwr->ofdm_40_siso[i] == 0)
  1146. txpwr->ofdm_40_siso[i] = txpwr->mcs_40_siso[j];
  1147. }
  1148. }
  1149. /*
  1150. * Copy the 20 and 40 MHz MCS0-7 CDD values to the corresponding
  1151. * STBC values if they weren't provided explicitly.
  1152. */
  1153. for (i = 0; i < BRCMS_NUM_RATES_MCS_1_STREAM; i++) {
  1154. if (txpwr->mcs_20_stbc[i] == 0)
  1155. txpwr->mcs_20_stbc[i] = txpwr->mcs_20_cdd[i];
  1156. if (txpwr->mcs_40_stbc[i] == 0)
  1157. txpwr->mcs_40_stbc[i] = txpwr->mcs_40_cdd[i];
  1158. }
  1159. return;
  1160. }
  1161. /*
  1162. * Verify the chanspec is using a legal set of parameters, i.e. that the
  1163. * chanspec specified a band, bw, ctl_sb and channel and that the
  1164. * combination could be legal given any set of circumstances.
  1165. * RETURNS: true is the chanspec is malformed, false if it looks good.
  1166. */
  1167. static bool brcms_c_chspec_malformed(u16 chanspec)
  1168. {
  1169. /* must be 2G or 5G band */
  1170. if (!CHSPEC_IS5G(chanspec) && !CHSPEC_IS2G(chanspec))
  1171. return true;
  1172. /* must be 20 or 40 bandwidth */
  1173. if (!CHSPEC_IS40(chanspec) && !CHSPEC_IS20(chanspec))
  1174. return true;
  1175. /* 20MHZ b/w must have no ctl sb, 40 must have a ctl sb */
  1176. if (CHSPEC_IS20(chanspec)) {
  1177. if (!CHSPEC_SB_NONE(chanspec))
  1178. return true;
  1179. } else if (!CHSPEC_SB_UPPER(chanspec) && !CHSPEC_SB_LOWER(chanspec)) {
  1180. return true;
  1181. }
  1182. return false;
  1183. }
  1184. /*
  1185. * Validate the chanspec for this locale, for 40MHZ we need to also
  1186. * check that the sidebands are valid 20MZH channels in this locale
  1187. * and they are also a legal HT combination
  1188. */
  1189. static bool
  1190. brcms_c_valid_chanspec_ext(struct brcms_cm_info *wlc_cm, u16 chspec,
  1191. bool dualband)
  1192. {
  1193. struct brcms_c_info *wlc = wlc_cm->wlc;
  1194. u8 channel = CHSPEC_CHANNEL(chspec);
  1195. /* check the chanspec */
  1196. if (brcms_c_chspec_malformed(chspec)) {
  1197. wiphy_err(wlc->wiphy, "wl%d: malformed chanspec 0x%x\n",
  1198. wlc->pub->unit, chspec);
  1199. return false;
  1200. }
  1201. if (CHANNEL_BANDUNIT(wlc_cm->wlc, channel) !=
  1202. chspec_bandunit(chspec))
  1203. return false;
  1204. /* Check a 20Mhz channel */
  1205. if (CHSPEC_IS20(chspec)) {
  1206. if (dualband)
  1207. return brcms_c_valid_channel20_db(wlc_cm->wlc->cmi,
  1208. channel);
  1209. else
  1210. return brcms_c_valid_channel20(wlc_cm->wlc->cmi,
  1211. channel);
  1212. }
  1213. #ifdef SUPPORT_40MHZ
  1214. /*
  1215. * We know we are now checking a 40MHZ channel, so we should
  1216. * only be here for NPHYS
  1217. */
  1218. if (BRCMS_ISNPHY(wlc->band) || BRCMS_ISSSLPNPHY(wlc->band)) {
  1219. u8 upper_sideband = 0, idx;
  1220. u8 num_ch20_entries =
  1221. sizeof(chan20_info) / sizeof(struct chan20_info);
  1222. if (!VALID_40CHANSPEC_IN_BAND(wlc, chspec_bandunit(chspec)))
  1223. return false;
  1224. if (dualband) {
  1225. if (!brcms_c_valid_channel20_db(wlc->cmi,
  1226. lower_20_sb(channel)) ||
  1227. !brcms_c_valid_channel20_db(wlc->cmi,
  1228. upper_20_sb(channel)))
  1229. return false;
  1230. } else {
  1231. if (!brcms_c_valid_channel20(wlc->cmi,
  1232. lower_20_sb(channel)) ||
  1233. !brcms_c_valid_channel20(wlc->cmi,
  1234. upper_20_sb(channel)))
  1235. return false;
  1236. }
  1237. /* find the lower sideband info in the sideband array */
  1238. for (idx = 0; idx < num_ch20_entries; idx++) {
  1239. if (chan20_info[idx].sb == lower_20_sb(channel))
  1240. upper_sideband = chan20_info[idx].adj_sbs;
  1241. }
  1242. /* check that the lower sideband allows an upper sideband */
  1243. if ((upper_sideband & (CH_UPPER_SB | CH_EWA_VALID)) ==
  1244. (CH_UPPER_SB | CH_EWA_VALID))
  1245. return true;
  1246. return false;
  1247. }
  1248. #endif /* 40 MHZ */
  1249. return false;
  1250. }
  1251. bool brcms_c_valid_chanspec_db(struct brcms_cm_info *wlc_cm, u16 chspec)
  1252. {
  1253. return brcms_c_valid_chanspec_ext(wlc_cm, chspec, true);
  1254. }