mac80211: brcmfmac: backport scheduled scan cleanup and chip support
[openwrt/openwrt.git] / package / kernel / mac80211 / patches / 357-0006-brcmfmac-make-internal-escan-more-generic.patch
1 From fa85b30a908455ff25def3a5f319aad272ef4862 Mon Sep 17 00:00:00 2001
2 From: Arend Van Spriel <arend.vanspriel@broadcom.com>
3 Date: Wed, 23 Nov 2016 10:25:25 +0000
4 Subject: [PATCH] brcmfmac: make internal escan more generic
5
6 For scheduled scan we initiate an escan in firmware to obtain more
7 info missing from the scheduled scan notification we get from firmware.
8 For upcoming functionality this is also required so make it a bit
9 more generic.
10
11 Reviewed-by: Hante Meuleman <hante.meuleman@broadcom.com>
12 Reviewed-by: Pieter-Paul Giesberts <pieter-paul.giesberts@broadcom.com>
13 Reviewed-by: Franky Lin <franky.lin@broadcom.com>
14 Signed-off-by: Arend van Spriel <arend.vanspriel@broadcom.com>
15 Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
16 ---
17 .../broadcom/brcm80211/brcmfmac/cfg80211.c | 187 ++++++++++++---------
18 .../broadcom/brcm80211/brcmfmac/cfg80211.h | 4 +-
19 2 files changed, 109 insertions(+), 82 deletions(-)
20
21 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
22 +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
23 @@ -757,12 +757,12 @@ s32 brcmf_notify_escan_complete(struct b
24 brcmf_scan_config_mpc(ifp, 1);
25
26 /*
27 - * e-scan can be initiated by scheduled scan
28 + * e-scan can be initiated internally
29 * which takes precedence.
30 */
31 - if (cfg->sched_escan) {
32 + if (cfg->internal_escan) {
33 brcmf_dbg(SCAN, "scheduled scan completed\n");
34 - cfg->sched_escan = false;
35 + cfg->internal_escan = false;
36 if (!aborted)
37 cfg80211_sched_scan_results(cfg_to_wiphy(cfg));
38 } else if (scan_request) {
39 @@ -3013,7 +3013,7 @@ void brcmf_abort_scanning(struct brcmf_c
40 struct escan_info *escan = &cfg->escan_info;
41
42 set_bit(BRCMF_SCAN_STATUS_ABORT, &cfg->scan_status);
43 - if (cfg->scan_request) {
44 + if (cfg->internal_escan || cfg->scan_request) {
45 escan->escan_state = WL_ESCAN_STATE_IDLE;
46 brcmf_notify_escan_complete(cfg, escan->ifp, true, true);
47 }
48 @@ -3036,7 +3036,7 @@ static void brcmf_escan_timeout(unsigned
49 struct brcmf_cfg80211_info *cfg =
50 (struct brcmf_cfg80211_info *)data;
51
52 - if (cfg->scan_request) {
53 + if (cfg->internal_escan || cfg->scan_request) {
54 brcmf_err("timer expired\n");
55 schedule_work(&cfg->escan_timeout_work);
56 }
57 @@ -3119,7 +3119,7 @@ brcmf_cfg80211_escan_handler(struct brcm
58 if (brcmf_p2p_scan_finding_common_channel(cfg, bss_info_le))
59 goto exit;
60
61 - if (!cfg->scan_request) {
62 + if (!cfg->internal_escan && !cfg->scan_request) {
63 brcmf_dbg(SCAN, "result without cfg80211 request\n");
64 goto exit;
65 }
66 @@ -3165,7 +3165,7 @@ brcmf_cfg80211_escan_handler(struct brcm
67 cfg->escan_info.escan_state = WL_ESCAN_STATE_IDLE;
68 if (brcmf_p2p_scan_finding_common_channel(cfg, NULL))
69 goto exit;
70 - if (cfg->scan_request) {
71 + if (cfg->internal_escan || cfg->scan_request) {
72 brcmf_inform_bss(cfg);
73 aborted = status != BRCMF_E_STATUS_SUCCESS;
74 brcmf_notify_escan_complete(cfg, ifp, aborted, false);
75 @@ -3190,6 +3190,73 @@ static void brcmf_init_escan(struct brcm
76 brcmf_cfg80211_escan_timeout_worker);
77 }
78
79 +static struct cfg80211_scan_request *
80 +brcmf_alloc_internal_escan_request(struct wiphy *wiphy, u32 n_netinfo) {
81 + struct cfg80211_scan_request *req;
82 + size_t req_size;
83 +
84 + req_size = sizeof(*req) +
85 + n_netinfo * sizeof(req->channels[0]) +
86 + n_netinfo * sizeof(*req->ssids);
87 +
88 + req = kzalloc(req_size, GFP_KERNEL);
89 + if (req) {
90 + req->wiphy = wiphy;
91 + req->ssids = (void *)(&req->channels[0]) +
92 + n_netinfo * sizeof(req->channels[0]);
93 + }
94 + return req;
95 +}
96 +
97 +static int brcmf_internal_escan_add_info(struct cfg80211_scan_request *req,
98 + u8 *ssid, u8 ssid_len, u8 channel)
99 +{
100 + struct ieee80211_channel *chan;
101 + enum nl80211_band band;
102 + int freq;
103 +
104 + if (channel <= CH_MAX_2G_CHANNEL)
105 + band = NL80211_BAND_2GHZ;
106 + else
107 + band = NL80211_BAND_5GHZ;
108 +
109 + freq = ieee80211_channel_to_frequency(channel, band);
110 + if (!freq)
111 + return -EINVAL;
112 +
113 + chan = ieee80211_get_channel(req->wiphy, freq);
114 + if (!chan)
115 + return -EINVAL;
116 +
117 + req->channels[req->n_channels++] = chan;
118 + memcpy(req->ssids[req->n_ssids].ssid, ssid, ssid_len);
119 + req->ssids[req->n_ssids++].ssid_len = ssid_len;
120 +
121 + return 0;
122 +}
123 +
124 +static int brcmf_start_internal_escan(struct brcmf_if *ifp,
125 + struct cfg80211_scan_request *request)
126 +{
127 + struct brcmf_cfg80211_info *cfg = ifp->drvr->config;
128 + int err;
129 +
130 + if (test_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status)) {
131 + /* Abort any on-going scan */
132 + brcmf_abort_scanning(cfg);
133 + }
134 +
135 + set_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status);
136 + cfg->escan_info.run = brcmf_run_escan;
137 + err = brcmf_do_escan(ifp, request);
138 + if (err) {
139 + clear_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status);
140 + return err;
141 + }
142 + cfg->internal_escan = true;
143 + return 0;
144 +}
145 +
146 /* PFN result doesn't have all the info which are required by the supplicant
147 * (For e.g IEs) Do a target Escan so that sched scan results are reported
148 * via wl_inform_single_bss in the required format. Escan does require the
149 @@ -3203,12 +3270,8 @@ brcmf_notify_sched_scan_results(struct b
150 struct brcmf_cfg80211_info *cfg = ifp->drvr->config;
151 struct brcmf_pno_net_info_le *netinfo, *netinfo_start;
152 struct cfg80211_scan_request *request = NULL;
153 - struct cfg80211_ssid *ssid = NULL;
154 - struct ieee80211_channel *channel = NULL;
155 struct wiphy *wiphy = cfg_to_wiphy(cfg);
156 - int err = 0;
157 - int channel_req = 0;
158 - int band = 0;
159 + int i, err = 0;
160 struct brcmf_pno_scanresults_le *pfn_result;
161 u32 result_count;
162 u32 status;
163 @@ -3234,83 +3297,47 @@ brcmf_notify_sched_scan_results(struct b
164 */
165 WARN_ON(status != BRCMF_PNO_SCAN_COMPLETE);
166 brcmf_dbg(SCAN, "PFN NET FOUND event. count: %d\n", result_count);
167 - if (result_count > 0) {
168 - int i;
169 -
170 - request = kzalloc(sizeof(*request), GFP_KERNEL);
171 - ssid = kcalloc(result_count, sizeof(*ssid), GFP_KERNEL);
172 - channel = kcalloc(result_count, sizeof(*channel), GFP_KERNEL);
173 - if (!request || !ssid || !channel) {
174 - err = -ENOMEM;
175 - goto out_err;
176 - }
177 + if (!result_count) {
178 + brcmf_err("FALSE PNO Event. (pfn_count == 0)\n");
179 + goto out_err;
180 + }
181 + request = brcmf_alloc_internal_escan_request(wiphy,
182 + result_count);
183 + if (!request) {
184 + err = -ENOMEM;
185 + goto out_err;
186 + }
187
188 - request->wiphy = wiphy;
189 - data += sizeof(struct brcmf_pno_scanresults_le);
190 - netinfo_start = (struct brcmf_pno_net_info_le *)data;
191 -
192 - for (i = 0; i < result_count; i++) {
193 - netinfo = &netinfo_start[i];
194 - if (!netinfo) {
195 - brcmf_err("Invalid netinfo ptr. index: %d\n",
196 - i);
197 - err = -EINVAL;
198 - goto out_err;
199 - }
200 + data += sizeof(struct brcmf_pno_scanresults_le);
201 + netinfo_start = (struct brcmf_pno_net_info_le *)data;
202
203 - brcmf_dbg(SCAN, "SSID:%s Channel:%d\n",
204 - netinfo->SSID, netinfo->channel);
205 - memcpy(ssid[i].ssid, netinfo->SSID, netinfo->SSID_len);
206 - ssid[i].ssid_len = netinfo->SSID_len;
207 - request->n_ssids++;
208 -
209 - channel_req = netinfo->channel;
210 - if (channel_req <= CH_MAX_2G_CHANNEL)
211 - band = NL80211_BAND_2GHZ;
212 - else
213 - band = NL80211_BAND_5GHZ;
214 - channel[i].center_freq =
215 - ieee80211_channel_to_frequency(channel_req,
216 - band);
217 - channel[i].band = band;
218 - channel[i].flags |= IEEE80211_CHAN_NO_HT40;
219 - request->channels[i] = &channel[i];
220 - request->n_channels++;
221 - }
222 -
223 - /* assign parsed ssid array */
224 - if (request->n_ssids)
225 - request->ssids = &ssid[0];
226 -
227 - if (test_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status)) {
228 - /* Abort any on-going scan */
229 - brcmf_abort_scanning(cfg);
230 + for (i = 0; i < result_count; i++) {
231 + netinfo = &netinfo_start[i];
232 + if (!netinfo) {
233 + brcmf_err("Invalid netinfo ptr. index: %d\n",
234 + i);
235 + err = -EINVAL;
236 + goto out_err;
237 }
238
239 - set_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status);
240 - cfg->escan_info.run = brcmf_run_escan;
241 - err = brcmf_do_escan(ifp, request);
242 - if (err) {
243 - clear_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status);
244 + brcmf_dbg(SCAN, "SSID:%.32s Channel:%d\n",
245 + netinfo->SSID, netinfo->channel);
246 + err = brcmf_internal_escan_add_info(request,
247 + netinfo->SSID,
248 + netinfo->SSID_len,
249 + netinfo->channel);
250 + if (err)
251 goto out_err;
252 - }
253 - cfg->sched_escan = true;
254 - cfg->scan_request = request;
255 - } else {
256 - brcmf_err("FALSE PNO Event. (pfn_count == 0)\n");
257 - goto out_err;
258 }
259
260 - kfree(ssid);
261 - kfree(channel);
262 - kfree(request);
263 - return 0;
264 + err = brcmf_start_internal_escan(ifp, request);
265 + if (!err)
266 + goto free_req;
267
268 out_err:
269 - kfree(ssid);
270 - kfree(channel);
271 - kfree(request);
272 cfg80211_sched_scan_stopped(wiphy);
273 +free_req:
274 + kfree(request);
275 return err;
276 }
277
278 @@ -3405,7 +3432,7 @@ static int brcmf_cfg80211_sched_scan_sto
279
280 brcmf_dbg(SCAN, "enter\n");
281 brcmf_pno_clean(ifp);
282 - if (cfg->sched_escan)
283 + if (cfg->internal_escan)
284 brcmf_notify_escan_complete(cfg, ifp, true, true);
285 return 0;
286 }
287 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.h
288 +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.h
289 @@ -271,7 +271,7 @@ struct brcmf_cfg80211_wowl {
290 * @pub: common driver information.
291 * @channel: current channel.
292 * @active_scan: current scan mode.
293 - * @sched_escan: e-scan for scheduled scan support running.
294 + * @internal_escan: indicates internally initiated e-scan is running.
295 * @ibss_starter: indicates this sta is ibss starter.
296 * @pwr_save: indicate whether dongle to support power save mode.
297 * @dongle_up: indicate whether dongle up or not.
298 @@ -303,7 +303,7 @@ struct brcmf_cfg80211_info {
299 struct brcmf_pub *pub;
300 u32 channel;
301 bool active_scan;
302 - bool sched_escan;
303 + bool internal_escan;
304 bool ibss_starter;
305 bool pwr_save;
306 bool dongle_up;