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