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