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