354-brcmfmac-use-static-superset-of-channels-for-wiphy-b.patch 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300
  1. From: Arend van Spriel <[email protected]>
  2. Date: Tue, 14 Apr 2015 20:10:24 +0200
  3. Subject: [PATCH] brcmfmac: use static superset of channels for wiphy
  4. bands
  5. The driver was constructing a list of channels per wiphy band
  6. by querying the device. This list is not what the hardware is
  7. able to do as it is already filtered by the country setting in
  8. the device. As user-space may change the country this would
  9. require updating the channel list which is not recommended [1].
  10. This patch introduces a superset of channels. The individual
  11. channels are disabled appropriately by querying the device.
  12. [1] http://mid.gmane.org/[email protected]
  13. Reviewed-by: Hante Meuleman <[email protected]>
  14. Reviewed-by: Daniel (Deognyoun) Kim <[email protected]>
  15. Reviewed-by: Pieter-Paul Giesberts <[email protected]>
  16. Signed-off-by: Arend van Spriel <[email protected]>
  17. ---
  18. --- a/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c
  19. +++ b/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c
  20. @@ -129,13 +129,47 @@ static struct ieee80211_rate __wl_rates[
  21. RATETAB_ENT(BRCM_RATE_54M, 0),
  22. };
  23. -#define wl_a_rates (__wl_rates + 4)
  24. -#define wl_a_rates_size 8
  25. #define wl_g_rates (__wl_rates + 0)
  26. -#define wl_g_rates_size 12
  27. +#define wl_g_rates_size ARRAY_SIZE(__wl_rates)
  28. +#define wl_a_rates (__wl_rates + 4)
  29. +#define wl_a_rates_size (wl_g_rates_size - 4)
  30. +
  31. +#define CHAN2G(_channel, _freq) { \
  32. + .band = IEEE80211_BAND_2GHZ, \
  33. + .center_freq = (_freq), \
  34. + .hw_value = (_channel), \
  35. + .flags = IEEE80211_CHAN_DISABLED, \
  36. + .max_antenna_gain = 0, \
  37. + .max_power = 30, \
  38. +}
  39. +
  40. +#define CHAN5G(_channel) { \
  41. + .band = IEEE80211_BAND_5GHZ, \
  42. + .center_freq = 5000 + (5 * (_channel)), \
  43. + .hw_value = (_channel), \
  44. + .flags = IEEE80211_CHAN_DISABLED, \
  45. + .max_antenna_gain = 0, \
  46. + .max_power = 30, \
  47. +}
  48. +
  49. +static struct ieee80211_channel __wl_2ghz_channels[] = {
  50. + CHAN2G(1, 2412), CHAN2G(2, 2417), CHAN2G(3, 2422), CHAN2G(4, 2427),
  51. + CHAN2G(5, 2432), CHAN2G(6, 2437), CHAN2G(7, 2442), CHAN2G(8, 2447),
  52. + CHAN2G(9, 2452), CHAN2G(10, 2457), CHAN2G(11, 2462), CHAN2G(12, 2467),
  53. + CHAN2G(13, 2472), CHAN2G(14, 2484)
  54. +};
  55. +
  56. +static struct ieee80211_channel __wl_5ghz_channels[] = {
  57. + CHAN5G(34), CHAN5G(36), CHAN5G(38), CHAN5G(40), CHAN5G(42),
  58. + CHAN5G(44), CHAN5G(46), CHAN5G(48), CHAN5G(52), CHAN5G(56),
  59. + CHAN5G(60), CHAN5G(64), CHAN5G(100), CHAN5G(104), CHAN5G(108),
  60. + CHAN5G(112), CHAN5G(116), CHAN5G(120), CHAN5G(124), CHAN5G(128),
  61. + CHAN5G(132), CHAN5G(136), CHAN5G(140), CHAN5G(144), CHAN5G(149),
  62. + CHAN5G(153), CHAN5G(157), CHAN5G(161), CHAN5G(165)
  63. +};
  64. /* Band templates duplicated per wiphy. The channel info
  65. - * is filled in after querying the device.
  66. + * above is added to the band during setup.
  67. */
  68. static const struct ieee80211_supported_band __wl_band_2ghz = {
  69. .band = IEEE80211_BAND_2GHZ,
  70. @@ -143,7 +177,7 @@ static const struct ieee80211_supported_
  71. .n_bitrates = wl_g_rates_size,
  72. };
  73. -static const struct ieee80211_supported_band __wl_band_5ghz_a = {
  74. +static const struct ieee80211_supported_band __wl_band_5ghz = {
  75. .band = IEEE80211_BAND_5GHZ,
  76. .bitrates = wl_a_rates,
  77. .n_bitrates = wl_a_rates_size,
  78. @@ -5252,40 +5286,6 @@ dongle_scantime_out:
  79. return err;
  80. }
  81. -/* Filter the list of channels received from firmware counting only
  82. - * the 20MHz channels. The wiphy band data only needs those which get
  83. - * flagged to indicate if they can take part in higher bandwidth.
  84. - */
  85. -static void brcmf_count_20mhz_channels(struct brcmf_cfg80211_info *cfg,
  86. - struct brcmf_chanspec_list *chlist,
  87. - u32 chcnt[])
  88. -{
  89. - u32 total = le32_to_cpu(chlist->count);
  90. - struct brcmu_chan ch;
  91. - int i;
  92. -
  93. - for (i = 0; i < total; i++) {
  94. - ch.chspec = (u16)le32_to_cpu(chlist->element[i]);
  95. - cfg->d11inf.decchspec(&ch);
  96. -
  97. - /* Firmware gives a ordered list. We skip non-20MHz
  98. - * channels is 2G. For 5G we can abort upon reaching
  99. - * a non-20MHz channel in the list.
  100. - */
  101. - if (ch.bw != BRCMU_CHAN_BW_20) {
  102. - if (ch.band == BRCMU_CHAN_BAND_5G)
  103. - break;
  104. - else
  105. - continue;
  106. - }
  107. -
  108. - if (ch.band == BRCMU_CHAN_BAND_2G)
  109. - chcnt[0] += 1;
  110. - else if (ch.band == BRCMU_CHAN_BAND_5G)
  111. - chcnt[1] += 1;
  112. - }
  113. -}
  114. -
  115. static void brcmf_update_bw40_channel_flag(struct ieee80211_channel *channel,
  116. struct brcmu_chan *ch)
  117. {
  118. @@ -5321,7 +5321,6 @@ static int brcmf_construct_chaninfo(stru
  119. u32 i, j;
  120. u32 total;
  121. u32 chaninfo;
  122. - u32 chcnt[2] = { 0, 0 };
  123. u32 index;
  124. pbuf = kzalloc(BRCMF_DCMD_MEDLEN, GFP_KERNEL);
  125. @@ -5338,42 +5337,15 @@ static int brcmf_construct_chaninfo(stru
  126. goto fail_pbuf;
  127. }
  128. - brcmf_count_20mhz_channels(cfg, list, chcnt);
  129. wiphy = cfg_to_wiphy(cfg);
  130. - if (chcnt[0]) {
  131. - band = kmemdup(&__wl_band_2ghz, sizeof(__wl_band_2ghz),
  132. - GFP_KERNEL);
  133. - if (band == NULL) {
  134. - err = -ENOMEM;
  135. - goto fail_pbuf;
  136. - }
  137. - band->channels = kcalloc(chcnt[0], sizeof(*channel),
  138. - GFP_KERNEL);
  139. - if (band->channels == NULL) {
  140. - kfree(band);
  141. - err = -ENOMEM;
  142. - goto fail_pbuf;
  143. - }
  144. - band->n_channels = 0;
  145. - wiphy->bands[IEEE80211_BAND_2GHZ] = band;
  146. - }
  147. - if (chcnt[1]) {
  148. - band = kmemdup(&__wl_band_5ghz_a, sizeof(__wl_band_5ghz_a),
  149. - GFP_KERNEL);
  150. - if (band == NULL) {
  151. - err = -ENOMEM;
  152. - goto fail_band2g;
  153. - }
  154. - band->channels = kcalloc(chcnt[1], sizeof(*channel),
  155. - GFP_KERNEL);
  156. - if (band->channels == NULL) {
  157. - kfree(band);
  158. - err = -ENOMEM;
  159. - goto fail_band2g;
  160. - }
  161. - band->n_channels = 0;
  162. - wiphy->bands[IEEE80211_BAND_5GHZ] = band;
  163. - }
  164. + band = wiphy->bands[IEEE80211_BAND_2GHZ];
  165. + if (band)
  166. + for (i = 0; i < band->n_channels; i++)
  167. + band->channels[i].flags = IEEE80211_CHAN_DISABLED;
  168. + band = wiphy->bands[IEEE80211_BAND_5GHZ];
  169. + if (band)
  170. + for (i = 0; i < band->n_channels; i++)
  171. + band->channels[i].flags = IEEE80211_CHAN_DISABLED;
  172. total = le32_to_cpu(list->count);
  173. for (i = 0; i < total; i++) {
  174. @@ -5388,6 +5360,8 @@ static int brcmf_construct_chaninfo(stru
  175. brcmf_err("Invalid channel Spec. 0x%x.\n", ch.chspec);
  176. continue;
  177. }
  178. + if (!band)
  179. + continue;
  180. if (!(bw_cap[band->band] & WLC_BW_40MHZ_BIT) &&
  181. ch.bw == BRCMU_CHAN_BW_40)
  182. continue;
  183. @@ -5415,9 +5389,9 @@ static int brcmf_construct_chaninfo(stru
  184. } else if (ch.bw == BRCMU_CHAN_BW_40) {
  185. brcmf_update_bw40_channel_flag(&channel[index], &ch);
  186. } else {
  187. - /* disable other bandwidths for now as mentioned
  188. - * order assure they are enabled for subsequent
  189. - * chanspecs.
  190. + /* enable the channel and disable other bandwidths
  191. + * for now as mentioned order assure they are enabled
  192. + * for subsequent chanspecs.
  193. */
  194. channel[index].flags = IEEE80211_CHAN_NO_HT40 |
  195. IEEE80211_CHAN_NO_80MHZ;
  196. @@ -5436,16 +5410,8 @@ static int brcmf_construct_chaninfo(stru
  197. IEEE80211_CHAN_NO_IR;
  198. }
  199. }
  200. - if (index == band->n_channels)
  201. - band->n_channels++;
  202. }
  203. - kfree(pbuf);
  204. - return 0;
  205. -fail_band2g:
  206. - kfree(wiphy->bands[IEEE80211_BAND_2GHZ]->channels);
  207. - kfree(wiphy->bands[IEEE80211_BAND_2GHZ]);
  208. - wiphy->bands[IEEE80211_BAND_2GHZ] = NULL;
  209. fail_pbuf:
  210. kfree(pbuf);
  211. return err;
  212. @@ -5778,7 +5744,12 @@ static void brcmf_wiphy_wowl_params(stru
  213. static int brcmf_setup_wiphy(struct wiphy *wiphy, struct brcmf_if *ifp)
  214. {
  215. + struct ieee80211_supported_band *band;
  216. struct ieee80211_iface_combination ifc_combo;
  217. + __le32 bandlist[3];
  218. + u32 n_bands;
  219. + int err, i;
  220. +
  221. wiphy->max_scan_ssids = WL_NUM_SCAN_MAX;
  222. wiphy->max_scan_ie_len = BRCMF_SCAN_IE_LEN_MAX;
  223. wiphy->max_num_pmkids = WL_NUM_PMKIDS_MAX;
  224. @@ -5820,7 +5791,52 @@ static int brcmf_setup_wiphy(struct wiph
  225. if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_WOWL))
  226. brcmf_wiphy_wowl_params(wiphy);
  227. - return brcmf_setup_wiphybands(wiphy);
  228. + err = brcmf_fil_cmd_data_get(ifp, BRCMF_C_GET_BANDLIST, &bandlist,
  229. + sizeof(bandlist));
  230. + if (err) {
  231. + brcmf_err("could not obtain band info: err=%d\n", err);
  232. + return err;
  233. + }
  234. + /* first entry in bandlist is number of bands */
  235. + n_bands = le32_to_cpu(bandlist[0]);
  236. + for (i = 1; i <= n_bands && i < ARRAY_SIZE(bandlist); i++) {
  237. + if (bandlist[i] == cpu_to_le32(WLC_BAND_2G)) {
  238. + band = kmemdup(&__wl_band_2ghz, sizeof(__wl_band_2ghz),
  239. + GFP_KERNEL);
  240. + if (!band)
  241. + return -ENOMEM;
  242. +
  243. + band->channels = kmemdup(&__wl_2ghz_channels,
  244. + sizeof(__wl_2ghz_channels),
  245. + GFP_KERNEL);
  246. + if (!band->channels) {
  247. + kfree(band);
  248. + return -ENOMEM;
  249. + }
  250. +
  251. + band->n_channels = ARRAY_SIZE(__wl_2ghz_channels);
  252. + wiphy->bands[IEEE80211_BAND_2GHZ] = band;
  253. + }
  254. + if (bandlist[i] == cpu_to_le32(WLC_BAND_5G)) {
  255. + band = kmemdup(&__wl_band_5ghz, sizeof(__wl_band_5ghz),
  256. + GFP_KERNEL);
  257. + if (!band)
  258. + return -ENOMEM;
  259. +
  260. + band->channels = kmemdup(&__wl_5ghz_channels,
  261. + sizeof(__wl_5ghz_channels),
  262. + GFP_KERNEL);
  263. + if (!band->channels) {
  264. + kfree(band);
  265. + return -ENOMEM;
  266. + }
  267. +
  268. + band->n_channels = ARRAY_SIZE(__wl_5ghz_channels);
  269. + wiphy->bands[IEEE80211_BAND_5GHZ] = band;
  270. + }
  271. + }
  272. + err = brcmf_setup_wiphybands(wiphy);
  273. + return err;
  274. }
  275. static s32 brcmf_config_dongle(struct brcmf_cfg80211_info *cfg)
  276. @@ -6011,6 +6027,9 @@ static void brcmf_cfg80211_reg_notifier(
  277. static void brcmf_free_wiphy(struct wiphy *wiphy)
  278. {
  279. + if (!wiphy)
  280. + return;
  281. +
  282. kfree(wiphy->iface_combinations);
  283. if (wiphy->bands[IEEE80211_BAND_2GHZ]) {
  284. kfree(wiphy->bands[IEEE80211_BAND_2GHZ]->channels);