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