1 /* SPDX-License-Identifier: GPL-2.0 */
2 /*
3 * Linux cfg80211 driver scan related code
4 *
5 * Copyright (C) 1999-2019, Broadcom.
6 *
7 * Unless you and Broadcom execute a separate written software license
8 * agreement governing use of this software, this software is licensed to you
9 * under the terms of the GNU General Public License version 2 (the "GPL"),
10 * available at http://www.broadcom.com/licenses/GPLv2.php, with the
11 * following added to such license:
12 *
13 * As a special exception, the copyright holders of this software give you
14 * permission to link this software with independent modules, and to copy and
15 * distribute the resulting executable under terms of your choice, provided that
16 * you also meet, for each linked independent module, the terms and conditions of
17 * the license of that module. An independent module is a module which is not
18 * derived from this software. The special exception does not apply to any
19 * modifications of the software.
20 *
21 * Notwithstanding the above, under no circumstances may you combine this
22 * software in any way with any other Broadcom software provided under a license
23 * other than the GPL, without Broadcom's express prior written consent.
24 *
25 *
26 * <<Broadcom-WL-IPTag/Open:>>
27 *
28 * $Id$
29 */
30 /* */
31 #include <typedefs.h>
32 #include <linuxver.h>
33 #include <osl.h>
34 #include <linux/kernel.h>
35
36 #include <bcmutils.h>
37 #include <bcmstdlib_s.h>
38 #include <bcmwifi_channels.h>
39 #include <bcmendian.h>
40 #include <ethernet.h>
41 #include <802.11.h>
42 #include <bcmiov.h>
43 #include <linux/if_arp.h>
44 #include <linux/uaccess.h>
45
46 #include <ethernet.h>
47 #include <linux/kernel.h>
48 #include <linux/kthread.h>
49 #include <linux/netdevice.h>
50 #include <linux/sched.h>
51 #include <linux/etherdevice.h>
52 #include <linux/wireless.h>
53 #include <linux/ieee80211.h>
54 #include <linux/wait.h>
55 #include <net/cfg80211.h>
56 #include <net/rtnetlink.h>
57
58 #include <wlioctl.h>
59 #include <bcmevent.h>
60 #include <wldev_common.h>
61 #include <wl_cfg80211.h>
62 #include <wl_cfgscan.h>
63 #include <wl_cfgp2p.h>
64 #include <bcmdevs.h>
65 #include <wl_android.h>
66 #include <dngl_stats.h>
67 #include <dhd.h>
68 #include <dhd_linux.h>
69 #include <dhd_debug.h>
70 #include <dhdioctl.h>
71 #include <wlioctl.h>
72 #include <dhd_cfg80211.h>
73 #include <dhd_bus.h>
74 #include <wl_cfgvendor.h>
75 #ifdef BCMPCIE
76 #include <dhd_flowring.h>
77 #endif // endif
78 #ifdef PNO_SUPPORT
79 #include <dhd_pno.h>
80 #endif /* PNO_SUPPORT */
81 #ifdef RTT_SUPPORT
82 #include "dhd_rtt.h"
83 #endif /* RTT_SUPPORT */
84 #include <dhd_config.h>
85 #ifdef CONFIG_AP6XXX_WIFI6_HDF
86 #include "hdf_bdh_event.h"
87 #endif
88
89 #define ACTIVE_SCAN 1
90 #define PASSIVE_SCAN 0
91
92 #define MIN_P2P_IE_LEN 8 /* p2p_ie->OUI(3) + p2p_ie->oui_type(1) +
93 * Attribute ID(1) + Length(2) + 1(Mininum length:1)
94 */
95 #define MAX_P2P_IE_LEN 251 /* Up To 251 */
96
97 #define WPS_ATTR_REQ_TYPE 0x103a
98 #define WPS_REQ_TYPE_ENROLLEE 0x01
99
100 #if defined(USE_INITIAL_2G_SCAN) || defined(USE_INITIAL_SHORT_DWELL_TIME)
101 #define FIRST_SCAN_ACTIVE_DWELL_TIME_MS 40
102 bool g_first_broadcast_scan = TRUE;
103 #endif /* USE_INITIAL_2G_SCAN || USE_INITIAL_SHORT_DWELL_TIME */
104 #ifdef P2P_LISTEN_OFFLOADING
105 void wl_cfg80211_cancel_p2plo(struct bcm_cfg80211 *cfg);
106 #endif /* P2P_LISTEN_OFFLOADING */
107 static void _wl_notify_scan_done(struct bcm_cfg80211 *cfg, bool aborted);
108
109 extern int passive_channel_skip;
110
111 #ifdef WL11U
112 static bcm_tlv_t *
wl_cfg80211_find_interworking_ie(const u8 * parse,u32 len)113 wl_cfg80211_find_interworking_ie(const u8 *parse, u32 len)
114 {
115 bcm_tlv_t *ie;
116
117 /* unfortunately it's too much work to dispose the const cast - bcm_parse_tlvs
118 * is used everywhere and changing its prototype to take const qualifier needs
119 * a massive change to all its callers...
120 */
121
122 if ((ie = bcm_parse_tlvs(parse, len, DOT11_MNG_INTERWORKING_ID))) {
123 return ie;
124 }
125 return NULL;
126 }
127
128 static s32
wl_cfg80211_clear_iw_ie(struct bcm_cfg80211 * cfg,struct net_device * ndev,s32 bssidx)129 wl_cfg80211_clear_iw_ie(struct bcm_cfg80211 *cfg, struct net_device *ndev, s32 bssidx)
130 {
131 ie_setbuf_t ie_setbuf;
132
133 WL_DBG(("clear interworking IE\n"));
134
135 bzero(&ie_setbuf, sizeof(ie_setbuf_t));
136
137 ie_setbuf.ie_buffer.iecount = htod32(1);
138 ie_setbuf.ie_buffer.ie_list[0].ie_data.id = DOT11_MNG_INTERWORKING_ID;
139 ie_setbuf.ie_buffer.ie_list[0].ie_data.len = 0;
140
141 return wldev_iovar_setbuf_bsscfg(ndev, "ie", &ie_setbuf, sizeof(ie_setbuf),
142 cfg->ioctl_buf, WLC_IOCTL_MAXLEN, bssidx, &cfg->ioctl_buf_sync);
143 }
144
145 static s32
wl_cfg80211_add_iw_ie(struct bcm_cfg80211 * cfg,struct net_device * ndev,s32 bssidx,s32 pktflag,uint8 ie_id,uint8 * data,uint8 data_len)146 wl_cfg80211_add_iw_ie(struct bcm_cfg80211 *cfg, struct net_device *ndev, s32 bssidx, s32 pktflag,
147 uint8 ie_id, uint8 *data, uint8 data_len)
148 {
149 s32 err = BCME_OK;
150 s32 buf_len;
151 ie_setbuf_t *ie_setbuf;
152 ie_getbuf_t ie_getbufp;
153 char getbuf[WLC_IOCTL_SMLEN];
154
155 if (ie_id != DOT11_MNG_INTERWORKING_ID) {
156 WL_ERR(("unsupported (id=%d)\n", ie_id));
157 return BCME_UNSUPPORTED;
158 }
159
160 /* access network options (1 octet) is the mandatory field */
161 if (!data || data_len == 0 || data_len > IW_IES_MAX_BUF_LEN) {
162 WL_ERR(("wrong interworking IE (len=%d)\n", data_len));
163 return BCME_BADARG;
164 }
165
166 /* Validate the pktflag parameter */
167 if ((pktflag & ~(VNDR_IE_BEACON_FLAG | VNDR_IE_PRBRSP_FLAG |
168 VNDR_IE_ASSOCRSP_FLAG | VNDR_IE_AUTHRSP_FLAG |
169 VNDR_IE_PRBREQ_FLAG | VNDR_IE_ASSOCREQ_FLAG|
170 VNDR_IE_CUSTOM_FLAG))) {
171 WL_ERR(("invalid packet flag 0x%x\n", pktflag));
172 return BCME_BADARG;
173 }
174
175 buf_len = sizeof(ie_setbuf_t) + data_len - 1;
176
177 ie_getbufp.id = DOT11_MNG_INTERWORKING_ID;
178 if (wldev_iovar_getbuf_bsscfg(ndev, "ie", (void *)&ie_getbufp,
179 sizeof(ie_getbufp), getbuf, WLC_IOCTL_SMLEN, bssidx, &cfg->ioctl_buf_sync)
180 == BCME_OK) {
181 if (!memcmp(&getbuf[TLV_HDR_LEN], data, data_len)) {
182 WL_DBG(("skip to set interworking IE\n"));
183 return BCME_OK;
184 }
185 }
186
187 /* if already set with previous values, delete it first */
188 if (cfg->wl11u) {
189 if ((err = wl_cfg80211_clear_iw_ie(cfg, ndev, bssidx)) != BCME_OK) {
190 return err;
191 }
192 }
193
194 ie_setbuf = (ie_setbuf_t *)MALLOCZ(cfg->osh, buf_len);
195 if (!ie_setbuf) {
196 WL_ERR(("Error allocating buffer for IE\n"));
197 return -ENOMEM;
198 }
199 strlcpy(ie_setbuf->cmd, "add", sizeof(ie_setbuf->cmd));
200
201 /* Buffer contains only 1 IE */
202 ie_setbuf->ie_buffer.iecount = htod32(1);
203 /* use VNDR_IE_CUSTOM_FLAG flags for none vendor IE . currently fixed value */
204 ie_setbuf->ie_buffer.ie_list[0].pktflag = htod32(pktflag);
205
206 /* Now, add the IE to the buffer */
207 ie_setbuf->ie_buffer.ie_list[0].ie_data.id = DOT11_MNG_INTERWORKING_ID;
208 ie_setbuf->ie_buffer.ie_list[0].ie_data.len = data_len;
209 /* Returning void here as max data_len can be 8 */
210 (void)memcpy_s((uchar *)&ie_setbuf->ie_buffer.ie_list[0].ie_data.data[0], sizeof(uint8),
211 data, data_len);
212
213 if ((err = wldev_iovar_setbuf_bsscfg(ndev, "ie", ie_setbuf, buf_len,
214 cfg->ioctl_buf, WLC_IOCTL_MAXLEN, bssidx, &cfg->ioctl_buf_sync))
215 == BCME_OK) {
216 WL_DBG(("set interworking IE\n"));
217 cfg->wl11u = TRUE;
218 err = wldev_iovar_setint_bsscfg(ndev, "grat_arp", 1, bssidx);
219 }
220
221 MFREE(cfg->osh, ie_setbuf, buf_len);
222 return err;
223 }
224 #endif /* WL11U */
225
226 #ifdef WL_BCNRECV
227 /* Beacon recv results handler sending to upper layer */
228 static s32
wl_bcnrecv_result_handler(struct bcm_cfg80211 * cfg,bcm_struct_cfgdev * cfgdev,wl_bss_info_v109_2_t * bi,uint32 scan_status)229 wl_bcnrecv_result_handler(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev,
230 wl_bss_info_v109_2_t *bi, uint32 scan_status)
231 {
232 s32 err = BCME_OK;
233 struct wiphy *wiphy = NULL;
234 wl_bcnrecv_result_t *bcn_recv = NULL;
235 struct osl_timespec ts;
236 if (!bi) {
237 WL_ERR(("%s: bi is NULL\n", __func__));
238 err = BCME_NORESOURCE;
239 goto exit;
240 }
241 if ((bi->length - bi->ie_length) < sizeof(wl_bss_info_v109_2_t)) {
242 WL_ERR(("bi info version doesn't support bcn_recv attributes\n"));
243 goto exit;
244 }
245
246 if (scan_status == WLC_E_STATUS_RXBCN) {
247 wiphy = cfg->wdev->wiphy;
248 if (!wiphy) {
249 WL_ERR(("wiphy is NULL\n"));
250 err = BCME_NORESOURCE;
251 goto exit;
252 }
253 bcn_recv = (wl_bcnrecv_result_t *)MALLOCZ(cfg->osh, sizeof(*bcn_recv));
254 if (unlikely(!bcn_recv)) {
255 WL_ERR(("Failed to allocate memory\n"));
256 return -ENOMEM;
257 }
258 /* Returning void here as copy size does not exceed dest size of SSID */
259 (void)memcpy_s((char *)bcn_recv->SSID, DOT11_MAX_SSID_LEN,
260 (char *)bi->SSID, DOT11_MAX_SSID_LEN);
261 /* Returning void here as copy size does not exceed dest size of ETH_LEN */
262 (void)memcpy_s(&bcn_recv->BSSID, ETHER_ADDR_LEN, &bi->BSSID, ETH_ALEN);
263 bcn_recv->channel = wf_chspec_ctlchan(
264 wl_chspec_driver_to_host(bi->chanspec));
265 bcn_recv->beacon_interval = bi->beacon_period;
266
267 /* kernal timestamp */
268 osl_get_monotonic_boottime(&ts);
269 bcn_recv->system_time = ((u64)ts.tv_sec*1000000)
270 + ts.tv_nsec / 1000;
271 bcn_recv->timestamp[0] = bi->timestamp[0];
272 bcn_recv->timestamp[1] = bi->timestamp[1];
273 if ((err = wl_android_bcnrecv_event(cfgdev_to_wlc_ndev(cfgdev, cfg),
274 BCNRECV_ATTR_BCNINFO, 0, 0,
275 (uint8 *)bcn_recv, sizeof(*bcn_recv)))
276 != BCME_OK) {
277 WL_ERR(("failed to send bcnrecv event, error:%d\n", err));
278 }
279 } else {
280 WL_DBG(("Ignoring Escan Event:%d \n", scan_status));
281 }
282 exit:
283 if (bcn_recv) {
284 MFREE(cfg->osh, bcn_recv, sizeof(*bcn_recv));
285 }
286 return err;
287 }
288 #endif /* WL_BCNRECV */
289
290 #ifdef ESCAN_BUF_OVERFLOW_MGMT
291 #ifndef WL_DRV_AVOID_SCANCACHE
292 static void
wl_cfg80211_find_removal_candidate(wl_bss_info_t * bss,removal_element_t * candidate)293 wl_cfg80211_find_removal_candidate(wl_bss_info_t *bss, removal_element_t *candidate)
294 {
295 int idx;
296 for (idx = 0; idx < BUF_OVERFLOW_MGMT_COUNT; idx++) {
297 int len = BUF_OVERFLOW_MGMT_COUNT - idx - 1;
298 if (bss->RSSI < candidate[idx].RSSI) {
299 if (len) {
300 /* In the below memcpy operation the candidate array always has the
301 * buffer space available to max 'len' calculated in the for loop.
302 */
303 (void)memcpy_s(&candidate[idx + 1],
304 (sizeof(removal_element_t) * len),
305 &candidate[idx], sizeof(removal_element_t) * len);
306 }
307 candidate[idx].RSSI = bss->RSSI;
308 candidate[idx].length = bss->length;
309 (void)memcpy_s(&candidate[idx].BSSID, ETHER_ADDR_LEN,
310 &bss->BSSID, ETHER_ADDR_LEN);
311 return;
312 }
313 }
314 }
315
316 static void
wl_cfg80211_remove_lowRSSI_info(wl_scan_results_t * list,removal_element_t * candidate,wl_bss_info_t * bi)317 wl_cfg80211_remove_lowRSSI_info(wl_scan_results_t *list, removal_element_t *candidate,
318 wl_bss_info_t *bi)
319 {
320 int idx1, idx2;
321 int total_delete_len = 0;
322 for (idx1 = 0; idx1 < BUF_OVERFLOW_MGMT_COUNT; idx1++) {
323 int cur_len = WL_SCAN_RESULTS_FIXED_SIZE;
324 wl_bss_info_t *bss = NULL;
325 if (candidate[idx1].RSSI >= bi->RSSI)
326 continue;
327 for (idx2 = 0; idx2 < list->count; idx2++) {
328 bss = bss ? (wl_bss_info_t *)((uintptr)bss + dtoh32(bss->length)) :
329 list->bss_info;
330 if (!bcmp(&candidate[idx1].BSSID, &bss->BSSID, ETHER_ADDR_LEN) &&
331 candidate[idx1].RSSI == bss->RSSI &&
332 candidate[idx1].length == dtoh32(bss->length)) {
333 u32 delete_len = dtoh32(bss->length);
334 WL_DBG(("delete scan info of " MACDBG " to add new AP\n",
335 MAC2STRDBG(bss->BSSID.octet)));
336 if (idx2 < list->count -1) {
337 memmove((u8 *)bss, (u8 *)bss + delete_len,
338 list->buflen - cur_len - delete_len);
339 }
340 list->buflen -= delete_len;
341 list->count--;
342 total_delete_len += delete_len;
343 /* if delete_len is greater than or equal to result length */
344 if (total_delete_len >= bi->length) {
345 return;
346 }
347 break;
348 }
349 cur_len += dtoh32(bss->length);
350 }
351 }
352 }
353 #endif /* WL_DRV_AVOID_SCANCACHE */
354 #endif /* ESCAN_BUF_OVERFLOW_MGMT */
355
356 s32
wl_escan_handler(struct bcm_cfg80211 * cfg,bcm_struct_cfgdev * cfgdev,const wl_event_msg_t * e,void * data)357 wl_escan_handler(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev,
358 const wl_event_msg_t *e, void *data)
359 {
360 s32 err = BCME_OK;
361 s32 status = ntoh32(e->status);
362 wl_escan_result_t *escan_result;
363 struct net_device *ndev = NULL;
364 #ifndef WL_DRV_AVOID_SCANCACHE
365 wl_bss_info_t *bi;
366 u32 bi_length;
367 const wifi_p2p_ie_t * p2p_ie;
368 const u8 *p2p_dev_addr = NULL;
369 wl_scan_results_t *list;
370 wl_bss_info_t *bss = NULL;
371 u32 i;
372 #endif /* WL_DRV_AVOID_SCANCACHE */
373 u16 channel;
374 struct ieee80211_supported_band *band;
375
376 WL_DBG((" enter event type : %d, status : %d \n",
377 ntoh32(e->event_type), ntoh32(e->status)));
378
379 ndev = cfgdev_to_wlc_ndev(cfgdev, cfg);
380
381 mutex_lock(&cfg->scan_sync);
382 /* P2P SCAN is coming from primary interface */
383 if (wl_get_p2p_status(cfg, SCANNING)) {
384 if (wl_get_drv_status_all(cfg, SENDING_ACT_FRM))
385 ndev = cfg->afx_hdl->dev;
386 else
387 ndev = cfg->escan_info.ndev;
388 }
389 escan_result = (wl_escan_result_t *)data;
390 #ifdef WL_BCNRECV
391 if (cfg->bcnrecv_info.bcnrecv_state == BEACON_RECV_STARTED &&
392 status == WLC_E_STATUS_RXBCN) {
393 /* handle beacon recv scan results */
394 wl_bss_info_v109_2_t *bi_info;
395 bi_info = (wl_bss_info_v109_2_t *)escan_result->bss_info;
396 err = wl_bcnrecv_result_handler(cfg, cfgdev, bi_info, status);
397 goto exit;
398 }
399 #endif /* WL_BCNRECV */
400 if (!ndev || (!wl_get_drv_status(cfg, SCANNING, ndev) && !cfg->sched_scan_running)) {
401 WL_ERR_RLMT(("escan is not ready. drv_scan_status 0x%x"
402 " e_type %d e_states %d\n",
403 wl_get_drv_status(cfg, SCANNING, ndev),
404 ntoh32(e->event_type), ntoh32(e->status)));
405 goto exit;
406 }
407
408 #ifndef WL_DRV_AVOID_SCANCACHE
409 if (status == WLC_E_STATUS_PARTIAL) {
410 WL_DBG(("WLC_E_STATUS_PARTIAL \n"));
411 DBG_EVENT_LOG((dhd_pub_t *)cfg->pub, WIFI_EVENT_DRIVER_SCAN_RESULT_FOUND);
412 if (!escan_result) {
413 WL_ERR(("Invalid escan result (NULL pointer)\n"));
414 goto exit;
415 }
416 if ((dtoh32(escan_result->buflen) > (int)ESCAN_BUF_SIZE) ||
417 (dtoh32(escan_result->buflen) < sizeof(wl_escan_result_t))) {
418 WL_ERR(("Invalid escan buffer len:%d\n", dtoh32(escan_result->buflen)));
419 goto exit;
420 }
421 if (dtoh16(escan_result->bss_count) != 1) {
422 WL_ERR(("Invalid bss_count %d: ignoring\n", escan_result->bss_count));
423 goto exit;
424 }
425 bi = escan_result->bss_info;
426 if (!bi) {
427 WL_ERR(("Invalid escan bss info (NULL pointer)\n"));
428 goto exit;
429 }
430 bi_length = dtoh32(bi->length);
431 if (bi_length != (dtoh32(escan_result->buflen) - WL_ESCAN_RESULTS_FIXED_SIZE)) {
432 WL_ERR(("Invalid bss_info length %d: ignoring\n", bi_length));
433 goto exit;
434 }
435
436 /* +++++ terence 20130524: skip invalid bss */
437 channel =
438 bi->ctl_ch ? bi->ctl_ch : CHSPEC_CHANNEL(wl_chspec_driver_to_host(bi->chanspec));
439 if (channel <= CH_MAX_2G_CHANNEL)
440 band = bcmcfg_to_wiphy(cfg)->bands[IEEE80211_BAND_2GHZ];
441 else
442 band = bcmcfg_to_wiphy(cfg)->bands[IEEE80211_BAND_5GHZ];
443 if (!band) {
444 WL_ERR(("No valid band\n"));
445 goto exit;
446 }
447 if (!dhd_conf_match_channel(cfg->pub, channel))
448 goto exit;
449 /* ----- terence 20130524: skip invalid bss */
450
451 if (wl_escan_check_sync_id(status, escan_result->sync_id,
452 cfg->escan_info.cur_sync_id) < 0)
453 goto exit;
454
455 if (!(bcmcfg_to_wiphy(cfg)->interface_modes & BIT(NL80211_IFTYPE_ADHOC))) {
456 if (dtoh16(bi->capability) & DOT11_CAP_IBSS) {
457 WL_DBG(("Ignoring IBSS result\n"));
458 goto exit;
459 }
460 }
461
462 if (wl_get_drv_status_all(cfg, FINDING_COMMON_CHANNEL)) {
463 p2p_dev_addr = wl_cfgp2p_retreive_p2p_dev_addr(bi, bi_length);
464 if (p2p_dev_addr && !memcmp(p2p_dev_addr,
465 cfg->afx_hdl->tx_dst_addr.octet, ETHER_ADDR_LEN)) {
466 s32 channel = wf_chspec_ctlchan(
467 wl_chspec_driver_to_host(bi->chanspec));
468
469 if ((channel > MAXCHANNEL) || (channel <= 0))
470 channel = WL_INVALID;
471 else
472 WL_ERR(("ACTION FRAME SCAN : Peer " MACDBG " found,"
473 " channel : %d\n",
474 MAC2STRDBG(cfg->afx_hdl->tx_dst_addr.octet),
475 channel));
476
477 wl_clr_p2p_status(cfg, SCANNING);
478 cfg->afx_hdl->peer_chan = channel;
479 complete(&cfg->act_frm_scan);
480 goto exit;
481 }
482
483 } else {
484 int cur_len = WL_SCAN_RESULTS_FIXED_SIZE;
485 #ifdef ESCAN_BUF_OVERFLOW_MGMT
486 removal_element_t candidate[BUF_OVERFLOW_MGMT_COUNT];
487 int remove_lower_rssi = FALSE;
488
489 bzero(candidate, sizeof(removal_element_t)*BUF_OVERFLOW_MGMT_COUNT);
490 #endif /* ESCAN_BUF_OVERFLOW_MGMT */
491
492 list = wl_escan_get_buf(cfg, FALSE);
493 if (scan_req_match(cfg)) {
494 #ifdef WL_HOST_BAND_MGMT
495 s32 channel_band = 0;
496 chanspec_t chspec;
497 #endif /* WL_HOST_BAND_MGMT */
498 /* p2p scan && allow only probe response */
499 if ((cfg->p2p->search_state != WL_P2P_DISC_ST_SCAN) &&
500 (bi->flags & WL_BSS_FLAGS_FROM_BEACON))
501 goto exit;
502 if ((p2p_ie = wl_cfgp2p_find_p2pie(((u8 *) bi) + bi->ie_offset,
503 bi->ie_length)) == NULL) {
504 WL_ERR(("Couldn't find P2PIE in probe"
505 " response/beacon\n"));
506 goto exit;
507 }
508 #ifdef WL_HOST_BAND_MGMT
509 chspec = wl_chspec_driver_to_host(bi->chanspec);
510 channel_band = CHSPEC2WLC_BAND(chspec);
511
512 if ((cfg->curr_band == WLC_BAND_5G) &&
513 (channel_band == WLC_BAND_2G)) {
514 /* Avoid sending the GO results in band conflict */
515 if (wl_cfgp2p_retreive_p2pattrib(p2p_ie,
516 P2P_SEID_GROUP_ID) != NULL)
517 goto exit;
518 }
519 #endif /* WL_HOST_BAND_MGMT */
520 }
521 #ifdef ESCAN_BUF_OVERFLOW_MGMT
522 if (bi_length > ESCAN_BUF_SIZE - list->buflen)
523 remove_lower_rssi = TRUE;
524 #endif /* ESCAN_BUF_OVERFLOW_MGMT */
525
526 for (i = 0; i < list->count; i++) {
527 bss = bss ? (wl_bss_info_t *)((uintptr)bss + dtoh32(bss->length))
528 : list->bss_info;
529 if (!bss) {
530 WL_ERR(("bss is NULL\n"));
531 goto exit;
532 }
533 #ifdef ESCAN_BUF_OVERFLOW_MGMT
534 WL_DBG(("%s("MACDBG"), i=%d bss: RSSI %d list->count %d\n",
535 bss->SSID, MAC2STRDBG(bss->BSSID.octet),
536 i, bss->RSSI, list->count));
537
538 if (remove_lower_rssi)
539 wl_cfg80211_find_removal_candidate(bss, candidate);
540 #endif /* ESCAN_BUF_OVERFLOW_MGMT */
541
542 if (!bcmp(&bi->BSSID, &bss->BSSID, ETHER_ADDR_LEN) &&
543 (CHSPEC_BAND(wl_chspec_driver_to_host(bi->chanspec))
544 == CHSPEC_BAND(wl_chspec_driver_to_host(bss->chanspec))) &&
545 bi->SSID_len == bss->SSID_len &&
546 !bcmp(bi->SSID, bss->SSID, bi->SSID_len)) {
547
548 /* do not allow beacon data to update
549 *the data recd from a probe response
550 */
551 if (!(bss->flags & WL_BSS_FLAGS_FROM_BEACON) &&
552 (bi->flags & WL_BSS_FLAGS_FROM_BEACON))
553 goto exit;
554
555 WL_DBG(("%s("MACDBG"), i=%d prev: RSSI %d"
556 " flags 0x%x, new: RSSI %d flags 0x%x\n",
557 bss->SSID, MAC2STRDBG(bi->BSSID.octet), i,
558 bss->RSSI, bss->flags, bi->RSSI, bi->flags));
559
560 if ((bss->flags & WL_BSS_FLAGS_RSSI_ONCHANNEL) ==
561 (bi->flags & WL_BSS_FLAGS_RSSI_ONCHANNEL)) {
562 /* preserve max RSSI if the measurements are
563 * both on-channel or both off-channel
564 */
565 WL_DBG(("%s("MACDBG"), same onchan"
566 ", RSSI: prev %d new %d\n",
567 bss->SSID, MAC2STRDBG(bi->BSSID.octet),
568 bss->RSSI, bi->RSSI));
569 bi->RSSI = MAX(bss->RSSI, bi->RSSI);
570 } else if ((bss->flags & WL_BSS_FLAGS_RSSI_ONCHANNEL) &&
571 (bi->flags & WL_BSS_FLAGS_RSSI_ONCHANNEL) == 0) {
572 /* preserve the on-channel rssi measurement
573 * if the new measurement is off channel
574 */
575 WL_DBG(("%s("MACDBG"), prev onchan"
576 ", RSSI: prev %d new %d\n",
577 bss->SSID, MAC2STRDBG(bi->BSSID.octet),
578 bss->RSSI, bi->RSSI));
579 bi->RSSI = bss->RSSI;
580 bi->flags |= WL_BSS_FLAGS_RSSI_ONCHANNEL;
581 }
582 if (dtoh32(bss->length) != bi_length) {
583 u32 prev_len = dtoh32(bss->length);
584
585 WL_DBG(("bss info replacement"
586 " is occured(bcast:%d->probresp%d)\n",
587 bss->ie_length, bi->ie_length));
588 WL_DBG(("%s("MACDBG"), replacement!(%d -> %d)\n",
589 bss->SSID, MAC2STRDBG(bi->BSSID.octet),
590 prev_len, bi_length));
591
592 if ((list->buflen - prev_len) + bi_length
593 > ESCAN_BUF_SIZE) {
594 WL_ERR(("Buffer is too small: keep the"
595 " previous result of this AP\n"));
596 /* Only update RSSI */
597 bss->RSSI = bi->RSSI;
598 bss->flags |= (bi->flags
599 & WL_BSS_FLAGS_RSSI_ONCHANNEL);
600 goto exit;
601 }
602
603 if (i < list->count - 1) {
604 /* memory copy required by this case only */
605 memmove((u8 *)bss + bi_length,
606 (u8 *)bss + prev_len,
607 list->buflen - cur_len - prev_len);
608 }
609 list->buflen -= prev_len;
610 list->buflen += bi_length;
611 }
612 list->version = dtoh32(bi->version);
613 /* In the above code under check
614 * '(dtoh32(bss->length) != bi_length)'
615 * buffer overflow is avoided. bi_length
616 * is already accounted in list->buflen
617 */
618 if ((err = memcpy_s((u8 *)bss,
619 (ESCAN_BUF_SIZE - (list->buflen - bi_length)),
620 (u8 *)bi, bi_length)) != BCME_OK) {
621 WL_ERR(("Failed to copy the recent bss_info."
622 "err:%d recv_len:%d bi_len:%d\n", err,
623 ESCAN_BUF_SIZE - (list->buflen - bi_length),
624 bi_length));
625 /* This scenario should never happen. If it happens,
626 * set list->count to zero for recovery
627 */
628 list->count = 0;
629 list->buflen = 0;
630 ASSERT(0);
631 }
632 goto exit;
633 }
634 cur_len += dtoh32(bss->length);
635 }
636 if (bi_length > ESCAN_BUF_SIZE - list->buflen) {
637 #ifdef ESCAN_BUF_OVERFLOW_MGMT
638 wl_cfg80211_remove_lowRSSI_info(list, candidate, bi);
639 if (bi_length > ESCAN_BUF_SIZE - list->buflen) {
640 WL_DBG(("RSSI(" MACDBG ") is too low(%d) to add Buffer\n",
641 MAC2STRDBG(bi->BSSID.octet), bi->RSSI));
642 goto exit;
643 }
644 #else
645 WL_ERR(("Buffer is too small: ignoring\n"));
646 goto exit;
647 #endif /* ESCAN_BUF_OVERFLOW_MGMT */
648 }
649 /* In the previous step check is added to ensure the bi_legth does not
650 * exceed the ESCAN_BUF_SIZE
651 */
652 (void)memcpy_s(&(((char *)list)[list->buflen]),
653 (ESCAN_BUF_SIZE - list->buflen), bi, bi_length);
654 list->version = dtoh32(bi->version);
655 list->buflen += bi_length;
656 list->count++;
657
658 /*
659 * !Broadcast && number of ssid = 1 && number of channels =1
660 * means specific scan to association
661 */
662 if (wl_cfgp2p_is_p2p_specific_scan(cfg->scan_request)) {
663 WL_ERR(("P2P assoc scan fast aborted.\n"));
664 wl_notify_escan_complete(cfg, cfg->escan_info.ndev, false, true);
665 goto exit;
666 }
667 }
668 }
669 else if (status == WLC_E_STATUS_SUCCESS) {
670 cfg->escan_info.escan_state = WL_ESCAN_STATE_IDLE;
671 wl_escan_print_sync_id(status, cfg->escan_info.cur_sync_id,
672 escan_result->sync_id);
673
674 if (wl_get_drv_status_all(cfg, FINDING_COMMON_CHANNEL)) {
675 WL_DBG(("ACTION FRAME SCAN DONE\n"));
676 wl_clr_p2p_status(cfg, SCANNING);
677 wl_clr_drv_status(cfg, SCANNING, cfg->afx_hdl->dev);
678 if (cfg->afx_hdl->peer_chan == WL_INVALID)
679 complete(&cfg->act_frm_scan);
680 } else if ((likely(cfg->scan_request)) || (cfg->sched_scan_running)) {
681 WL_INFORM_MEM(("ESCAN COMPLETED\n"));
682 DBG_EVENT_LOG((dhd_pub_t *)cfg->pub, WIFI_EVENT_DRIVER_SCAN_COMPLETE);
683 cfg->bss_list = wl_escan_get_buf(cfg, FALSE);
684 if (!scan_req_match(cfg)) {
685 WL_DBG(("SCAN COMPLETED: scanned AP count=%d\n",
686 cfg->bss_list->count));
687 }
688 wl_inform_bss(cfg);
689 wl_notify_escan_complete(cfg, ndev, false, false);
690 #ifdef CONFIG_AP6XXX_WIFI6_HDF
691 printk("scan done success!\n");
692 HdfScanEventCallback(ndev, HDF_WIFI_SCAN_SUCCESS);
693 #endif
694 }
695 wl_escan_increment_sync_id(cfg, SCAN_BUF_NEXT);
696 } else if ((status == WLC_E_STATUS_ABORT) || (status == WLC_E_STATUS_NEWSCAN) ||
697 (status == WLC_E_STATUS_11HQUIET) || (status == WLC_E_STATUS_CS_ABORT) ||
698 (status == WLC_E_STATUS_NEWASSOC)) {
699 #ifdef CONFIG_AP6XXX_WIFI6_HDF
700 printk("scan abort status=%d\n", status);
701 //HdfScanEventCallback(ndev, HDF_WIFI_SCAN_FAILED);
702 #endif
703 /* Dump FW preserve buffer content */
704 if (status == WLC_E_STATUS_ABORT) {
705 wl_flush_fw_log_buffer(ndev, FW_LOGSET_MASK_ALL);
706 }
707 /* Handle all cases of scan abort */
708 cfg->escan_info.escan_state = WL_ESCAN_STATE_IDLE;
709 wl_escan_print_sync_id(status, escan_result->sync_id,
710 cfg->escan_info.cur_sync_id);
711 WL_DBG(("ESCAN ABORT reason: %d\n", status));
712 if (wl_get_drv_status_all(cfg, FINDING_COMMON_CHANNEL)) {
713 WL_DBG(("ACTION FRAME SCAN DONE\n"));
714 wl_clr_drv_status(cfg, SCANNING, cfg->afx_hdl->dev);
715 wl_clr_p2p_status(cfg, SCANNING);
716 if (cfg->afx_hdl->peer_chan == WL_INVALID)
717 complete(&cfg->act_frm_scan);
718 } else if ((likely(cfg->scan_request)) || (cfg->sched_scan_running)) {
719 WL_INFORM_MEM(("ESCAN ABORTED\n"));
720
721 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0))
722 if (p2p_scan(cfg) && cfg->scan_request &&
723 (cfg->scan_request->flags & NL80211_SCAN_FLAG_FLUSH)) {
724 WL_ERR(("scan list is changed"));
725 cfg->bss_list = wl_escan_get_buf(cfg, FALSE);
726 } else
727 #endif // endif
728 cfg->bss_list = wl_escan_get_buf(cfg, TRUE);
729
730 if (!scan_req_match(cfg)) {
731 WL_TRACE_HW4(("SCAN ABORTED: scanned AP count=%d\n",
732 cfg->bss_list->count));
733 }
734 #ifdef DUAL_ESCAN_RESULT_BUFFER
735 if (escan_result->sync_id != cfg->escan_info.cur_sync_id) {
736 /* If sync_id is not matching, then the abort might have
737 * come for the old scan req or for the in-driver initiated
738 * scan. So do abort for scan_req for which sync_id is
739 * matching.
740 */
741 WL_INFORM_MEM(("sync_id mismatch (%d != %d). "
742 "Ignore the scan abort event.\n",
743 escan_result->sync_id, cfg->escan_info.cur_sync_id));
744 goto exit;
745 } else {
746 /* sync id is matching, abort the scan */
747 WL_INFORM_MEM(("scan aborted for sync_id: %d \n",
748 cfg->escan_info.cur_sync_id));
749 wl_inform_bss(cfg);
750 wl_notify_escan_complete(cfg, ndev, true, false);
751 }
752 #else
753 wl_inform_bss(cfg);
754 wl_notify_escan_complete(cfg, ndev, true, false);
755 #endif /* DUAL_ESCAN_RESULT_BUFFER */
756 } else {
757 /* If there is no pending host initiated scan, do nothing */
758 WL_DBG(("ESCAN ABORT: No pending scans. Ignoring event.\n"));
759 }
760 wl_escan_increment_sync_id(cfg, SCAN_BUF_CNT);
761 } else if (status == WLC_E_STATUS_TIMEOUT) {
762 #ifdef CONFIG_AP6XXX_WIFI6_HDF
763 HdfScanEventCallback(ndev, HDF_WIFI_SCAN_TIMEOUT);
764 #endif
765 WL_ERR(("WLC_E_STATUS_TIMEOUT : scan_request[%p]\n", cfg->scan_request));
766 WL_ERR(("reason[0x%x]\n", e->reason));
767 if (e->reason == 0xFFFFFFFF) {
768 wl_notify_escan_complete(cfg, cfg->escan_info.ndev, true, true);
769 }
770 } else {
771 #ifdef CONFIG_AP6XXX_WIFI6_HDF
772 printk("scan failed 3\n");
773 HdfScanEventCallback(ndev, HDF_WIFI_SCAN_FAILED);
774 #endif
775 WL_ERR(("unexpected Escan Event %d : abort\n", status));
776 cfg->escan_info.escan_state = WL_ESCAN_STATE_IDLE;
777 wl_escan_print_sync_id(status, escan_result->sync_id,
778 cfg->escan_info.cur_sync_id);
779 if (wl_get_drv_status_all(cfg, FINDING_COMMON_CHANNEL)) {
780 WL_DBG(("ACTION FRAME SCAN DONE\n"));
781 wl_clr_p2p_status(cfg, SCANNING);
782 wl_clr_drv_status(cfg, SCANNING, cfg->afx_hdl->dev);
783 if (cfg->afx_hdl->peer_chan == WL_INVALID)
784 complete(&cfg->act_frm_scan);
785 } else if ((likely(cfg->scan_request)) || (cfg->sched_scan_running)) {
786 cfg->bss_list = wl_escan_get_buf(cfg, TRUE);
787 if (!scan_req_match(cfg)) {
788 WL_TRACE_HW4(("SCAN ABORTED(UNEXPECTED): "
789 "scanned AP count=%d\n",
790 cfg->bss_list->count));
791 }
792 wl_inform_bss(cfg);
793 wl_notify_escan_complete(cfg, ndev, true, false);
794 }
795 wl_escan_increment_sync_id(cfg, 2);
796 }
797 #else /* WL_DRV_AVOID_SCANCACHE */
798 err = wl_escan_without_scan_cache(cfg, escan_result, ndev, e, status);
799 #endif /* WL_DRV_AVOID_SCANCACHE */
800 exit:
801 mutex_unlock(&cfg->scan_sync);
802 return err;
803 }
804
805 /* Find listen channel */
wl_find_listen_channel(struct bcm_cfg80211 * cfg,const u8 * ie,u32 ie_len)806 static s32 wl_find_listen_channel(struct bcm_cfg80211 *cfg,
807 const u8 *ie, u32 ie_len)
808 {
809 const wifi_p2p_ie_t *p2p_ie;
810 const u8 *end, *pos;
811 s32 listen_channel;
812
813 pos = (const u8 *)ie;
814
815 p2p_ie = wl_cfgp2p_find_p2pie(pos, ie_len);
816
817 if (p2p_ie == NULL) {
818 return 0;
819 }
820
821 if (p2p_ie->len < MIN_P2P_IE_LEN || p2p_ie->len > MAX_P2P_IE_LEN) {
822 CFGP2P_ERR(("p2p_ie->len out of range - %d\n", p2p_ie->len));
823 return 0;
824 }
825 pos = p2p_ie->subelts;
826 end = p2p_ie->subelts + (p2p_ie->len - 4);
827
828 CFGP2P_DBG((" found p2p ie ! lenth %d \n",
829 p2p_ie->len));
830
831 while (pos < end) {
832 uint16 attr_len;
833 if (pos + 2 >= end) {
834 CFGP2P_DBG((" -- Invalid P2P attribute"));
835 return 0;
836 }
837 attr_len = ((uint16) (((pos + 1)[1] << 8) | (pos + 1)[0]));
838
839 if (pos + 3 + attr_len > end) {
840 CFGP2P_DBG(("P2P: Attribute underflow "
841 "(len=%u left=%d)",
842 attr_len, (int) (end - pos - 3)));
843 return 0;
844 }
845
846 /* if Listen Channel att id is 6 and the vailue is valid,
847 * return the listen channel
848 */
849 if (pos[0] == 6) {
850 /* listen channel subel length format
851 * 1(id) + 2(len) + 3(country) + 1(op. class) + 1(chan num)
852 */
853 listen_channel = pos[1 + 2 + 3 + 1];
854
855 if (listen_channel == SOCIAL_CHAN_1 ||
856 listen_channel == SOCIAL_CHAN_2 ||
857 listen_channel == SOCIAL_CHAN_3) {
858 CFGP2P_DBG((" Found my Listen Channel %d \n", listen_channel));
859 return listen_channel;
860 }
861 }
862 pos += 3 + attr_len;
863 }
864 return 0;
865 }
866
867 #ifdef WL_SCAN_TYPE
868 static u32
wl_cfgscan_map_nl80211_scan_type(struct bcm_cfg80211 * cfg,struct cfg80211_scan_request * request)869 wl_cfgscan_map_nl80211_scan_type(struct bcm_cfg80211 *cfg, struct cfg80211_scan_request *request)
870 {
871 u32 scan_flags = 0;
872
873 if (!request) {
874 return scan_flags;
875 }
876
877 if (request->flags & NL80211_SCAN_FLAG_LOW_SPAN) {
878 scan_flags |= WL_SCANFLAGS_LOW_SPAN;
879 }
880 if (request->flags & NL80211_SCAN_FLAG_HIGH_ACCURACY) {
881 scan_flags |= WL_SCANFLAGS_HIGH_ACCURACY;
882 }
883 if (request->flags & NL80211_SCAN_FLAG_LOW_POWER) {
884 scan_flags |= WL_SCANFLAGS_LOW_POWER_SCAN;
885 }
886 if (request->flags & NL80211_SCAN_FLAG_LOW_PRIORITY) {
887 scan_flags |= WL_SCANFLAGS_LOW_PRIO;
888 }
889
890 WL_INFORM(("scan flags. wl:%x cfg80211:%x\n", scan_flags, request->flags));
891 return scan_flags;
892 }
893 #endif /* WL_SCAN_TYPE */
894
895 #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 14, 0))
896 #define IS_RADAR_CHAN(flags) (flags & (IEEE80211_CHAN_RADAR | IEEE80211_CHAN_PASSIVE_SCAN))
897 #else
898 #define IS_RADAR_CHAN(flags) (flags & (IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IR))
899 #endif // endif
900 static void
wl_cfgscan_populate_scan_channels(struct bcm_cfg80211 * cfg,u16 * channel_list,struct cfg80211_scan_request * request,u32 * num_channels)901 wl_cfgscan_populate_scan_channels(struct bcm_cfg80211 *cfg, u16 *channel_list,
902 struct cfg80211_scan_request *request, u32 *num_channels)
903 {
904 u32 i = 0, j = 0;
905 u32 channel;
906 u32 n_channels = 0;
907 u32 chanspec = 0;
908
909 if (!request || !request->n_channels) {
910 /* Do full channel scan */
911 return;
912 }
913
914 n_channels = request->n_channels;
915 for (i = 0; i < n_channels; i++) {
916 channel = ieee80211_frequency_to_channel(request->channels[i]->center_freq);
917 /* SKIP DFS channels for Secondary interface */
918 if ((cfg->escan_info.ndev != bcmcfg_to_prmry_ndev(cfg)) &&
919 (IS_RADAR_CHAN(request->channels[i]->flags)))
920 continue;
921 if (!dhd_conf_match_channel(cfg->pub, channel))
922 continue;
923
924 chanspec = WL_CHANSPEC_BW_20;
925 if (chanspec == INVCHANSPEC) {
926 WL_ERR(("Invalid chanspec! Skipping channel\n"));
927 continue;
928 }
929
930 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0))
931 if (request->channels[i]->band == IEEE80211_BAND_60GHZ) {
932 /* Not supported */
933 continue;
934 }
935 #endif /* LINUX_VER >= 3.6 */
936
937 if (request->channels[i]->band == IEEE80211_BAND_2GHZ) {
938 #ifdef WL_HOST_BAND_MGMT
939 if (cfg->curr_band == WLC_BAND_5G) {
940 WL_DBG(("In 5G only mode, omit 2G channel:%d\n", channel));
941 continue;
942 }
943 #endif /* WL_HOST_BAND_MGMT */
944 chanspec |= WL_CHANSPEC_BAND_2G;
945 } else {
946 #ifdef WL_HOST_BAND_MGMT
947 if (cfg->curr_band == WLC_BAND_2G) {
948 WL_DBG(("In 2G only mode, omit 5G channel:%d\n", channel));
949 continue;
950 }
951 #endif /* WL_HOST_BAND_MGMT */
952 chanspec |= WL_CHANSPEC_BAND_5G;
953 }
954 channel_list[j] = channel;
955 channel_list[j] &= WL_CHANSPEC_CHAN_MASK;
956 channel_list[j] |= chanspec;
957 WL_SCAN(("Chan : %d, Channel spec: %x \n",
958 channel, channel_list[j]));
959 channel_list[j] = wl_chspec_host_to_driver(channel_list[j]);
960 j++;
961 }
962 *num_channels = j;
963
964 }
965
966 static void
wl_cfgscan_populate_scan_ssids(struct bcm_cfg80211 * cfg,u8 * buf_ptr,u32 buf_len,struct cfg80211_scan_request * request,u32 * ssid_num)967 wl_cfgscan_populate_scan_ssids(struct bcm_cfg80211 *cfg, u8 *buf_ptr, u32 buf_len,
968 struct cfg80211_scan_request *request, u32 *ssid_num)
969 {
970 u32 n_ssids;
971 wlc_ssid_t ssid;
972 int i, j = 0;
973
974 if (!request || !buf_ptr) {
975 /* Do full channel scan */
976 return;
977 }
978
979 n_ssids = request->n_ssids;
980 if (n_ssids > 0) {
981
982 if (buf_len < (n_ssids * sizeof(wlc_ssid_t))) {
983 WL_ERR(("buf len not sufficient for scan ssids\n"));
984 return;
985 }
986
987 for (i = 0; i < n_ssids; i++) {
988 bzero(&ssid, sizeof(wlc_ssid_t));
989 ssid.SSID_len = MIN(request->ssids[i].ssid_len, DOT11_MAX_SSID_LEN);
990 /* Returning void here, as per previous line copy length does not exceed
991 * DOT11_MAX_SSID_LEN
992 */
993 (void)memcpy_s(ssid.SSID, DOT11_MAX_SSID_LEN, request->ssids[i].ssid,
994 ssid.SSID_len);
995 if (!ssid.SSID_len) {
996 WL_SCAN(("%d: Broadcast scan\n", i));
997 } else {
998 WL_SCAN(("%d: scan for %s size =%d\n", i,
999 ssid.SSID, ssid.SSID_len));
1000 }
1001 /* For multiple ssid case copy the each SSID info the ptr below corresponds
1002 * to that so dest is of type wlc_ssid_t
1003 */
1004 (void)memcpy_s(buf_ptr, sizeof(wlc_ssid_t), &ssid, sizeof(wlc_ssid_t));
1005 buf_ptr += sizeof(wlc_ssid_t);
1006 j++;
1007 }
1008 } else {
1009 WL_SCAN(("Broadcast scan\n"));
1010 }
1011 *ssid_num = j;
1012 }
1013
1014 static s32
wl_scan_prep(struct bcm_cfg80211 * cfg,void * scan_params,u32 len,struct cfg80211_scan_request * request)1015 wl_scan_prep(struct bcm_cfg80211 *cfg, void *scan_params, u32 len,
1016 struct cfg80211_scan_request *request)
1017 {
1018 wl_scan_params_t *params = NULL;
1019 wl_scan_params_v2_t *params_v2 = NULL;
1020 u32 scan_type = 0;
1021 u32 scan_param_size = 0;
1022 u32 n_channels = 0;
1023 u32 n_ssids = 0;
1024 uint16 *chan_list = NULL;
1025 u32 channel_offset = 0;
1026 u32 cur_offset;
1027
1028 if (!scan_params) {
1029 return BCME_ERROR;
1030 }
1031
1032 if (cfg->active_scan == PASSIVE_SCAN) {
1033 WL_INFORM_MEM(("Enforcing passive scan\n"));
1034 scan_type = WL_SCANFLAGS_PASSIVE;
1035 }
1036
1037 WL_DBG(("Preparing Scan request\n"));
1038 if (cfg->scan_params_v2) {
1039 params_v2 = (wl_scan_params_v2_t *)scan_params;
1040 scan_param_size = sizeof(wl_scan_params_v2_t);
1041 channel_offset = offsetof(wl_scan_params_v2_t, channel_list);
1042 } else {
1043 params = (wl_scan_params_t *)scan_params;
1044 scan_param_size = sizeof(wl_scan_params_t);
1045 channel_offset = offsetof(wl_scan_params_t, channel_list);
1046 }
1047
1048 if (params_v2) {
1049 /* scan params ver2 */
1050 #if defined(WL_SCAN_TYPE)
1051 scan_type += wl_cfgscan_map_nl80211_scan_type(cfg, request);
1052 #endif /* WL_SCAN_TYPE */
1053
1054 (void)memcpy_s(¶ms_v2->bssid, ETHER_ADDR_LEN, ðer_bcast, ETHER_ADDR_LEN);
1055 params_v2->version = htod16(WL_SCAN_PARAMS_VERSION_V2);
1056 params_v2->length = htod16(sizeof(wl_scan_params_v2_t));
1057 params_v2->bss_type = DOT11_BSSTYPE_ANY;
1058 params_v2->scan_type = htod32(scan_type);
1059 params_v2->nprobes = htod32(-1);
1060 params_v2->active_time = htod32(-1);
1061 params_v2->passive_time = htod32(-1);
1062 params_v2->home_time = htod32(-1);
1063 params_v2->channel_num = 0;
1064 bzero(¶ms_v2->ssid, sizeof(wlc_ssid_t));
1065 chan_list = params_v2->channel_list;
1066 } else {
1067 /* scan params ver 1 */
1068 if (!params) {
1069 ASSERT(0);
1070 return BCME_ERROR;
1071 }
1072 (void)memcpy_s(¶ms->bssid, ETHER_ADDR_LEN, ðer_bcast, ETHER_ADDR_LEN);
1073 params->bss_type = DOT11_BSSTYPE_ANY;
1074 params->scan_type = 0;
1075 params->nprobes = htod32(-1);
1076 params->active_time = htod32(-1);
1077 params->passive_time = htod32(-1);
1078 params->home_time = htod32(-1);
1079 params->channel_num = 0;
1080 bzero(¶ms->ssid, sizeof(wlc_ssid_t));
1081 chan_list = params->channel_list;
1082 }
1083
1084 if (!request) {
1085 /* scan_request null, do scan based on base config */
1086 WL_DBG(("scan_request is null\n"));
1087 return BCME_OK;
1088 }
1089
1090 WL_INFORM(("n_channels:%d n_ssids:%d\n", request->n_channels, request->n_ssids));
1091
1092 cur_offset = channel_offset;
1093 /* Copy channel array if applicable */
1094 if ((request->n_channels > 0) && chan_list) {
1095 if (len >= (scan_param_size + (request->n_channels * sizeof(u16)))) {
1096 wl_cfgscan_populate_scan_channels(cfg,
1097 chan_list, request, &n_channels);
1098 cur_offset += (n_channels * (sizeof(u16)));
1099 }
1100 }
1101
1102 /* Copy ssid array if applicable */
1103 if (request->n_ssids > 0) {
1104 cur_offset = (u32) roundup(cur_offset, sizeof(u32));
1105 if (len > (cur_offset + (request->n_ssids * sizeof(wlc_ssid_t)))) {
1106 u32 rem_len = len - cur_offset;
1107 wl_cfgscan_populate_scan_ssids(cfg,
1108 ((u8 *)scan_params + cur_offset), rem_len, request, &n_ssids);
1109 }
1110 }
1111
1112 if (n_ssids || n_channels) {
1113 u32 channel_num =
1114 htod32((n_ssids << WL_SCAN_PARAMS_NSSID_SHIFT) |
1115 (n_channels & WL_SCAN_PARAMS_COUNT_MASK));
1116 if (params_v2) {
1117 params_v2->channel_num = channel_num;
1118 if (n_channels == 1) {
1119 params_v2->active_time = htod32(WL_SCAN_CONNECT_DWELL_TIME_MS);
1120 params_v2->nprobes = htod32(
1121 params_v2->active_time / WL_SCAN_JOIN_PROBE_INTERVAL_MS);
1122 }
1123 } else {
1124 params->channel_num = channel_num;
1125 if (n_channels == 1) {
1126 params->active_time = htod32(WL_SCAN_CONNECT_DWELL_TIME_MS);
1127 params->nprobes = htod32(
1128 params->active_time / WL_SCAN_JOIN_PROBE_INTERVAL_MS);
1129 }
1130 }
1131 }
1132
1133 WL_INFORM(("scan_prep done. n_channels:%d n_ssids:%d\n", n_channels, n_ssids));
1134 return BCME_OK;
1135 }
1136
1137 static s32
wl_get_valid_channels(struct net_device * ndev,u8 * valid_chan_list,s32 size)1138 wl_get_valid_channels(struct net_device *ndev, u8 *valid_chan_list, s32 size)
1139 {
1140 wl_uint32_list_t *list;
1141 s32 err = BCME_OK;
1142 if (valid_chan_list == NULL || size <= 0)
1143 return -ENOMEM;
1144
1145 bzero(valid_chan_list, size);
1146 list = (wl_uint32_list_t *)(void *) valid_chan_list;
1147 list->count = htod32(WL_NUMCHANNELS);
1148 err = wldev_ioctl_get(ndev, WLC_GET_VALID_CHANNELS, valid_chan_list, size);
1149 if (err != 0) {
1150 WL_ERR(("get channels failed with %d\n", err));
1151 }
1152
1153 return err;
1154 }
1155
1156 static s32
wl_run_escan(struct bcm_cfg80211 * cfg,struct net_device * ndev,struct cfg80211_scan_request * request,uint16 action)1157 wl_run_escan(struct bcm_cfg80211 *cfg, struct net_device *ndev,
1158 struct cfg80211_scan_request *request, uint16 action)
1159 {
1160 s32 err = BCME_OK;
1161 u32 n_channels;
1162 u32 n_ssids;
1163 s32 params_size;
1164 wl_escan_params_t *eparams = NULL;
1165 wl_escan_params_v2_t *eparams_v2 = NULL;
1166 u8 *scan_params = NULL;
1167 u8 *params = NULL;
1168 u8 chan_buf[sizeof(u32)*(WL_NUMCHANNELS + 1)];
1169 u32 num_chans = 0;
1170 s32 channel;
1171 u32 n_valid_chan;
1172 s32 search_state = WL_P2P_DISC_ST_SCAN;
1173 u32 i, j, n_nodfs = 0;
1174 u16 *default_chan_list = NULL;
1175 wl_uint32_list_t *list;
1176 s32 bssidx = -1;
1177 struct net_device *dev = NULL;
1178 #if defined(USE_INITIAL_2G_SCAN) || defined(USE_INITIAL_SHORT_DWELL_TIME)
1179 bool is_first_init_2g_scan = false;
1180 #endif /* USE_INITIAL_2G_SCAN || USE_INITIAL_SHORT_DWELL_TIME */
1181 p2p_scan_purpose_t p2p_scan_purpose = P2P_SCAN_PURPOSE_MIN;
1182 u32 chan_mem = 0;
1183 u32 sync_id = 0;
1184
1185 WL_DBG(("Enter \n"));
1186
1187 /* scan request can come with empty request : perform all default scan */
1188 if (!cfg) {
1189 err = -EINVAL;
1190 goto exit;
1191 }
1192
1193 if (cfg->scan_params_v2) {
1194 params_size = (WL_SCAN_PARAMS_V2_FIXED_SIZE +
1195 OFFSETOF(wl_escan_params_v2_t, params));
1196 } else {
1197 params_size = (WL_SCAN_PARAMS_FIXED_SIZE + OFFSETOF(wl_escan_params_t, params));
1198 }
1199
1200 if (!cfg->p2p_supported || !p2p_scan(cfg)) {
1201 /* LEGACY SCAN TRIGGER */
1202 WL_SCAN((" LEGACY E-SCAN START\n"));
1203
1204 #if defined(USE_INITIAL_2G_SCAN) || defined(USE_INITIAL_SHORT_DWELL_TIME)
1205 if (!request) {
1206 err = -EINVAL;
1207 goto exit;
1208 }
1209 if (ndev == bcmcfg_to_prmry_ndev(cfg) && g_first_broadcast_scan == true) {
1210 #ifdef USE_INITIAL_2G_SCAN
1211 struct ieee80211_channel tmp_channel_list[CH_MAX_2G_CHANNEL];
1212 /* allow one 5G channel to add previous connected channel in 5G */
1213 bool allow_one_5g_channel = TRUE;
1214 j = 0;
1215 for (i = 0; i < request->n_channels; i++) {
1216 int tmp_chan = ieee80211_frequency_to_channel
1217 (request->channels[i]->center_freq);
1218 if (tmp_chan > CH_MAX_2G_CHANNEL) {
1219 if (allow_one_5g_channel)
1220 allow_one_5g_channel = FALSE;
1221 else
1222 continue;
1223 }
1224 if (j > CH_MAX_2G_CHANNEL) {
1225 WL_ERR(("Index %d exceeds max 2.4GHz channels %d"
1226 " and previous 5G connected channel\n",
1227 j, CH_MAX_2G_CHANNEL));
1228 break;
1229 }
1230 bcopy(request->channels[i], &tmp_channel_list[j],
1231 sizeof(struct ieee80211_channel));
1232 WL_SCAN(("channel of request->channels[%d]=%d\n", i, tmp_chan));
1233 j++;
1234 }
1235 if ((j > 0) && (j <= CH_MAX_2G_CHANNEL)) {
1236 for (i = 0; i < j; i++)
1237 bcopy(&tmp_channel_list[i], request->channels[i],
1238 sizeof(struct ieee80211_channel));
1239
1240 request->n_channels = j;
1241 is_first_init_2g_scan = true;
1242 }
1243 else
1244 WL_ERR(("Invalid number of 2.4GHz channels %d\n", j));
1245
1246 WL_SCAN(("request->n_channels=%d\n", request->n_channels));
1247 #else /* USE_INITIAL_SHORT_DWELL_TIME */
1248 is_first_init_2g_scan = true;
1249 #endif /* USE_INITIAL_2G_SCAN */
1250 g_first_broadcast_scan = false;
1251 }
1252 #endif /* USE_INITIAL_2G_SCAN || USE_INITIAL_SHORT_DWELL_TIME */
1253
1254 /* if scan request is not empty parse scan request paramters */
1255 if (request != NULL) {
1256 n_channels = request->n_channels;
1257 n_ssids = request->n_ssids;
1258 if (n_channels % 2)
1259 /* If n_channels is odd, add a padd of u16 */
1260 params_size += sizeof(u16) * (n_channels + 1);
1261 else
1262 params_size += sizeof(u16) * n_channels;
1263
1264 /* Allocate space for populating ssids in wl_escan_params_t struct */
1265 params_size += sizeof(struct wlc_ssid) * n_ssids;
1266 }
1267 params = MALLOCZ(cfg->osh, params_size);
1268 if (params == NULL) {
1269 err = -ENOMEM;
1270 goto exit;
1271 }
1272
1273 wl_escan_set_sync_id(sync_id, cfg);
1274 if (cfg->scan_params_v2) {
1275 eparams_v2 = (wl_escan_params_v2_t *)params;
1276 scan_params = (u8 *)&eparams_v2->params;
1277 eparams_v2->version = htod32(ESCAN_REQ_VERSION_V2);
1278 eparams_v2->action = htod16(action);
1279 eparams_v2->sync_id = sync_id;
1280 } else {
1281 eparams = (wl_escan_params_t *)params;
1282 scan_params = (u8 *)&eparams->params;
1283 eparams->version = htod32(ESCAN_REQ_VERSION);
1284 eparams->action = htod16(action);
1285 eparams->sync_id = sync_id;
1286 }
1287
1288 if (wl_scan_prep(cfg, scan_params, params_size, request) < 0) {
1289 WL_ERR(("scan_prep failed\n"));
1290 err = -EINVAL;
1291 goto exit;
1292 }
1293
1294 #if defined(USE_INITIAL_2G_SCAN) || defined(USE_INITIAL_SHORT_DWELL_TIME)
1295 /* Override active_time to reduce scan time if it's first bradcast scan. */
1296 if (is_first_init_2g_scan) {
1297 if (eparams_v2) {
1298 eparams_v2->params.active_time = FIRST_SCAN_ACTIVE_DWELL_TIME_MS;
1299 } else {
1300 eparams->params.active_time = FIRST_SCAN_ACTIVE_DWELL_TIME_MS;
1301 }
1302 }
1303 #endif /* USE_INITIAL_2G_SCAN || USE_INITIAL_SHORT_DWELL_TIME */
1304
1305 wl_escan_set_type(cfg, WL_SCANTYPE_LEGACY);
1306 if (params_size + sizeof("escan") >= WLC_IOCTL_MEDLEN) {
1307 WL_ERR(("ioctl buffer length not sufficient\n"));
1308 MFREE(cfg->osh, params, params_size);
1309 err = -ENOMEM;
1310 goto exit;
1311 }
1312
1313 bssidx = wl_get_bssidx_by_wdev(cfg, ndev->ieee80211_ptr);
1314 WL_MSG(ndev->name, "LEGACY_SCAN sync ID: %d, bssidx: %d\n", sync_id, bssidx);
1315 err = wldev_iovar_setbuf(ndev, "escan", params, params_size,
1316 cfg->escan_ioctl_buf, WLC_IOCTL_MEDLEN, NULL);
1317 if (unlikely(err)) {
1318 if (err == BCME_EPERM)
1319 /* Scan Not permitted at this point of time */
1320 WL_DBG((" Escan not permitted at this time (%d)\n", err));
1321 else
1322 WL_ERR((" Escan set error (%d)\n", err));
1323 } else {
1324 DBG_EVENT_LOG((dhd_pub_t *)cfg->pub, WIFI_EVENT_DRIVER_SCAN_REQUESTED);
1325 }
1326 MFREE(cfg->osh, params, params_size);
1327 }
1328 else if (p2p_is_on(cfg) && p2p_scan(cfg)) {
1329 /* P2P SCAN TRIGGER */
1330 s32 _freq = 0;
1331 n_nodfs = 0;
1332
1333 if (request && request->n_channels) {
1334 num_chans = request->n_channels;
1335 WL_SCAN((" chann number : %d\n", num_chans));
1336 chan_mem = (u32)(num_chans * sizeof(*default_chan_list));
1337 default_chan_list = MALLOCZ(cfg->osh, chan_mem);
1338 if (default_chan_list == NULL) {
1339 WL_ERR(("channel list allocation failed \n"));
1340 err = -ENOMEM;
1341 goto exit;
1342 }
1343 if (!wl_get_valid_channels(ndev, chan_buf, sizeof(chan_buf))) {
1344 #ifdef P2P_SKIP_DFS
1345 int is_printed = false;
1346 #endif /* P2P_SKIP_DFS */
1347 list = (wl_uint32_list_t *) chan_buf;
1348 n_valid_chan = dtoh32(list->count);
1349 if (n_valid_chan > WL_NUMCHANNELS) {
1350 WL_ERR(("wrong n_valid_chan:%d\n", n_valid_chan));
1351 MFREE(cfg->osh, default_chan_list, chan_mem);
1352 err = -EINVAL;
1353 goto exit;
1354 }
1355
1356 for (i = 0; i < num_chans; i++)
1357 {
1358 #ifdef WL_HOST_BAND_MGMT
1359 int channel_band = 0;
1360 #endif /* WL_HOST_BAND_MGMT */
1361 _freq = request->channels[i]->center_freq;
1362 channel = ieee80211_frequency_to_channel(_freq);
1363 #ifdef WL_HOST_BAND_MGMT
1364 channel_band = (channel > CH_MAX_2G_CHANNEL) ?
1365 WLC_BAND_5G : WLC_BAND_2G;
1366 if ((cfg->curr_band != WLC_BAND_AUTO) &&
1367 (cfg->curr_band != channel_band) &&
1368 !IS_P2P_SOCIAL_CHANNEL(channel))
1369 continue;
1370 #endif /* WL_HOST_BAND_MGMT */
1371
1372 /* ignore DFS channels */
1373 if (request->channels[i]->flags &
1374 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0))
1375 (IEEE80211_CHAN_NO_IR
1376 | IEEE80211_CHAN_RADAR))
1377 #else
1378 (IEEE80211_CHAN_RADAR
1379 | IEEE80211_CHAN_PASSIVE_SCAN))
1380 #endif // endif
1381 continue;
1382 #ifdef P2P_SKIP_DFS
1383 if (channel >= 52 && channel <= 144) {
1384 if (is_printed == false) {
1385 WL_ERR(("SKIP DFS CHANs(52~144)\n"));
1386 is_printed = true;
1387 }
1388 continue;
1389 }
1390 #endif /* P2P_SKIP_DFS */
1391
1392 for (j = 0; j < n_valid_chan; j++) {
1393 /* allows only supported channel on
1394 * current reguatory
1395 */
1396 if (n_nodfs >= num_chans) {
1397 break;
1398 }
1399 if (channel == (dtoh32(list->element[j]))) {
1400 default_chan_list[n_nodfs++] =
1401 channel;
1402 }
1403 }
1404
1405 }
1406 }
1407 if (num_chans == SOCIAL_CHAN_CNT && (
1408 (default_chan_list[0] == SOCIAL_CHAN_1) &&
1409 (default_chan_list[1] == SOCIAL_CHAN_2) &&
1410 (default_chan_list[2] == SOCIAL_CHAN_3))) {
1411 /* SOCIAL CHANNELS 1, 6, 11 */
1412 search_state = WL_P2P_DISC_ST_SEARCH;
1413 p2p_scan_purpose = P2P_SCAN_SOCIAL_CHANNEL;
1414 WL_DBG(("P2P SEARCH PHASE START \n"));
1415 } else if (((dev = wl_to_p2p_bss_ndev(cfg, P2PAPI_BSSCFG_CONNECTION1)) &&
1416 (wl_get_mode_by_netdev(cfg, dev) == WL_MODE_AP)) ||
1417 ((dev = wl_to_p2p_bss_ndev(cfg, P2PAPI_BSSCFG_CONNECTION2)) &&
1418 (wl_get_mode_by_netdev(cfg, dev) == WL_MODE_AP))) {
1419 /* If you are already a GO, then do SEARCH only */
1420 WL_DBG(("Already a GO. Do SEARCH Only"));
1421 search_state = WL_P2P_DISC_ST_SEARCH;
1422 num_chans = n_nodfs;
1423 p2p_scan_purpose = P2P_SCAN_NORMAL;
1424
1425 } else if (num_chans == 1) {
1426 p2p_scan_purpose = P2P_SCAN_CONNECT_TRY;
1427 WL_INFORM_MEM(("Trigger p2p join scan\n"));
1428 } else if (num_chans == SOCIAL_CHAN_CNT + 1) {
1429 /* SOCIAL_CHAN_CNT + 1 takes care of the Progressive scan supported by
1430 * the supplicant
1431 */
1432 p2p_scan_purpose = P2P_SCAN_SOCIAL_CHANNEL;
1433 } else {
1434 WL_DBG(("P2P SCAN STATE START \n"));
1435 num_chans = n_nodfs;
1436 p2p_scan_purpose = P2P_SCAN_NORMAL;
1437 }
1438 } else {
1439 err = -EINVAL;
1440 goto exit;
1441 }
1442 err = wl_cfgp2p_escan(cfg, ndev, ACTIVE_SCAN, num_chans, default_chan_list,
1443 search_state, action,
1444 wl_to_p2p_bss_bssidx(cfg, P2PAPI_BSSCFG_DEVICE), NULL,
1445 p2p_scan_purpose);
1446
1447 if (!err)
1448 cfg->p2p->search_state = search_state;
1449
1450 MFREE(cfg->osh, default_chan_list, chan_mem);
1451 }
1452 exit:
1453 if (unlikely(err)) {
1454 /* Don't print Error incase of Scan suppress */
1455 if ((err == BCME_EPERM) && cfg->scan_suppressed)
1456 WL_DBG(("Escan failed: Scan Suppressed \n"));
1457 else
1458 WL_ERR(("scan error (%d)\n", err));
1459 }
1460 return err;
1461 }
1462
1463 s32
wl_do_escan(struct bcm_cfg80211 * cfg,struct wiphy * wiphy,struct net_device * ndev,struct cfg80211_scan_request * request)1464 wl_do_escan(struct bcm_cfg80211 *cfg, struct wiphy *wiphy, struct net_device *ndev,
1465 struct cfg80211_scan_request *request)
1466 {
1467 s32 err = BCME_OK;
1468 s32 passive_scan;
1469 s32 passive_scan_time;
1470 s32 passive_scan_time_org;
1471 wl_scan_results_t *results;
1472 WL_SCAN(("Enter \n"));
1473
1474 results = wl_escan_get_buf(cfg, FALSE);
1475 results->version = 0;
1476 results->count = 0;
1477 results->buflen = WL_SCAN_RESULTS_FIXED_SIZE;
1478
1479 cfg->escan_info.ndev = ndev;
1480 cfg->escan_info.wiphy = wiphy;
1481 cfg->escan_info.escan_state = WL_ESCAN_STATE_SCANING;
1482 passive_scan = cfg->active_scan ? 0 : 1;
1483 err = wldev_ioctl_set(ndev, WLC_SET_PASSIVE_SCAN,
1484 &passive_scan, sizeof(passive_scan));
1485 if (unlikely(err)) {
1486 WL_ERR(("error (%d)\n", err));
1487 goto exit;
1488 }
1489
1490 if (passive_channel_skip) {
1491
1492 err = wldev_ioctl_get(ndev, WLC_GET_SCAN_PASSIVE_TIME,
1493 &passive_scan_time_org, sizeof(passive_scan_time_org));
1494 if (unlikely(err)) {
1495 WL_ERR(("== error (%d)\n", err));
1496 goto exit;
1497 }
1498
1499 WL_SCAN(("PASSIVE SCAN time : %d \n", passive_scan_time_org));
1500
1501 passive_scan_time = 0;
1502 err = wldev_ioctl_set(ndev, WLC_SET_SCAN_PASSIVE_TIME,
1503 &passive_scan_time, sizeof(passive_scan_time));
1504 if (unlikely(err)) {
1505 WL_ERR(("== error (%d)\n", err));
1506 goto exit;
1507 }
1508
1509 WL_SCAN(("PASSIVE SCAN SKIPED!! (passive_channel_skip:%d) \n",
1510 passive_channel_skip));
1511 }
1512
1513 err = wl_run_escan(cfg, ndev, request, WL_SCAN_ACTION_START);
1514
1515 if (passive_channel_skip) {
1516 err = wldev_ioctl_set(ndev, WLC_SET_SCAN_PASSIVE_TIME,
1517 &passive_scan_time_org, sizeof(passive_scan_time_org));
1518 if (unlikely(err)) {
1519 WL_ERR(("== error (%d)\n", err));
1520 goto exit;
1521 }
1522
1523 WL_SCAN(("PASSIVE SCAN RECOVERED!! (passive_scan_time_org:%d) \n",
1524 passive_scan_time_org));
1525 }
1526
1527 exit:
1528 return err;
1529 }
1530
1531 static s32
wl_get_scan_timeout_val(struct bcm_cfg80211 * cfg)1532 wl_get_scan_timeout_val(struct bcm_cfg80211 *cfg)
1533 {
1534 u32 scan_timer_interval_ms = WL_SCAN_TIMER_INTERVAL_MS;
1535
1536 /* If NAN is enabled adding +10 sec to the existing timeout value */
1537 #ifdef WL_NAN
1538 if (cfg->nan_enable) {
1539 scan_timer_interval_ms += WL_SCAN_TIMER_INTERVAL_MS_NAN;
1540 }
1541 #endif /* WL_NAN */
1542 WL_MEM(("scan_timer_interval_ms %d\n", scan_timer_interval_ms));
1543 return scan_timer_interval_ms;
1544 }
1545
1546 #define SCAN_EBUSY_RETRY_LIMIT 20
1547 static s32
wl_cfgscan_handle_scanbusy(struct bcm_cfg80211 * cfg,struct net_device * ndev,s32 err)1548 wl_cfgscan_handle_scanbusy(struct bcm_cfg80211 *cfg, struct net_device *ndev, s32 err)
1549 {
1550 s32 scanbusy_err = 0;
1551 static u32 busy_count = 0;
1552
1553 if (!err) {
1554 busy_count = 0;
1555 return scanbusy_err;
1556 }
1557 if (err == BCME_BUSY || err == BCME_NOTREADY) {
1558 WL_ERR(("Scan err = (%d), busy?%d", err, -EBUSY));
1559 scanbusy_err = -EBUSY;
1560 } else if ((err == BCME_EPERM) && cfg->scan_suppressed) {
1561 WL_ERR(("Scan not permitted due to scan suppress\n"));
1562 scanbusy_err = -EPERM;
1563 } else {
1564 /* For all other fw errors, use a generic error code as return
1565 * value to cfg80211 stack
1566 */
1567 scanbusy_err = -EAGAIN;
1568 }
1569
1570 if (scanbusy_err == -EBUSY) {
1571 /* Flush FW preserve buffer logs for checking failure */
1572 if (busy_count++ > (SCAN_EBUSY_RETRY_LIMIT/5)) {
1573 wl_flush_fw_log_buffer(ndev, FW_LOGSET_MASK_ALL);
1574 }
1575 if (busy_count > SCAN_EBUSY_RETRY_LIMIT) {
1576 struct ether_addr bssid;
1577 s32 ret = 0;
1578 dhd_pub_t *dhdp = (dhd_pub_t *)(cfg->pub);
1579 if (dhd_query_bus_erros(dhdp)) {
1580 return BCME_NOTREADY;
1581 }
1582 dhdp->scan_busy_occurred = TRUE;
1583 busy_count = 0;
1584 WL_ERR(("Unusual continuous EBUSY error, %d %d %d %d %d %d %d %d %d\n",
1585 wl_get_drv_status(cfg, SCANNING, ndev),
1586 wl_get_drv_status(cfg, SCAN_ABORTING, ndev),
1587 wl_get_drv_status(cfg, CONNECTING, ndev),
1588 wl_get_drv_status(cfg, CONNECTED, ndev),
1589 wl_get_drv_status(cfg, DISCONNECTING, ndev),
1590 wl_get_drv_status(cfg, AP_CREATING, ndev),
1591 wl_get_drv_status(cfg, AP_CREATED, ndev),
1592 wl_get_drv_status(cfg, SENDING_ACT_FRM, ndev),
1593 wl_get_drv_status(cfg, SENDING_ACT_FRM, ndev)));
1594
1595 #if defined(DHD_DEBUG) && defined(DHD_FW_COREDUMP)
1596 if (dhdp->memdump_enabled) {
1597 dhdp->memdump_type = DUMP_TYPE_SCAN_BUSY;
1598 dhd_bus_mem_dump(dhdp);
1599 }
1600 #endif /* DHD_DEBUG && DHD_FW_COREDUMP */
1601 dhdp->hang_reason = HANG_REASON_SCAN_BUSY;
1602 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27))
1603 dhd_os_send_hang_message(dhdp);
1604 #else
1605 WL_ERR(("%s: HANG event is unsupported\n", __FUNCTION__));
1606 #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27) && OEM_ANDROID */
1607
1608 bzero(&bssid, sizeof(bssid));
1609 if ((ret = wldev_ioctl_get(ndev, WLC_GET_BSSID,
1610 &bssid, ETHER_ADDR_LEN)) == 0) {
1611 WL_ERR(("FW is connected with " MACDBG "/n",
1612 MAC2STRDBG(bssid.octet)));
1613 } else {
1614 WL_ERR(("GET BSSID failed with %d\n", ret));
1615 }
1616
1617 wl_cfg80211_scan_abort(cfg);
1618
1619 } else {
1620 /* Hold the context for 400msec, so that 10 subsequent scans
1621 * can give a buffer of 4sec which is enough to
1622 * cover any on-going scan in the firmware
1623 */
1624 WL_DBG(("Enforcing delay for EBUSY case \n"));
1625 msleep(400);
1626 }
1627 } else {
1628 busy_count = 0;
1629 }
1630
1631 return scanbusy_err;
1632 }
1633
1634 s32
__wl_cfg80211_scan(struct wiphy * wiphy,struct net_device * ndev,struct cfg80211_scan_request * request,struct cfg80211_ssid * this_ssid)1635 __wl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev,
1636 struct cfg80211_scan_request *request,
1637 struct cfg80211_ssid *this_ssid)
1638 {
1639 struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
1640 struct cfg80211_ssid *ssids;
1641 struct ether_addr primary_mac;
1642 bool p2p_ssid;
1643 #ifdef WL11U
1644 bcm_tlv_t *interworking_ie;
1645 #endif // endif
1646 s32 err = 0;
1647 s32 bssidx = -1;
1648 s32 i;
1649 bool escan_req_failed = false;
1650 s32 scanbusy_err = 0;
1651
1652 unsigned long flags;
1653 #ifdef WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST
1654 struct net_device *remain_on_channel_ndev = NULL;
1655 #endif // endif
1656 /*
1657 * Hostapd triggers scan before starting automatic channel selection
1658 * to collect channel characteristics. However firmware scan engine
1659 * doesn't support any channel characteristics collection along with
1660 * scan. Hence return scan success.
1661 */
1662 if (request && (scan_req_iftype(request) == NL80211_IFTYPE_AP)) {
1663 WL_DBG(("Scan Command on SoftAP Interface. Ignoring...\n"));
1664 // terence 20161023: let it scan in SoftAP mode
1665 // return 0;
1666 }
1667
1668 ndev = ndev_to_wlc_ndev(ndev, cfg);
1669
1670 if (WL_DRV_STATUS_SENDING_AF_FRM_EXT(cfg)) {
1671 WL_ERR(("Sending Action Frames. Try it again.\n"));
1672 return -EAGAIN;
1673 }
1674
1675 WL_DBG(("Enter wiphy (%p)\n", wiphy));
1676 if (wl_get_drv_status_all(cfg, SCANNING)) {
1677 if (cfg->scan_request == NULL) {
1678 wl_clr_drv_status_all(cfg, SCANNING);
1679 WL_DBG(("<<<<<<<<<<<Force Clear Scanning Status>>>>>>>>>>>\n"));
1680 } else {
1681 WL_ERR(("Scanning already\n"));
1682 return -EAGAIN;
1683 }
1684 }
1685 if (wl_get_drv_status(cfg, SCAN_ABORTING, ndev)) {
1686 WL_ERR(("Scanning being aborted\n"));
1687 return -EAGAIN;
1688 }
1689 if (request && request->n_ssids > WL_SCAN_PARAMS_SSID_MAX) {
1690 WL_ERR(("request null or n_ssids > WL_SCAN_PARAMS_SSID_MAX\n"));
1691 return -EOPNOTSUPP;
1692 }
1693 #ifdef WL_BCNRECV
1694 /* check fakeapscan in progress then abort */
1695 wl_android_bcnrecv_stop(ndev, WL_BCNRECV_SCANBUSY);
1696 #endif /* WL_BCNRECV */
1697
1698 #ifdef WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST
1699 mutex_lock(&cfg->scan_sync);
1700 remain_on_channel_ndev = wl_cfg80211_get_remain_on_channel_ndev(cfg);
1701 if (remain_on_channel_ndev) {
1702 WL_DBG(("Remain_on_channel bit is set, somehow it didn't get cleared\n"));
1703 wl_notify_escan_complete(cfg, remain_on_channel_ndev, true, true);
1704 }
1705 mutex_unlock(&cfg->scan_sync);
1706 #endif /* WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST */
1707
1708 #ifdef P2P_LISTEN_OFFLOADING
1709 wl_cfg80211_cancel_p2plo(cfg);
1710 #endif /* P2P_LISTEN_OFFLOADING */
1711
1712 if (request) { /* scan bss */
1713 ssids = request->ssids;
1714 p2p_ssid = false;
1715 for (i = 0; i < request->n_ssids; i++) {
1716 if (ssids[i].ssid_len &&
1717 IS_P2P_SSID(ssids[i].ssid, ssids[i].ssid_len)) {
1718 /* P2P Scan */
1719 #ifdef WL_BLOCK_P2P_SCAN_ON_STA
1720 if (!(IS_P2P_IFACE(request->wdev))) {
1721 /* P2P scan on non-p2p iface. Fail scan */
1722 WL_ERR(("p2p_search on non p2p iface\n"));
1723 goto scan_out;
1724 }
1725 #endif /* WL_BLOCK_P2P_SCAN_ON_STA */
1726 p2p_ssid = true;
1727 break;
1728 }
1729 }
1730 if (p2p_ssid) {
1731 if (cfg->p2p_supported) {
1732 /* p2p scan trigger */
1733 if (p2p_on(cfg) == false) {
1734 /* p2p on at the first time */
1735 p2p_on(cfg) = true;
1736 wl_cfgp2p_set_firm_p2p(cfg);
1737 get_primary_mac(cfg, &primary_mac);
1738 #ifndef WL_P2P_USE_RANDMAC
1739 wl_cfgp2p_generate_bss_mac(cfg, &primary_mac);
1740 #endif /* WL_P2P_USE_RANDMAC */
1741 #if defined(P2P_IE_MISSING_FIX)
1742 cfg->p2p_prb_noti = false;
1743 #endif // endif
1744 }
1745 wl_clr_p2p_status(cfg, GO_NEG_PHASE);
1746 WL_DBG(("P2P: GO_NEG_PHASE status cleared \n"));
1747 p2p_scan(cfg) = true;
1748 }
1749 } else {
1750 /* legacy scan trigger
1751 * So, we have to disable p2p discovery if p2p discovery is on
1752 */
1753 if (cfg->p2p_supported) {
1754 p2p_scan(cfg) = false;
1755 /* If Netdevice is not equals to primary and p2p is on
1756 * , we will do p2p scan using P2PAPI_BSSCFG_DEVICE.
1757 */
1758
1759 if (p2p_scan(cfg) == false) {
1760 if (wl_get_p2p_status(cfg, DISCOVERY_ON)) {
1761 err = wl_cfgp2p_discover_enable_search(cfg,
1762 false);
1763 if (unlikely(err)) {
1764 goto scan_out;
1765 }
1766
1767 }
1768 }
1769 }
1770 if (!cfg->p2p_supported || !p2p_scan(cfg)) {
1771 if ((bssidx = wl_get_bssidx_by_wdev(cfg,
1772 ndev->ieee80211_ptr)) < 0) {
1773 WL_ERR(("Find p2p index from ndev(%p) failed\n",
1774 ndev));
1775 err = BCME_ERROR;
1776 goto scan_out;
1777 }
1778 #ifdef WL11U
1779 if (request && (interworking_ie = wl_cfg80211_find_interworking_ie(
1780 request->ie, request->ie_len)) != NULL) {
1781 if ((err = wl_cfg80211_add_iw_ie(cfg, ndev, bssidx,
1782 VNDR_IE_CUSTOM_FLAG, interworking_ie->id,
1783 interworking_ie->data,
1784 interworking_ie->len)) != BCME_OK) {
1785 WL_ERR(("Failed to add interworking IE"));
1786 }
1787 } else if (cfg->wl11u) {
1788 /* we have to clear IW IE and disable gratuitous APR */
1789 wl_cfg80211_clear_iw_ie(cfg, ndev, bssidx);
1790 err = wldev_iovar_setint_bsscfg(ndev, "grat_arp",
1791 0, bssidx);
1792 /* we don't care about error here
1793 * because the only failure case is unsupported,
1794 * which is fine
1795 */
1796 if (unlikely(err)) {
1797 WL_ERR(("Set grat_arp failed:(%d) Ignore!\n", err));
1798 }
1799 cfg->wl11u = FALSE;
1800 }
1801 #endif /* WL11U */
1802 if (request) {
1803 err = wl_cfg80211_set_mgmt_vndr_ies(cfg,
1804 ndev_to_cfgdev(ndev), bssidx, VNDR_IE_PRBREQ_FLAG,
1805 request->ie, request->ie_len);
1806 }
1807
1808 if (unlikely(err)) {
1809 // terence 20161023: let it scan in SoftAP mode
1810 // goto scan_out;
1811 }
1812
1813 }
1814 }
1815 } else { /* scan in ibss */
1816 ssids = this_ssid;
1817 }
1818
1819 if (request && cfg->p2p_supported) {
1820 WL_TRACE_HW4(("START SCAN\n"));
1821 DHD_OS_SCAN_WAKE_LOCK_TIMEOUT((dhd_pub_t *)(cfg->pub),
1822 SCAN_WAKE_LOCK_TIMEOUT);
1823 DHD_DISABLE_RUNTIME_PM((dhd_pub_t *)(cfg->pub));
1824 }
1825
1826 if (cfg->p2p_supported) {
1827 if (request && p2p_on(cfg) && p2p_scan(cfg)) {
1828
1829 /* find my listen channel */
1830 cfg->afx_hdl->my_listen_chan =
1831 wl_find_listen_channel(cfg, request->ie,
1832 request->ie_len);
1833 err = wl_cfgp2p_enable_discovery(cfg, ndev,
1834 request->ie, request->ie_len);
1835
1836 if (unlikely(err)) {
1837 goto scan_out;
1838 }
1839 }
1840 }
1841
1842 mutex_lock(&cfg->scan_sync);
1843 err = wl_do_escan(cfg, wiphy, ndev, request);
1844 if (likely(!err)) {
1845 goto scan_success;
1846 } else {
1847 escan_req_failed = true;
1848 goto scan_out;
1849 }
1850
1851 scan_success:
1852 wl_cfgscan_handle_scanbusy(cfg, ndev, BCME_OK);
1853 cfg->scan_request = request;
1854 wl_set_drv_status(cfg, SCANNING, ndev);
1855 /* Arm the timer */
1856 mod_timer(&cfg->scan_timeout,
1857 jiffies + msecs_to_jiffies(wl_get_scan_timeout_val(cfg)));
1858 mutex_unlock(&cfg->scan_sync);
1859 return 0;
1860
1861 scan_out:
1862 if (escan_req_failed) {
1863 WL_CFG_DRV_LOCK(&cfg->cfgdrv_lock, flags);
1864 cfg->scan_request = NULL;
1865 WL_CFG_DRV_UNLOCK(&cfg->cfgdrv_lock, flags);
1866 mutex_unlock(&cfg->scan_sync);
1867 /* Handling for scan busy errors */
1868 scanbusy_err = wl_cfgscan_handle_scanbusy(cfg, ndev, err);
1869 if (scanbusy_err == BCME_NOTREADY) {
1870 /* In case of bus failures avoid ioctl calls */
1871 DHD_OS_SCAN_WAKE_UNLOCK((dhd_pub_t *)(cfg->pub));
1872 return -ENODEV;
1873 }
1874 err = scanbusy_err;
1875 }
1876
1877 DHD_OS_SCAN_WAKE_UNLOCK((dhd_pub_t *)(cfg->pub));
1878 return err;
1879 }
1880
1881 s32
1882 #if defined(WL_CFG80211_P2P_DEV_IF)
wl_cfg80211_scan(struct wiphy * wiphy,struct cfg80211_scan_request * request)1883 wl_cfg80211_scan(struct wiphy *wiphy, struct cfg80211_scan_request *request)
1884 #else
1885 wl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev,
1886 struct cfg80211_scan_request *request)
1887 #endif /* WL_CFG80211_P2P_DEV_IF */
1888 {
1889 s32 err = 0;
1890 struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
1891 #if defined(WL_CFG80211_P2P_DEV_IF)
1892 struct net_device *ndev = wdev_to_wlc_ndev(request->wdev, cfg);
1893 #endif /* WL_CFG80211_P2P_DEV_IF */
1894
1895 WL_DBG(("Enter request wdev netdev=%s, wdev iftype=%d\n", ndev->name, request->wdev->iftype));
1896 RETURN_EIO_IF_NOT_UP(cfg);
1897
1898 #ifdef DHD_IFDEBUG
1899 #ifdef WL_CFG80211_P2P_DEV_IF
1900 PRINT_WDEV_INFO(request->wdev);
1901 #else
1902 PRINT_WDEV_INFO(ndev);
1903 #endif /* WL_CFG80211_P2P_DEV_IF */
1904 #endif /* DHD_IFDEBUG */
1905
1906 if (ndev == bcmcfg_to_prmry_ndev(cfg)) {
1907 if (wl_cfg_multip2p_operational(cfg)) {
1908 WL_ERR(("wlan0 scan failed, p2p devices are operational"));
1909 return -ENODEV;
1910 }
1911 }
1912 err = wl_ext_in4way_sync(ndev_to_wlc_ndev(ndev, cfg), STA_NO_SCAN_IN4WAY,
1913 WL_EXT_STATUS_SCAN, NULL);
1914 if (err)
1915 return err;
1916
1917 err = __wl_cfg80211_scan(wiphy, ndev, request, NULL);
1918 if (unlikely(err)) {
1919 WL_ERR(("scan error (%d)\n", err));
1920 }
1921 #ifdef WL_DRV_AVOID_SCANCACHE
1922 /* Reset roam cache after successful scan request */
1923 #ifdef ROAM_CHANNEL_CACHE
1924 if (!err) {
1925 reset_roam_cache(cfg);
1926 }
1927 #endif /* ROAM_CHANNEL_CACHE */
1928 #endif /* WL_DRV_AVOID_SCANCACHE */
1929 return err;
1930 }
1931
1932 /* Note: This API should be invoked with scan_sync mutex
1933 * held so that scan_request data structures doesn't
1934 * get modified in between.
1935 */
1936 struct wireless_dev *
wl_get_scan_wdev(struct bcm_cfg80211 * cfg)1937 wl_get_scan_wdev(struct bcm_cfg80211 *cfg)
1938 {
1939 struct wireless_dev *wdev = NULL;
1940
1941 if (!cfg) {
1942 WL_ERR(("cfg ptr null\n"));
1943 return NULL;
1944 }
1945
1946 if (!cfg->scan_request && !cfg->sched_scan_req) {
1947 /* No scans in progress */
1948 WL_MEM(("no scan in progress \n"));
1949 return NULL;
1950 }
1951
1952 if (cfg->scan_request) {
1953 wdev = GET_SCAN_WDEV(cfg->scan_request);
1954 #ifdef WL_SCHED_SCAN
1955 } else if (cfg->sched_scan_req) {
1956 wdev = GET_SCHED_SCAN_WDEV(cfg->sched_scan_req);
1957 #endif /* WL_SCHED_SCAN */
1958 } else {
1959 WL_MEM(("no scan in progress \n"));
1960 }
1961
1962 return wdev;
1963 }
1964
wl_cfg80211_cancel_scan(struct bcm_cfg80211 * cfg)1965 void wl_cfg80211_cancel_scan(struct bcm_cfg80211 *cfg)
1966 {
1967 struct wireless_dev *wdev = NULL;
1968 struct net_device *ndev = NULL;
1969
1970 mutex_lock(&cfg->scan_sync);
1971 if (!cfg->scan_request && !cfg->sched_scan_req) {
1972 /* No scans in progress */
1973 WL_INFORM_MEM(("No scan in progress\n"));
1974 goto exit;
1975 }
1976
1977 wdev = wl_get_scan_wdev(cfg);
1978 if (!wdev) {
1979 WL_ERR(("No wdev present\n"));
1980 goto exit;
1981 }
1982
1983 ndev = wdev_to_wlc_ndev(wdev, cfg);
1984 wl_notify_escan_complete(cfg, ndev, true, true);
1985 WL_INFORM_MEM(("Scan aborted! \n"));
1986 exit:
1987 mutex_unlock(&cfg->scan_sync);
1988 }
1989
wl_cfg80211_scan_abort(struct bcm_cfg80211 * cfg)1990 void wl_cfg80211_scan_abort(struct bcm_cfg80211 *cfg)
1991 {
1992 void *params = NULL;
1993 s32 params_size = 0;
1994 s32 err = BCME_OK;
1995 struct net_device *dev = bcmcfg_to_prmry_ndev(cfg);
1996 u32 channel, channel_num;
1997
1998 if (!in_atomic()) {
1999 /* Abort scan params only need space for 1 channel and 0 ssids */
2000 if (cfg->scan_params_v2) {
2001 params_size = WL_SCAN_PARAMS_V2_FIXED_SIZE + 1 * sizeof(uint16);
2002 } else {
2003 params_size = WL_SCAN_PARAMS_FIXED_SIZE + 1 * sizeof(uint16);
2004 }
2005 params = MALLOCZ(cfg->osh, params_size);
2006 if (params == NULL) {
2007 WL_ERR(("mem alloc failed (%d bytes)\n", params_size));
2008 return;
2009 }
2010
2011 /* Use magic value of channel=-1 to abort scan */
2012 channel = htodchanspec(-1);
2013 channel_num = htod32((0 << WL_SCAN_PARAMS_NSSID_SHIFT) |
2014 (1 & WL_SCAN_PARAMS_COUNT_MASK));
2015 if (cfg->scan_params_v2) {
2016 wl_scan_params_v2_t *params_v2 = (wl_scan_params_v2_t *)params;
2017 params_v2->channel_list[0] = channel;
2018 params_v2->channel_num = channel_num;
2019 } else {
2020 wl_scan_params_t *params_v1 = (wl_scan_params_t *)params;
2021 params_v1->channel_list[0] = channel;
2022 params_v1->channel_num = channel_num;
2023 }
2024 /* Do a scan abort to stop the driver's scan engine */
2025 err = wldev_ioctl_set(dev, WLC_SCAN, params, params_size);
2026 if (err < 0) {
2027 /* scan abort can fail if there is no outstanding scan */
2028 WL_DBG(("scan abort failed. ret:%d\n", err));
2029 }
2030 MFREE(cfg->osh, params, params_size);
2031 }
2032 #ifdef WLTDLS
2033 if (cfg->tdls_mgmt_frame) {
2034 MFREE(cfg->osh, cfg->tdls_mgmt_frame, cfg->tdls_mgmt_frame_len);
2035 cfg->tdls_mgmt_frame = NULL;
2036 cfg->tdls_mgmt_frame_len = 0;
2037 }
2038 #endif /* WLTDLS */
2039 }
2040
wl_notify_escan_complete(struct bcm_cfg80211 * cfg,struct net_device * ndev,bool aborted,bool fw_abort)2041 s32 wl_notify_escan_complete(struct bcm_cfg80211 *cfg,
2042 struct net_device *ndev,
2043 bool aborted, bool fw_abort)
2044 {
2045 s32 err = BCME_OK;
2046 unsigned long flags;
2047 struct net_device *dev;
2048 dhd_pub_t *dhdp = (dhd_pub_t *)(cfg->pub);
2049
2050 WL_DBG(("Enter \n"));
2051 BCM_REFERENCE(dhdp);
2052
2053 if (!ndev) {
2054 WL_ERR(("ndev is null\n"));
2055 err = BCME_ERROR;
2056 goto out;
2057 }
2058
2059 if (cfg->escan_info.ndev != ndev) {
2060 WL_ERR(("Outstanding scan req ndev not matching (%p:%p)\n",
2061 cfg->escan_info.ndev, ndev));
2062 err = BCME_ERROR;
2063 goto out;
2064 }
2065
2066 if (cfg->scan_request) {
2067 dev = bcmcfg_to_prmry_ndev(cfg);
2068 #if defined(WL_ENABLE_P2P_IF)
2069 if (cfg->scan_request->dev != cfg->p2p_net)
2070 dev = cfg->scan_request->dev;
2071 #elif defined(WL_CFG80211_P2P_DEV_IF)
2072 if (cfg->scan_request->wdev->iftype != NL80211_IFTYPE_P2P_DEVICE)
2073 dev = cfg->scan_request->wdev->netdev;
2074 #endif // endif
2075 }
2076 else {
2077 WL_DBG(("cfg->scan_request is NULL. Internal scan scenario."
2078 "doing scan_abort for ndev %p primary %p",
2079 ndev, bcmcfg_to_prmry_ndev(cfg)));
2080 dev = ndev;
2081 }
2082 if (fw_abort && !in_atomic())
2083 wl_cfg80211_scan_abort(cfg);
2084 if (timer_pending(&cfg->scan_timeout))
2085 del_timer_sync(&cfg->scan_timeout);
2086 cfg->scan_enq_time = 0;
2087 #if defined(ESCAN_RESULT_PATCH)
2088 if (likely(cfg->scan_request)) {
2089 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0))
2090 if (aborted && cfg->p2p && p2p_scan(cfg) &&
2091 (cfg->scan_request->flags & NL80211_SCAN_FLAG_FLUSH)) {
2092 WL_ERR(("scan list is changed"));
2093 cfg->bss_list = wl_escan_get_buf(cfg, !aborted);
2094 } else
2095 #endif // endif
2096 cfg->bss_list = wl_escan_get_buf(cfg, aborted);
2097
2098 wl_inform_bss(cfg);
2099 }
2100 #endif /* ESCAN_RESULT_PATCH */
2101 WL_CFG_DRV_LOCK(&cfg->cfgdrv_lock, flags);
2102 #ifdef WL_SCHED_SCAN
2103 if (cfg->sched_scan_req && !cfg->scan_request) {
2104 if (!aborted) {
2105 WL_INFORM_MEM(("[%s] Report sched scan done.\n", dev->name));
2106 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0))
2107 cfg80211_sched_scan_results(cfg->sched_scan_req->wiphy,
2108 cfg->sched_scan_req->reqid);
2109 #else
2110 cfg80211_sched_scan_results(cfg->sched_scan_req->wiphy);
2111 #endif /* LINUX_VER > 4.11 */
2112 }
2113
2114 DBG_EVENT_LOG(dhdp, WIFI_EVENT_DRIVER_PNO_SCAN_COMPLETE);
2115 cfg->sched_scan_running = FALSE;
2116 cfg->sched_scan_req = NULL;
2117 }
2118 #endif /* WL_SCHED_SCAN */
2119 if (likely(cfg->scan_request)) {
2120 WL_INFORM_MEM(("[%s] Report scan done.\n", dev->name));
2121 /* scan_sync mutex is already held */
2122 _wl_notify_scan_done(cfg, aborted);
2123 cfg->scan_request = NULL;
2124 }
2125 if (p2p_is_on(cfg))
2126 wl_clr_p2p_status(cfg, SCANNING);
2127 wl_clr_drv_status(cfg, SCANNING, dev);
2128 wake_up_interruptible(&dhdp->conf->event_complete);
2129
2130 DHD_OS_SCAN_WAKE_UNLOCK((dhd_pub_t *)(cfg->pub));
2131 DHD_ENABLE_RUNTIME_PM((dhd_pub_t *)(cfg->pub));
2132 WL_CFG_DRV_UNLOCK(&cfg->cfgdrv_lock, flags);
2133
2134 out:
2135 return err;
2136 }
2137
2138 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 5, 0))
2139 void
wl_cfg80211_abort_scan(struct wiphy * wiphy,struct wireless_dev * wdev)2140 wl_cfg80211_abort_scan(struct wiphy *wiphy, struct wireless_dev *wdev)
2141 {
2142 struct bcm_cfg80211 *cfg;
2143
2144 WL_DBG(("Enter wl_cfg80211_abort_scan\n"));
2145 cfg = wiphy_priv(wdev->wiphy);
2146
2147 /* Check if any scan in progress only then abort */
2148 if (wl_get_drv_status_all(cfg, SCANNING)) {
2149 wl_cfg80211_scan_abort(cfg);
2150 /* Only scan abort is issued here. As per the expectation of abort_scan
2151 * the status of abort is needed to be communicated using cfg80211_scan_done call.
2152 * Here we just issue abort request and let the scan complete path to indicate
2153 * abort to cfg80211 layer.
2154 */
2155 WL_DBG(("wl_cfg80211_abort_scan: Scan abort issued to FW\n"));
2156 }
2157 }
2158 #else
2159 #ifdef CONFIG_AP6XXX_WIFI6_HDF
2160 void
wl_cfg80211_abort_scan(struct wiphy * wiphy,struct wireless_dev * wdev)2161 wl_cfg80211_abort_scan(struct wiphy *wiphy, struct wireless_dev *wdev)
2162 {
2163 struct bcm_cfg80211 *cfg;
2164
2165 WL_DBG(("Enter wl_cfg80211_abort_scan\n"));
2166 cfg = wiphy_priv(wdev->wiphy);
2167
2168 /* cancel scan and notify scan status */
2169 wl_cfg80211_cancel_scan(cfg);
2170 }
2171 #endif
2172 #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 5, 0)) */
2173
wl_cfg80211_scan_stop(struct bcm_cfg80211 * cfg,bcm_struct_cfgdev * cfgdev)2174 int wl_cfg80211_scan_stop(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev)
2175 {
2176 int ret = 0;
2177
2178 WL_TRACE(("Enter\n"));
2179
2180 if (!cfg || !cfgdev) {
2181 return -EINVAL;
2182 }
2183
2184 /* cancel scan and notify scan status */
2185 wl_cfg80211_cancel_scan(cfg);
2186
2187 return ret;
2188 }
2189
2190 /* This API is just meant as a wrapper for cfg80211_scan_done
2191 * API. This doesn't do state mgmt. For cancelling scan,
2192 * please use wl_cfg80211_cancel_scan API.
2193 */
2194 static void
_wl_notify_scan_done(struct bcm_cfg80211 * cfg,bool aborted)2195 _wl_notify_scan_done(struct bcm_cfg80211 *cfg, bool aborted)
2196 {
2197 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 8, 0))
2198 struct cfg80211_scan_info info;
2199 #endif // endif
2200
2201 if (!cfg->scan_request) {
2202 return;
2203 }
2204
2205 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 8, 0))
2206 memset_s(&info, sizeof(struct cfg80211_scan_info), 0, sizeof(struct cfg80211_scan_info));
2207 info.aborted = aborted;
2208
2209 #ifndef CONFIG_AP6XXX_WIFI6_HDF
2210 cfg80211_scan_done(cfg->scan_request, &info);
2211 #endif
2212 #else
2213 #ifndef CONFIG_AP6XXX_WIFI6_HDF
2214 cfg80211_scan_done(cfg->scan_request, aborted);
2215 #endif
2216 #endif // endif
2217
2218 #ifdef CONFIG_AP6XXX_WIFI6_HDF
2219 WifiScanFree(&cfg->scan_request);
2220 #endif
2221 cfg->scan_request = NULL;
2222 }
2223
2224 #ifdef WL_DRV_AVOID_SCANCACHE
wl_p2p_find_peer_channel(struct bcm_cfg80211 * cfg,s32 status,wl_bss_info_t * bi,u32 bi_length)2225 static u32 wl_p2p_find_peer_channel(struct bcm_cfg80211 *cfg, s32 status, wl_bss_info_t *bi,
2226 u32 bi_length)
2227 {
2228 u32 ret;
2229 u8 *p2p_dev_addr = NULL;
2230
2231 ret = wl_get_drv_status_all(cfg, FINDING_COMMON_CHANNEL);
2232 if (!ret) {
2233 return ret;
2234 }
2235 if (status == WLC_E_STATUS_PARTIAL) {
2236 p2p_dev_addr = wl_cfgp2p_retreive_p2p_dev_addr(bi, bi_length);
2237 if (p2p_dev_addr && !memcmp(p2p_dev_addr,
2238 cfg->afx_hdl->tx_dst_addr.octet, ETHER_ADDR_LEN)) {
2239 s32 channel = wf_chspec_ctlchan(
2240 wl_chspec_driver_to_host(bi->chanspec));
2241
2242 if ((channel > MAXCHANNEL) || (channel <= 0)) {
2243 channel = WL_INVALID;
2244 } else {
2245 WL_ERR(("ACTION FRAME SCAN : Peer " MACDBG " found,"
2246 " channel : %d\n",
2247 MAC2STRDBG(cfg->afx_hdl->tx_dst_addr.octet),
2248 channel));
2249 }
2250 wl_clr_p2p_status(cfg, SCANNING);
2251 cfg->afx_hdl->peer_chan = channel;
2252 complete(&cfg->act_frm_scan);
2253 }
2254 } else {
2255 WL_INFORM_MEM(("ACTION FRAME SCAN DONE\n"));
2256 wl_clr_p2p_status(cfg, SCANNING);
2257 wl_clr_drv_status(cfg, SCANNING, cfg->afx_hdl->dev);
2258 if (cfg->afx_hdl->peer_chan == WL_INVALID)
2259 complete(&cfg->act_frm_scan);
2260 }
2261
2262 return ret;
2263 }
2264
wl_escan_without_scan_cache(struct bcm_cfg80211 * cfg,wl_escan_result_t * escan_result,struct net_device * ndev,const wl_event_msg_t * e,s32 status)2265 static s32 wl_escan_without_scan_cache(struct bcm_cfg80211 *cfg, wl_escan_result_t *escan_result,
2266 struct net_device *ndev, const wl_event_msg_t *e, s32 status)
2267 {
2268 s32 err = BCME_OK;
2269 wl_bss_info_t *bi;
2270 u32 bi_length;
2271 bool aborted = false;
2272 bool fw_abort = false;
2273 bool notify_escan_complete = false;
2274
2275 if (wl_escan_check_sync_id(status, escan_result->sync_id,
2276 cfg->escan_info.cur_sync_id) < 0) {
2277 goto exit;
2278 }
2279
2280 wl_escan_print_sync_id(status, escan_result->sync_id,
2281 cfg->escan_info.cur_sync_id);
2282
2283 if (!(status == WLC_E_STATUS_TIMEOUT) || !(status == WLC_E_STATUS_PARTIAL)) {
2284 cfg->escan_info.escan_state = WL_ESCAN_STATE_IDLE;
2285 }
2286
2287 if ((likely(cfg->scan_request)) || (cfg->sched_scan_running)) {
2288 notify_escan_complete = true;
2289 }
2290
2291 if (status == WLC_E_STATUS_PARTIAL) {
2292 WL_DBG(("WLC_E_STATUS_PARTIAL \n"));
2293 DBG_EVENT_LOG((dhd_pub_t *)cfg->pub, WIFI_EVENT_DRIVER_SCAN_RESULT_FOUND);
2294 if ((!escan_result) || (dtoh16(escan_result->bss_count) != 1)) {
2295 WL_ERR(("Invalid escan result (NULL pointer) or invalid bss_count\n"));
2296 goto exit;
2297 }
2298
2299 bi = escan_result->bss_info;
2300 bi_length = dtoh32(bi->length);
2301 if ((!bi) ||
2302 (bi_length != (dtoh32(escan_result->buflen) - WL_ESCAN_RESULTS_FIXED_SIZE))) {
2303 WL_ERR(("Invalid escan bss info (NULL pointer)"
2304 "or invalid bss_info length\n"));
2305 goto exit;
2306 }
2307
2308 if (!(bcmcfg_to_wiphy(cfg)->interface_modes & BIT(NL80211_IFTYPE_ADHOC))) {
2309 if (dtoh16(bi->capability) & DOT11_CAP_IBSS) {
2310 WL_DBG(("Ignoring IBSS result\n"));
2311 goto exit;
2312 }
2313 }
2314
2315 if (wl_p2p_find_peer_channel(cfg, status, bi, bi_length)) {
2316 goto exit;
2317 } else {
2318 if (scan_req_match(cfg)) {
2319 /* p2p scan && allow only probe response */
2320 if ((cfg->p2p->search_state != WL_P2P_DISC_ST_SCAN) &&
2321 (bi->flags & WL_BSS_FLAGS_FROM_BEACON))
2322 goto exit;
2323 }
2324 #ifdef ROAM_CHANNEL_CACHE
2325 add_roam_cache(cfg, bi);
2326 #endif /* ROAM_CHANNEL_CACHE */
2327 err = wl_inform_single_bss(cfg, bi, false);
2328 #ifdef ROAM_CHANNEL_CACHE
2329 /* print_roam_cache(); */
2330 update_roam_cache(cfg, ioctl_version);
2331 #endif /* ROAM_CHANNEL_CACHE */
2332
2333 /*
2334 * !Broadcast && number of ssid = 1 && number of channels =1
2335 * means specific scan to association
2336 */
2337 if (wl_cfgp2p_is_p2p_specific_scan(cfg->scan_request)) {
2338 WL_ERR(("P2P assoc scan fast aborted.\n"));
2339 aborted = false;
2340 fw_abort = true;
2341 }
2342 /* Directly exit from function here and
2343 * avoid sending notify completion to cfg80211
2344 */
2345 goto exit;
2346 }
2347 } else if (status == WLC_E_STATUS_SUCCESS) {
2348 if (wl_p2p_find_peer_channel(cfg, status, NULL, 0)) {
2349 goto exit;
2350 }
2351 WL_INFORM_MEM(("ESCAN COMPLETED\n"));
2352 DBG_EVENT_LOG((dhd_pub_t *)cfg->pub, WIFI_EVENT_DRIVER_SCAN_COMPLETE);
2353
2354 /* Update escan complete status */
2355 aborted = false;
2356 fw_abort = false;
2357
2358 } else if ((status == WLC_E_STATUS_ABORT) || (status == WLC_E_STATUS_NEWSCAN) ||
2359 (status == WLC_E_STATUS_11HQUIET) || (status == WLC_E_STATUS_CS_ABORT) ||
2360 (status == WLC_E_STATUS_NEWASSOC)) {
2361 /* Handle all cases of scan abort */
2362
2363 WL_DBG(("ESCAN ABORT reason: %d\n", status));
2364 if (wl_p2p_find_peer_channel(cfg, status, NULL, 0)) {
2365 goto exit;
2366 }
2367 WL_INFORM_MEM(("ESCAN ABORTED\n"));
2368
2369 /* Update escan complete status */
2370 aborted = true;
2371 fw_abort = false;
2372
2373 } else if (status == WLC_E_STATUS_TIMEOUT) {
2374 WL_ERR(("WLC_E_STATUS_TIMEOUT : scan_request[%p]\n", cfg->scan_request));
2375 WL_ERR(("reason[0x%x]\n", e->reason));
2376 if (e->reason == 0xFFFFFFFF) {
2377 /* Update escan complete status */
2378 aborted = true;
2379 fw_abort = true;
2380 }
2381 } else {
2382 WL_ERR(("unexpected Escan Event %d : abort\n", status));
2383
2384 if (wl_p2p_find_peer_channel(cfg, status, NULL, 0)) {
2385 goto exit;
2386 }
2387 /* Update escan complete status */
2388 aborted = true;
2389 fw_abort = false;
2390 }
2391
2392 /* Notify escan complete status */
2393 if (notify_escan_complete) {
2394 wl_notify_escan_complete(cfg, ndev, aborted, fw_abort);
2395 }
2396
2397 exit:
2398 return err;
2399
2400 }
2401 #endif /* WL_DRV_AVOID_SCANCACHE */
2402
2403 s32
wl_notify_scan_status(struct bcm_cfg80211 * cfg,bcm_struct_cfgdev * cfgdev,const wl_event_msg_t * e,void * data)2404 wl_notify_scan_status(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev,
2405 const wl_event_msg_t *e, void *data)
2406 {
2407 struct channel_info channel_inform;
2408 struct wl_scan_results *bss_list;
2409 struct net_device *ndev = NULL;
2410 u32 len = WL_SCAN_BUF_MAX;
2411 s32 err = 0;
2412 unsigned long flags;
2413
2414 WL_DBG(("Enter \n"));
2415 if (!wl_get_drv_status(cfg, SCANNING, ndev)) {
2416 WL_DBG(("scan is not ready \n"));
2417 return err;
2418 }
2419 ndev = cfgdev_to_wlc_ndev(cfgdev, cfg);
2420
2421 mutex_lock(&cfg->scan_sync);
2422 wl_clr_drv_status(cfg, SCANNING, ndev);
2423 bzero(&channel_inform, sizeof(channel_inform));
2424 err = wldev_ioctl_get(ndev, WLC_GET_CHANNEL, &channel_inform,
2425 sizeof(channel_inform));
2426 if (unlikely(err)) {
2427 WL_ERR(("scan busy (%d)\n", err));
2428 goto scan_done_out;
2429 }
2430 channel_inform.scan_channel = dtoh32(channel_inform.scan_channel);
2431 if (unlikely(channel_inform.scan_channel)) {
2432
2433 WL_DBG(("channel_inform.scan_channel (%d)\n",
2434 channel_inform.scan_channel));
2435 }
2436 cfg->bss_list = cfg->scan_results;
2437 bss_list = cfg->bss_list;
2438 bzero(bss_list, len);
2439 bss_list->buflen = htod32(len);
2440 err = wldev_ioctl_get(ndev, WLC_SCAN_RESULTS, bss_list, len);
2441 if (unlikely(err) && unlikely(!cfg->scan_suppressed)) {
2442 WL_ERR(("%s Scan_results error (%d)\n", ndev->name, err));
2443 err = -EINVAL;
2444 goto scan_done_out;
2445 }
2446 bss_list->buflen = dtoh32(bss_list->buflen);
2447 bss_list->version = dtoh32(bss_list->version);
2448 bss_list->count = dtoh32(bss_list->count);
2449
2450 err = wl_inform_bss(cfg);
2451
2452 scan_done_out:
2453 del_timer_sync(&cfg->scan_timeout);
2454 WL_CFG_DRV_LOCK(&cfg->cfgdrv_lock, flags);
2455 if (cfg->scan_request) {
2456 _wl_notify_scan_done(cfg, false);
2457 cfg->scan_request = NULL;
2458 }
2459 WL_CFG_DRV_UNLOCK(&cfg->cfgdrv_lock, flags);
2460 WL_DBG(("cfg80211_scan_done\n"));
2461 mutex_unlock(&cfg->scan_sync);
2462 return err;
2463 }
2464
wl_notify_scan_done(struct bcm_cfg80211 * cfg,bool aborted)2465 void wl_notify_scan_done(struct bcm_cfg80211 *cfg, bool aborted)
2466 {
2467 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 8, 0))
2468 struct cfg80211_scan_info info;
2469
2470 bzero(&info, sizeof(struct cfg80211_scan_info));
2471 info.aborted = aborted;
2472
2473 #ifndef CONFIG_AP6XXX_WIFI6_HDF
2474 cfg80211_scan_done(cfg->scan_request, &info);
2475 #endif
2476 #else
2477 #ifndef CONFIG_AP6XXX_WIFI6_HDF
2478 cfg80211_scan_done(cfg->scan_request, aborted);
2479 #endif
2480 #endif // endif
2481
2482 #ifdef CONFIG_AP6XXX_WIFI6_HDF
2483 WifiScanFree(&cfg->scan_request);
2484 #endif
2485 }
2486
2487 #ifdef WL_SCHED_SCAN
2488 #define PNO_TIME 30
2489 #define PNO_REPEAT 4
2490 #define PNO_FREQ_EXPO_MAX 2
2491 static bool
is_ssid_in_list(struct cfg80211_ssid * ssid,struct cfg80211_ssid * ssid_list,int count)2492 is_ssid_in_list(struct cfg80211_ssid *ssid, struct cfg80211_ssid *ssid_list, int count)
2493 {
2494 int i;
2495
2496 if (!ssid || !ssid_list)
2497 return FALSE;
2498
2499 for (i = 0; i < count; i++) {
2500 if (ssid->ssid_len == ssid_list[i].ssid_len) {
2501 if (strncmp(ssid->ssid, ssid_list[i].ssid, ssid->ssid_len) == 0)
2502 return TRUE;
2503 }
2504 }
2505 return FALSE;
2506 }
2507
2508 int
wl_cfg80211_sched_scan_start(struct wiphy * wiphy,struct net_device * dev,struct cfg80211_sched_scan_request * request)2509 wl_cfg80211_sched_scan_start(struct wiphy *wiphy,
2510 struct net_device *dev,
2511 struct cfg80211_sched_scan_request *request)
2512 {
2513 ushort pno_time = PNO_TIME;
2514 int pno_repeat = PNO_REPEAT;
2515 int pno_freq_expo_max = PNO_FREQ_EXPO_MAX;
2516 wlc_ssid_ext_t ssids_local[MAX_PFN_LIST_COUNT];
2517 struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
2518 dhd_pub_t *dhdp = (dhd_pub_t *)(cfg->pub);
2519 struct cfg80211_ssid *ssid = NULL;
2520 struct cfg80211_ssid *hidden_ssid_list = NULL;
2521 log_conn_event_t *event_data = NULL;
2522 tlv_log *tlv_data = NULL;
2523 u32 alloc_len, tlv_len;
2524 u32 payload_len;
2525 int ssid_cnt = 0;
2526 int i;
2527 int ret = 0;
2528 unsigned long flags;
2529
2530 if (!request) {
2531 WL_ERR(("Sched scan request was NULL\n"));
2532 return -EINVAL;
2533 }
2534
2535 WL_DBG(("Enter \n"));
2536 WL_PNO((">>> SCHED SCAN START\n"));
2537 WL_PNO(("Enter n_match_sets:%d n_ssids:%d \n",
2538 request->n_match_sets, request->n_ssids));
2539 WL_PNO(("ssids:%d pno_time:%d pno_repeat:%d pno_freq:%d \n",
2540 request->n_ssids, pno_time, pno_repeat, pno_freq_expo_max));
2541
2542 if (!request->n_ssids || !request->n_match_sets) {
2543 WL_ERR(("Invalid sched scan req!! n_ssids:%d \n", request->n_ssids));
2544 return -EINVAL;
2545 }
2546
2547 bzero(&ssids_local, sizeof(ssids_local));
2548
2549 if (request->n_ssids > 0) {
2550 hidden_ssid_list = request->ssids;
2551 }
2552
2553 if (DBG_RING_ACTIVE(dhdp, DHD_EVENT_RING_ID)) {
2554 alloc_len = sizeof(log_conn_event_t) + DOT11_MAX_SSID_LEN;
2555 event_data = (log_conn_event_t *)MALLOC(cfg->osh, alloc_len);
2556 if (!event_data) {
2557 WL_ERR(("%s: failed to allocate log_conn_event_t with "
2558 "length(%d)\n", __func__, alloc_len));
2559 return -ENOMEM;
2560 }
2561 bzero(event_data, alloc_len);
2562 event_data->tlvs = NULL;
2563 tlv_len = sizeof(tlv_log);
2564 event_data->tlvs = (tlv_log *)MALLOC(cfg->osh, tlv_len);
2565 if (!event_data->tlvs) {
2566 WL_ERR(("%s: failed to allocate log_tlv with "
2567 "length(%d)\n", __func__, tlv_len));
2568 MFREE(cfg->osh, event_data, alloc_len);
2569 return -ENOMEM;
2570 }
2571 }
2572 for (i = 0; i < request->n_match_sets && ssid_cnt < MAX_PFN_LIST_COUNT; i++) {
2573 ssid = &request->match_sets[i].ssid;
2574 /* No need to include null ssid */
2575 if (ssid->ssid_len) {
2576 ssids_local[ssid_cnt].SSID_len = MIN(ssid->ssid_len,
2577 (uint32)DOT11_MAX_SSID_LEN);
2578 /* In previous step max SSID_len is limited to DOT11_MAX_SSID_LEN,
2579 * returning void
2580 */
2581 (void)memcpy_s(ssids_local[ssid_cnt].SSID, DOT11_MAX_SSID_LEN, ssid->ssid,
2582 ssids_local[ssid_cnt].SSID_len);
2583 if (is_ssid_in_list(ssid, hidden_ssid_list, request->n_ssids)) {
2584 ssids_local[ssid_cnt].hidden = TRUE;
2585 WL_PNO((">>> PNO hidden SSID (%s) \n", ssid->ssid));
2586 } else {
2587 ssids_local[ssid_cnt].hidden = FALSE;
2588 WL_PNO((">>> PNO non-hidden SSID (%s) \n", ssid->ssid));
2589 }
2590 #if (LINUX_VERSION_CODE > KERNEL_VERSION(3, 15, 0))
2591 if (request->match_sets[i].rssi_thold != NL80211_SCAN_RSSI_THOLD_OFF) {
2592 ssids_local[ssid_cnt].rssi_thresh =
2593 (int8)request->match_sets[i].rssi_thold;
2594 }
2595 #endif /* (LINUX_VERSION_CODE > KERNEL_VERSION(3, 15, 0)) */
2596 ssid_cnt++;
2597 }
2598 }
2599
2600 if (ssid_cnt) {
2601 if ((ret = dhd_dev_pno_set_for_ssid(dev, ssids_local, ssid_cnt,
2602 pno_time, pno_repeat, pno_freq_expo_max, NULL, 0)) < 0) {
2603 WL_ERR(("PNO setup failed!! ret=%d \n", ret));
2604 ret = -EINVAL;
2605 goto exit;
2606 }
2607
2608 if (DBG_RING_ACTIVE(dhdp, DHD_EVENT_RING_ID)) {
2609 for (i = 0; i < ssid_cnt; i++) {
2610 payload_len = sizeof(log_conn_event_t);
2611 event_data->event = WIFI_EVENT_DRIVER_PNO_ADD;
2612 tlv_data = event_data->tlvs;
2613 /* ssid */
2614 tlv_data->tag = WIFI_TAG_SSID;
2615 tlv_data->len = ssids_local[i].SSID_len;
2616 (void)memcpy_s(tlv_data->value, DOT11_MAX_SSID_LEN,
2617 ssids_local[i].SSID, ssids_local[i].SSID_len);
2618 payload_len += TLV_LOG_SIZE(tlv_data);
2619
2620 dhd_os_push_push_ring_data(dhdp, DHD_EVENT_RING_ID,
2621 event_data, payload_len);
2622 }
2623 }
2624
2625 WL_CFG_DRV_LOCK(&cfg->cfgdrv_lock, flags);
2626 cfg->sched_scan_req = request;
2627 WL_CFG_DRV_UNLOCK(&cfg->cfgdrv_lock, flags);
2628 } else {
2629 ret = -EINVAL;
2630 }
2631 exit:
2632 if (event_data) {
2633 MFREE(cfg->osh, event_data->tlvs, tlv_len);
2634 MFREE(cfg->osh, event_data, alloc_len);
2635 }
2636 return ret;
2637 }
2638
2639 int
2640 #if (LINUX_VERSION_CODE > KERNEL_VERSION(4, 11, 0))
wl_cfg80211_sched_scan_stop(struct wiphy * wiphy,struct net_device * dev,u64 reqid)2641 wl_cfg80211_sched_scan_stop(struct wiphy *wiphy, struct net_device *dev, u64 reqid)
2642 #else
2643 wl_cfg80211_sched_scan_stop(struct wiphy *wiphy, struct net_device *dev)
2644 #endif /* LINUX_VER > 4.11 */
2645 {
2646 struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
2647 dhd_pub_t *dhdp = (dhd_pub_t *)(cfg->pub);
2648 unsigned long flags;
2649
2650 WL_DBG(("Enter \n"));
2651 WL_PNO((">>> SCHED SCAN STOP\n"));
2652
2653 if (dhd_dev_pno_stop_for_ssid(dev) < 0) {
2654 WL_ERR(("PNO Stop for SSID failed"));
2655 } else {
2656 DBG_EVENT_LOG(dhdp, WIFI_EVENT_DRIVER_PNO_REMOVE);
2657 }
2658
2659 if (cfg->sched_scan_req || cfg->sched_scan_running) {
2660 WL_PNO((">>> Sched scan running. Aborting it..\n"));
2661 wl_cfg80211_cancel_scan(cfg);
2662 }
2663 WL_CFG_DRV_LOCK(&cfg->cfgdrv_lock, flags);
2664 cfg->sched_scan_req = NULL;
2665 cfg->sched_scan_running = FALSE;
2666 WL_CFG_DRV_UNLOCK(&cfg->cfgdrv_lock, flags);
2667 return 0;
2668 }
2669 #endif /* WL_SCHED_SCAN */
2670
wl_scan_timeout(unsigned long data)2671 static void wl_scan_timeout(unsigned long data)
2672 {
2673 wl_event_msg_t msg;
2674 struct bcm_cfg80211 *cfg = (struct bcm_cfg80211 *)data;
2675 struct wireless_dev *wdev = NULL;
2676 struct net_device *ndev = NULL;
2677 struct wl_scan_results *bss_list;
2678 wl_bss_info_t *bi = NULL;
2679 s32 i;
2680 u32 channel;
2681 u64 cur_time = OSL_LOCALTIME_NS();
2682 dhd_pub_t *dhdp = (dhd_pub_t *)(cfg->pub);
2683 unsigned long flags;
2684 #ifdef RTT_SUPPORT
2685 rtt_status_info_t *rtt_status = NULL;
2686 UNUSED_PARAMETER(rtt_status);
2687 #endif /* RTT_SUPPORT */
2688
2689 UNUSED_PARAMETER(cur_time);
2690 WL_CFG_DRV_LOCK(&cfg->cfgdrv_lock, flags);
2691 if (!(cfg->scan_request)) {
2692 WL_ERR(("timer expired but no scan request\n"));
2693 WL_CFG_DRV_UNLOCK(&cfg->cfgdrv_lock, flags);
2694 return;
2695 }
2696
2697 wdev = GET_SCAN_WDEV(cfg->scan_request);
2698 WL_CFG_DRV_UNLOCK(&cfg->cfgdrv_lock, flags);
2699
2700 if (!wdev) {
2701 WL_ERR(("No wireless_dev present\n"));
2702 return;
2703 }
2704
2705 if (dhd_query_bus_erros(dhdp)) {
2706 return;
2707 }
2708 #if defined(DHD_KERNEL_SCHED_DEBUG) && defined(DHD_FW_COREDUMP)
2709 if (dhdp->memdump_enabled == DUMP_MEMFILE_BUGON &&
2710 ((cfg->scan_deq_time < cfg->scan_enq_time) ||
2711 dhd_bus_query_dpc_sched_errors(dhdp))) {
2712 WL_ERR(("****SCAN event timeout due to scheduling problem\n"));
2713 /* change g_assert_type to trigger Kernel panic */
2714 g_assert_type = 2;
2715 #ifdef RTT_SUPPORT
2716 rtt_status = GET_RTTSTATE(dhdp);
2717 #endif /* RTT_SUPPORT */
2718 WL_ERR(("***SCAN event timeout. WQ state:0x%x scan_enq_time:"SEC_USEC_FMT
2719 " evt_hdlr_entry_time:"SEC_USEC_FMT" evt_deq_time:"SEC_USEC_FMT
2720 "\nscan_deq_time:"SEC_USEC_FMT" scan_hdlr_cmplt_time:"SEC_USEC_FMT
2721 " scan_cmplt_time:"SEC_USEC_FMT" evt_hdlr_exit_time:"SEC_USEC_FMT
2722 "\ncurrent_time:"SEC_USEC_FMT"\n", work_busy(&cfg->event_work),
2723 GET_SEC_USEC(cfg->scan_enq_time), GET_SEC_USEC(cfg->wl_evt_hdlr_entry_time),
2724 GET_SEC_USEC(cfg->wl_evt_deq_time), GET_SEC_USEC(cfg->scan_deq_time),
2725 GET_SEC_USEC(cfg->scan_hdlr_cmplt_time), GET_SEC_USEC(cfg->scan_cmplt_time),
2726 GET_SEC_USEC(cfg->wl_evt_hdlr_exit_time), GET_SEC_USEC(cur_time)));
2727 if (cfg->scan_enq_time) {
2728 WL_ERR(("Elapsed time(ns): %llu\n", (cur_time - cfg->scan_enq_time)));
2729 }
2730 WL_ERR(("lock_states:[%d:%d:%d:%d:%d:%d]\n",
2731 mutex_is_locked(&cfg->if_sync),
2732 mutex_is_locked(&cfg->usr_sync),
2733 mutex_is_locked(&cfg->pm_sync),
2734 mutex_is_locked(&cfg->scan_sync),
2735 spin_is_locked(&cfg->cfgdrv_lock),
2736 spin_is_locked(&cfg->eq_lock)));
2737 #ifdef RTT_SUPPORT
2738 WL_ERR(("RTT lock_state:[%d]\n",
2739 mutex_is_locked(&rtt_status->rtt_mutex)));
2740 #ifdef WL_NAN
2741 WL_ERR(("RTT and Geofence lock_states:[%d:%d]\n",
2742 mutex_is_locked(&cfg->nancfg.nan_sync),
2743 mutex_is_locked(&(rtt_status)->geofence_mutex)));
2744 #endif /* WL_NAN */
2745 #endif /* RTT_SUPPORT */
2746
2747 /* use ASSERT() to trigger panic */
2748 ASSERT(0);
2749 }
2750 #endif /* DHD_KERNEL_SCHED_DEBUG && DHD_FW_COREDUMP */
2751 dhd_bus_intr_count_dump(dhdp);
2752
2753 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0)) && !defined(CONFIG_MODULES)
2754 /* Print WQ states. Enable only for in-built drivers as the symbol is not exported */
2755 show_workqueue_state();
2756 #endif /* LINUX_VER >= 4.1 && !CONFIG_MODULES */
2757
2758 bss_list = wl_escan_get_buf(cfg, FALSE);
2759 if (!bss_list) {
2760 WL_ERR(("bss_list is null. Didn't receive any partial scan results\n"));
2761 } else {
2762 WL_ERR(("Dump scan buffer:\n"
2763 "scanned AP count (%d)\n", bss_list->count));
2764
2765 bi = next_bss(bss_list, bi);
2766 for_each_bss(bss_list, bi, i) {
2767 channel = wf_chspec_ctlchan(wl_chspec_driver_to_host(bi->chanspec));
2768 WL_ERR(("SSID :%s Channel :%d\n", bi->SSID, channel));
2769 }
2770 }
2771
2772 ndev = wdev_to_wlc_ndev(wdev, cfg);
2773 bzero(&msg, sizeof(wl_event_msg_t));
2774 WL_ERR(("timer expired\n"));
2775 dhdp->scan_timeout_occurred = TRUE;
2776 #ifdef BCMPCIE
2777 (void)dhd_pcie_dump_int_regs(dhdp);
2778 dhd_pcie_dump_rc_conf_space_cap(dhdp);
2779 #endif /* BCMPCIE */
2780 #if 0
2781 if (dhdp->memdump_enabled) {
2782 dhdp->memdump_type = DUMP_TYPE_SCAN_TIMEOUT;
2783 dhd_bus_mem_dump(dhdp);
2784 }
2785 #endif /* DHD_FW_COREDUMP */
2786 /*
2787 * For the memdump sanity, blocking bus transactions for a while
2788 * Keeping it TRUE causes the sequential private cmd error
2789 */
2790 dhdp->scan_timeout_occurred = FALSE;
2791 msg.event_type = hton32(WLC_E_ESCAN_RESULT);
2792 msg.status = hton32(WLC_E_STATUS_TIMEOUT);
2793 msg.reason = 0xFFFFFFFF;
2794 wl_cfg80211_event(ndev, &msg, NULL);
2795 }
2796
wl_init_scan(struct bcm_cfg80211 * cfg)2797 s32 wl_init_scan(struct bcm_cfg80211 *cfg)
2798 {
2799 int err = 0;
2800
2801 cfg->evt_handler[WLC_E_ESCAN_RESULT] = wl_escan_handler;
2802 cfg->escan_info.escan_state = WL_ESCAN_STATE_IDLE;
2803 wl_escan_init_sync_id(cfg);
2804
2805 /* Init scan_timeout timer */
2806 init_timer_compat(&cfg->scan_timeout, wl_scan_timeout, cfg);
2807
2808 wl_cfg80211_set_bcmcfg(cfg);
2809
2810 return err;
2811 }
2812
2813 #ifdef WL_SCHED_SCAN
2814 /* If target scan is not reliable, set the below define to "1" to do a
2815 * full escan
2816 */
2817 #define FULL_ESCAN_ON_PFN_NET_FOUND 0
2818 static s32
wl_notify_sched_scan_results(struct bcm_cfg80211 * cfg,struct net_device * ndev,const wl_event_msg_t * e,void * data)2819 wl_notify_sched_scan_results(struct bcm_cfg80211 *cfg, struct net_device *ndev,
2820 const wl_event_msg_t *e, void *data)
2821 {
2822 wl_pfn_net_info_v1_t *netinfo, *pnetinfo;
2823 wl_pfn_net_info_v2_t *netinfo_v2, *pnetinfo_v2;
2824 struct wiphy *wiphy = bcmcfg_to_wiphy(cfg);
2825 dhd_pub_t *dhdp = (dhd_pub_t *)(cfg->pub);
2826 int err = 0;
2827 struct cfg80211_scan_request *request = NULL;
2828 struct cfg80211_ssid ssid[MAX_PFN_LIST_COUNT];
2829 struct ieee80211_channel *channel = NULL;
2830 int channel_req = 0;
2831 int band = 0;
2832 wl_pfn_scanresults_v1_t *pfn_result_v1 = (wl_pfn_scanresults_v1_t *)data;
2833 wl_pfn_scanresults_v2_t *pfn_result_v2 = (wl_pfn_scanresults_v2_t *)data;
2834 int n_pfn_results = 0;
2835 log_conn_event_t *event_data = NULL;
2836 tlv_log *tlv_data = NULL;
2837 u32 alloc_len, tlv_len;
2838 u32 payload_len;
2839 u8 tmp_buf[DOT11_MAX_SSID_LEN + 1];
2840
2841 WL_DBG(("Enter\n"));
2842
2843 /* These static asserts guarantee v1/v2 net_info and subnet_info are compatible
2844 * in size and SSID offset, allowing v1 to be used below except for the results
2845 * fields themselves (status, count, offset to netinfo).
2846 */
2847 STATIC_ASSERT(sizeof(wl_pfn_net_info_v1_t) == sizeof(wl_pfn_net_info_v2_t));
2848 STATIC_ASSERT(sizeof(wl_pfn_lnet_info_v1_t) == sizeof(wl_pfn_lnet_info_v2_t));
2849 STATIC_ASSERT(sizeof(wl_pfn_subnet_info_v1_t) == sizeof(wl_pfn_subnet_info_v2_t));
2850 STATIC_ASSERT(OFFSETOF(wl_pfn_subnet_info_v1_t, SSID) ==
2851 OFFSETOF(wl_pfn_subnet_info_v2_t, u.SSID));
2852
2853 /* Extract the version-specific items */
2854 if (pfn_result_v1->version == PFN_SCANRESULT_VERSION_V1) {
2855 n_pfn_results = pfn_result_v1->count;
2856 pnetinfo = pfn_result_v1->netinfo;
2857 WL_INFORM_MEM(("PFN NET FOUND event. count:%d \n", n_pfn_results));
2858
2859 if (n_pfn_results > 0) {
2860 int i;
2861
2862 if (n_pfn_results > MAX_PFN_LIST_COUNT)
2863 n_pfn_results = MAX_PFN_LIST_COUNT;
2864
2865 bzero(&ssid, sizeof(ssid));
2866
2867 request = (struct cfg80211_scan_request *)MALLOCZ(cfg->osh,
2868 sizeof(*request) + sizeof(*request->channels) * n_pfn_results);
2869 channel = (struct ieee80211_channel *)MALLOCZ(cfg->osh,
2870 (sizeof(struct ieee80211_channel) * n_pfn_results));
2871 if (!request || !channel) {
2872 WL_ERR(("No memory"));
2873 err = -ENOMEM;
2874 goto out_err;
2875 }
2876
2877 request->wiphy = wiphy;
2878
2879 if (DBG_RING_ACTIVE(dhdp, DHD_EVENT_RING_ID)) {
2880 alloc_len = sizeof(log_conn_event_t) + DOT11_MAX_SSID_LEN +
2881 sizeof(uint16) + sizeof(int16);
2882 event_data = (log_conn_event_t *)MALLOC(cfg->osh, alloc_len);
2883 if (!event_data) {
2884 WL_ERR(("%s: failed to allocate the log_conn_event_t with "
2885 "length(%d)\n", __func__, alloc_len));
2886 goto out_err;
2887 }
2888 tlv_len = 3 * sizeof(tlv_log);
2889 event_data->tlvs = (tlv_log *)MALLOC(cfg->osh, tlv_len);
2890 if (!event_data->tlvs) {
2891 WL_ERR(("%s: failed to allocate the tlv_log with "
2892 "length(%d)\n", __func__, tlv_len));
2893 goto out_err;
2894 }
2895 }
2896
2897 for (i = 0; i < n_pfn_results; i++) {
2898 netinfo = &pnetinfo[i];
2899 if (!netinfo) {
2900 WL_ERR(("Invalid netinfo ptr. index:%d", i));
2901 err = -EINVAL;
2902 goto out_err;
2903 }
2904 if (netinfo->pfnsubnet.SSID_len > DOT11_MAX_SSID_LEN) {
2905 WL_ERR(("Wrong SSID length:%d\n",
2906 netinfo->pfnsubnet.SSID_len));
2907 err = -EINVAL;
2908 goto out_err;
2909 }
2910 /* In previous step max SSID_len limited to DOT11_MAX_SSID_LEN
2911 * and tmp_buf size is DOT11_MAX_SSID_LEN+1
2912 */
2913 (void)memcpy_s(tmp_buf, DOT11_MAX_SSID_LEN,
2914 netinfo->pfnsubnet.SSID, netinfo->pfnsubnet.SSID_len);
2915 tmp_buf[netinfo->pfnsubnet.SSID_len] = '\0';
2916 WL_PNO((">>> SSID:%s Channel:%d \n",
2917 tmp_buf, netinfo->pfnsubnet.channel));
2918 /* PFN result doesn't have all the info which are required by
2919 * the supplicant. (For e.g IEs) Do a target Escan so that
2920 * sched scan results are reported via wl_inform_single_bss in
2921 * the required format. Escan does require the scan request in
2922 * the form of cfg80211_scan_request. For timebeing, create
2923 * cfg80211_scan_request one out of the received PNO event.
2924 */
2925
2926 ssid[i].ssid_len = netinfo->pfnsubnet.SSID_len;
2927 /* Returning void as ssid[i].ssid_len is limited to max of
2928 * DOT11_MAX_SSID_LEN
2929 */
2930 (void)memcpy_s(ssid[i].ssid, IEEE80211_MAX_SSID_LEN,
2931 netinfo->pfnsubnet.SSID, ssid[i].ssid_len);
2932 request->n_ssids++;
2933
2934 channel_req = netinfo->pfnsubnet.channel;
2935 band = (channel_req <= CH_MAX_2G_CHANNEL) ? NL80211_BAND_2GHZ
2936 : NL80211_BAND_5GHZ;
2937 channel[i].center_freq =
2938 ieee80211_channel_to_frequency(channel_req, band);
2939 channel[i].band = band;
2940 channel[i].flags |= IEEE80211_CHAN_NO_HT40;
2941 request->channels[i] = &channel[i];
2942 request->n_channels++;
2943
2944 if (DBG_RING_ACTIVE(dhdp, DHD_EVENT_RING_ID)) {
2945 payload_len = sizeof(log_conn_event_t);
2946 event_data->event = WIFI_EVENT_DRIVER_PNO_NETWORK_FOUND;
2947 tlv_data = event_data->tlvs;
2948
2949 /* ssid */
2950 tlv_data->tag = WIFI_TAG_SSID;
2951 tlv_data->len = ssid[i].ssid_len;
2952 (void)memcpy_s(tlv_data->value, DOT11_MAX_SSID_LEN,
2953 ssid[i].ssid, ssid[i].ssid_len);
2954 payload_len += TLV_LOG_SIZE(tlv_data);
2955 tlv_data = TLV_LOG_NEXT(tlv_data);
2956
2957 /* channel */
2958 tlv_data->tag = WIFI_TAG_CHANNEL;
2959 tlv_data->len = sizeof(uint16);
2960 (void)memcpy_s(tlv_data->value, sizeof(uint16),
2961 &channel_req, sizeof(uint16));
2962 payload_len += TLV_LOG_SIZE(tlv_data);
2963 tlv_data = TLV_LOG_NEXT(tlv_data);
2964
2965 /* rssi */
2966 tlv_data->tag = WIFI_TAG_RSSI;
2967 tlv_data->len = sizeof(int16);
2968 (void)memcpy_s(tlv_data->value, sizeof(int16),
2969 &netinfo->RSSI, sizeof(int16));
2970 payload_len += TLV_LOG_SIZE(tlv_data);
2971 tlv_data = TLV_LOG_NEXT(tlv_data);
2972
2973 dhd_os_push_push_ring_data(dhdp, DHD_EVENT_RING_ID,
2974 &event_data->event, payload_len);
2975 }
2976 }
2977
2978 /* assign parsed ssid array */
2979 if (request->n_ssids)
2980 request->ssids = &ssid[0];
2981
2982 if (wl_get_drv_status_all(cfg, SCANNING)) {
2983 /* Abort any on-going scan */
2984 wl_cfg80211_cancel_scan(cfg);
2985 }
2986
2987 if (wl_get_p2p_status(cfg, DISCOVERY_ON)) {
2988 WL_PNO((">>> P2P discovery was ON. Disabling it\n"));
2989 err = wl_cfgp2p_discover_enable_search(cfg, false);
2990 if (unlikely(err)) {
2991 wl_clr_drv_status(cfg, SCANNING, ndev);
2992 goto out_err;
2993 }
2994 p2p_scan(cfg) = false;
2995 }
2996 wl_set_drv_status(cfg, SCANNING, ndev);
2997 #if FULL_ESCAN_ON_PFN_NET_FOUND
2998 WL_PNO((">>> Doing Full ESCAN on PNO event\n"));
2999 err = wl_do_escan(cfg, wiphy, ndev, NULL);
3000 #else
3001 WL_PNO((">>> Doing targeted ESCAN on PNO event\n"));
3002 err = wl_do_escan(cfg, wiphy, ndev, request);
3003 #endif // endif
3004 if (err) {
3005 wl_clr_drv_status(cfg, SCANNING, ndev);
3006 goto out_err;
3007 }
3008 DBG_EVENT_LOG(dhdp, WIFI_EVENT_DRIVER_PNO_SCAN_REQUESTED);
3009 cfg->sched_scan_running = TRUE;
3010 }
3011 else {
3012 WL_ERR(("FALSE PNO Event. (pfn_count == 0) \n"));
3013 }
3014
3015 } else if (pfn_result_v2->version == PFN_SCANRESULT_VERSION_V2) {
3016 n_pfn_results = pfn_result_v2->count;
3017 pnetinfo_v2 = (wl_pfn_net_info_v2_t *)pfn_result_v2->netinfo;
3018
3019 if (e->event_type == WLC_E_PFN_NET_LOST) {
3020 WL_PNO(("Do Nothing %d\n", e->event_type));
3021 return 0;
3022 }
3023
3024 WL_INFORM_MEM(("PFN NET FOUND event. count:%d \n", n_pfn_results));
3025
3026 if (n_pfn_results > 0) {
3027 int i;
3028
3029 if (n_pfn_results > MAX_PFN_LIST_COUNT)
3030 n_pfn_results = MAX_PFN_LIST_COUNT;
3031
3032 bzero(&ssid, sizeof(ssid));
3033
3034 request = (struct cfg80211_scan_request *)MALLOCZ(cfg->osh,
3035 sizeof(*request) + sizeof(*request->channels) * n_pfn_results);
3036 channel = (struct ieee80211_channel *)MALLOCZ(cfg->osh,
3037 (sizeof(struct ieee80211_channel) * n_pfn_results));
3038 if (!request || !channel) {
3039 WL_ERR(("No memory"));
3040 err = -ENOMEM;
3041 goto out_err;
3042 }
3043
3044 request->wiphy = wiphy;
3045
3046 if (DBG_RING_ACTIVE(dhdp, DHD_EVENT_RING_ID)) {
3047 alloc_len = sizeof(log_conn_event_t) + DOT11_MAX_SSID_LEN +
3048 sizeof(uint16) + sizeof(int16);
3049 event_data = (log_conn_event_t *)MALLOC(cfg->osh, alloc_len);
3050 if (!event_data) {
3051 WL_ERR(("%s: failed to allocate the log_conn_event_t with "
3052 "length(%d)\n", __func__, alloc_len));
3053 goto out_err;
3054 }
3055 tlv_len = 3 * sizeof(tlv_log);
3056 event_data->tlvs = (tlv_log *)MALLOC(cfg->osh, tlv_len);
3057 if (!event_data->tlvs) {
3058 WL_ERR(("%s: failed to allocate the tlv_log with "
3059 "length(%d)\n", __func__, tlv_len));
3060 goto out_err;
3061 }
3062 }
3063
3064 for (i = 0; i < n_pfn_results; i++) {
3065 netinfo_v2 = &pnetinfo_v2[i];
3066 if (!netinfo_v2) {
3067 WL_ERR(("Invalid netinfo ptr. index:%d", i));
3068 err = -EINVAL;
3069 goto out_err;
3070 }
3071 WL_PNO((">>> SSID:%s Channel:%d \n",
3072 netinfo_v2->pfnsubnet.u.SSID,
3073 netinfo_v2->pfnsubnet.channel));
3074 /* PFN result doesn't have all the info which are required by the
3075 * supplicant. (For e.g IEs) Do a target Escan so that sched scan
3076 * results are reported via wl_inform_single_bss in the required
3077 * format. Escan does require the scan request in the form of
3078 * cfg80211_scan_request. For timebeing, create
3079 * cfg80211_scan_request one out of the received PNO event.
3080 */
3081 ssid[i].ssid_len = MIN(DOT11_MAX_SSID_LEN,
3082 netinfo_v2->pfnsubnet.SSID_len);
3083 /* max ssid_len as in previous step DOT11_MAX_SSID_LEN is same
3084 * as DOT11_MAX_SSID_LEN = 32
3085 */
3086 (void)memcpy_s(ssid[i].ssid, IEEE80211_MAX_SSID_LEN,
3087 netinfo_v2->pfnsubnet.u.SSID, ssid[i].ssid_len);
3088 request->n_ssids++;
3089
3090 channel_req = netinfo_v2->pfnsubnet.channel;
3091 band = (channel_req <= CH_MAX_2G_CHANNEL) ? NL80211_BAND_2GHZ
3092 : NL80211_BAND_5GHZ;
3093 channel[i].center_freq =
3094 ieee80211_channel_to_frequency(channel_req, band);
3095 channel[i].band = band;
3096 channel[i].flags |= IEEE80211_CHAN_NO_HT40;
3097 request->channels[i] = &channel[i];
3098 request->n_channels++;
3099
3100 if (DBG_RING_ACTIVE(dhdp, DHD_EVENT_RING_ID)) {
3101 payload_len = sizeof(log_conn_event_t);
3102 event_data->event = WIFI_EVENT_DRIVER_PNO_NETWORK_FOUND;
3103 tlv_data = event_data->tlvs;
3104
3105 /* ssid */
3106 tlv_data->tag = WIFI_TAG_SSID;
3107 tlv_data->len = netinfo_v2->pfnsubnet.SSID_len;
3108 (void)memcpy_s(tlv_data->value, DOT11_MAX_SSID_LEN,
3109 ssid[i].ssid, ssid[i].ssid_len);
3110 payload_len += TLV_LOG_SIZE(tlv_data);
3111 tlv_data = TLV_LOG_NEXT(tlv_data);
3112
3113 /* channel */
3114 tlv_data->tag = WIFI_TAG_CHANNEL;
3115 tlv_data->len = sizeof(uint16);
3116 (void)memcpy_s(tlv_data->value, sizeof(uint16),
3117 &channel_req, sizeof(uint16));
3118 payload_len += TLV_LOG_SIZE(tlv_data);
3119 tlv_data = TLV_LOG_NEXT(tlv_data);
3120
3121 /* rssi */
3122 tlv_data->tag = WIFI_TAG_RSSI;
3123 tlv_data->len = sizeof(int16);
3124 (void)memcpy_s(tlv_data->value, sizeof(uint16),
3125 &netinfo_v2->RSSI, sizeof(int16));
3126 payload_len += TLV_LOG_SIZE(tlv_data);
3127 tlv_data = TLV_LOG_NEXT(tlv_data);
3128
3129 dhd_os_push_push_ring_data(dhdp, DHD_EVENT_RING_ID,
3130 &event_data->event, payload_len);
3131 }
3132 }
3133
3134 /* assign parsed ssid array */
3135 if (request->n_ssids)
3136 request->ssids = &ssid[0];
3137
3138 if (wl_get_drv_status_all(cfg, SCANNING)) {
3139 /* Abort any on-going scan */
3140 wl_cfg80211_cancel_scan(cfg);
3141 }
3142
3143 if (wl_get_p2p_status(cfg, DISCOVERY_ON)) {
3144 WL_PNO((">>> P2P discovery was ON. Disabling it\n"));
3145 err = wl_cfgp2p_discover_enable_search(cfg, false);
3146 if (unlikely(err)) {
3147 wl_clr_drv_status(cfg, SCANNING, ndev);
3148 goto out_err;
3149 }
3150 p2p_scan(cfg) = false;
3151 }
3152
3153 wl_set_drv_status(cfg, SCANNING, ndev);
3154 #if FULL_ESCAN_ON_PFN_NET_FOUND
3155 WL_PNO((">>> Doing Full ESCAN on PNO event\n"));
3156 err = wl_do_escan(cfg, wiphy, ndev, NULL);
3157 #else
3158 WL_PNO((">>> Doing targeted ESCAN on PNO event\n"));
3159 err = wl_do_escan(cfg, wiphy, ndev, request);
3160 #endif // endif
3161 if (err) {
3162 wl_clr_drv_status(cfg, SCANNING, ndev);
3163 goto out_err;
3164 }
3165 DBG_EVENT_LOG(dhdp, WIFI_EVENT_DRIVER_PNO_SCAN_REQUESTED);
3166 cfg->sched_scan_running = TRUE;
3167 }
3168 else {
3169 WL_ERR(("FALSE PNO Event. (pfn_count == 0) \n"));
3170 }
3171 } else {
3172 WL_ERR(("Unsupported version %d, expected %d or %d\n", pfn_result_v1->version,
3173 PFN_SCANRESULT_VERSION_V1, PFN_SCANRESULT_VERSION_V2));
3174 return 0;
3175 }
3176 out_err:
3177 if (request) {
3178 MFREE(cfg->osh, request,
3179 sizeof(*request) + sizeof(*request->channels) * n_pfn_results);
3180 }
3181 if (channel) {
3182 MFREE(cfg->osh, channel,
3183 (sizeof(struct ieee80211_channel) * n_pfn_results));
3184 }
3185
3186 if (event_data) {
3187 if (event_data->tlvs) {
3188 MFREE(cfg->osh, event_data->tlvs, tlv_len);
3189 }
3190 MFREE(cfg->osh, event_data, alloc_len);
3191 }
3192 return err;
3193 }
3194 #endif /* WL_SCHED_SCAN */
3195
3196 #ifdef PNO_SUPPORT
3197 s32
wl_notify_pfn_status(struct bcm_cfg80211 * cfg,bcm_struct_cfgdev * cfgdev,const wl_event_msg_t * e,void * data)3198 wl_notify_pfn_status(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev,
3199 const wl_event_msg_t *e, void *data)
3200 {
3201 struct net_device *ndev = NULL;
3202 #ifdef GSCAN_SUPPORT
3203 void *ptr;
3204 int send_evt_bytes = 0;
3205 u32 event = be32_to_cpu(e->event_type);
3206 struct wiphy *wiphy = bcmcfg_to_wiphy(cfg);
3207 #endif /* GSCAN_SUPPORT */
3208
3209 WL_INFORM_MEM((">>> PNO Event\n"));
3210
3211 if (!data) {
3212 WL_ERR(("Data received is NULL!\n"));
3213 return 0;
3214 }
3215
3216 ndev = cfgdev_to_wlc_ndev(cfgdev, cfg);
3217 #ifdef GSCAN_SUPPORT
3218 ptr = dhd_dev_process_epno_result(ndev, data, event, &send_evt_bytes);
3219 if (ptr) {
3220 wl_cfgvendor_send_async_event(wiphy, ndev,
3221 GOOGLE_SCAN_EPNO_EVENT, ptr, send_evt_bytes);
3222 MFREE(cfg->osh, ptr, send_evt_bytes);
3223 }
3224 if (!dhd_dev_is_legacy_pno_enabled(ndev))
3225 return 0;
3226 #endif /* GSCAN_SUPPORT */
3227
3228 #ifndef WL_SCHED_SCAN
3229 mutex_lock(&cfg->usr_sync);
3230 /* TODO: Use cfg80211_sched_scan_results(wiphy); */
3231 CFG80211_DISCONNECTED(ndev, 0, NULL, 0, false, GFP_KERNEL);
3232 mutex_unlock(&cfg->usr_sync);
3233 #else
3234 /* If cfg80211 scheduled scan is supported, report the pno results via sched
3235 * scan results
3236 */
3237 wl_notify_sched_scan_results(cfg, ndev, e, data);
3238 #endif /* WL_SCHED_SCAN */
3239 return 0;
3240 }
3241 #endif /* PNO_SUPPORT */
3242
3243 #ifdef GSCAN_SUPPORT
3244 s32
wl_notify_gscan_event(struct bcm_cfg80211 * cfg,bcm_struct_cfgdev * cfgdev,const wl_event_msg_t * e,void * data)3245 wl_notify_gscan_event(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev,
3246 const wl_event_msg_t *e, void *data)
3247 {
3248 s32 err = 0;
3249 u32 event = be32_to_cpu(e->event_type);
3250 void *ptr = NULL;
3251 int send_evt_bytes = 0;
3252 int event_type;
3253 struct net_device *ndev = cfgdev_to_wlc_ndev(cfgdev, cfg);
3254 struct wiphy *wiphy = bcmcfg_to_wiphy(cfg);
3255 u32 len = ntoh32(e->datalen);
3256 u32 buf_len = 0;
3257
3258 switch (event) {
3259 case WLC_E_PFN_BEST_BATCHING:
3260 err = dhd_dev_retrieve_batch_scan(ndev);
3261 if (err < 0) {
3262 WL_ERR(("Batch retrieval already in progress %d\n", err));
3263 } else {
3264 event_type = WIFI_SCAN_THRESHOLD_NUM_SCANS;
3265 if (data && len) {
3266 event_type = *((int *)data);
3267 }
3268 wl_cfgvendor_send_async_event(wiphy, ndev,
3269 GOOGLE_GSCAN_BATCH_SCAN_EVENT,
3270 &event_type, sizeof(int));
3271 }
3272 break;
3273 case WLC_E_PFN_SCAN_COMPLETE:
3274 event_type = WIFI_SCAN_COMPLETE;
3275 wl_cfgvendor_send_async_event(wiphy, ndev,
3276 GOOGLE_SCAN_COMPLETE_EVENT,
3277 &event_type, sizeof(int));
3278 break;
3279 case WLC_E_PFN_BSSID_NET_FOUND:
3280 ptr = dhd_dev_hotlist_scan_event(ndev, data, &send_evt_bytes,
3281 HOTLIST_FOUND, &buf_len);
3282 if (ptr) {
3283 wl_cfgvendor_send_hotlist_event(wiphy, ndev,
3284 ptr, send_evt_bytes, GOOGLE_GSCAN_GEOFENCE_FOUND_EVENT);
3285 dhd_dev_gscan_hotlist_cache_cleanup(ndev, HOTLIST_FOUND);
3286 } else {
3287 err = -ENOMEM;
3288 }
3289 break;
3290 case WLC_E_PFN_BSSID_NET_LOST:
3291 /* WLC_E_PFN_BSSID_NET_LOST is conflict shared with WLC_E_PFN_SCAN_ALLGONE
3292 * We currently do not use WLC_E_PFN_SCAN_ALLGONE, so if we get it, ignore
3293 */
3294 if (len) {
3295 ptr = dhd_dev_hotlist_scan_event(ndev, data, &send_evt_bytes,
3296 HOTLIST_LOST, &buf_len);
3297 if (ptr) {
3298 wl_cfgvendor_send_hotlist_event(wiphy, ndev,
3299 ptr, send_evt_bytes, GOOGLE_GSCAN_GEOFENCE_LOST_EVENT);
3300 dhd_dev_gscan_hotlist_cache_cleanup(ndev, HOTLIST_LOST);
3301 MFREE(cfg->osh, ptr, buf_len);
3302 } else {
3303 err = -ENOMEM;
3304 }
3305 } else {
3306 err = -EINVAL;
3307 }
3308 break;
3309 case WLC_E_PFN_GSCAN_FULL_RESULT:
3310 ptr = dhd_dev_process_full_gscan_result(ndev, data, len, &send_evt_bytes);
3311 if (ptr) {
3312 wl_cfgvendor_send_async_event(wiphy, ndev,
3313 GOOGLE_SCAN_FULL_RESULTS_EVENT, ptr, send_evt_bytes);
3314 MFREE(cfg->osh, ptr, send_evt_bytes);
3315 } else {
3316 err = -ENOMEM;
3317 }
3318 break;
3319 case WLC_E_PFN_SSID_EXT:
3320 ptr = dhd_dev_process_epno_result(ndev, data, event, &send_evt_bytes);
3321 if (ptr) {
3322 wl_cfgvendor_send_async_event(wiphy, ndev,
3323 GOOGLE_SCAN_EPNO_EVENT, ptr, send_evt_bytes);
3324 MFREE(cfg->osh, ptr, send_evt_bytes);
3325 } else {
3326 err = -ENOMEM;
3327 }
3328 break;
3329 default:
3330 WL_ERR(("Unknown event %d\n", event));
3331 break;
3332 }
3333 return err;
3334 }
3335 #endif /* GSCAN_SUPPORT */
3336
wl_cfg80211_set_passive_scan(struct net_device * dev,char * command)3337 void wl_cfg80211_set_passive_scan(struct net_device *dev, char *command)
3338 {
3339 struct bcm_cfg80211 *cfg = wl_get_cfg(dev);
3340
3341 if (strcmp(command, "SCAN-ACTIVE") == 0) {
3342 cfg->active_scan = 1;
3343 } else if (strcmp(command, "SCAN-PASSIVE") == 0) {
3344 cfg->active_scan = 0;
3345 } else
3346 WL_ERR(("Unknown command \n"));
3347 return;
3348 }
3349