xref: /OK3568_Linux_fs/kernel/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/wl_cfgscan.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1 /*
2  * Linux cfg80211 driver scan related code
3  *
4  * Copyright (C) 2020, Broadcom.
5  *
6  *      Unless you and Broadcom execute a separate written software license
7  * agreement governing use of this software, this software is licensed to you
8  * under the terms of the GNU General Public License version 2 (the "GPL"),
9  * available at http://www.broadcom.com/licenses/GPLv2.php, with the
10  * following added to such license:
11  *
12  *      As a special exception, the copyright holders of this software give you
13  * permission to link this software with independent modules, and to copy and
14  * distribute the resulting executable under terms of your choice, provided that
15  * you also meet, for each linked independent module, the terms and conditions of
16  * the license of that module.  An independent module is a module which is not
17  * derived from this software.  The special exception does not apply to any
18  * modifications of the software.
19  *
20  *
21  * <<Broadcom-WL-IPTag/Dual:>>
22  */
23 /* */
24 #include <typedefs.h>
25 #include <linuxver.h>
26 #include <osl.h>
27 #include <linux/kernel.h>
28 
29 #include <bcmutils.h>
30 #include <bcmstdlib_s.h>
31 #include <bcmwifi_channels.h>
32 #include <bcmendian.h>
33 #include <ethernet.h>
34 #include <802.11.h>
35 #include <bcmiov.h>
36 #include <linux/if_arp.h>
37 #include <asm/uaccess.h>
38 
39 #include <ethernet.h>
40 #include <linux/kernel.h>
41 #include <linux/kthread.h>
42 #include <linux/netdevice.h>
43 #include <linux/sched.h>
44 #include <linux/etherdevice.h>
45 #include <linux/wireless.h>
46 #include <linux/ieee80211.h>
47 #include <linux/wait.h>
48 #if defined(CONFIG_TIZEN)
49 #include <linux/net_stat_tizen.h>
50 #endif /* CONFIG_TIZEN */
51 #include <net/cfg80211.h>
52 #include <net/rtnetlink.h>
53 
54 #include <wlioctl.h>
55 #include <bcmevent.h>
56 #include <wldev_common.h>
57 #include <wl_cfg80211.h>
58 #include <wl_cfgscan.h>
59 #include <wl_cfgp2p.h>
60 #include <wl_cfgvif.h>
61 #include <bcmdevs.h>
62 
63 #ifdef OEM_ANDROID
64 #include <wl_android.h>
65 #endif
66 
67 #if defined(BCMDONGLEHOST)
68 #include <dngl_stats.h>
69 #include <dhd.h>
70 #include <dhd_linux.h>
71 #include <dhd_debug.h>
72 #include <dhdioctl.h>
73 #include <wlioctl.h>
74 #include <dhd_cfg80211.h>
75 #include <dhd_bus.h>
76 #include <wl_cfgvendor.h>
77 #endif /* defined(BCMDONGLEHOST) */
78 #ifdef BCMPCIE
79 #include <dhd_flowring.h>
80 #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 #include <dhd_config.h>
88 
89 #define ACTIVE_SCAN 1
90 #define PASSIVE_SCAN 0
91 
92 #define MIN_P2P_IE_LEN	8	/* p2p_ie->OUI(3) + p2p_ie->oui_type(1) +
93 				 * Attribute ID(1) + Length(2) + 1(Mininum length:1)
94 				 */
95 #define MAX_P2P_IE_LEN	251	/* Up To 251 */
96 
97 #define WPS_ATTR_REQ_TYPE 0x103a
98 #define WPS_REQ_TYPE_ENROLLEE 0x01
99 #define SCAN_WAKE_LOCK_MARGIN_MS 500
100 
101 #if defined(WL_CFG80211_P2P_DEV_IF)
102 #define CFG80211_READY_ON_CHANNEL(cfgdev, cookie, channel, channel_type, duration, flags) \
103 	cfg80211_ready_on_channel(cfgdev, cookie, channel, duration, GFP_KERNEL);
104 #else
105 #define CFG80211_READY_ON_CHANNEL(cfgdev, cookie, channel, channel_type, duration, flags) \
106 	cfg80211_ready_on_channel(cfgdev, cookie, channel, channel_type, duration, GFP_KERNEL);
107 #endif /* WL_CFG80211_P2P_DEV_IF */
108 
109 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0))
110 #define CFG80211_SCHED_SCAN_STOPPED(wiphy, schedscan_req) \
111 	cfg80211_sched_scan_stopped(wiphy, schedscan_req->reqid);
112 #else
113 #define CFG80211_SCHED_SCAN_STOPPED(wiphy, schedscan_req) \
114 	cfg80211_sched_scan_stopped(wiphy);
115 #endif /* KERNEL > 4.11.0 */
116 
117 #ifdef DHD_GET_VALID_CHANNELS
118 #define IS_DFS(chaninfo) ((chaninfo & WL_CHAN_RADAR) || \
119 	 (chaninfo & WL_CHAN_PASSIVE))
120 #endif /* DHD_GET_VALID_CHANNELS */
121 
122 #if defined(USE_INITIAL_2G_SCAN) || defined(USE_INITIAL_SHORT_DWELL_TIME)
123 #define FIRST_SCAN_ACTIVE_DWELL_TIME_MS 40
124 bool g_first_broadcast_scan = TRUE;
125 #endif /* USE_INITIAL_2G_SCAN || USE_INITIAL_SHORT_DWELL_TIME */
126 #ifdef CUSTOMER_HW4_DEBUG
127 bool wl_scan_timeout_dbg_enabled = 0;
128 #endif /* CUSTOMER_HW4_DEBUG */
129 #ifdef P2P_LISTEN_OFFLOADING
130 void wl_cfg80211_cancel_p2plo(struct bcm_cfg80211 *cfg);
131 #endif /* P2P_LISTEN_OFFLOADING */
132 static void _wl_notify_scan_done(struct bcm_cfg80211 *cfg, bool aborted);
133 static s32 wl_notify_escan_complete(struct bcm_cfg80211 *cfg,
134 	struct net_device *ndev, bool aborted);
135 void wl_cfgscan_scan_abort(struct bcm_cfg80211 *cfg);
136 static void _wl_cfgscan_cancel_scan(struct bcm_cfg80211 *cfg);
137 
138 #if defined (WL_SCHED_SCAN) && defined (SCHED_SCAN_DELAYED_WORK)
139 void wl_cfg80211_stop_pno(struct bcm_cfg80211 *cfg, struct net_device *dev);
140 #endif /* WL_SCHED_SCAN */
141 
142 #ifdef ESCAN_CHANNEL_CACHE
143 void reset_roam_cache(struct bcm_cfg80211 *cfg);
144 void add_roam_cache(struct bcm_cfg80211 *cfg, wl_bss_info_t *bi);
145 int get_roam_channel_list(struct bcm_cfg80211 *cfg, chanspec_t target_chan, chanspec_t *channels,
146 	int n_channels, const wlc_ssid_t *ssid, int ioctl_ver);
147 void set_roam_band(int band);
148 #endif /* ESCAN_CHANNEL_CACHE */
149 
150 #ifdef ROAM_CHANNEL_CACHE
151 void print_roam_cache(struct bcm_cfg80211 *cfg);
152 #endif /* ROAM_CHANNEL_CACHE */
153 
154 extern int passive_channel_skip;
155 
156 #ifdef DUAL_ESCAN_RESULT_BUFFER
157 static wl_scan_results_t *
wl_escan_get_buf(struct bcm_cfg80211 * cfg,bool aborted)158 wl_escan_get_buf(struct bcm_cfg80211 *cfg, bool aborted)
159 {
160 	u8 index;
161 	if (aborted) {
162 		if (cfg->escan_info.escan_type[0] == cfg->escan_info.escan_type[1]) {
163 			index = (cfg->escan_info.cur_sync_id + 1)%SCAN_BUF_CNT;
164 		} else {
165 			index = (cfg->escan_info.cur_sync_id)%SCAN_BUF_CNT;
166 		}
167 	} else {
168 		index = (cfg->escan_info.cur_sync_id)%SCAN_BUF_CNT;
169 	}
170 
171 	return (wl_scan_results_t *)cfg->escan_info.escan_buf[index];
172 }
173 static int
wl_escan_check_sync_id(struct bcm_cfg80211 * cfg,s32 status,u16 result_id,u16 wl_id)174 wl_escan_check_sync_id(struct bcm_cfg80211 *cfg, s32 status, u16 result_id, u16 wl_id)
175 {
176 	if (result_id != wl_id) {
177 		WL_ERR(("ESCAN sync id mismatch :status :%d "
178 			"cur_sync_id:%d coming sync_id:%d\n",
179 			status, wl_id, result_id));
180 #ifdef DHD_SEND_HANG_ESCAN_SYNCID_MISMATCH
181 		if (cfg->escan_info.prev_escan_aborted == FALSE) {
182 			wl_cfg80211_handle_hang_event(bcmcfg_to_prmry_ndev(cfg),
183 				HANG_REASON_ESCAN_SYNCID_MISMATCH, DUMP_TYPE_ESCAN_SYNCID_MISMATCH);
184 		}
185 #endif /* DHD_SEND_HANG_ESCAN_SYNCID_MISMATCH */
186 		return -1;
187 	} else {
188 		return 0;
189 	}
190 }
191 #define wl_escan_increment_sync_id(a, b) ((a)->escan_info.cur_sync_id += b)
192 #define wl_escan_init_sync_id(a) ((a)->escan_info.cur_sync_id = 0)
193 #else
194 #define wl_escan_get_buf(a, b) ((wl_scan_results_t *) (a)->escan_info.escan_buf)
195 #define wl_escan_check_sync_id(a, b, c, d) 0
196 #define wl_escan_increment_sync_id(a, b)
197 #define wl_escan_init_sync_id(a)
198 #endif /* DUAL_ESCAN_RESULT_BUFFER */
199 
200 /*
201  * information element utilities
202  */
wl_rst_ie(struct bcm_cfg80211 * cfg)203 static void wl_rst_ie(struct bcm_cfg80211 *cfg)
204 {
205 	struct wl_ie *ie = wl_to_ie(cfg);
206 
207 	ie->offset = 0;
208 	bzero(ie->buf, sizeof(ie->buf));
209 }
210 
wl_update_hidden_ap_ie(wl_bss_info_t * bi,const u8 * ie_stream,u32 * ie_size,bool update_ssid)211 static void wl_update_hidden_ap_ie(wl_bss_info_t *bi, const u8 *ie_stream, u32 *ie_size,
212 	bool update_ssid)
213 {
214 	u8 *ssidie;
215 	int32 ssid_len = MIN(bi->SSID_len, DOT11_MAX_SSID_LEN);
216 	int32 remaining_ie_buf_len, available_buffer_len, unused_buf_len;
217 	/* cfg80211_find_ie defined in kernel returning const u8 */
218 
219 	GCC_DIAGNOSTIC_PUSH_SUPPRESS_CAST();
220 	ssidie = (u8 *)cfg80211_find_ie(WLAN_EID_SSID, ie_stream, *ie_size);
221 	GCC_DIAGNOSTIC_POP();
222 
223 	/* ERROR out if
224 	 * 1. No ssid IE is FOUND or
225 	 * 2. New ssid length is > what was allocated for existing ssid (as
226 	 * we do not want to overwrite the rest of the IEs) or
227 	 * 3. If in case of erroneous buffer input where ssid length doesnt match the space
228 	 * allocated to it.
229 	 */
230 	if (!ssidie) {
231 		return;
232 	}
233 	available_buffer_len = ((int)(*ie_size)) - (ssidie + 2 - ie_stream);
234 	remaining_ie_buf_len = available_buffer_len - (int)ssidie[1];
235 	unused_buf_len = WL_EXTRA_BUF_MAX - (4 + bi->length + *ie_size);
236 	if (ssidie[1] > available_buffer_len) {
237 		WL_ERR_MEM(("wl_update_hidden_ap_ie: skip wl_update_hidden_ap_ie : overflow\n"));
238 		return;
239 	}
240 
241 	/* ssidie[1] can be different with bi->SSID_len only if roaming status
242 	 * On scanning the values will be same each other.
243 	 */
244 
245 	if (ssidie[1] != ssid_len) {
246 		if (ssidie[1]) {
247 			WL_ERR_RLMT(("wl_update_hidden_ap_ie: Wrong SSID len: %d != %d\n",
248 				ssidie[1], bi->SSID_len));
249 		}
250 		/* ssidie[1] is 1 in beacon on CISCO hidden networks. */
251 		/*
252 		 * The bss info in firmware gets updated from beacon and probe resp.
253 		 * In case of hidden network, the bss_info that got updated by beacon,
254 		 * will not carry SSID and this can result in cfg80211_get_bss not finding a match.
255 		 * so include the SSID element.
256 		 */
257 		if ((update_ssid && (ssid_len > ssidie[1])) && (unused_buf_len > ssid_len)) {
258 			WL_INFORM_MEM(("Changing the SSID Info.\n"));
259 			memmove(ssidie + ssid_len + 2,
260 				(ssidie + 2) + ssidie[1],
261 				remaining_ie_buf_len);
262 			memcpy(ssidie + 2, bi->SSID, ssid_len);
263 			*ie_size = *ie_size + ssid_len - ssidie[1];
264 			ssidie[1] = ssid_len;
265 		} else if (ssid_len < ssidie[1]) {
266 			WL_ERR_MEM(("wl_update_hidden_ap_ie: Invalid SSID len: %d < %d\n",
267 				bi->SSID_len, ssidie[1]));
268 		}
269 		return;
270 	}
271 	if (*(ssidie + 2) == '\0')
272 		 memcpy(ssidie + 2, bi->SSID, ssid_len);
273 	return;
274 }
275 
wl_mrg_ie(struct bcm_cfg80211 * cfg,u8 * ie_stream,u16 ie_size)276 static s32 wl_mrg_ie(struct bcm_cfg80211 *cfg, u8 *ie_stream, u16 ie_size)
277 {
278 	struct wl_ie *ie = wl_to_ie(cfg);
279 	s32 err = 0;
280 
281 	if (unlikely(ie->offset + ie_size > WL_TLV_INFO_MAX)) {
282 		WL_ERR(("ei_stream crosses buffer boundary\n"));
283 		return -ENOSPC;
284 	}
285 	memcpy(&ie->buf[ie->offset], ie_stream, ie_size);
286 	ie->offset += ie_size;
287 
288 	return err;
289 }
290 
wl_cp_ie(struct bcm_cfg80211 * cfg,u8 * dst,u16 dst_size)291 static s32 wl_cp_ie(struct bcm_cfg80211 *cfg, u8 *dst, u16 dst_size)
292 {
293 	struct wl_ie *ie = wl_to_ie(cfg);
294 	s32 err = 0;
295 
296 	if (unlikely(ie->offset > dst_size)) {
297 		WL_ERR(("dst_size is not enough\n"));
298 		return -ENOSPC;
299 	}
300 	memcpy(dst, &ie->buf[0], ie->offset);
301 
302 	return err;
303 }
304 
wl_get_ielen(struct bcm_cfg80211 * cfg)305 static u32 wl_get_ielen(struct bcm_cfg80211 *cfg)
306 {
307 	struct wl_ie *ie = wl_to_ie(cfg);
308 
309 	return ie->offset;
310 }
311 
wl_inform_single_bss(struct bcm_cfg80211 * cfg,wl_bss_info_t * bi,bool update_ssid)312 s32 wl_inform_single_bss(struct bcm_cfg80211 *cfg, wl_bss_info_t *bi, bool update_ssid)
313 {
314 	struct wiphy *wiphy = bcmcfg_to_wiphy(cfg);
315 	struct ieee80211_mgmt *mgmt;
316 	struct ieee80211_channel *channel;
317 	struct wl_cfg80211_bss_info *notif_bss_info;
318 	struct wl_scan_req *sr = wl_to_sr(cfg);
319 	struct beacon_proberesp *beacon_proberesp;
320 	struct cfg80211_bss *cbss = NULL;
321 	dhd_pub_t *dhdp = (dhd_pub_t *)(cfg->pub);
322 	log_conn_event_t *event_data = NULL;
323 	tlv_log *tlv_data = NULL;
324 	u32 alloc_len;
325 	u32 payload_len;
326 	s32 mgmt_type;
327 	s32 signal;
328 	u32 freq;
329 	s32 err = 0;
330 	gfp_t aflags;
331 	u8 tmp_buf[IEEE80211_MAX_SSID_LEN + 1];
332 	chanspec_t chanspec;
333 
334 	if (unlikely(dtoh32(bi->length) > WL_BSS_INFO_MAX)) {
335 		WL_DBG(("Beacon is larger than buffer. Discarding\n"));
336 		return err;
337 	}
338 
339 	if (bi->SSID_len > IEEE80211_MAX_SSID_LEN) {
340 		WL_ERR(("wrong SSID len:%d\n", bi->SSID_len));
341 		return -EINVAL;
342 	}
343 
344 	aflags = (in_atomic()) ? GFP_ATOMIC : GFP_KERNEL;
345 	notif_bss_info = (struct wl_cfg80211_bss_info *)MALLOCZ(cfg->osh,
346 		sizeof(*notif_bss_info) + sizeof(*mgmt) - sizeof(u8) + WL_BSS_INFO_MAX);
347 	if (unlikely(!notif_bss_info)) {
348 		WL_ERR(("notif_bss_info alloc failed\n"));
349 		return -ENOMEM;
350 	}
351 	/* Check for all currently supported bands */
352 	if (!(
353 #ifdef WL_6G_BAND
354 		CHSPEC_IS6G(bi->chanspec) ||
355 #endif /* WL_6G_BAND */
356 		CHSPEC_IS5G(bi->chanspec) || CHSPEC_IS2G(bi->chanspec))) {
357 		WL_ERR(("No valid band"));
358 		MFREE(cfg->osh, notif_bss_info, sizeof(*notif_bss_info)
359 			+ sizeof(*mgmt) - sizeof(u8) + WL_BSS_INFO_MAX);
360 		return -EINVAL;
361 	}
362 
363 	mgmt = (struct ieee80211_mgmt *)notif_bss_info->frame_buf;
364 	chanspec = wl_chspec_driver_to_host(bi->chanspec);
365 	notif_bss_info->channel = wf_chspec_ctlchan(chanspec);
366 	notif_bss_info->band = CHSPEC_BAND(bi->chanspec);
367 	notif_bss_info->rssi = dtoh16(bi->RSSI);
368 #if defined(RSSIAVG)
369 	notif_bss_info->rssi = wl_get_avg_rssi(&cfg->g_rssi_cache_ctrl, &bi->BSSID);
370 	if (notif_bss_info->rssi == RSSI_MINVAL)
371 		notif_bss_info->rssi = MIN(dtoh16(bi->RSSI), RSSI_MAXVAL);
372 #endif
373 #if defined(RSSIOFFSET)
374 	notif_bss_info->rssi = wl_update_rssi_offset(bcmcfg_to_prmry_ndev(cfg), notif_bss_info->rssi);
375 #endif
376 #if !defined(RSSIAVG) && !defined(RSSIOFFSET)
377 	// terence 20150419: limit the max. rssi to -2 or the bss will be filtered out in android OS
378 	notif_bss_info->rssi = MIN(notif_bss_info->rssi, RSSI_MAXVAL);
379 #endif
380 	memcpy(mgmt->bssid, &bi->BSSID, ETHER_ADDR_LEN);
381 	mgmt_type = cfg->active_scan ?
382 		IEEE80211_STYPE_PROBE_RESP : IEEE80211_STYPE_BEACON;
383 	if (!memcmp(bi->SSID, sr->ssid.SSID, bi->SSID_len)) {
384 	    mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | mgmt_type);
385 	}
386 	beacon_proberesp = cfg->active_scan ?
387 		(struct beacon_proberesp *)&mgmt->u.probe_resp :
388 		(struct beacon_proberesp *)&mgmt->u.beacon;
389 	beacon_proberesp->timestamp = 0;
390 	beacon_proberesp->beacon_int = cpu_to_le16(bi->beacon_period);
391 	beacon_proberesp->capab_info = cpu_to_le16(bi->capability);
392 	wl_rst_ie(cfg);
393 	wl_update_hidden_ap_ie(bi, ((u8 *) bi) + bi->ie_offset, &bi->ie_length, update_ssid);
394 	wl_mrg_ie(cfg, ((u8 *) bi) + bi->ie_offset, bi->ie_length);
395 	wl_cp_ie(cfg, beacon_proberesp->variable, WL_BSS_INFO_MAX -
396 		offsetof(struct wl_cfg80211_bss_info, frame_buf));
397 	notif_bss_info->frame_len = offsetof(struct ieee80211_mgmt,
398 		u.beacon.variable) + wl_get_ielen(cfg);
399 	freq = wl_channel_to_frequency(notif_bss_info->channel, notif_bss_info->band);
400 	if (freq == 0) {
401 		WL_ERR(("Invalid channel, failed to change channel to freq\n"));
402 		MFREE(cfg->osh, notif_bss_info, sizeof(*notif_bss_info)
403 			+ sizeof(*mgmt) - sizeof(u8) + WL_BSS_INFO_MAX);
404 		return -EINVAL;
405 	}
406 	channel = ieee80211_get_channel(wiphy, freq);
407 	memcpy(tmp_buf, bi->SSID, bi->SSID_len);
408 	tmp_buf[bi->SSID_len] = '\0';
409 	WL_SCAN(("BSSID %pM, channel %3d(%3d %3sMHz), rssi %3d, capa 0x%-4x, mgmt_type %d, "
410 		"frame_len %3d, SSID \"%s\"\n",
411 		&bi->BSSID, notif_bss_info->channel, CHSPEC_CHANNEL(chanspec),
412 		CHSPEC_IS20(chanspec)?"20":
413 		CHSPEC_IS40(chanspec)?"40":
414 		CHSPEC_IS80(chanspec)?"80":
415 		CHSPEC_IS160(chanspec)?"160":"??",
416 		notif_bss_info->rssi, mgmt->u.beacon.capab_info, mgmt_type,
417 		notif_bss_info->frame_len, tmp_buf));
418 	if (unlikely(!channel)) {
419 		WL_ERR(("ieee80211_get_channel error\n"));
420 		MFREE(cfg->osh, notif_bss_info, sizeof(*notif_bss_info)
421 			+ sizeof(*mgmt) - sizeof(u8) + WL_BSS_INFO_MAX);
422 		return -EINVAL;
423 	}
424 
425 	signal = notif_bss_info->rssi * 100;
426 	if (!mgmt->u.probe_resp.timestamp) {
427 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 39))
428 		struct osl_timespec ts;
429 		osl_get_monotonic_boottime(&ts);
430 		mgmt->u.probe_resp.timestamp = ((u64)ts.tv_sec*1000000)
431 				+ ts.tv_nsec / 1000;
432 #else
433 		struct osl_timespec tv;
434 		osl_do_gettimeofday(&tv);
435 		mgmt->u.probe_resp.timestamp = ((u64)tv.tv_sec*1000000)
436 				+ tv.tv_usec;
437 #endif
438 	}
439 
440 	cbss = cfg80211_inform_bss_frame(wiphy, channel, mgmt,
441 		le16_to_cpu(notif_bss_info->frame_len), signal, aflags);
442 	if (unlikely(!cbss)) {
443 		WL_ERR(("cfg80211_inform_bss_frame error bssid " MACDBG " channel %d \n",
444 			MAC2STRDBG((u8*)(&bi->BSSID)), notif_bss_info->channel));
445 		err = -EINVAL;
446 		goto out_err;
447 	}
448 
449 	CFG80211_PUT_BSS(wiphy, cbss);
450 
451 	if (DBG_RING_ACTIVE(dhdp, DHD_EVENT_RING_ID) &&
452 			(cfg->sched_scan_req && !cfg->scan_request)) {
453 		alloc_len = sizeof(log_conn_event_t) + (3 * sizeof(tlv_log)) +
454 			IEEE80211_MAX_SSID_LEN + sizeof(uint16) +
455 			sizeof(int16);
456 		event_data = (log_conn_event_t *)MALLOCZ(dhdp->osh, alloc_len);
457 		if (!event_data) {
458 			WL_ERR(("%s: failed to allocate the log_conn_event_t with "
459 				"length(%d)\n", __func__, alloc_len));
460 			goto out_err;
461 		}
462 
463 		payload_len = sizeof(log_conn_event_t);
464 		event_data->event = WIFI_EVENT_DRIVER_PNO_SCAN_RESULT_FOUND;
465 		tlv_data = event_data->tlvs;
466 
467 		/* ssid */
468 		tlv_data->tag = WIFI_TAG_SSID;
469 		tlv_data->len = bi->SSID_len;
470 		memcpy(tlv_data->value, bi->SSID, bi->SSID_len);
471 		payload_len += TLV_LOG_SIZE(tlv_data);
472 		tlv_data = TLV_LOG_NEXT(tlv_data);
473 
474 		/* channel */
475 		tlv_data->tag = WIFI_TAG_CHANNEL;
476 		tlv_data->len = sizeof(uint16);
477 		memcpy(tlv_data->value, &notif_bss_info->channel, sizeof(uint16));
478 		payload_len += TLV_LOG_SIZE(tlv_data);
479 		tlv_data = TLV_LOG_NEXT(tlv_data);
480 
481 		/* rssi */
482 		tlv_data->tag = WIFI_TAG_RSSI;
483 		tlv_data->len = sizeof(int16);
484 		memcpy(tlv_data->value, &notif_bss_info->rssi, sizeof(int16));
485 		payload_len += TLV_LOG_SIZE(tlv_data);
486 		tlv_data = TLV_LOG_NEXT(tlv_data);
487 
488 		dhd_os_push_push_ring_data(dhdp, DHD_EVENT_RING_ID,
489 			event_data, payload_len);
490 		MFREE(dhdp->osh, event_data, alloc_len);
491 	}
492 
493 out_err:
494 	MFREE(cfg->osh, notif_bss_info, sizeof(*notif_bss_info)
495 			+ sizeof(*mgmt) - sizeof(u8) + WL_BSS_INFO_MAX);
496 	return err;
497 }
498 
499 struct wireless_dev * wl_get_scan_wdev(struct bcm_cfg80211 *cfg);
500 struct net_device *
wl_get_scan_ndev(struct bcm_cfg80211 * cfg)501 wl_get_scan_ndev(struct bcm_cfg80211 *cfg)
502 {
503 	struct wireless_dev *wdev = NULL;
504 	struct net_device *ndev = NULL;
505 
506 	wdev = wl_get_scan_wdev(cfg);
507 	if (!wdev) {
508 		WL_ERR(("No wdev present\n"));
509 		return NULL;
510 	}
511 
512 	ndev = wdev_to_wlc_ndev(wdev, cfg);
513 	if (!ndev) {
514 		WL_ERR(("No ndev present\n"));
515 	}
516 
517 	return ndev;
518 }
519 
520 #if defined(BSSCACHE) || defined(RSSIAVG)
wl_cfg80211_update_bss_cache(struct bcm_cfg80211 * cfg)521 void wl_cfg80211_update_bss_cache(struct bcm_cfg80211 *cfg)
522 {
523 #if defined(RSSIAVG)
524 	struct net_device *ndev = wl_get_scan_ndev(cfg);
525 	int rssi;
526 #endif
527 	wl_scan_results_t *bss_list = cfg->bss_list;
528 
529 	/* Free cache in p2p scanning*/
530 	if (p2p_is_on(cfg) && p2p_scan(cfg)) {
531 #if defined(RSSIAVG)
532 		wl_free_rssi_cache(&cfg->g_rssi_cache_ctrl);
533 #endif
534 #if defined(BSSCACHE)
535 		wl_free_bss_cache(&cfg->g_bss_cache_ctrl);
536 #endif
537 	}
538 
539 	/* Update cache */
540 #if defined(RSSIAVG)
541 	wl_update_rssi_cache(&cfg->g_rssi_cache_ctrl, bss_list);
542 	if (!in_atomic() && ndev) {
543 		wl_update_connected_rssi_cache(ndev, &cfg->g_rssi_cache_ctrl, &rssi);
544 	}
545 #endif
546 #if defined(BSSCACHE)
547 	wl_update_bss_cache(&cfg->g_bss_cache_ctrl,
548 #if defined(RSSIAVG)
549 		&cfg->g_rssi_cache_ctrl,
550 #endif
551 		bss_list);
552 #endif
553 
554 	/* delete dirty cache */
555 #if defined(RSSIAVG)
556 	wl_delete_dirty_rssi_cache(&cfg->g_rssi_cache_ctrl);
557 	wl_reset_rssi_cache(&cfg->g_rssi_cache_ctrl);
558 #endif
559 #if defined(BSSCACHE)
560 	wl_delete_dirty_bss_cache(&cfg->g_bss_cache_ctrl);
561 	wl_reset_bss_cache(&cfg->g_bss_cache_ctrl);
562 #endif
563 
564 }
565 #endif
566 
567 #if defined(BSSCACHE)
wl_inform_bss_cache(struct bcm_cfg80211 * cfg)568 s32 wl_inform_bss_cache(struct bcm_cfg80211 *cfg)
569 {
570 	wl_scan_results_t *bss_list = cfg->bss_list;
571 	wl_bss_info_t *bi = NULL;	/* must be initialized */
572 	s32 err = 0;
573 	s32 i, cnt;
574 	wl_bss_cache_t *node;
575 
576 	WL_SCAN(("scanned AP count (%d)\n", bss_list->count));
577 	bss_list = cfg->bss_list;
578 	preempt_disable();
579 	bi = next_bss(bss_list, bi);
580 	for_each_bss(bss_list, bi, i) {
581 		err = wl_inform_single_bss(cfg, bi, false);
582 		if (unlikely(err)) {
583 			WL_ERR(("bss inform failed\n"));
584 		}
585 	}
586 
587 	cnt = i;
588 	node = cfg->g_bss_cache_ctrl.m_cache_head;
589 	WL_SCAN(("cached AP count (%d)\n", wl_bss_cache_size(&cfg->g_bss_cache_ctrl)));
590 	for (i=cnt; node && i<WL_AP_MAX; i++) {
591 		if (node->dirty > 1) {
592 			bi = node->results.bss_info;
593 			err = wl_inform_single_bss(cfg, bi, false);
594 		}
595 		node = node->next;
596 	}
597 	preempt_enable();
598 
599 	return err;
600 }
601 #endif
602 
603 static s32
wl_inform_bss(struct bcm_cfg80211 * cfg)604 wl_inform_bss(struct bcm_cfg80211 *cfg)
605 {
606 #if !defined(BSSCACHE)
607 	wl_scan_results_t *bss_list;
608 	wl_bss_info_t *bi = NULL;	/* must be initialized */
609 	s32 i;
610 #endif
611 	struct net_device *ndev = wl_get_scan_ndev(cfg);
612 	s32 err = 0;
613 
614 #ifdef WL_EXT_IAPSTA
615 	if (ndev)
616 		wl_ext_in4way_sync(ndev, 0, WL_EXT_STATUS_SCAN_COMPLETE, NULL);
617 #endif
618 
619 #if defined(BSSCACHE) || defined(RSSIAVG)
620 	wl_cfg80211_update_bss_cache(cfg);
621 #endif
622 
623 #if defined(BSSCACHE)
624 	err = wl_inform_bss_cache(cfg);
625 #else
626 	bss_list = cfg->bss_list;
627 	WL_SCAN(("scanned AP count (%d)\n", bss_list->count));
628 #ifdef ESCAN_CHANNEL_CACHE
629 	reset_roam_cache(cfg);
630 #endif /* ESCAN_CHANNEL_CACHE */
631 	preempt_disable();
632 	bi = next_bss(bss_list, bi);
633 	for_each_bss(bss_list, bi, i) {
634 #ifdef ESCAN_CHANNEL_CACHE
635 		add_roam_cache(cfg, bi);
636 #endif /* ESCAN_CHANNEL_CACHE */
637 		err = wl_inform_single_bss(cfg, bi, false);
638 		if (unlikely(err)) {
639 			WL_ERR(("bss inform failed\n"));
640 		}
641 	}
642 	preempt_enable();
643 #endif
644 
645 	if (cfg->autochannel && ndev) {
646 #if defined(BSSCACHE)
647 		wl_ext_get_best_channel(ndev, &cfg->g_bss_cache_ctrl, ioctl_version,
648 			&cfg->best_2g_ch, &cfg->best_5g_ch, &cfg->best_6g_ch);
649 #else
650 		wl_ext_get_best_channel(ndev, bss_list, ioctl_version,
651 			&cfg->best_2g_ch, &cfg->best_5g_ch, &cfg->best_6g_ch);
652 #endif
653 	}
654 
655 	WL_MEM(("cfg80211 scan cache updated\n"));
656 #ifdef ROAM_CHANNEL_CACHE
657 	/* print_roam_cache(); */
658 	update_roam_cache(cfg, ioctl_version);
659 #endif /* ROAM_CHANNEL_CACHE */
660 	return err;
661 }
662 
663 #ifdef WL11U
664 static bcm_tlv_t *
wl_cfg80211_find_interworking_ie(const u8 * parse,u32 len)665 wl_cfg80211_find_interworking_ie(const u8 *parse, u32 len)
666 {
667 	bcm_tlv_t *ie;
668 
669 /* unfortunately it's too much work to dispose the const cast - bcm_parse_tlvs
670  * is used everywhere and changing its prototype to take const qualifier needs
671  * a massive change to all its callers...
672  */
673 
674 	if ((ie = bcm_parse_tlvs(parse, len, DOT11_MNG_INTERWORKING_ID))) {
675 		return ie;
676 	}
677 	return NULL;
678 }
679 
680 static s32
wl_cfg80211_clear_iw_ie(struct bcm_cfg80211 * cfg,struct net_device * ndev,s32 bssidx)681 wl_cfg80211_clear_iw_ie(struct bcm_cfg80211 *cfg, struct net_device *ndev, s32 bssidx)
682 {
683 	ie_setbuf_t ie_setbuf;
684 
685 	WL_DBG(("clear interworking IE\n"));
686 
687 	bzero(&ie_setbuf, sizeof(ie_setbuf_t));
688 
689 	ie_setbuf.ie_buffer.iecount = htod32(1);
690 	ie_setbuf.ie_buffer.ie_list[0].ie_data.id = DOT11_MNG_INTERWORKING_ID;
691 	ie_setbuf.ie_buffer.ie_list[0].ie_data.len = 0;
692 
693 	return wldev_iovar_setbuf_bsscfg(ndev, "ie", &ie_setbuf, sizeof(ie_setbuf),
694 		cfg->ioctl_buf, WLC_IOCTL_MAXLEN, bssidx, &cfg->ioctl_buf_sync);
695 }
696 
697 static s32
wl_cfg80211_add_iw_ie(struct bcm_cfg80211 * cfg,struct net_device * ndev,s32 bssidx,s32 pktflag,uint8 ie_id,uint8 * data,uint8 data_len)698 wl_cfg80211_add_iw_ie(struct bcm_cfg80211 *cfg, struct net_device *ndev, s32 bssidx, s32 pktflag,
699                       uint8 ie_id, uint8 *data, uint8 data_len)
700 {
701 	s32 err = BCME_OK;
702 	s32 buf_len;
703 	ie_setbuf_t *ie_setbuf;
704 	ie_getbuf_t ie_getbufp;
705 	char getbuf[WLC_IOCTL_SMLEN];
706 
707 	if (ie_id != DOT11_MNG_INTERWORKING_ID) {
708 		WL_ERR(("unsupported (id=%d)\n", ie_id));
709 		return BCME_UNSUPPORTED;
710 	}
711 
712 	/* access network options (1 octet)  is the mandatory field */
713 	if (!data || data_len == 0 || data_len > IW_IES_MAX_BUF_LEN) {
714 		WL_ERR(("wrong interworking IE (len=%d)\n", data_len));
715 		return BCME_BADARG;
716 	}
717 
718 	/* Validate the pktflag parameter */
719 	if ((pktflag & ~(VNDR_IE_BEACON_FLAG | VNDR_IE_PRBRSP_FLAG |
720 			VNDR_IE_ASSOCRSP_FLAG | VNDR_IE_AUTHRSP_FLAG |
721 			VNDR_IE_PRBREQ_FLAG | VNDR_IE_ASSOCREQ_FLAG|
722 			VNDR_IE_CUSTOM_FLAG))) {
723 		WL_ERR(("invalid packet flag 0x%x\n", pktflag));
724 		return BCME_BADARG;
725 	}
726 
727 	buf_len = sizeof(ie_setbuf_t) + data_len - 1;
728 
729 	ie_getbufp.id = DOT11_MNG_INTERWORKING_ID;
730 	if (wldev_iovar_getbuf_bsscfg(ndev, "ie", (void *)&ie_getbufp,
731 			sizeof(ie_getbufp), getbuf, WLC_IOCTL_SMLEN, bssidx, &cfg->ioctl_buf_sync)
732 			== BCME_OK) {
733 		if (!memcmp(&getbuf[TLV_HDR_LEN], data, data_len)) {
734 			WL_DBG(("skip to set interworking IE\n"));
735 			return BCME_OK;
736 		}
737 	}
738 
739 	/* if already set with previous values, delete it first */
740 	if (cfg->wl11u) {
741 		if ((err = wl_cfg80211_clear_iw_ie(cfg, ndev, bssidx)) != BCME_OK) {
742 			return err;
743 		}
744 	}
745 
746 	ie_setbuf = (ie_setbuf_t *)MALLOCZ(cfg->osh, buf_len);
747 	if (!ie_setbuf) {
748 		WL_ERR(("Error allocating buffer for IE\n"));
749 		return -ENOMEM;
750 	}
751 	strlcpy(ie_setbuf->cmd, "add", sizeof(ie_setbuf->cmd));
752 
753 	/* Buffer contains only 1 IE */
754 	ie_setbuf->ie_buffer.iecount = htod32(1);
755 	/* use VNDR_IE_CUSTOM_FLAG flags for none vendor IE . currently fixed value */
756 	ie_setbuf->ie_buffer.ie_list[0].pktflag = htod32(pktflag);
757 
758 	/* Now, add the IE to the buffer */
759 	ie_setbuf->ie_buffer.ie_list[0].ie_data.id = DOT11_MNG_INTERWORKING_ID;
760 	ie_setbuf->ie_buffer.ie_list[0].ie_data.len = data_len;
761 	/* Returning void here as max data_len can be 8 */
762 	(void)memcpy_s((uchar *)&ie_setbuf->ie_buffer.ie_list[0].ie_data.data[0], sizeof(uint8),
763 		data, data_len);
764 
765 	if ((err = wldev_iovar_setbuf_bsscfg(ndev, "ie", ie_setbuf, buf_len,
766 			cfg->ioctl_buf, WLC_IOCTL_MAXLEN, bssidx, &cfg->ioctl_buf_sync))
767 			== BCME_OK) {
768 		WL_DBG(("set interworking IE\n"));
769 		cfg->wl11u = TRUE;
770 		err = wldev_iovar_setint_bsscfg(ndev, "grat_arp", 1, bssidx);
771 	}
772 
773 	MFREE(cfg->osh, ie_setbuf, buf_len);
774 	return err;
775 }
776 #endif /* WL11U */
777 
778 #ifdef WL_BCNRECV
779 /* Beacon recv results handler sending to upper layer */
780 static s32
wl_bcnrecv_result_handler(struct bcm_cfg80211 * cfg,bcm_struct_cfgdev * cfgdev,wl_bss_info_v109_2_t * bi,uint32 scan_status)781 wl_bcnrecv_result_handler(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev,
782 		wl_bss_info_v109_2_t *bi, uint32 scan_status)
783 {
784 	s32 err = BCME_OK;
785 	struct wiphy *wiphy = NULL;
786 	wl_bcnrecv_result_t *bcn_recv = NULL;
787 	struct osl_timespec ts;
788 	if (!bi) {
789 		WL_ERR(("%s: bi is NULL\n", __func__));
790 		err = BCME_NORESOURCE;
791 		goto exit;
792 	}
793 	if ((bi->length - bi->ie_length) < sizeof(wl_bss_info_v109_2_t)) {
794 		WL_ERR(("bi info version doesn't support bcn_recv attributes\n"));
795 		goto exit;
796 	}
797 
798 	if (scan_status == WLC_E_STATUS_RXBCN) {
799 		wiphy = cfg->wdev->wiphy;
800 		if (!wiphy) {
801 			 WL_ERR(("wiphy is NULL\n"));
802 			 err = BCME_NORESOURCE;
803 			 goto exit;
804 		}
805 		bcn_recv = (wl_bcnrecv_result_t *)MALLOCZ(cfg->osh, sizeof(*bcn_recv));
806 		if (unlikely(!bcn_recv)) {
807 			WL_ERR(("Failed to allocate memory\n"));
808 			return -ENOMEM;
809 		}
810 		/* Returning void here as copy size does not exceed dest size of SSID */
811 		(void)memcpy_s((char *)bcn_recv->SSID, DOT11_MAX_SSID_LEN,
812 			(char *)bi->SSID, DOT11_MAX_SSID_LEN);
813 		/* Returning void here as copy size does not exceed dest size of ETH_LEN */
814 		(void)memcpy_s(&bcn_recv->BSSID, ETHER_ADDR_LEN, &bi->BSSID, ETH_ALEN);
815 		bcn_recv->channel = wf_chspec_ctlchan(
816 			wl_chspec_driver_to_host(bi->chanspec));
817 		bcn_recv->beacon_interval = bi->beacon_period;
818 
819 		/* kernal timestamp */
820 		osl_get_monotonic_boottime(&ts);
821 		bcn_recv->system_time = ((u64)ts.tv_sec*1000000)
822 				+ ts.tv_nsec / 1000;
823 		bcn_recv->timestamp[0] = bi->timestamp[0];
824 		bcn_recv->timestamp[1] = bi->timestamp[1];
825 		if ((err = wl_android_bcnrecv_event(cfgdev_to_wlc_ndev(cfgdev, cfg),
826 				BCNRECV_ATTR_BCNINFO, 0, 0,
827 				(uint8 *)bcn_recv, sizeof(*bcn_recv)))
828 				!= BCME_OK) {
829 			WL_ERR(("failed to send bcnrecv event, error:%d\n", err));
830 		}
831 	} else {
832 		WL_DBG(("Ignoring Escan Event:%d \n", scan_status));
833 	}
834 exit:
835 	if (bcn_recv) {
836 		MFREE(cfg->osh, bcn_recv, sizeof(*bcn_recv));
837 	}
838 	return err;
839 }
840 #endif /* WL_BCNRECV */
841 
842 #ifdef ESCAN_BUF_OVERFLOW_MGMT
843 #ifndef WL_DRV_AVOID_SCANCACHE
844 static void
wl_cfg80211_find_removal_candidate(wl_bss_info_t * bss,removal_element_t * candidate)845 wl_cfg80211_find_removal_candidate(wl_bss_info_t *bss, removal_element_t *candidate)
846 {
847 	int idx;
848 	for (idx = 0; idx < BUF_OVERFLOW_MGMT_COUNT; idx++) {
849 		int len = BUF_OVERFLOW_MGMT_COUNT - idx - 1;
850 		if (bss->RSSI < candidate[idx].RSSI) {
851 			if (len) {
852 				/* In the below memcpy operation the candidate array always has the
853 				* buffer space available to max 'len' calculated in the for loop.
854 				*/
855 				(void)memcpy_s(&candidate[idx + 1],
856 					(sizeof(removal_element_t) * len),
857 					&candidate[idx], sizeof(removal_element_t) * len);
858 			}
859 			candidate[idx].RSSI = bss->RSSI;
860 			candidate[idx].length = bss->length;
861 			(void)memcpy_s(&candidate[idx].BSSID, ETHER_ADDR_LEN,
862 				&bss->BSSID, ETHER_ADDR_LEN);
863 			return;
864 		}
865 	}
866 }
867 
868 static void
wl_cfg80211_remove_lowRSSI_info(wl_scan_results_t * list,removal_element_t * candidate,wl_bss_info_t * bi)869 wl_cfg80211_remove_lowRSSI_info(wl_scan_results_t *list, removal_element_t *candidate,
870 	wl_bss_info_t *bi)
871 {
872 	int idx1, idx2;
873 	int total_delete_len = 0;
874 	for (idx1 = 0; idx1 < BUF_OVERFLOW_MGMT_COUNT; idx1++) {
875 		int cur_len = WL_SCAN_RESULTS_FIXED_SIZE;
876 		wl_bss_info_t *bss = NULL;
877 		if (candidate[idx1].RSSI >= bi->RSSI)
878 			continue;
879 		for (idx2 = 0; idx2 < list->count; idx2++) {
880 			bss = bss ? (wl_bss_info_t *)((uintptr)bss + dtoh32(bss->length)) :
881 				list->bss_info;
882 			if (!bss) {
883 				continue;
884 			}
885 			if (!bcmp(&candidate[idx1].BSSID, &bss->BSSID, ETHER_ADDR_LEN) &&
886 				candidate[idx1].RSSI == bss->RSSI &&
887 				candidate[idx1].length == dtoh32(bss->length)) {
888 				u32 delete_len = dtoh32(bss->length);
889 				WL_DBG(("delete scan info of " MACDBG " to add new AP\n",
890 					MAC2STRDBG(bss->BSSID.octet)));
891 				if (idx2 < list->count -1) {
892 					memmove((u8 *)bss, (u8 *)bss + delete_len,
893 						list->buflen - cur_len - delete_len);
894 				}
895 				list->buflen -= delete_len;
896 				list->count--;
897 				total_delete_len += delete_len;
898 				/* if delete_len is greater than or equal to result length */
899 				if (total_delete_len >= bi->length) {
900 					return;
901 				}
902 				break;
903 			}
904 			cur_len += dtoh32(bss->length);
905 		}
906 	}
907 }
908 #endif /* WL_DRV_AVOID_SCANCACHE */
909 #endif /* ESCAN_BUF_OVERFLOW_MGMT */
910 
911 s32
wl_escan_handler(struct bcm_cfg80211 * cfg,bcm_struct_cfgdev * cfgdev,const wl_event_msg_t * e,void * data)912 wl_escan_handler(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev,
913 	const wl_event_msg_t *e, void *data)
914 {
915 	s32 err = BCME_OK;
916 	s32 status = ntoh32(e->status);
917 	wl_escan_result_t *escan_result;
918 	struct net_device *ndev = NULL;
919 #ifndef WL_DRV_AVOID_SCANCACHE
920 	wl_bss_info_t *bi;
921 	u32 bi_length;
922 	const wifi_p2p_ie_t * p2p_ie;
923 	const u8 *p2p_dev_addr = NULL;
924 	wl_scan_results_t *list;
925 	wl_bss_info_t *bss = NULL;
926 	u32 i;
927 #endif /* WL_DRV_AVOID_SCANCACHE */
928 	u16 channel;
929 	struct ieee80211_supported_band *band;
930 
931 	WL_DBG((" enter event type : %d, status : %d \n",
932 		ntoh32(e->event_type), ntoh32(e->status)));
933 
934 	ndev = cfgdev_to_wlc_ndev(cfgdev, cfg);
935 
936 	mutex_lock(&cfg->scan_sync);
937 
938 	if (cfg->loc.in_progress) {
939 		/* Listen in progress */
940 		if ((status == WLC_E_STATUS_SUCCESS) || (status == WLC_E_STATUS_ABORT)) {
941 			if (delayed_work_pending(&cfg->loc.work)) {
942 				cancel_delayed_work_sync(&cfg->loc.work);
943 			}
944 			err = wl_cfgscan_notify_listen_complete(cfg);
945 			goto exit;
946 		} else {
947 			WL_DBG(("Listen in progress. Unknown status. %d\n", status));
948 		}
949 	}
950 
951 	/* P2P SCAN is coming from primary interface */
952 	if (wl_get_p2p_status(cfg, SCANNING)) {
953 		if (wl_get_drv_status_all(cfg, SENDING_ACT_FRM))
954 			ndev = cfg->afx_hdl->dev;
955 		else
956 			ndev = cfg->escan_info.ndev;
957 	}
958 	escan_result = (wl_escan_result_t *)data;
959 	if (!escan_result) {
960 		WL_ERR(("Invalid escan result (NULL data)\n"));
961 		goto exit;
962 	}
963 #ifdef WL_BCNRECV
964 	if (status == WLC_E_STATUS_RXBCN) {
965 		if (cfg->bcnrecv_info.bcnrecv_state == BEACON_RECV_STARTED) {
966 			/* handle beacon recv scan results */
967 			wl_bss_info_v109_2_t *bi_info;
968 			bi_info = (wl_bss_info_v109_2_t *)escan_result->bss_info;
969 			err = wl_bcnrecv_result_handler(cfg, cfgdev, bi_info, status);
970 		} else {
971 			WL_ERR(("ignore bcnrx event in disabled state(%d)\n",
972 				cfg->bcnrecv_info.bcnrecv_state));
973 		}
974 		goto exit;
975 	}
976 #endif /* WL_BCNRECV */
977 	if (!ndev || (!wl_get_drv_status(cfg, SCANNING, ndev) && !cfg->sched_scan_running)) {
978 		WL_ERR_RLMT(("escan is not ready. drv_scan_status 0x%x"
979 			" e_type %d e_status %d\n",
980 			wl_get_drv_status(cfg, SCANNING, ndev),
981 			ntoh32(e->event_type), ntoh32(e->status)));
982 		goto exit;
983 	}
984 
985 #ifndef WL_DRV_AVOID_SCANCACHE
986 	if (wl_escan_check_sync_id(cfg, status, escan_result->sync_id,
987 			cfg->escan_info.cur_sync_id) < 0) {
988 			goto exit;
989 	}
990 
991 	if (status == WLC_E_STATUS_PARTIAL) {
992 		WL_DBG(("WLC_E_STATUS_PARTIAL \n"));
993 		DBG_EVENT_LOG((dhd_pub_t *)cfg->pub, WIFI_EVENT_DRIVER_SCAN_RESULT_FOUND);
994 		if ((dtoh32(escan_result->buflen) > (int)ESCAN_BUF_SIZE) ||
995 		    (dtoh32(escan_result->buflen) < sizeof(wl_escan_result_t))) {
996 			WL_ERR(("Invalid escan buffer len:%d\n", dtoh32(escan_result->buflen)));
997 			goto exit;
998 		}
999 		if (dtoh16(escan_result->bss_count) != 1) {
1000 			WL_ERR(("Invalid bss_count %d: ignoring\n", escan_result->bss_count));
1001 			goto exit;
1002 		}
1003 		bi = escan_result->bss_info;
1004 		if (!bi) {
1005 			WL_ERR(("Invalid escan bss info (NULL pointer)\n"));
1006 			goto exit;
1007 		}
1008 		bi_length = dtoh32(bi->length);
1009 		if (bi_length != (dtoh32(escan_result->buflen) - WL_ESCAN_RESULTS_FIXED_SIZE)) {
1010 			WL_ERR(("Invalid bss_info length %d: ignoring\n", bi_length));
1011 			goto exit;
1012 		}
1013 
1014 		/* +++++ terence 20130524: skip invalid bss */
1015 		channel =
1016 			bi->ctl_ch ? bi->ctl_ch : CHSPEC_CHANNEL(wl_chspec_driver_to_host(bi->chanspec));
1017 		if (channel <= CH_MAX_2G_CHANNEL)
1018 			band = bcmcfg_to_wiphy(cfg)->bands[IEEE80211_BAND_2GHZ];
1019 		else
1020 			band = bcmcfg_to_wiphy(cfg)->bands[IEEE80211_BAND_5GHZ];
1021 		if (!band) {
1022 			WL_ERR(("No valid band\n"));
1023 			goto exit;
1024 		}
1025 		if (!dhd_conf_match_channel(cfg->pub, channel))
1026 			goto exit;
1027 		/* ----- terence 20130524: skip invalid bss */
1028 
1029 		if (!(bcmcfg_to_wiphy(cfg)->interface_modes & BIT(NL80211_IFTYPE_ADHOC))) {
1030 			if (dtoh16(bi->capability) & DOT11_CAP_IBSS) {
1031 				WL_DBG(("Ignoring IBSS result\n"));
1032 				goto exit;
1033 			}
1034 		}
1035 
1036 		if (wl_get_drv_status_all(cfg, FINDING_COMMON_CHANNEL)) {
1037 			p2p_dev_addr = wl_cfgp2p_retreive_p2p_dev_addr(bi, bi_length);
1038 			if (p2p_dev_addr && !memcmp(p2p_dev_addr,
1039 				cfg->afx_hdl->tx_dst_addr.octet, ETHER_ADDR_LEN)) {
1040 				s32 channel = wf_chspec_ctlchan(
1041 					wl_chspec_driver_to_host(bi->chanspec));
1042 
1043 				if ((channel > MAXCHANNEL) || (channel <= 0))
1044 					channel = WL_INVALID;
1045 				else
1046 					WL_ERR(("ACTION FRAME SCAN : Peer " MACDBG " found,"
1047 						" channel : %d\n",
1048 						MAC2STRDBG(cfg->afx_hdl->tx_dst_addr.octet),
1049 						channel));
1050 
1051 				wl_clr_p2p_status(cfg, SCANNING);
1052 				cfg->afx_hdl->peer_chan = channel;
1053 				complete(&cfg->act_frm_scan);
1054 				goto exit;
1055 			}
1056 
1057 		} else {
1058 			int cur_len = WL_SCAN_RESULTS_FIXED_SIZE;
1059 #ifdef ESCAN_BUF_OVERFLOW_MGMT
1060 			removal_element_t candidate[BUF_OVERFLOW_MGMT_COUNT];
1061 			int remove_lower_rssi = FALSE;
1062 
1063 			bzero(candidate, sizeof(removal_element_t)*BUF_OVERFLOW_MGMT_COUNT);
1064 #endif /* ESCAN_BUF_OVERFLOW_MGMT */
1065 
1066 			list = wl_escan_get_buf(cfg, FALSE);
1067 			if (scan_req_match(cfg)) {
1068 #ifdef WL_HOST_BAND_MGMT
1069 				s32 channel_band = 0;
1070 				chanspec_t chspec;
1071 #endif /* WL_HOST_BAND_MGMT */
1072 				/* p2p scan && allow only probe response */
1073 				if ((cfg->p2p->search_state != WL_P2P_DISC_ST_SCAN) &&
1074 					(bi->flags & WL_BSS_FLAGS_FROM_BEACON))
1075 					goto exit;
1076 				if ((p2p_ie = wl_cfgp2p_find_p2pie(((u8 *) bi) + bi->ie_offset,
1077 					bi->ie_length)) == NULL) {
1078 						WL_ERR(("Couldn't find P2PIE in probe"
1079 							" response/beacon\n"));
1080 						goto exit;
1081 				}
1082 #ifdef WL_HOST_BAND_MGMT
1083 				chspec = wl_chspec_driver_to_host(bi->chanspec);
1084 				channel_band = CHSPEC2WLC_BAND(chspec);
1085 
1086 				if ((
1087 #ifdef WL_6G_BAND
1088 					(cfg->curr_band == WLC_BAND_6G) ||
1089 #endif /* WL_6G_BAND */
1090 					(cfg->curr_band == WLC_BAND_5G)) &&
1091 					(channel_band == WLC_BAND_2G)) {
1092 					/* Avoid sending the GO results in band conflict */
1093 					if (wl_cfgp2p_retreive_p2pattrib(p2p_ie,
1094 						P2P_SEID_GROUP_ID) != NULL)
1095 						goto exit;
1096 				}
1097 #endif /* WL_HOST_BAND_MGMT */
1098 			}
1099 #ifdef ESCAN_BUF_OVERFLOW_MGMT
1100 			if (bi_length > ESCAN_BUF_SIZE - list->buflen)
1101 				remove_lower_rssi = TRUE;
1102 #endif /* ESCAN_BUF_OVERFLOW_MGMT */
1103 
1104 			for (i = 0; i < list->count; i++) {
1105 				bss = bss ? (wl_bss_info_t *)((uintptr)bss + dtoh32(bss->length))
1106 					: list->bss_info;
1107 				if (!bss) {
1108 					WL_ERR(("bss is NULL\n"));
1109 					goto exit;
1110 				}
1111 #ifdef ESCAN_BUF_OVERFLOW_MGMT
1112 				WL_DBG(("%s("MACDBG"), i=%d bss: RSSI %d list->count %d\n",
1113 					bss->SSID, MAC2STRDBG(bss->BSSID.octet),
1114 					i, bss->RSSI, list->count));
1115 
1116 				if (remove_lower_rssi)
1117 					wl_cfg80211_find_removal_candidate(bss, candidate);
1118 #endif /* ESCAN_BUF_OVERFLOW_MGMT */
1119 
1120 				if (!bcmp(&bi->BSSID, &bss->BSSID, ETHER_ADDR_LEN) &&
1121 					(CHSPEC_BAND(wl_chspec_driver_to_host(bi->chanspec))
1122 					== CHSPEC_BAND(wl_chspec_driver_to_host(bss->chanspec))) &&
1123 					bi->SSID_len == bss->SSID_len &&
1124 					!bcmp(bi->SSID, bss->SSID, bi->SSID_len)) {
1125 
1126 					/* do not allow beacon data to update
1127 					*the data recd from a probe response
1128 					*/
1129 					if (!(bss->flags & WL_BSS_FLAGS_FROM_BEACON) &&
1130 						(bi->flags & WL_BSS_FLAGS_FROM_BEACON))
1131 						goto exit;
1132 
1133 					WL_DBG(("%s("MACDBG"), i=%d prev: RSSI %d"
1134 						" flags 0x%x, new: RSSI %d flags 0x%x\n",
1135 						bss->SSID, MAC2STRDBG(bi->BSSID.octet), i,
1136 						bss->RSSI, bss->flags, bi->RSSI, bi->flags));
1137 
1138 					if ((bss->flags & WL_BSS_FLAGS_RSSI_ONCHANNEL) ==
1139 						(bi->flags & WL_BSS_FLAGS_RSSI_ONCHANNEL)) {
1140 						/* preserve max RSSI if the measurements are
1141 						* both on-channel or both off-channel
1142 						*/
1143 						WL_DBG(("%s("MACDBG"), same onchan"
1144 						", RSSI: prev %d new %d\n",
1145 						bss->SSID, MAC2STRDBG(bi->BSSID.octet),
1146 						bss->RSSI, bi->RSSI));
1147 						bi->RSSI = MAX(bss->RSSI, bi->RSSI);
1148 					} else if ((bss->flags & WL_BSS_FLAGS_RSSI_ONCHANNEL) &&
1149 						(bi->flags & WL_BSS_FLAGS_RSSI_ONCHANNEL) == 0) {
1150 						/* preserve the on-channel rssi measurement
1151 						* if the new measurement is off channel
1152 						*/
1153 						WL_DBG(("%s("MACDBG"), prev onchan"
1154 						", RSSI: prev %d new %d\n",
1155 						bss->SSID, MAC2STRDBG(bi->BSSID.octet),
1156 						bss->RSSI, bi->RSSI));
1157 						bi->RSSI = bss->RSSI;
1158 						bi->flags |= WL_BSS_FLAGS_RSSI_ONCHANNEL;
1159 					}
1160 					if (dtoh32(bss->length) != bi_length) {
1161 						u32 prev_len = dtoh32(bss->length);
1162 
1163 						WL_DBG(("bss info replacement"
1164 							" is occured(bcast:%d->probresp%d)\n",
1165 							bss->ie_length, bi->ie_length));
1166 						WL_DBG(("%s("MACDBG"), replacement!(%d -> %d)\n",
1167 						bss->SSID, MAC2STRDBG(bi->BSSID.octet),
1168 						prev_len, bi_length));
1169 
1170 						if ((list->buflen - prev_len) + bi_length
1171 							> ESCAN_BUF_SIZE) {
1172 							WL_ERR(("Buffer is too small: keep the"
1173 								" previous result of this AP\n"));
1174 							/* Only update RSSI */
1175 							bss->RSSI = bi->RSSI;
1176 							bss->flags |= (bi->flags
1177 								& WL_BSS_FLAGS_RSSI_ONCHANNEL);
1178 							goto exit;
1179 						}
1180 
1181 						if (i < list->count - 1) {
1182 							/* memory copy required by this case only */
1183 							memmove((u8 *)bss + bi_length,
1184 								(u8 *)bss + prev_len,
1185 								list->buflen - cur_len - prev_len);
1186 						}
1187 						list->buflen -= prev_len;
1188 						list->buflen += bi_length;
1189 					}
1190 					list->version = dtoh32(bi->version);
1191 					/* In the above code under check
1192 					*  '(dtoh32(bss->length) != bi_length)'
1193 					* buffer overflow is avoided. bi_length
1194 					* is already accounted in list->buflen
1195 					*/
1196 					if ((err = memcpy_s((u8 *)bss,
1197 						(ESCAN_BUF_SIZE - (list->buflen - bi_length)),
1198 						(u8 *)bi, bi_length)) != BCME_OK) {
1199 						WL_ERR(("Failed to copy the recent bss_info."
1200 							"err:%d recv_len:%d bi_len:%d\n", err,
1201 							ESCAN_BUF_SIZE - (list->buflen - bi_length),
1202 							bi_length));
1203 						/* This scenario should never happen. If it happens,
1204 						 * set list->count to zero for recovery
1205 						 */
1206 						list->count = 0;
1207 						list->buflen = 0;
1208 						ASSERT(0);
1209 					}
1210 					goto exit;
1211 				}
1212 				cur_len += dtoh32(bss->length);
1213 			}
1214 			if (bi_length > ESCAN_BUF_SIZE - list->buflen) {
1215 #ifdef ESCAN_BUF_OVERFLOW_MGMT
1216 				wl_cfg80211_remove_lowRSSI_info(list, candidate, bi);
1217 				if (bi_length > ESCAN_BUF_SIZE - list->buflen) {
1218 					WL_DBG(("RSSI(" MACDBG ") is too low(%d) to add Buffer\n",
1219 						MAC2STRDBG(bi->BSSID.octet), bi->RSSI));
1220 					goto exit;
1221 				}
1222 #else
1223 				WL_ERR(("Buffer is too small: ignoring\n"));
1224 				goto exit;
1225 #endif /* ESCAN_BUF_OVERFLOW_MGMT */
1226 			}
1227 			/* In the previous step check is added to ensure the bi_legth does not
1228 			* exceed the ESCAN_BUF_SIZE
1229 			*/
1230 			(void)memcpy_s(&(((char *)list)[list->buflen]),
1231 				(ESCAN_BUF_SIZE - list->buflen), bi, bi_length);
1232 			list->version = dtoh32(bi->version);
1233 			list->buflen += bi_length;
1234 			list->count++;
1235 
1236 			/*
1237 			 * !Broadcast && number of ssid = 1 && number of channels =1
1238 			 * means specific scan to association
1239 			 */
1240 			if (wl_cfgp2p_is_p2p_specific_scan(cfg->scan_request)) {
1241 				WL_ERR(("P2P assoc scan fast aborted.\n"));
1242 				wl_cfgscan_scan_abort(cfg);
1243 				wl_notify_escan_complete(cfg, cfg->escan_info.ndev, false);
1244 				goto exit;
1245 			}
1246 		}
1247 	}
1248 	else if (status == WLC_E_STATUS_SUCCESS) {
1249 		cfg->escan_info.escan_state = WL_ESCAN_STATE_IDLE;
1250 #ifdef DHD_SEND_HANG_ESCAN_SYNCID_MISMATCH
1251 		cfg->escan_info.prev_escan_aborted = FALSE;
1252 #endif /* DHD_SEND_HANG_ESCAN_SYNCID_MISMATCH */
1253 		if (wl_get_drv_status_all(cfg, FINDING_COMMON_CHANNEL)) {
1254 			WL_DBG(("ACTION FRAME SCAN DONE\n"));
1255 			wl_clr_p2p_status(cfg, SCANNING);
1256 			wl_clr_drv_status(cfg, SCANNING, cfg->afx_hdl->dev);
1257 			if (cfg->afx_hdl->peer_chan == WL_INVALID)
1258 				complete(&cfg->act_frm_scan);
1259 		} else if ((likely(cfg->scan_request)) || (cfg->sched_scan_running)) {
1260 			WL_INFORM_MEM(("ESCAN COMPLETED\n"));
1261 			DBG_EVENT_LOG((dhd_pub_t *)cfg->pub, WIFI_EVENT_DRIVER_SCAN_COMPLETE);
1262 			cfg->bss_list = wl_escan_get_buf(cfg, FALSE);
1263 			if (!scan_req_match(cfg)) {
1264 				WL_DBG(("SCAN COMPLETED: scanned AP count=%d\n",
1265 					cfg->bss_list->count));
1266 			}
1267 			wl_inform_bss(cfg);
1268 			wl_notify_escan_complete(cfg, ndev, false);
1269 		}
1270 		wl_escan_increment_sync_id(cfg, SCAN_BUF_NEXT);
1271 #ifdef CUSTOMER_HW4_DEBUG
1272 		if (wl_scan_timeout_dbg_enabled)
1273 			wl_scan_timeout_dbg_clear();
1274 #endif /* CUSTOMER_HW4_DEBUG */
1275 	} else if ((status == WLC_E_STATUS_ABORT) || (status == WLC_E_STATUS_NEWSCAN) ||
1276 		(status == WLC_E_STATUS_11HQUIET) || (status == WLC_E_STATUS_CS_ABORT) ||
1277 		(status == WLC_E_STATUS_NEWASSOC)) {
1278 		/* Dump FW preserve buffer content */
1279 		if (status == WLC_E_STATUS_ABORT) {
1280 			wl_flush_fw_log_buffer(ndev, FW_LOGSET_MASK_ALL);
1281 		}
1282 		/* Handle all cases of scan abort */
1283 		cfg->escan_info.escan_state = WL_ESCAN_STATE_IDLE;
1284 		WL_DBG(("ESCAN ABORT reason: %d\n", status));
1285 		if (wl_get_drv_status_all(cfg, FINDING_COMMON_CHANNEL)) {
1286 			WL_DBG(("ACTION FRAME SCAN DONE\n"));
1287 			wl_clr_drv_status(cfg, SCANNING, cfg->afx_hdl->dev);
1288 			wl_clr_p2p_status(cfg, SCANNING);
1289 			if (cfg->afx_hdl->peer_chan == WL_INVALID)
1290 				complete(&cfg->act_frm_scan);
1291 		} else if ((likely(cfg->scan_request)) || (cfg->sched_scan_running)) {
1292 			WL_INFORM_MEM(("ESCAN ABORTED\n"));
1293 
1294 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0))
1295 			if (p2p_scan(cfg) && cfg->scan_request &&
1296 				(cfg->scan_request->flags & NL80211_SCAN_FLAG_FLUSH)) {
1297 				WL_ERR(("scan list is changed"));
1298 				cfg->bss_list = wl_escan_get_buf(cfg, FALSE);
1299 			} else
1300 #endif
1301 				cfg->bss_list = wl_escan_get_buf(cfg, TRUE);
1302 
1303 			if (!scan_req_match(cfg)) {
1304 				WL_TRACE_HW4(("SCAN ABORTED: scanned AP count=%d\n",
1305 					cfg->bss_list->count));
1306 			}
1307 #ifdef DUAL_ESCAN_RESULT_BUFFER
1308 			if (escan_result->sync_id != cfg->escan_info.cur_sync_id) {
1309 				/* If sync_id is not matching, then the abort might have
1310 				 * come for the old scan req or for the in-driver initiated
1311 				 * scan. So do abort for scan_req for which sync_id is
1312 				 * matching.
1313 				 */
1314 				WL_INFORM_MEM(("sync_id mismatch (%d != %d). "
1315 					"Ignore the scan abort event.\n",
1316 					escan_result->sync_id, cfg->escan_info.cur_sync_id));
1317 				goto exit;
1318 			} else {
1319 				/* sync id is matching, abort the scan */
1320 				WL_INFORM_MEM(("scan aborted for sync_id: %d \n",
1321 					cfg->escan_info.cur_sync_id));
1322 				wl_inform_bss(cfg);
1323 				wl_notify_escan_complete(cfg, ndev, true);
1324 			}
1325 #else
1326 			wl_inform_bss(cfg);
1327 			wl_notify_escan_complete(cfg, ndev, true);
1328 #endif /* DUAL_ESCAN_RESULT_BUFFER */
1329 		} else {
1330 			/* If there is no pending host initiated scan, do nothing */
1331 			WL_DBG(("ESCAN ABORT: No pending scans. Ignoring event.\n"));
1332 		}
1333 		/* scan aborted, need to set previous success result */
1334 		wl_escan_increment_sync_id(cfg, SCAN_BUF_CNT);
1335 	} else if (status == WLC_E_STATUS_TIMEOUT) {
1336 		WL_ERR(("WLC_E_STATUS_TIMEOUT : scan_request[%p]\n", cfg->scan_request));
1337 		WL_ERR(("reason[0x%x]\n", e->reason));
1338 		if (e->reason == 0xFFFFFFFF) {
1339 			wl_scan_results_t *bss_list;
1340 			bss_list = wl_escan_get_buf(cfg, FALSE);
1341 			if (!bss_list) {
1342 				WL_ERR(("bss_list is null. Didn't receive any partial scan results\n"));
1343 			} else {
1344 				WL_ERR(("Dump scan buffer: scanned AP count (%d)\n", bss_list->count));
1345 				bi = NULL;
1346 				bi = next_bss(bss_list, bi);
1347 				for_each_bss(bss_list, bi, i) {
1348 					channel = wf_chspec_ctlchan(wl_chspec_driver_to_host(bi->chanspec));
1349 					WL_ERR(("SSID :%s  Channel :%d\n", bi->SSID, channel));
1350 				}
1351 			}
1352 			_wl_cfgscan_cancel_scan(cfg);
1353 		}
1354 	} else {
1355 		WL_ERR(("unexpected Escan Event %d : abort\n", status));
1356 		cfg->escan_info.escan_state = WL_ESCAN_STATE_IDLE;
1357 		if (wl_get_drv_status_all(cfg, FINDING_COMMON_CHANNEL)) {
1358 			WL_DBG(("ACTION FRAME SCAN DONE\n"));
1359 			wl_clr_p2p_status(cfg, SCANNING);
1360 			wl_clr_drv_status(cfg, SCANNING, cfg->afx_hdl->dev);
1361 			if (cfg->afx_hdl->peer_chan == WL_INVALID)
1362 				complete(&cfg->act_frm_scan);
1363 		} else if ((likely(cfg->scan_request)) || (cfg->sched_scan_running)) {
1364 			cfg->bss_list = wl_escan_get_buf(cfg, TRUE);
1365 			if (!scan_req_match(cfg)) {
1366 				WL_TRACE_HW4(("SCAN ABORTED(UNEXPECTED): "
1367 					"scanned AP count=%d\n",
1368 					cfg->bss_list->count));
1369 			}
1370 			wl_inform_bss(cfg);
1371 			wl_notify_escan_complete(cfg, ndev, true);
1372 		}
1373 		/* scan aborted, need to set previous success result */
1374 		wl_escan_increment_sync_id(cfg, 2);
1375 	}
1376 #else /* WL_DRV_AVOID_SCANCACHE */
1377 	err = wl_escan_without_scan_cache(cfg, escan_result, ndev, e, status);
1378 #endif /* WL_DRV_AVOID_SCANCACHE */
1379 exit:
1380 	mutex_unlock(&cfg->scan_sync);
1381 	return err;
1382 }
1383 
1384 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 19, 0)) && defined(SUPPORT_RANDOM_MAC_SCAN)
1385 static const u8 *
wl_retrieve_wps_attribute(const u8 * buf,u16 element_id)1386 wl_retrieve_wps_attribute(const u8 *buf, u16 element_id)
1387 {
1388 	const wl_wps_ie_t *ie = NULL;
1389 	u16 len = 0;
1390 	const u8 *attrib;
1391 
1392 	if (!buf) {
1393 		WL_ERR(("WPS IE not present"));
1394 		return 0;
1395 	}
1396 
1397 	ie = (const wl_wps_ie_t*) buf;
1398 	len = ie->len;
1399 
1400 	/* Point subel to the P2P IE's subelt field.
1401 	 * Subtract the preceding fields (id, len, OUI, oui_type) from the length.
1402 	 */
1403 	attrib = ie->attrib;
1404 	len -= 4;	/* exclude OUI + OUI_TYPE */
1405 
1406 	/* Search for attrib */
1407 	return wl_find_attribute(attrib, len, element_id);
1408 }
1409 
1410 bool
wl_is_wps_enrollee_active(struct net_device * ndev,const u8 * ie_ptr,u16 len)1411 wl_is_wps_enrollee_active(struct net_device *ndev, const u8 *ie_ptr, u16 len)
1412 {
1413 	const u8 *ie;
1414 	const u8 *attrib;
1415 
1416 	if ((ie = (const u8 *)wl_cfgp2p_find_wpsie(ie_ptr, len)) == NULL) {
1417 		WL_DBG(("WPS IE not present. Do nothing.\n"));
1418 		return false;
1419 	}
1420 
1421 	if ((attrib = wl_retrieve_wps_attribute(ie, WPS_ATTR_REQ_TYPE)) == NULL) {
1422 		WL_DBG(("WPS_ATTR_REQ_TYPE not found!\n"));
1423 		return false;
1424 	}
1425 
1426 	if (*attrib == WPS_REQ_TYPE_ENROLLEE) {
1427 		WL_INFORM_MEM(("WPS Enrolle Active\n"));
1428 		return true;
1429 	} else {
1430 		WL_DBG(("WPS_REQ_TYPE:%d\n", *attrib));
1431 	}
1432 
1433 	return false;
1434 }
1435 #endif /* LINUX_VERSION_CODE < KERNEL_VERSION(3, 19, 0) && defined(SUPPORT_RANDOM_MAC_SCAN) */
1436 
1437 /* Find listen channel */
wl_find_listen_channel(struct bcm_cfg80211 * cfg,const u8 * ie,u32 ie_len)1438 static s32 wl_find_listen_channel(struct bcm_cfg80211 *cfg,
1439 	const u8 *ie, u32 ie_len)
1440 {
1441 	const wifi_p2p_ie_t *p2p_ie;
1442 	const u8 *end, *pos;
1443 	s32 listen_channel;
1444 
1445 	pos = (const u8 *)ie;
1446 
1447 	p2p_ie = wl_cfgp2p_find_p2pie(pos, ie_len);
1448 
1449 	if (p2p_ie == NULL) {
1450 		return 0;
1451 	}
1452 
1453 	if (p2p_ie->len < MIN_P2P_IE_LEN || p2p_ie->len > MAX_P2P_IE_LEN) {
1454 		CFGP2P_ERR(("p2p_ie->len out of range - %d\n", p2p_ie->len));
1455 		return 0;
1456 	}
1457 	pos = p2p_ie->subelts;
1458 	end = p2p_ie->subelts + (p2p_ie->len - 4);
1459 
1460 	CFGP2P_DBG((" found p2p ie ! lenth %d \n",
1461 		p2p_ie->len));
1462 
1463 	while (pos < end) {
1464 		uint16 attr_len;
1465 		if (pos + 2 >= end) {
1466 			CFGP2P_DBG((" -- Invalid P2P attribute"));
1467 			return 0;
1468 		}
1469 		attr_len = ((uint16) (((pos + 1)[1] << 8) | (pos + 1)[0]));
1470 
1471 		if (pos + 3 + attr_len > end) {
1472 			CFGP2P_DBG(("P2P: Attribute underflow "
1473 				   "(len=%u left=%d)",
1474 				   attr_len, (int) (end - pos - 3)));
1475 			return 0;
1476 		}
1477 
1478 		/* if Listen Channel att id is 6 and the vailue is valid,
1479 		 * return the listen channel
1480 		 */
1481 		if (pos[0] == 6) {
1482 			/* listen channel subel length format
1483 			 * 1(id) + 2(len) + 3(country) + 1(op. class) + 1(chan num)
1484 			 */
1485 			listen_channel = pos[1 + 2 + 3 + 1];
1486 
1487 			if (listen_channel == SOCIAL_CHAN_1 ||
1488 				listen_channel == SOCIAL_CHAN_2 ||
1489 				listen_channel == SOCIAL_CHAN_3) {
1490 				CFGP2P_DBG((" Found my Listen Channel %d \n", listen_channel));
1491 				return listen_channel;
1492 			}
1493 		}
1494 		pos += 3 + attr_len;
1495 	}
1496 	return 0;
1497 }
1498 
1499 #ifdef WL_SCAN_TYPE
1500 static u32
wl_cfgscan_map_nl80211_scan_type(struct bcm_cfg80211 * cfg,struct cfg80211_scan_request * request)1501 wl_cfgscan_map_nl80211_scan_type(struct bcm_cfg80211 *cfg, struct cfg80211_scan_request *request)
1502 {
1503 	u32 scan_flags = 0;
1504 
1505 	if (!request) {
1506 		return scan_flags;
1507 	}
1508 
1509 	if (request->flags & NL80211_SCAN_FLAG_LOW_SPAN) {
1510 		scan_flags |= WL_SCANFLAGS_LOW_SPAN;
1511 	}
1512 	if (request->flags & NL80211_SCAN_FLAG_HIGH_ACCURACY) {
1513 		scan_flags |= WL_SCANFLAGS_HIGH_ACCURACY;
1514 	}
1515 	if (request->flags & NL80211_SCAN_FLAG_LOW_POWER) {
1516 		scan_flags |= WL_SCANFLAGS_LOW_POWER_SCAN;
1517 	}
1518 	if (request->flags & NL80211_SCAN_FLAG_LOW_PRIORITY) {
1519 		scan_flags |= WL_SCANFLAGS_LOW_PRIO;
1520 	}
1521 
1522 	WL_INFORM(("scan flags. wl:%x cfg80211:%x\n", scan_flags, request->flags));
1523 	return scan_flags;
1524 }
1525 #endif /* WL_SCAN_TYPE */
1526 
wl_freq_to_chanspec(int freq)1527 chanspec_t wl_freq_to_chanspec(int freq)
1528 {
1529 	chanspec_t chanspec = 0;
1530 	u16 bw;
1531 
1532 	/* see 802.11 17.3.8.3.2 and Annex J */
1533 	if (freq == 2484) {
1534 		chanspec = 14;
1535 		chanspec |= WL_CHANSPEC_BAND_2G;
1536 		bw = WL_CHANSPEC_BW_20;
1537 	} else if (freq >= 2412 && freq < 2484) {
1538 		chanspec = (freq - 2407) / 5;
1539 		chanspec |= WL_CHANSPEC_BAND_2G;
1540 		bw = WL_CHANSPEC_BW_20;
1541 	} else if (freq >= 4005 && freq <= 4980) {
1542 		chanspec = (freq - 4000) / 5;
1543 		chanspec |= WL_CHANSPEC_BAND_5G;
1544 		bw = WL_CHANSPEC_BW_20;
1545 	} else if (freq >= 5005 && freq < 5895) {
1546 		chanspec = (freq - 5000) / 5;
1547 		chanspec |= WL_CHANSPEC_BAND_5G;
1548 		bw = WL_CHANSPEC_BW_20;
1549 #ifdef WL_6G_BAND
1550 	} else if (freq >= 5945 && freq <= 7200) {
1551 		/* see 802.11ax D4.1 27.3.22.2 */
1552 		chanspec = (freq - 5950) / 5;
1553 		bw = WL_CHANSPEC_BW_20;
1554 		if ((chanspec % 8) == 3) {
1555 			bw = WL_CHANSPEC_BW_40;
1556 		} else if ((chanspec % 16) == 7) {
1557 			bw = WL_CHANSPEC_BW_80;
1558 		} else if ((chanspec % 32) == 15) {
1559 			bw = WL_CHANSPEC_BW_160;
1560 		}
1561 		chanspec |= WL_CHANSPEC_BAND_6G;
1562 	} else if (freq == 5935) {
1563 		chanspec = 2;
1564 		bw = WL_CHANSPEC_BW_20;
1565 		chanspec |= WL_CHANSPEC_BAND_6G;
1566 #endif /* WL_6G_BAND */
1567 	} else {
1568 		WL_ERR(("Invalid frequency %d\n", freq));
1569 		return INVCHANSPEC;
1570 	}
1571 
1572 	/* Get the min_bw set for the interface */
1573 	chanspec |= bw;
1574 	chanspec |= WL_CHANSPEC_CTL_SB_NONE;
1575 
1576 	return chanspec;
1577 }
1578 
1579 #ifdef SCAN_SUPPRESS
1580 static void
wl_cfgscan_populate_scan_channel(struct bcm_cfg80211 * cfg,struct ieee80211_channel ** channels,u32 n_channels,u16 * channel_list,struct wl_chan_info * chan_info)1581 wl_cfgscan_populate_scan_channel(struct bcm_cfg80211 *cfg,
1582 	struct ieee80211_channel **channels, u32 n_channels,
1583 	u16 *channel_list, struct wl_chan_info *chan_info)
1584 {
1585 	u32 i, chanspec = 0;
1586 
1587 	for (i=0; i<n_channels; i++) {
1588 		chanspec = wl_freq_to_chanspec(channels[i]->center_freq);
1589 		if (chanspec == INVCHANSPEC) {
1590 			WL_ERR(("Invalid chanspec! Skipping channel\n"));
1591 			continue;
1592 		}
1593 		if (chan_info->band == CHSPEC2WLC_BAND(chanspec) &&
1594 				chan_info->chan == wf_chspec_ctlchan(chanspec)) {
1595 			channel_list[0] = chanspec;
1596 			break;
1597 		}
1598 	}
1599 	WL_SCAN(("chan: %s-%d, chanspec: %x\n",
1600 		WLCBAND2STR(chan_info->band), chan_info->chan, chanspec));
1601 }
1602 #endif
1603 
1604 #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 14, 0))
1605 #define IS_RADAR_CHAN(flags) (flags & (IEEE80211_CHAN_RADAR | IEEE80211_CHAN_PASSIVE_SCAN))
1606 #else
1607 #define IS_RADAR_CHAN(flags) (flags & (IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IR))
1608 #endif
1609 static void
wl_cfgscan_populate_scan_channels(struct bcm_cfg80211 * cfg,struct ieee80211_channel ** channels,u32 n_channels,u16 * channel_list,u32 * num_channels,bool use_chanspecs,bool skip_dfs)1610 wl_cfgscan_populate_scan_channels(struct bcm_cfg80211 *cfg,
1611 	struct ieee80211_channel **channels, u32 n_channels,
1612 	u16 *channel_list, u32 *num_channels, bool use_chanspecs, bool skip_dfs)
1613 {
1614 	u32 i = 0, j = 0;
1615 	u32 chanspec = 0;
1616 	struct wireless_dev *wdev;
1617 	bool is_p2p_scan = false;
1618 #ifdef P2P_SKIP_DFS
1619 	int is_printed = false;
1620 #endif /* P2P_SKIP_DFS */
1621 	u32 channel;
1622 
1623 	if (!channels || !n_channels) {
1624 		/* Do full channel scan */
1625 		return;
1626 	}
1627 
1628 	 wdev = GET_SCAN_WDEV(cfg->scan_request);
1629 	if (!skip_dfs && wdev && wdev->netdev &&
1630 			(wdev->netdev != bcmcfg_to_prmry_ndev(cfg))) {
1631 		/* SKIP DFS channels for Secondary interface */
1632 		skip_dfs = true;
1633 	}
1634 
1635 	/* Check if request is for p2p scans */
1636 	is_p2p_scan = p2p_is_on(cfg) && p2p_scan(cfg);
1637 
1638 	for (i = 0; i < n_channels; i++) {
1639 		channel = ieee80211_frequency_to_channel(channels[i]->center_freq);
1640 		if (skip_dfs && (IS_RADAR_CHAN(channels[i]->flags))) {
1641 			WL_DBG(("Skipping radar channel. freq:%d\n",
1642 				(channels[i]->center_freq)));
1643 			continue;
1644 		}
1645 		if (!dhd_conf_match_channel(cfg->pub, channel))
1646 			continue;
1647 
1648 		chanspec = wl_freq_to_chanspec(channels[i]->center_freq);
1649 		if (chanspec == INVCHANSPEC) {
1650 			WL_ERR(("Invalid chanspec! Skipping channel\n"));
1651 			continue;
1652 		}
1653 
1654 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0))
1655 		if (channels[i]->band == IEEE80211_BAND_60GHZ) {
1656 			/* Not supported */
1657 			continue;
1658 		}
1659 #endif /* LINUX_VER >= 3.6 */
1660 #ifdef WL_HOST_BAND_MGMT
1661 		if (channels[i]->band == IEEE80211_BAND_2GHZ) {
1662 			if ((cfg->curr_band == WLC_BAND_5G) ||
1663 				(cfg->curr_band == WLC_BAND_6G)) {
1664 				if !(is_p2p_scan &&
1665 					IS_P2P_SOCIAL_CHANNEL(CHSPEC_CHANNEL(chanspec))) {
1666 					WL_DBG(("In 5G only mode, omit 2G channel:%d\n", channel));
1667 					continue;
1668 				}
1669 			}
1670 		} else {
1671 			if (cfg->curr_band == WLC_BAND_2G) {
1672 				WL_DBG(("In 2G only mode, omit 5G channel:%d\n", channel));
1673 				continue;
1674 			}
1675 		}
1676 #endif /* WL_HOST_BAND_MGMT */
1677 
1678 		if (is_p2p_scan) {
1679 #ifdef WL_P2P_6G
1680 			if (!(cfg->p2p_6g_enabled)) {
1681 #endif /* WL_P2P_6G */
1682 				if (CHSPEC_IS6G(chanspec)) {
1683 					continue;
1684 				}
1685 #ifdef WL_P2P_6G
1686 			}
1687 #endif /* WL_P2P_6G */
1688 
1689 #ifdef P2P_SKIP_DFS
1690 			if (CHSPEC_IS5G(chanspec) &&
1691 				(CHSPEC_CHANNEL(chanspec) >= 52 &&
1692 				CHSPEC_CHANNEL(chanspec) <= 144)) {
1693 				if (is_printed == false) {
1694 					WL_ERR(("SKIP DFS CHANs(52~144)\n"));
1695 					is_printed = true;
1696 				}
1697 				continue;
1698 			}
1699 #endif /* P2P_SKIP_DFS */
1700 		}
1701 
1702 		if (use_chanspecs) {
1703 			channel_list[j] = chanspec;
1704 		} else {
1705 			channel_list[j] = CHSPEC_CHANNEL(chanspec);
1706 		}
1707 		WL_SCAN(("chan: %d, chanspec: %x\n", channel, channel_list[j]));
1708 		j++;
1709 		if (j == WL_NUMCHANSPECS) {
1710 			/* max limit */
1711 			break;
1712 		}
1713 	}
1714 	*num_channels = j;
1715 }
1716 
1717 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)1718 wl_cfgscan_populate_scan_ssids(struct bcm_cfg80211 *cfg, u8 *buf_ptr, u32 buf_len,
1719 	struct cfg80211_scan_request *request, u32 *ssid_num)
1720 {
1721 	u32 n_ssids;
1722 	wlc_ssid_t ssid;
1723 	int i, j = 0;
1724 
1725 	if (!request || !buf_ptr) {
1726 		/* Do full channel scan */
1727 		return;
1728 	}
1729 
1730 	n_ssids = request->n_ssids;
1731 	if (n_ssids > 0) {
1732 
1733 		if (buf_len < (n_ssids * sizeof(wlc_ssid_t))) {
1734 			WL_ERR(("buf len not sufficient for scan ssids\n"));
1735 			return;
1736 		}
1737 
1738 		for (i = 0; i < n_ssids; i++) {
1739 			bzero(&ssid, sizeof(wlc_ssid_t));
1740 			ssid.SSID_len = MIN(request->ssids[i].ssid_len, DOT11_MAX_SSID_LEN);
1741 			/* Returning void here, as per previous line copy length does not exceed
1742 			* DOT11_MAX_SSID_LEN
1743 			*/
1744 			(void)memcpy_s(ssid.SSID, DOT11_MAX_SSID_LEN, request->ssids[i].ssid,
1745 				ssid.SSID_len);
1746 			if (!ssid.SSID_len) {
1747 				WL_SCAN(("%d: Broadcast scan\n", i));
1748 			} else {
1749 				WL_SCAN(("%d: scan  for  %s size =%d\n", i,
1750 				ssid.SSID, ssid.SSID_len));
1751 			}
1752 			/* For multiple ssid case copy the each SSID info the ptr below corresponds
1753 			* to that so dest is of type wlc_ssid_t
1754 			*/
1755 			(void)memcpy_s(buf_ptr, sizeof(wlc_ssid_t), &ssid, sizeof(wlc_ssid_t));
1756 			buf_ptr += sizeof(wlc_ssid_t);
1757 			j++;
1758 		}
1759 	} else {
1760 		WL_SCAN(("Broadcast scan\n"));
1761 	}
1762 	*ssid_num = j;
1763 }
1764 
1765 static s32
wl_scan_prep(struct bcm_cfg80211 * cfg,struct net_device * ndev,void * scan_params,u32 len,struct cfg80211_scan_request * request)1766 wl_scan_prep(struct bcm_cfg80211 *cfg, struct net_device *ndev, void *scan_params, u32 len,
1767 	struct cfg80211_scan_request *request)
1768 {
1769 #ifdef SCAN_SUPPRESS
1770 	struct wl_chan_info chan_info;
1771 	u32 channel;
1772 #endif
1773 	wl_scan_params_t *params = NULL;
1774 	wl_scan_params_v2_t *params_v2 = NULL;
1775 	u32 scan_type = 0;
1776 	u32 scan_param_size = 0;
1777 	u32 n_channels = 0;
1778 	u32 n_ssids = 0;
1779 	uint16 *chan_list = NULL;
1780 	u32 channel_offset = 0;
1781 	u32 cur_offset;
1782 
1783 	if (!scan_params) {
1784 		return BCME_ERROR;
1785 	}
1786 
1787 	if (cfg->active_scan == PASSIVE_SCAN) {
1788 		WL_INFORM_MEM(("Enforcing passive scan\n"));
1789 		scan_type = WL_SCANFLAGS_PASSIVE;
1790 	}
1791 
1792 	WL_DBG(("Preparing Scan request\n"));
1793 	if (cfg->scan_params_v2) {
1794 		params_v2 = (wl_scan_params_v2_t *)scan_params;
1795 		scan_param_size = sizeof(wl_scan_params_v2_t);
1796 		channel_offset = offsetof(wl_scan_params_v2_t, channel_list);
1797 	} else {
1798 		params = (wl_scan_params_t *)scan_params;
1799 		scan_param_size = sizeof(wl_scan_params_t);
1800 		channel_offset = offsetof(wl_scan_params_t, channel_list);
1801 	}
1802 
1803 	if (params_v2) {
1804 		/* scan params ver2 */
1805 #if defined(WL_SCAN_TYPE)
1806 		scan_type  += wl_cfgscan_map_nl80211_scan_type(cfg, request);
1807 #endif /* WL_SCAN_TYPE */
1808 
1809 		(void)memcpy_s(&params_v2->bssid, ETHER_ADDR_LEN, &ether_bcast, ETHER_ADDR_LEN);
1810 		params_v2->version = htod16(WL_SCAN_PARAMS_VERSION_V2);
1811 		params_v2->length = htod16(sizeof(wl_scan_params_v2_t));
1812 		params_v2->bss_type = DOT11_BSSTYPE_ANY;
1813 		params_v2->scan_type = htod32(scan_type);
1814 		params_v2->nprobes = htod32(-1);
1815 		params_v2->active_time = htod32(-1);
1816 		params_v2->passive_time = htod32(-1);
1817 		params_v2->home_time = htod32(-1);
1818 		params_v2->channel_num = 0;
1819 		bzero(&params_v2->ssid, sizeof(wlc_ssid_t));
1820 		chan_list = params_v2->channel_list;
1821 	} else {
1822 		/* scan params ver 1 */
1823 		if (!params) {
1824 			ASSERT(0);
1825 			return BCME_ERROR;
1826 		}
1827 		(void)memcpy_s(&params->bssid, ETHER_ADDR_LEN, &ether_bcast, ETHER_ADDR_LEN);
1828 		params->bss_type = DOT11_BSSTYPE_ANY;
1829 		params->scan_type = 0;
1830 		params->nprobes = htod32(-1);
1831 		params->active_time = htod32(-1);
1832 		params->passive_time = htod32(-1);
1833 		params->home_time = htod32(-1);
1834 		params->channel_num = 0;
1835 		bzero(&params->ssid, sizeof(wlc_ssid_t));
1836 		chan_list = params->channel_list;
1837 	}
1838 
1839 	if (!request) {
1840 		/* scan_request null, do scan based on base config */
1841 		WL_DBG(("scan_request is null\n"));
1842 		return BCME_OK;
1843 	}
1844 
1845 	WL_INFORM(("n_channels:%d n_ssids:%d\n", request->n_channels, request->n_ssids));
1846 
1847 	cur_offset = channel_offset;
1848 	/* Copy channel array if applicable */
1849 #ifdef SCAN_SUPPRESS
1850 	channel = wl_ext_scan_suppress(ndev, scan_params, cfg->scan_params_v2, &chan_info);
1851 	if (channel) {
1852 		n_channels = 1;
1853 		if ((n_channels > 0) && chan_list) {
1854 			if (len >= (scan_param_size + (n_channels * sizeof(u16)))) {
1855 				wl_cfgscan_populate_scan_channel(cfg,
1856 					request->channels, request->n_channels,
1857 					chan_list, &chan_info);
1858 				cur_offset += (n_channels * (sizeof(u16)));
1859 			}
1860 		}
1861 	} else
1862 #endif
1863 	if ((request->n_channels > 0) && chan_list) {
1864 		if (len >= (scan_param_size + (request->n_channels * sizeof(u16)))) {
1865 			wl_cfgscan_populate_scan_channels(cfg,
1866 					request->channels, request->n_channels,
1867 					chan_list, &n_channels, true, false);
1868 			cur_offset += (uint32)(n_channels * (sizeof(u16)));
1869 		}
1870 	}
1871 
1872 	/* Copy ssid array if applicable */
1873 	if (request->n_ssids > 0) {
1874 		cur_offset = (u32) roundup(cur_offset, sizeof(u32));
1875 		if (len > (cur_offset + (request->n_ssids * sizeof(wlc_ssid_t)))) {
1876 			u32 rem_len = len - cur_offset;
1877 			wl_cfgscan_populate_scan_ssids(cfg,
1878 				((u8 *)scan_params + cur_offset), rem_len, request, &n_ssids);
1879 		}
1880 	}
1881 
1882 	if (n_ssids || n_channels) {
1883 		u32 channel_num =
1884 				htod32((n_ssids << WL_SCAN_PARAMS_NSSID_SHIFT) |
1885 				(n_channels & WL_SCAN_PARAMS_COUNT_MASK));
1886 		if (params_v2) {
1887 			params_v2->channel_num = channel_num;
1888 			if (n_channels == 1) {
1889 				params_v2->active_time = htod32(WL_SCAN_CONNECT_DWELL_TIME_MS);
1890 				params_v2->nprobes = htod32(
1891 					params_v2->active_time / WL_SCAN_JOIN_PROBE_INTERVAL_MS);
1892 			}
1893 		} else {
1894 			params->channel_num = channel_num;
1895 			if (n_channels == 1) {
1896 				params->active_time = htod32(WL_SCAN_CONNECT_DWELL_TIME_MS);
1897 				params->nprobes = htod32(
1898 					params->active_time / WL_SCAN_JOIN_PROBE_INTERVAL_MS);
1899 			}
1900 		}
1901 	}
1902 
1903 	WL_DBG_MEM(("scan_prep done. n_channels:%d n_ssids:%d\n", n_channels, n_ssids));
1904 	return BCME_OK;
1905 }
1906 
1907 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 19, 0)) && defined(SUPPORT_RANDOM_MAC_SCAN)
1908 static s32
wl_config_scan_macaddr(struct bcm_cfg80211 * cfg,struct net_device * ndev,bool randmac_enable,u8 * mac_addr,u8 * mac_addr_mask)1909 wl_config_scan_macaddr(struct bcm_cfg80211 *cfg,
1910 		struct net_device *ndev, bool randmac_enable, u8 *mac_addr, u8 *mac_addr_mask)
1911 {
1912 	s32 err = BCME_OK;
1913 
1914 	if (randmac_enable) {
1915 		if (!cfg->scanmac_enabled) {
1916 			err = wl_cfg80211_scan_mac_enable(ndev);
1917 			if (unlikely(err)) {
1918 				goto exit;
1919 			}
1920 			WL_DBG(("randmac enabled\n"));
1921 		}
1922 
1923 #ifdef WL_HOST_RANDMAC_CONFIG
1924 		/* If mask provided, apply user space configuration */
1925 		if (!mac_addr_mask && !mac_addr && !ETHER_ISNULLADDR(mac_addr_mask)) {
1926 			err = wl_cfg80211_scan_mac_config(ndev,
1927 				mac_addr, mac_addr_mask);
1928 			if (unlikely(err)) {
1929 				WL_ERR(("scan mac config failed\n"));
1930 				goto exit;
1931 			}
1932 		}
1933 #endif /* WL_HOST_RANDMAC_CONFIG */
1934 		if (cfg->scanmac_config) {
1935 			/* Use default scanmac configuration */
1936 			WL_DBG(("Use host provided scanmac config\n"));
1937 		} else {
1938 			WL_DBG(("Use fw default scanmac config\n"));
1939 		}
1940 	} else if (!randmac_enable && cfg->scanmac_enabled) {
1941 		WL_DBG(("randmac disabled\n"));
1942 		err = wl_cfg80211_scan_mac_disable(ndev);
1943 	} else {
1944 		WL_DBG(("no change in randmac configuration\n"));
1945 	}
1946 
1947 exit:
1948 	if (err < 0) {
1949 		if (err == BCME_UNSUPPORTED) {
1950 			/* Ignore if chip doesnt support the feature */
1951 			err = BCME_OK;
1952 		} else {
1953 			/* For errors other than unsupported fail the scan */
1954 			WL_ERR(("%s : failed to configure random mac for host scan, %d\n",
1955 				__FUNCTION__, err));
1956 			err = -EAGAIN;
1957 		}
1958 	}
1959 
1960 	return err;
1961 }
1962 #endif /* LINUX VER > 3.19 && SUPPORT_RANDOM_MAC_SCAN */
1963 
1964 static s32
wl_run_escan(struct bcm_cfg80211 * cfg,struct net_device * ndev,struct cfg80211_scan_request * request,uint16 action)1965 wl_run_escan(struct bcm_cfg80211 *cfg, struct net_device *ndev,
1966 	struct cfg80211_scan_request *request, uint16 action)
1967 {
1968 	s32 err = BCME_OK;
1969 	u32 num_chans = 0;
1970 	u32 n_channels = 0;
1971 	u32 n_ssids;
1972 	s32 params_size;
1973 	wl_escan_params_t *eparams = NULL;
1974 	wl_escan_params_v2_t *eparams_v2 = NULL;
1975 	u8 *scan_params = NULL;
1976 	u8 *params = NULL;
1977 	s32 search_state = WL_P2P_DISC_ST_SCAN;
1978 	u16 *default_chan_list = NULL;
1979 	s32 bssidx = -1;
1980 	struct net_device *dev = NULL;
1981 #if defined(USE_INITIAL_2G_SCAN) || defined(USE_INITIAL_SHORT_DWELL_TIME)
1982 	bool is_first_init_2g_scan = false;
1983 #endif /* USE_INITIAL_2G_SCAN || USE_INITIAL_SHORT_DWELL_TIME */
1984 	p2p_scan_purpose_t	p2p_scan_purpose = P2P_SCAN_PURPOSE_MIN;
1985 	u32 chan_mem = 0;
1986 	u32 sync_id = 0;
1987 
1988 	WL_DBG(("Enter \n"));
1989 
1990 	if (!cfg || !request) {
1991 		err = -EINVAL;
1992 		goto exit;
1993 	}
1994 
1995 	if (cfg->scan_params_v2) {
1996 		params_size = (WL_SCAN_PARAMS_V2_FIXED_SIZE +
1997 				OFFSETOF(wl_escan_params_v2_t, params));
1998 	} else {
1999 		params_size = (WL_SCAN_PARAMS_FIXED_SIZE + OFFSETOF(wl_escan_params_t, params));
2000 	}
2001 
2002 	if (!cfg->p2p_supported || !p2p_scan(cfg)) {
2003 		/* LEGACY SCAN TRIGGER */
2004 		WL_SCAN((" LEGACY E-SCAN START\n"));
2005 
2006 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 19, 0)) && defined(SUPPORT_RANDOM_MAC_SCAN)
2007 	if (request) {
2008 		bool randmac_enable = (request->flags & NL80211_SCAN_FLAG_RANDOM_ADDR);
2009 		if (wl_is_wps_enrollee_active(ndev, request->ie, request->ie_len)) {
2010 			randmac_enable = false;
2011 		}
2012 		if ((err = wl_config_scan_macaddr(cfg, ndev, randmac_enable,
2013 			request->mac_addr, request->mac_addr_mask)) != BCME_OK) {
2014 				WL_ERR(("scanmac addr config failed\n"));
2015 			goto exit;
2016 		}
2017 	}
2018 #endif /* KERNEL_VER >= 3.19 && SUPPORT_RANDOM_MAC_SCAN */
2019 
2020 #if defined(USE_INITIAL_2G_SCAN) || defined(USE_INITIAL_SHORT_DWELL_TIME)
2021 		if (ndev == bcmcfg_to_prmry_ndev(cfg) && g_first_broadcast_scan == true) {
2022 #ifdef USE_INITIAL_2G_SCAN
2023 			struct ieee80211_channel tmp_channel_list[CH_MAX_2G_CHANNEL];
2024 			/* allow one 5G channel to add previous connected channel in 5G */
2025 			bool allow_one_5g_channel = TRUE;
2026 			int i, j;
2027 			j = 0;
2028 			for (i = 0; i < request->n_channels; i++) {
2029 				int tmp_chan = ieee80211_frequency_to_channel
2030 					(request->channels[i]->center_freq);
2031 				if (tmp_chan > CH_MAX_2G_CHANNEL) {
2032 					if (allow_one_5g_channel)
2033 						allow_one_5g_channel = FALSE;
2034 					else
2035 						continue;
2036 				}
2037 				if (j > CH_MAX_2G_CHANNEL) {
2038 					WL_ERR(("Index %d exceeds max 2.4GHz channels %d"
2039 						" and previous 5G connected channel\n",
2040 						j, CH_MAX_2G_CHANNEL));
2041 					break;
2042 				}
2043 				bcopy(request->channels[i], &tmp_channel_list[j],
2044 					sizeof(struct ieee80211_channel));
2045 				WL_SCAN(("channel of request->channels[%d]=%d\n", i, tmp_chan));
2046 				j++;
2047 			}
2048 			if ((j > 0) && (j <= CH_MAX_2G_CHANNEL)) {
2049 				for (i = 0; i < j; i++)
2050 					bcopy(&tmp_channel_list[i], request->channels[i],
2051 						sizeof(struct ieee80211_channel));
2052 
2053 				request->n_channels = j;
2054 				is_first_init_2g_scan = true;
2055 			}
2056 			else
2057 				WL_ERR(("Invalid number of 2.4GHz channels %d\n", j));
2058 
2059 			WL_SCAN(("request->n_channels=%d\n", request->n_channels));
2060 #else /* USE_INITIAL_SHORT_DWELL_TIME */
2061 			is_first_init_2g_scan = true;
2062 #endif /* USE_INITIAL_2G_SCAN */
2063 			g_first_broadcast_scan = false;
2064 		}
2065 #endif /* USE_INITIAL_2G_SCAN || USE_INITIAL_SHORT_DWELL_TIME */
2066 
2067 		n_channels = request->n_channels;
2068 		n_ssids = request->n_ssids;
2069 		if (n_channels % 2)
2070 			/* If n_channels is odd, add a padd of u16 */
2071 			params_size += sizeof(u16) * (n_channels + 1);
2072 		else
2073 			params_size += sizeof(u16) * n_channels;
2074 
2075 		/* Allocate space for populating ssids in wl_escan_params_t struct */
2076 		params_size += sizeof(struct wlc_ssid) * n_ssids;
2077 		params = MALLOCZ(cfg->osh, params_size);
2078 		if (params == NULL) {
2079 			err = -ENOMEM;
2080 			goto exit;
2081 		}
2082 
2083 		wl_escan_set_sync_id(sync_id, cfg);
2084 		if (cfg->scan_params_v2) {
2085 			eparams_v2 = (wl_escan_params_v2_t *)params;
2086 			scan_params = (u8 *)&eparams_v2->params;
2087 			eparams_v2->version = htod32(ESCAN_REQ_VERSION_V2);
2088 			eparams_v2->action =  htod16(action);
2089 			eparams_v2->sync_id = sync_id;
2090 		} else {
2091 			eparams = (wl_escan_params_t *)params;
2092 			scan_params = (u8 *)&eparams->params;
2093 			eparams->version = htod32(ESCAN_REQ_VERSION);
2094 			eparams->action =  htod16(action);
2095 			eparams->sync_id = sync_id;
2096 		}
2097 
2098 		if (wl_scan_prep(cfg, ndev, scan_params, params_size, request) < 0) {
2099 			WL_ERR(("scan_prep failed\n"));
2100 			err = -EINVAL;
2101 			goto exit;
2102 		}
2103 
2104 #if defined(USE_INITIAL_2G_SCAN) || defined(USE_INITIAL_SHORT_DWELL_TIME)
2105 		/* Override active_time to reduce scan time if it's first bradcast scan. */
2106 		if (is_first_init_2g_scan) {
2107 			if (eparams_v2) {
2108 				eparams_v2->params.active_time = FIRST_SCAN_ACTIVE_DWELL_TIME_MS;
2109 			} else {
2110 				eparams->params.active_time = FIRST_SCAN_ACTIVE_DWELL_TIME_MS;
2111 			}
2112 		}
2113 #endif /* USE_INITIAL_2G_SCAN || USE_INITIAL_SHORT_DWELL_TIME */
2114 
2115 		wl_escan_set_type(cfg, WL_SCANTYPE_LEGACY);
2116 		if (params_size + sizeof("escan") >= WLC_IOCTL_MEDLEN) {
2117 			WL_ERR(("ioctl buffer length not sufficient\n"));
2118 			MFREE(cfg->osh, params, params_size);
2119 			err = -ENOMEM;
2120 			goto exit;
2121 		}
2122 
2123 		bssidx = wl_get_bssidx_by_wdev(cfg, ndev->ieee80211_ptr);
2124 		WL_MSG(ndev->name, "LEGACY_SCAN sync ID: %d, bssidx: %d\n", sync_id, bssidx);
2125 		err = wldev_iovar_setbuf(ndev, "escan", params, params_size,
2126 			cfg->escan_ioctl_buf, WLC_IOCTL_MEDLEN, NULL);
2127 		if (unlikely(err)) {
2128 			if (err == BCME_EPERM)
2129 				/* Scan Not permitted at this point of time */
2130 				WL_DBG((" Escan not permitted at this time (%d)\n", err));
2131 			else
2132 				WL_ERR((" Escan set error (%d)\n", err));
2133 		} else {
2134 			DBG_EVENT_LOG((dhd_pub_t *)cfg->pub, WIFI_EVENT_DRIVER_SCAN_REQUESTED);
2135 		}
2136 		MFREE(cfg->osh, params, params_size);
2137 	}
2138 	else if (p2p_is_on(cfg) && p2p_scan(cfg)) {
2139 		/* P2P SCAN TRIGGER */
2140 		if (request->n_channels) {
2141 			num_chans = request->n_channels;
2142 			WL_SCAN((" chan number : %d\n", num_chans));
2143 			chan_mem = (u32)(num_chans * sizeof(*default_chan_list));
2144 			default_chan_list = MALLOCZ(cfg->osh, chan_mem);
2145 			if (default_chan_list == NULL) {
2146 				WL_ERR(("channel list allocation failed \n"));
2147 				err = -ENOMEM;
2148 				goto exit;
2149 			}
2150 			/* Populate channels for p2p scanning */
2151 			wl_cfgscan_populate_scan_channels(cfg,
2152 				request->channels, request->n_channels,
2153 				default_chan_list, &num_chans, true, true);
2154 
2155 			if (num_chans == SOCIAL_CHAN_CNT && (
2156 						(CHSPEC_CHANNEL(default_chan_list[0]) ==
2157 						SOCIAL_CHAN_1) &&
2158 						(CHSPEC_CHANNEL(default_chan_list[1]) ==
2159 						SOCIAL_CHAN_2) &&
2160 						(CHSPEC_CHANNEL(default_chan_list[2]) ==
2161 						SOCIAL_CHAN_3))) {
2162 				/* SOCIAL CHANNELS 1, 6, 11 */
2163 				search_state = WL_P2P_DISC_ST_SEARCH;
2164 				p2p_scan_purpose = P2P_SCAN_SOCIAL_CHANNEL;
2165 				WL_DBG(("P2P SEARCH PHASE START \n"));
2166 			} else if (((dev = wl_to_p2p_bss_ndev(cfg, P2PAPI_BSSCFG_CONNECTION1)) &&
2167 				(wl_get_mode_by_netdev(cfg, dev) == WL_MODE_AP)) ||
2168 				((dev = wl_to_p2p_bss_ndev(cfg, P2PAPI_BSSCFG_CONNECTION2)) &&
2169 				(wl_get_mode_by_netdev(cfg, dev) == WL_MODE_AP))) {
2170 				/* If you are already a GO, then do SEARCH only */
2171 				WL_DBG(("Already a GO. Do SEARCH Only"));
2172 				search_state = WL_P2P_DISC_ST_SEARCH;
2173 				p2p_scan_purpose = P2P_SCAN_NORMAL;
2174 
2175 			} else if (num_chans == 1) {
2176 				p2p_scan_purpose = P2P_SCAN_CONNECT_TRY;
2177 			} else if (num_chans == SOCIAL_CHAN_CNT + 1) {
2178 			/* SOCIAL_CHAN_CNT + 1 takes care of the Progressive scan supported by
2179 			 * the supplicant
2180 			 */
2181 				p2p_scan_purpose = P2P_SCAN_SOCIAL_CHANNEL;
2182 			} else {
2183 				WL_DBG(("P2P SCAN STATE START \n"));
2184 				p2p_scan_purpose = P2P_SCAN_NORMAL;
2185 			}
2186 		} else {
2187 			err = -EINVAL;
2188 			goto exit;
2189 		}
2190 		WL_INFORM_MEM(("p2p_scan  num_channels:%d\n", num_chans));
2191 		err = wl_cfgp2p_escan(cfg, ndev, ACTIVE_SCAN, num_chans, default_chan_list,
2192 			search_state, action,
2193 			wl_to_p2p_bss_bssidx(cfg, P2PAPI_BSSCFG_DEVICE), NULL,
2194 			p2p_scan_purpose);
2195 
2196 		if (!err)
2197 			cfg->p2p->search_state = search_state;
2198 
2199 		MFREE(cfg->osh, default_chan_list, chan_mem);
2200 	}
2201 exit:
2202 	if (unlikely(err)) {
2203 		/* Don't print Error incase of Scan suppress */
2204 		if ((err == BCME_EPERM) && cfg->scan_suppressed)
2205 			WL_DBG(("Escan failed: Scan Suppressed \n"));
2206 		else
2207 			WL_ERR(("scan error (%d)\n", err));
2208 	}
2209 	return err;
2210 }
2211 
2212 s32
wl_do_escan(struct bcm_cfg80211 * cfg,struct wiphy * wiphy,struct net_device * ndev,struct cfg80211_scan_request * request)2213 wl_do_escan(struct bcm_cfg80211 *cfg, struct wiphy *wiphy, struct net_device *ndev,
2214 	struct cfg80211_scan_request *request)
2215 {
2216 	s32 err = BCME_OK;
2217 	s32 passive_scan;
2218 	s32 passive_scan_time;
2219 	s32 passive_scan_time_org;
2220 	wl_scan_results_t *results;
2221 	WL_SCAN(("Enter \n"));
2222 
2223 	results = wl_escan_get_buf(cfg, FALSE);
2224 	results->version = 0;
2225 	results->count = 0;
2226 	results->buflen = WL_SCAN_RESULTS_FIXED_SIZE;
2227 
2228 	cfg->escan_info.ndev = ndev;
2229 	cfg->escan_info.wiphy = wiphy;
2230 	cfg->escan_info.escan_state = WL_ESCAN_STATE_SCANING;
2231 	passive_scan = cfg->active_scan ? 0 : 1;
2232 	err = wldev_ioctl_set(ndev, WLC_SET_PASSIVE_SCAN,
2233 	                      &passive_scan, sizeof(passive_scan));
2234 	if (unlikely(err)) {
2235 		WL_ERR(("error (%d)\n", err));
2236 		goto exit;
2237 	}
2238 
2239 	if (passive_channel_skip) {
2240 
2241 		err = wldev_ioctl_get(ndev, WLC_GET_SCAN_PASSIVE_TIME,
2242 			&passive_scan_time_org, sizeof(passive_scan_time_org));
2243 		if (unlikely(err)) {
2244 			WL_ERR(("== error (%d)\n", err));
2245 			goto exit;
2246 		}
2247 
2248 		WL_SCAN(("PASSIVE SCAN time : %d \n", passive_scan_time_org));
2249 
2250 		passive_scan_time = 0;
2251 		err = wldev_ioctl_set(ndev, WLC_SET_SCAN_PASSIVE_TIME,
2252 			&passive_scan_time, sizeof(passive_scan_time));
2253 		if (unlikely(err)) {
2254 			WL_ERR(("== error (%d)\n", err));
2255 			goto exit;
2256 		}
2257 
2258 		WL_SCAN(("PASSIVE SCAN SKIPED!! (passive_channel_skip:%d) \n",
2259 			passive_channel_skip));
2260 	}
2261 
2262 	err = wl_run_escan(cfg, ndev, request, WL_SCAN_ACTION_START);
2263 
2264 	if (passive_channel_skip) {
2265 		err = wldev_ioctl_set(ndev, WLC_SET_SCAN_PASSIVE_TIME,
2266 			&passive_scan_time_org, sizeof(passive_scan_time_org));
2267 		if (unlikely(err)) {
2268 			WL_ERR(("== error (%d)\n", err));
2269 			goto exit;
2270 		}
2271 
2272 		WL_SCAN(("PASSIVE SCAN RECOVERED!! (passive_scan_time_org:%d) \n",
2273 			passive_scan_time_org));
2274 	}
2275 
2276 exit:
2277 	return err;
2278 }
2279 
2280 static s32
wl_get_scan_timeout_val(struct bcm_cfg80211 * cfg)2281 wl_get_scan_timeout_val(struct bcm_cfg80211 *cfg)
2282 {
2283 	u32 scan_timer_interval_ms = WL_SCAN_TIMER_INTERVAL_MS;
2284 
2285 #ifdef WES_SUPPORT
2286 #ifdef CUSTOMER_SCAN_TIMEOUT_SETTING
2287 	if ((cfg->custom_scan_channel_time > DHD_SCAN_ASSOC_ACTIVE_TIME) |
2288 		(cfg->custom_scan_unassoc_time > DHD_SCAN_UNASSOC_ACTIVE_TIME) |
2289 		(cfg->custom_scan_passive_time > DHD_SCAN_PASSIVE_TIME) |
2290 		(cfg->custom_scan_home_time > DHD_SCAN_HOME_TIME) |
2291 		(cfg->custom_scan_home_away_time > DHD_SCAN_HOME_AWAY_TIME)) {
2292 		scan_timer_interval_ms = CUSTOMER_WL_SCAN_TIMER_INTERVAL_MS;
2293 	}
2294 #endif /* CUSTOMER_SCAN_TIMEOUT_SETTING */
2295 #endif /* WES_SUPPORT */
2296 
2297 	/* If NAN is enabled adding +10 sec to the existing timeout value */
2298 #ifdef WL_NAN
2299 	if (wl_cfgnan_is_enabled(cfg)) {
2300 		scan_timer_interval_ms += WL_SCAN_TIMER_INTERVAL_MS_NAN;
2301 	}
2302 #endif /* WL_NAN */
2303 	/* Additional time to scan 6GHz band channels */
2304 #ifdef WL_6G_BAND
2305 	if (cfg->band_6g_supported) {
2306 		scan_timer_interval_ms += WL_SCAN_TIMER_INTERVAL_MS_6G;
2307 	}
2308 #endif /* WL_6G_BAND */
2309 	WL_MEM(("scan_timer_interval_ms %d\n", scan_timer_interval_ms));
2310 	return scan_timer_interval_ms;
2311 }
2312 
2313 #define SCAN_EBUSY_RETRY_LIMIT 20
2314 static s32
wl_cfgscan_handle_scanbusy(struct bcm_cfg80211 * cfg,struct net_device * ndev,s32 err)2315 wl_cfgscan_handle_scanbusy(struct bcm_cfg80211 *cfg, struct net_device *ndev, s32 err)
2316 {
2317 	s32	scanbusy_err = 0;
2318 	static u32 busy_count = 0;
2319 
2320 	if (!err) {
2321 		busy_count = 0;
2322 		return scanbusy_err;
2323 	}
2324 	if (err == BCME_BUSY || err == BCME_NOTREADY) {
2325 		WL_ERR(("Scan err = (%d), busy?%d\n", err, -EBUSY));
2326 		scanbusy_err = -EBUSY;
2327 	} else if ((err == BCME_EPERM) && cfg->scan_suppressed) {
2328 		WL_ERR(("Scan not permitted due to scan suppress\n"));
2329 		scanbusy_err = -EPERM;
2330 	} else {
2331 		/* For all other fw errors, use a generic error code as return
2332 		 * value to cfg80211 stack
2333 		 */
2334 		scanbusy_err = -EAGAIN;
2335 	}
2336 
2337 	/* if continuous busy state, clear assoc type in FW by disassoc cmd */
2338 	if (scanbusy_err == -EBUSY) {
2339 		/* Flush FW preserve buffer logs for checking failure */
2340 		if (busy_count++ > (SCAN_EBUSY_RETRY_LIMIT/5)) {
2341 			wl_flush_fw_log_buffer(ndev, FW_LOGSET_MASK_ALL);
2342 		}
2343 		if (busy_count > SCAN_EBUSY_RETRY_LIMIT) {
2344 			struct ether_addr bssid;
2345 			s32 ret = 0;
2346 #ifdef BCMDONGLEHOST
2347 			dhd_pub_t *dhdp = (dhd_pub_t *)(cfg->pub);
2348 			if (dhd_query_bus_erros(dhdp)) {
2349 				return BCME_NOTREADY;
2350 			}
2351 			dhdp->scan_busy_occurred = TRUE;
2352 #endif /* BCMDONGLEHOST */
2353 			busy_count = 0;
2354 			WL_ERR(("Unusual continuous EBUSY error, %d %d %d %d %d %d %d %d %d\n",
2355 				wl_get_drv_status(cfg, SCANNING, ndev),
2356 				wl_get_drv_status(cfg, SCAN_ABORTING, ndev),
2357 				wl_get_drv_status(cfg, CONNECTING, ndev),
2358 				wl_get_drv_status(cfg, CONNECTED, ndev),
2359 				wl_get_drv_status(cfg, DISCONNECTING, ndev),
2360 				wl_get_drv_status(cfg, AP_CREATING, ndev),
2361 				wl_get_drv_status(cfg, AP_CREATED, ndev),
2362 				wl_get_drv_status(cfg, SENDING_ACT_FRM, ndev),
2363 				wl_get_drv_status(cfg, SENDING_ACT_FRM, ndev)));
2364 
2365 #ifdef BCMDONGLEHOST
2366 #if defined(DHD_DEBUG) && defined(DHD_FW_COREDUMP)
2367 			if (dhdp->memdump_enabled) {
2368 				dhdp->memdump_type = DUMP_TYPE_SCAN_BUSY;
2369 				dhd_bus_mem_dump(dhdp);
2370 			}
2371 #endif /* DHD_DEBUG && DHD_FW_COREDUMP */
2372 			dhdp->hang_reason = HANG_REASON_SCAN_BUSY;
2373 
2374 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && defined(OEM_ANDROID)
2375 			dhd_os_send_hang_message(dhdp);
2376 #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && defined(OEM_ANDROID) */
2377 
2378 #if !((LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && \
2379 	defined(OEM_ANDROID))
2380 			WL_ERR(("%s: HANG event is unsupported\n", __FUNCTION__));
2381 #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27) && OEM_ANDROID */
2382 #endif /* BCMDONGLEHOST */
2383 
2384 			bzero(&bssid, sizeof(bssid));
2385 			if ((ret = wldev_ioctl_get(ndev, WLC_GET_BSSID,
2386 				&bssid, ETHER_ADDR_LEN)) == 0) {
2387 				WL_ERR(("FW is connected with " MACDBG "\n",
2388 					MAC2STRDBG(bssid.octet)));
2389 			} else {
2390 				WL_ERR(("GET BSSID failed with %d\n", ret));
2391 			}
2392 
2393 			/* To support GO, wl_cfgscan_cancel_scan()
2394 			 * is needed instead of wl_cfg80211_disconnect()
2395 			 */
2396 			wl_cfgscan_cancel_scan(cfg);
2397 
2398 		} else {
2399 			/* Hold the context for 400msec, so that 10 subsequent scans
2400 			* can give a buffer of 4sec which is enough to
2401 			* cover any on-going scan in the firmware
2402 			*/
2403 			WL_DBG(("Enforcing delay for EBUSY case \n"));
2404 			msleep(400);
2405 		}
2406 	} else {
2407 		busy_count = 0;
2408 	}
2409 
2410 	return scanbusy_err;
2411 }
2412 
2413 s32
__wl_cfg80211_scan(struct wiphy * wiphy,struct net_device * ndev,struct cfg80211_scan_request * request,struct cfg80211_ssid * this_ssid)2414 __wl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev,
2415 	struct cfg80211_scan_request *request,
2416 	struct cfg80211_ssid *this_ssid)
2417 {
2418 	struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
2419 	struct cfg80211_ssid *ssids;
2420 	bool p2p_ssid;
2421 #ifdef WL11U
2422 	bcm_tlv_t *interworking_ie;
2423 #endif
2424 	s32 err = 0;
2425 	s32 bssidx = -1;
2426 	s32 i;
2427 	bool escan_req_failed = false;
2428 	s32 scanbusy_err = 0;
2429 
2430 	unsigned long flags;
2431 #ifdef WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST
2432 	struct net_device *remain_on_channel_ndev = NULL;
2433 #endif
2434 	/*
2435 	 * Hostapd triggers scan before starting automatic channel selection
2436 	 * to collect channel characteristics. However firmware scan engine
2437 	 * doesn't support any channel characteristics collection along with
2438 	 * scan. Hence return scan success.
2439 	 */
2440 	if (request && (scan_req_iftype(request) == NL80211_IFTYPE_AP)) {
2441 		WL_DBG(("Scan Command on SoftAP Interface. Ignoring...\n"));
2442 // terence 20161023: let it scan in SoftAP mode
2443 //		return 0;
2444 	}
2445 
2446 	if (request && request->n_ssids > WL_SCAN_PARAMS_SSID_MAX) {
2447 		WL_ERR(("request null or n_ssids > WL_SCAN_PARAMS_SSID_MAX\n"));
2448 		return -EOPNOTSUPP;
2449 	}
2450 
2451 	ndev = ndev_to_wlc_ndev(ndev, cfg);
2452 
2453 	if (WL_DRV_STATUS_SENDING_AF_FRM_EXT(cfg)) {
2454 		WL_ERR(("Sending Action Frames. Try it again.\n"));
2455 		return -EAGAIN;
2456 	}
2457 
2458 	WL_DBG(("Enter wiphy (%p)\n", wiphy));
2459 	mutex_lock(&cfg->scan_sync);
2460 	if (wl_get_drv_status_all(cfg, SCANNING)) {
2461 		if (cfg->scan_request == NULL) {
2462 			wl_clr_drv_status_all(cfg, SCANNING);
2463 			WL_DBG(("<<<<<<<<<<<Force Clear Scanning Status>>>>>>>>>>>\n"));
2464 		} else {
2465 			WL_ERR(("Scanning already\n"));
2466 			mutex_unlock(&cfg->scan_sync);
2467 			return -EAGAIN;
2468 		}
2469 	}
2470 	if (wl_get_drv_status(cfg, SCAN_ABORTING, ndev)) {
2471 		WL_ERR(("Scanning being aborted\n"));
2472 		mutex_unlock(&cfg->scan_sync);
2473 		return -EAGAIN;
2474 	}
2475 
2476 	if (cfg->loc.in_progress) {
2477 		/* Listen in progress, avoid new scan trigger */
2478 		mutex_unlock(&cfg->scan_sync);
2479 		return -EBUSY;
2480 	}
2481 	mutex_unlock(&cfg->scan_sync);
2482 
2483 #ifdef WL_BCNRECV
2484 	/* check fakeapscan in progress then abort */
2485 	wl_android_bcnrecv_stop(ndev, WL_BCNRECV_SCANBUSY);
2486 #endif /* WL_BCNRECV */
2487 
2488 #ifdef WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST
2489 	mutex_lock(&cfg->scan_sync);
2490 	remain_on_channel_ndev = wl_cfg80211_get_remain_on_channel_ndev(cfg);
2491 	if (remain_on_channel_ndev) {
2492 		WL_DBG(("Remain_on_channel bit is set, somehow it didn't get cleared\n"));
2493 		_wl_cfgscan_cancel_scan(cfg);
2494 	}
2495 	mutex_unlock(&cfg->scan_sync);
2496 #endif /* WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST */
2497 
2498 #ifdef P2P_LISTEN_OFFLOADING
2499 	wl_cfg80211_cancel_p2plo(cfg);
2500 #endif /* P2P_LISTEN_OFFLOADING */
2501 
2502 #ifdef WL_SDO
2503 	if (wl_get_p2p_status(cfg, DISC_IN_PROGRESS)) {
2504 		wl_cfg80211_pause_sdo(ndev, cfg);
2505 	}
2506 #endif
2507 
2508 	if (request) {		/* scan bss */
2509 		ssids = request->ssids;
2510 		p2p_ssid = false;
2511 		for (i = 0; i < request->n_ssids; i++) {
2512 			if (ssids[i].ssid_len &&
2513 				IS_P2P_SSID(ssids[i].ssid, ssids[i].ssid_len)) {
2514 				/* P2P Scan */
2515 #ifdef WL_BLOCK_P2P_SCAN_ON_STA
2516 				if (!(IS_P2P_IFACE(request->wdev))) {
2517 					/* P2P scan on non-p2p iface. Fail scan */
2518 					WL_ERR(("p2p_search on non p2p iface\n"));
2519 					goto scan_out;
2520 				}
2521 #endif /* WL_BLOCK_P2P_SCAN_ON_STA */
2522 				p2p_ssid = true;
2523 				break;
2524 			}
2525 		}
2526 		if (p2p_ssid) {
2527 			if (cfg->p2p_supported) {
2528 				/* p2p scan trigger */
2529 				if (p2p_on(cfg) == false) {
2530 					/* p2p on at the first time */
2531 					p2p_on(cfg) = true;
2532 					wl_cfgp2p_set_firm_p2p(cfg);
2533 #if defined(P2P_IE_MISSING_FIX)
2534 					cfg->p2p_prb_noti = false;
2535 #endif
2536 				}
2537 				wl_clr_p2p_status(cfg, GO_NEG_PHASE);
2538 				WL_DBG(("P2P: GO_NEG_PHASE status cleared \n"));
2539 				p2p_scan(cfg) = true;
2540 			}
2541 		} else {
2542 			/* legacy scan trigger
2543 			 * So, we have to disable p2p discovery if p2p discovery is on
2544 			 */
2545 			if (cfg->p2p_supported) {
2546 				p2p_scan(cfg) = false;
2547 				/* If Netdevice is not equals to primary and p2p is on
2548 				*  , we will do p2p scan using P2PAPI_BSSCFG_DEVICE.
2549 				*/
2550 
2551 				if (p2p_scan(cfg) == false) {
2552 					if (wl_get_p2p_status(cfg, DISCOVERY_ON)) {
2553 						err = wl_cfgp2p_discover_enable_search(cfg,
2554 						false);
2555 						if (unlikely(err)) {
2556 							goto scan_out;
2557 						}
2558 
2559 					}
2560 				}
2561 			}
2562 			if (!cfg->p2p_supported || !p2p_scan(cfg)) {
2563 				if ((bssidx = wl_get_bssidx_by_wdev(cfg,
2564 					ndev->ieee80211_ptr)) < 0) {
2565 					WL_ERR(("Find p2p index from ndev(%p) failed\n",
2566 						ndev));
2567 					err = BCME_ERROR;
2568 					goto scan_out;
2569 				}
2570 #ifdef WL11U
2571 				if (request && (interworking_ie = wl_cfg80211_find_interworking_ie(
2572 						request->ie, request->ie_len)) != NULL) {
2573 					if ((err = wl_cfg80211_add_iw_ie(cfg, ndev, bssidx,
2574 							VNDR_IE_CUSTOM_FLAG, interworking_ie->id,
2575 							interworking_ie->data,
2576 							interworking_ie->len)) != BCME_OK) {
2577 						WL_ERR(("Failed to add interworking IE"));
2578 					}
2579 				} else if (cfg->wl11u) {
2580 					/* we have to clear IW IE and disable gratuitous APR */
2581 					wl_cfg80211_clear_iw_ie(cfg, ndev, bssidx);
2582 					err = wldev_iovar_setint_bsscfg(ndev, "grat_arp",
2583 					                                0, bssidx);
2584 					/* we don't care about error here
2585 					 * because the only failure case is unsupported,
2586 					 * which is fine
2587 					 */
2588 					if (unlikely(err)) {
2589 						WL_ERR(("Set grat_arp failed:(%d) Ignore!\n", err));
2590 					}
2591 					cfg->wl11u = FALSE;
2592 				}
2593 #endif /* WL11U */
2594 				if (request) {
2595 					err = wl_cfg80211_set_mgmt_vndr_ies(cfg,
2596 						ndev_to_cfgdev(ndev), bssidx, VNDR_IE_PRBREQ_FLAG,
2597 						request->ie, request->ie_len);
2598 				}
2599 
2600 				if (unlikely(err)) {
2601 // terence 20161023: let it scan in SoftAP mode
2602 //					goto scan_out;
2603 				}
2604 
2605 			}
2606 		}
2607 	} else {		/* scan in ibss */
2608 		ssids = this_ssid;
2609 	}
2610 
2611 	WL_TRACE_HW4(("START SCAN\n"));
2612 
2613 #if defined(BCMDONGLEHOST) && defined(OEM_ANDROID)
2614 	DHD_OS_SCAN_WAKE_LOCK_TIMEOUT((dhd_pub_t *)(cfg->pub),
2615 		wl_get_scan_timeout_val(cfg) + SCAN_WAKE_LOCK_MARGIN_MS);
2616 	DHD_DISABLE_RUNTIME_PM((dhd_pub_t *)(cfg->pub));
2617 #endif
2618 
2619 	if (cfg->p2p_supported) {
2620 		if (request && p2p_on(cfg) && p2p_scan(cfg)) {
2621 
2622 #ifdef WL_SDO
2623 			if (wl_get_p2p_status(cfg, DISC_IN_PROGRESS)) {
2624 				/* We shouldn't be getting p2p_find while discovery
2625 				 * offload is in progress
2626 				 */
2627 				WL_SD(("P2P_FIND: Discovery offload is in progress."
2628 					" Do nothing\n"));
2629 				err = -EINVAL;
2630 				goto scan_out;
2631 			}
2632 #endif
2633 			/* find my listen channel */
2634 			cfg->afx_hdl->my_listen_chan =
2635 				wl_find_listen_channel(cfg, request->ie,
2636 				request->ie_len);
2637 			err = wl_cfgp2p_enable_discovery(cfg, ndev,
2638 			request->ie, request->ie_len);
2639 
2640 			if (unlikely(err)) {
2641 				goto scan_out;
2642 			}
2643 		}
2644 	}
2645 
2646 #ifdef WL_EXT_IAPSTA
2647 	if (wl_ext_in4way_sync(ndev, STA_FAKE_SCAN_IN_CONNECT, WL_EXT_STATUS_SCANNING, NULL)) {
2648 		mutex_lock(&cfg->scan_sync);
2649 		goto scan_success;
2650 	}
2651 #endif
2652 	mutex_lock(&cfg->scan_sync);
2653 	err = wl_do_escan(cfg, wiphy, ndev, request);
2654 	if (likely(!err)) {
2655 		goto scan_success;
2656 	} else {
2657 		escan_req_failed = true;
2658 		goto scan_out;
2659 	}
2660 
2661 scan_success:
2662 	wl_cfgscan_handle_scanbusy(cfg, ndev, BCME_OK);
2663 	cfg->scan_request = request;
2664 	LOG_TS(cfg, scan_start);
2665 	wl_set_drv_status(cfg, SCANNING, ndev);
2666 	/* Arm the timer */
2667 	mod_timer(&cfg->scan_timeout,
2668 		jiffies + msecs_to_jiffies(wl_get_scan_timeout_val(cfg)));
2669 	mutex_unlock(&cfg->scan_sync);
2670 	return 0;
2671 
2672 scan_out:
2673 	if (escan_req_failed) {
2674 		WL_CFG_DRV_LOCK(&cfg->cfgdrv_lock, flags);
2675 		cfg->scan_request = NULL;
2676 		WL_CFG_DRV_UNLOCK(&cfg->cfgdrv_lock, flags);
2677 		mutex_unlock(&cfg->scan_sync);
2678 		/* Handling for scan busy errors */
2679 		scanbusy_err = wl_cfgscan_handle_scanbusy(cfg, ndev, err);
2680 		if (scanbusy_err == BCME_NOTREADY) {
2681 			/* In case of bus failures avoid ioctl calls */
2682 
2683 #if defined(BCMDONGLEHOST) && defined(OEM_ANDROID)
2684 			DHD_OS_SCAN_WAKE_UNLOCK((dhd_pub_t *)(cfg->pub));
2685 			DHD_ENABLE_RUNTIME_PM((dhd_pub_t *)(cfg->pub));
2686 #endif
2687 
2688 			return -ENODEV;
2689 		}
2690 		err = scanbusy_err;
2691 	}
2692 
2693 #if defined(BCMDONGLEHOST) && defined(OEM_ANDROID)
2694 	DHD_OS_SCAN_WAKE_UNLOCK((dhd_pub_t *)(cfg->pub));
2695 	DHD_ENABLE_RUNTIME_PM((dhd_pub_t *)(cfg->pub));
2696 #endif
2697 
2698 #ifdef WL_SDO
2699 	if (wl_get_p2p_status(cfg, DISC_IN_PROGRESS)) {
2700 		wl_cfg80211_resume_sdo(ndev, cfg);
2701 	}
2702 #endif
2703 	return err;
2704 }
2705 
2706 s32
2707 #if defined(WL_CFG80211_P2P_DEV_IF)
wl_cfg80211_scan(struct wiphy * wiphy,struct cfg80211_scan_request * request)2708 wl_cfg80211_scan(struct wiphy *wiphy, struct cfg80211_scan_request *request)
2709 #else
2710 wl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev,
2711 	struct cfg80211_scan_request *request)
2712 #endif /* WL_CFG80211_P2P_DEV_IF */
2713 {
2714 	s32 err = 0;
2715 	struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
2716 #if defined(WL_CFG80211_P2P_DEV_IF)
2717 	struct net_device *ndev = wdev_to_wlc_ndev(request->wdev, cfg);
2718 #endif /* WL_CFG80211_P2P_DEV_IF */
2719 
2720 	WL_DBG(("Enter\n"));
2721 	RETURN_EIO_IF_NOT_UP(cfg);
2722 
2723 #ifdef DHD_IFDEBUG
2724 #ifdef WL_CFG80211_P2P_DEV_IF
2725 	PRINT_WDEV_INFO(request->wdev);
2726 #else
2727 	PRINT_WDEV_INFO(ndev);
2728 #endif /* WL_CFG80211_P2P_DEV_IF */
2729 #endif /* DHD_IFDEBUG */
2730 
2731 	if (ndev == bcmcfg_to_prmry_ndev(cfg)) {
2732 		if (wl_cfg_multip2p_operational(cfg)) {
2733 			WL_ERR(("wlan0 scan failed, p2p devices are operational"));
2734 			 return -ENODEV;
2735 		}
2736 	}
2737 #ifdef WL_EXT_IAPSTA
2738 	err = wl_ext_in4way_sync(ndev_to_wlc_ndev(ndev, cfg), STA_NO_SCAN_IN4WAY,
2739 		WL_EXT_STATUS_SCAN, NULL);
2740 	if (err) {
2741 		WL_SCAN(("scan suppressed %d\n", err));
2742 		return err;
2743 	}
2744 #endif
2745 
2746 	err = __wl_cfg80211_scan(wiphy, ndev, request, NULL);
2747 	if (unlikely(err)) {
2748 		WL_ERR(("scan error (%d)\n", err));
2749 	}
2750 #ifdef WL_DRV_AVOID_SCANCACHE
2751 	/* Reset roam cache after successful scan request */
2752 #ifdef ROAM_CHANNEL_CACHE
2753 	if (!err) {
2754 		reset_roam_cache(cfg);
2755 	}
2756 #endif /* ROAM_CHANNEL_CACHE */
2757 #endif /* WL_DRV_AVOID_SCANCACHE */
2758 	return err;
2759 }
2760 
2761 /* Note: This API should be invoked with scan_sync mutex
2762  * held so that scan_request data structures doesn't
2763  * get modified in between.
2764  */
2765 struct wireless_dev *
wl_get_scan_wdev(struct bcm_cfg80211 * cfg)2766 wl_get_scan_wdev(struct bcm_cfg80211 *cfg)
2767 {
2768 	struct wireless_dev *wdev = NULL;
2769 
2770 	if (!cfg) {
2771 		WL_ERR(("cfg ptr null\n"));
2772 		return NULL;
2773 	}
2774 
2775 	if (!cfg->scan_request && !cfg->sched_scan_req) {
2776 		/* No scans in progress */
2777 		WL_MEM(("no scan in progress \n"));
2778 		return NULL;
2779 	}
2780 
2781 	if (cfg->scan_request) {
2782 		wdev = GET_SCAN_WDEV(cfg->scan_request);
2783 #ifdef WL_SCHED_SCAN
2784 	} else if (cfg->sched_scan_req) {
2785 		wdev = GET_SCHED_SCAN_WDEV(cfg->sched_scan_req);
2786 #endif /* WL_SCHED_SCAN */
2787 	} else {
2788 		WL_MEM(("no scan in progress \n"));
2789 	}
2790 
2791 	return wdev;
2792 }
2793 
_wl_cfgscan_cancel_scan(struct bcm_cfg80211 * cfg)2794 static void _wl_cfgscan_cancel_scan(struct bcm_cfg80211 *cfg)
2795 {
2796 	struct wireless_dev *wdev = NULL;
2797 	struct net_device *ndev = NULL;
2798 
2799 	if (!cfg->scan_request && !cfg->sched_scan_req) {
2800 		/* No scans in progress */
2801 		WL_INFORM_MEM(("No scan in progress\n"));
2802 		return;
2803 	}
2804 
2805 	wdev = wl_get_scan_wdev(cfg);
2806 	if (!wdev) {
2807 		WL_ERR(("No wdev present\n"));
2808 		return;
2809 	}
2810 
2811 	ndev = wdev_to_wlc_ndev(wdev, cfg);
2812 
2813 	/* Check if any scan in progress only then abort */
2814 	if (wl_get_drv_status_all(cfg, SCANNING)) {
2815 		wl_cfgscan_scan_abort(cfg);
2816 
2817 		/* Indicate escan completion to upper layer */
2818 		wl_notify_escan_complete(cfg, ndev, true);
2819 	}
2820 	WL_INFORM_MEM(("Scan aborted! \n"));
2821 }
2822 
2823 /* Wrapper function for cancel_scan with scan_sync mutex */
wl_cfgscan_cancel_scan(struct bcm_cfg80211 * cfg)2824 void wl_cfgscan_cancel_scan(struct bcm_cfg80211 *cfg)
2825 {
2826 	mutex_lock(&cfg->scan_sync);
2827 	_wl_cfgscan_cancel_scan(cfg);
2828 	mutex_unlock(&cfg->scan_sync);
2829 }
2830 
2831 /* Use wl_cfgscan_cancel_scan function for scan abort, as this would do a FW abort
2832 * followed by indication to upper layer, the current function wl_cfgscan_scan_abort, does
2833 * only FW abort.
2834 */
wl_cfgscan_scan_abort(struct bcm_cfg80211 * cfg)2835 void wl_cfgscan_scan_abort(struct bcm_cfg80211 *cfg)
2836 {
2837 	void *params = NULL;
2838 	s32 params_size = 0;
2839 	s32 err = BCME_OK;
2840 	struct net_device *dev = bcmcfg_to_prmry_ndev(cfg);
2841 	u32 channel, channel_num;
2842 
2843 	/* Abort scan params only need space for 1 channel and 0 ssids */
2844 	if (cfg->scan_params_v2) {
2845 		params_size = WL_SCAN_PARAMS_V2_FIXED_SIZE + (1 * sizeof(uint16));
2846 	} else {
2847 		params_size = WL_SCAN_PARAMS_FIXED_SIZE + (1 * sizeof(uint16));
2848 	}
2849 
2850 	params = MALLOCZ(cfg->osh, params_size);
2851 	if (params == NULL) {
2852 		WL_ERR(("mem alloc failed (%d bytes)\n", params_size));
2853 		return;
2854 	}
2855 
2856 	/* Use magic value of channel=-1 to abort scan */
2857 	channel = htodchanspec(-1);
2858 	channel_num = htod32((0 << WL_SCAN_PARAMS_NSSID_SHIFT) |
2859 			(1 & WL_SCAN_PARAMS_COUNT_MASK));
2860 	if (cfg->scan_params_v2) {
2861 		wl_scan_params_v2_t *params_v2 = (wl_scan_params_v2_t *)params;
2862 		params_v2->channel_list[0] = channel;
2863 		params_v2->channel_num = channel_num;
2864 		params_v2->length = htod16(sizeof(wl_scan_params_v2_t));
2865 	} else {
2866 		wl_scan_params_t *params_v1 = (wl_scan_params_t *)params;
2867 		params_v1->channel_list[0] = channel;
2868 		params_v1->channel_num = channel_num;
2869 	}
2870 #ifdef DHD_SEND_HANG_ESCAN_SYNCID_MISMATCH
2871 	cfg->escan_info.prev_escan_aborted = TRUE;
2872 #endif /* DHD_SEND_HANG_ESCAN_SYNCID_MISMATCH */
2873 	/* Do a scan abort to stop the driver's scan engine */
2874 	err = wldev_ioctl_set(dev, WLC_SCAN, params, params_size);
2875 	if (err < 0) {
2876 		/* scan abort can fail if there is no outstanding scan */
2877 		WL_ERR(("scan engine not aborted ret(%d)\n", err));
2878 	}
2879 	MFREE(cfg->osh, params, params_size);
2880 #ifdef WLTDLS
2881 	if (cfg->tdls_mgmt_frame) {
2882 		MFREE(cfg->osh, cfg->tdls_mgmt_frame, cfg->tdls_mgmt_frame_len);
2883 		cfg->tdls_mgmt_frame = NULL;
2884 		cfg->tdls_mgmt_frame_len = 0;
2885 	}
2886 #endif /* WLTDLS */
2887 }
2888 
2889 static s32
wl_notify_escan_complete(struct bcm_cfg80211 * cfg,struct net_device * ndev,bool aborted)2890 wl_notify_escan_complete(struct bcm_cfg80211 *cfg,
2891 	struct net_device *ndev, bool aborted)
2892 {
2893 	s32 err = BCME_OK;
2894 	unsigned long flags;
2895 	struct net_device *dev;
2896 	dhd_pub_t *dhdp = (dhd_pub_t *)(cfg->pub);
2897 
2898 	WL_DBG(("Enter \n"));
2899 	BCM_REFERENCE(dhdp);
2900 
2901 	if (!ndev) {
2902 		WL_ERR(("ndev is null\n"));
2903 		err = BCME_ERROR;
2904 		goto out;
2905 	}
2906 
2907 	if (cfg->escan_info.ndev != ndev) {
2908 		WL_ERR(("Outstanding scan req ndev not matching (%p:%p)\n",
2909 			cfg->escan_info.ndev, ndev));
2910 		err = BCME_ERROR;
2911 		goto out;
2912 	}
2913 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 19, 0)) && defined(SUPPORT_RANDOM_MAC_SCAN) && \
2914 	(!defined(WL_USE_RANDOMIZED_SCAN))
2915 	/* Disable scanmac if enabled */
2916 	if (cfg->scanmac_enabled) {
2917 		wl_cfg80211_scan_mac_disable(ndev);
2918 	}
2919 #endif /* LINUX_VERSION_CODE < KERNEL_VERSION(3, 19, 0) && defined(SUPPORT_RANDOM_MAC_SCAN) */
2920 	if (cfg->scan_request) {
2921 		dev = bcmcfg_to_prmry_ndev(cfg);
2922 #if defined(WL_ENABLE_P2P_IF)
2923 		if (cfg->scan_request->dev != cfg->p2p_net)
2924 			dev = cfg->scan_request->dev;
2925 #elif defined(WL_CFG80211_P2P_DEV_IF)
2926 		if (cfg->scan_request->wdev->iftype != NL80211_IFTYPE_P2P_DEVICE)
2927 			dev = cfg->scan_request->wdev->netdev;
2928 #endif /* WL_ENABLE_P2P_IF */
2929 	}
2930 	else {
2931 		WL_DBG(("cfg->scan_request is NULL. Internal scan scenario."
2932 			"doing scan_abort for ndev %p primary %p",
2933 			ndev, bcmcfg_to_prmry_ndev(cfg)));
2934 		dev = ndev;
2935 	}
2936 
2937 	del_timer_sync(&cfg->scan_timeout);
2938 	/* clear scan enq time on complete */
2939 	CLR_TS(cfg, scan_enq);
2940 	CLR_TS(cfg, scan_start);
2941 #if defined (ESCAN_RESULT_PATCH)
2942 	if (likely(cfg->scan_request)) {
2943 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0))
2944 		if (aborted && cfg->p2p && p2p_scan(cfg) &&
2945 			(cfg->scan_request->flags & NL80211_SCAN_FLAG_FLUSH)) {
2946 			WL_ERR(("scan list is changed"));
2947 			cfg->bss_list = wl_escan_get_buf(cfg, !aborted);
2948 		} else
2949 #endif
2950 			cfg->bss_list = wl_escan_get_buf(cfg, aborted);
2951 
2952 		wl_inform_bss(cfg);
2953 	}
2954 #endif /* ESCAN_RESULT_PATCH */
2955 
2956 	WL_CFG_DRV_LOCK(&cfg->cfgdrv_lock, flags);
2957 	if (likely(cfg->scan_request)) {
2958 		WL_INFORM_MEM(("[%s] Report scan done.\n", dev->name));
2959 		/* scan_sync mutex is already held */
2960 		_wl_notify_scan_done(cfg, aborted);
2961 		cfg->scan_request = NULL;
2962 	}
2963 	if (p2p_is_on(cfg))
2964 		wl_clr_p2p_status(cfg, SCANNING);
2965 	wl_clr_drv_status(cfg, SCANNING, dev);
2966 	CLR_TS(cfg, scan_start);
2967 	WL_CFG_DRV_UNLOCK(&cfg->cfgdrv_lock, flags);
2968 
2969 #ifdef WL_SCHED_SCAN
2970 	if (cfg->sched_scan_running && cfg->sched_scan_req) {
2971 		struct wiphy *wiphy = cfg->sched_scan_req->wiphy;
2972 		if (!aborted) {
2973 			WL_INFORM_MEM(("[%s] Report sched scan done.\n", dev->name));
2974 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0))
2975 			cfg80211_sched_scan_results(wiphy,
2976 					cfg->sched_scan_req->reqid);
2977 #else
2978 			cfg80211_sched_scan_results(wiphy);
2979 #endif /* LINUX_VER > 4.11 */
2980 		}
2981 
2982 		DBG_EVENT_LOG(dhdp, WIFI_EVENT_DRIVER_PNO_SCAN_COMPLETE);
2983 		/* Mark target scan as done */
2984 		cfg->sched_scan_running = FALSE;
2985 
2986 		if (cfg->bss_list && (cfg->bss_list->count == 0)) {
2987 			WL_INFORM_MEM(("bss list empty. report sched_scan_stop\n"));
2988 
2989 #if defined (WL_SCHED_SCAN) && defined (SCHED_SCAN_DELAYED_WORK)
2990 			wl_cfg80211_stop_pno(cfg,  bcmcfg_to_prmry_ndev(cfg));
2991 			/* schedule the work to indicate sched scan stop to cfg layer */
2992 			schedule_delayed_work(&cfg->sched_scan_stop_work, 0);
2993 #else
2994 			/* Indicated sched scan stopped so that user space
2995 			 * can do a full scan incase found match is empty.
2996 			 */
2997 			CFG80211_SCHED_SCAN_STOPPED(wiphy, cfg->sched_scan_req);
2998 			cfg->sched_scan_req = NULL;
2999 #endif
3000 
3001 		}
3002 	}
3003 #endif /* WL_SCHED_SCAN */
3004 	wake_up_interruptible(&dhdp->conf->event_complete);
3005 
3006 #if defined(BCMDONGLEHOST) && defined(OEM_ANDROID)
3007 	DHD_OS_SCAN_WAKE_UNLOCK((dhd_pub_t *)(cfg->pub));
3008 	DHD_ENABLE_RUNTIME_PM((dhd_pub_t *)(cfg->pub));
3009 #endif
3010 
3011 #ifdef WL_SDO
3012 	if (wl_get_p2p_status(cfg, DISC_IN_PROGRESS) && !in_atomic()) {
3013 		/* If it is in atomic, we probably have to wait till the
3014 		 * next event or find someother way of invoking this.
3015 		 */
3016 		wl_cfg80211_resume_sdo(ndev, cfg);
3017 	}
3018 #endif
3019 
3020 out:
3021 	return err;
3022 }
3023 
3024 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 5, 0))
3025 void
wl_cfg80211_abort_scan(struct wiphy * wiphy,struct wireless_dev * wdev)3026 wl_cfg80211_abort_scan(struct wiphy *wiphy, struct wireless_dev *wdev)
3027 {
3028 	struct bcm_cfg80211 *cfg;
3029 
3030 	WL_DBG(("Enter wl_cfg80211_abort_scan\n"));
3031 	cfg = wiphy_priv(wdev->wiphy);
3032 
3033 	/* Check if any scan in progress only then abort */
3034 	if (wl_get_drv_status_all(cfg, SCANNING)) {
3035 		wl_cfgscan_scan_abort(cfg);
3036 		/* Only scan abort is issued here. As per the expectation of abort_scan
3037 		* the status of abort is needed to be communicated using cfg80211_scan_done call.
3038 		* Here we just issue abort request and let the scan complete path to indicate
3039 		* abort to cfg80211 layer.
3040 		*/
3041 		WL_DBG(("wl_cfg80211_abort_scan: Scan abort issued to FW\n"));
3042 	}
3043 }
3044 #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 5, 0)) */
3045 
3046 #if defined(OEM_ANDROID) && defined(DHCP_SCAN_SUPPRESS)
wl_cfg80211_scan_supp_timerfunc(ulong data)3047 static void wl_cfg80211_scan_supp_timerfunc(ulong data)
3048 {
3049 	struct bcm_cfg80211 *cfg = (struct bcm_cfg80211 *)data;
3050 
3051 	WL_DBG(("Enter \n"));
3052 	schedule_work(&cfg->wlan_work);
3053 }
3054 
wl_cfg80211_scan_suppress(struct net_device * dev,int suppress)3055 int wl_cfg80211_scan_suppress(struct net_device *dev, int suppress)
3056 {
3057 	int ret = 0;
3058 	struct wireless_dev *wdev;
3059 	struct bcm_cfg80211 *cfg;
3060 	if (!dev || ((suppress != 0) && (suppress != 1))) {
3061 		ret = -EINVAL;
3062 		goto exit;
3063 	}
3064 	wdev = ndev_to_wdev(dev);
3065 	if (!wdev) {
3066 		ret = -EINVAL;
3067 		goto exit;
3068 	}
3069 	cfg = (struct bcm_cfg80211 *)wiphy_priv(wdev->wiphy);
3070 	if (!cfg) {
3071 		ret = -EINVAL;
3072 		goto exit;
3073 	}
3074 
3075 	if (suppress == cfg->scan_suppressed) {
3076 		WL_DBG(("No change in scan_suppress state. Ignoring cmd..\n"));
3077 		return 0;
3078 	}
3079 
3080 	del_timer_sync(&cfg->scan_supp_timer);
3081 
3082 	if ((ret = wldev_ioctl_set(dev, WLC_SET_SCANSUPPRESS,
3083 		&suppress, sizeof(int))) < 0) {
3084 		WL_ERR(("Scan suppress setting failed ret:%d \n", ret));
3085 	} else {
3086 		WL_DBG(("Scan suppress %s \n", suppress ? "Enabled" : "Disabled"));
3087 		cfg->scan_suppressed = suppress;
3088 	}
3089 
3090 	/* If scan_suppress is set, Start a timer to monitor it (just incase) */
3091 	if (cfg->scan_suppressed) {
3092 		if (ret) {
3093 			WL_ERR(("Retry scan_suppress reset at a later time \n"));
3094 			mod_timer(&cfg->scan_supp_timer,
3095 				jiffies + msecs_to_jiffies(WL_SCAN_SUPPRESS_RETRY));
3096 		} else {
3097 			WL_DBG(("Start wlan_timer to clear of scan_suppress \n"));
3098 			mod_timer(&cfg->scan_supp_timer,
3099 				jiffies + msecs_to_jiffies(WL_SCAN_SUPPRESS_TIMEOUT));
3100 		}
3101 	}
3102 exit:
3103 	return ret;
3104 }
3105 #endif /* DHCP_SCAN_SUPPRESS */
3106 
wl_cfg80211_scan_stop(struct bcm_cfg80211 * cfg,bcm_struct_cfgdev * cfgdev)3107 int wl_cfg80211_scan_stop(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev)
3108 {
3109 	int ret = 0;
3110 
3111 	WL_TRACE(("Enter\n"));
3112 
3113 	if (!cfg || !cfgdev) {
3114 		return -EINVAL;
3115 	}
3116 
3117 	/* cancel scan and notify scan status */
3118 	wl_cfgscan_cancel_scan(cfg);
3119 
3120 	return ret;
3121 }
3122 
3123 /* This API is just meant as a wrapper for cfg80211_scan_done
3124  * API. This doesn't do state mgmt. For cancelling scan,
3125  * please use wl_cfgscan_cancel_scan API.
3126  */
3127 static void
_wl_notify_scan_done(struct bcm_cfg80211 * cfg,bool aborted)3128 _wl_notify_scan_done(struct bcm_cfg80211 *cfg, bool aborted)
3129 {
3130 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 8, 0))
3131 	struct cfg80211_scan_info info;
3132 #endif
3133 
3134 	if (!cfg->scan_request) {
3135 		return;
3136 	}
3137 
3138 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 8, 0))
3139 	memset_s(&info, sizeof(struct cfg80211_scan_info), 0, sizeof(struct cfg80211_scan_info));
3140 	info.aborted = aborted;
3141 	cfg80211_scan_done(cfg->scan_request, &info);
3142 #else
3143 	cfg80211_scan_done(cfg->scan_request, aborted);
3144 #endif
3145 	cfg->scan_request = NULL;
3146 }
3147 
3148 #ifdef WL_DRV_AVOID_SCANCACHE
wl_p2p_find_peer_channel(struct bcm_cfg80211 * cfg,s32 status,wl_bss_info_t * bi,u32 bi_length)3149 static u32 wl_p2p_find_peer_channel(struct bcm_cfg80211 *cfg, s32 status, wl_bss_info_t *bi,
3150 		u32 bi_length)
3151 {
3152 	u32 ret;
3153 	u8 *p2p_dev_addr = NULL;
3154 
3155 	ret = wl_get_drv_status_all(cfg, FINDING_COMMON_CHANNEL);
3156 	if (!ret) {
3157 		return ret;
3158 	}
3159 	if (status == WLC_E_STATUS_PARTIAL) {
3160 		p2p_dev_addr = wl_cfgp2p_retreive_p2p_dev_addr(bi, bi_length);
3161 		if (p2p_dev_addr && !memcmp(p2p_dev_addr,
3162 			cfg->afx_hdl->tx_dst_addr.octet, ETHER_ADDR_LEN)) {
3163 			s32 channel = wf_chspec_ctlchan(
3164 				wl_chspec_driver_to_host(bi->chanspec));
3165 
3166 			if ((channel > MAXCHANNEL) || (channel <= 0)) {
3167 				channel = WL_INVALID;
3168 			} else {
3169 				WL_ERR(("ACTION FRAME SCAN : Peer " MACDBG " found,"
3170 					" channel : %d\n",
3171 					MAC2STRDBG(cfg->afx_hdl->tx_dst_addr.octet),
3172 					channel));
3173 			}
3174 			wl_clr_p2p_status(cfg, SCANNING);
3175 			cfg->afx_hdl->peer_chan = channel;
3176 			complete(&cfg->act_frm_scan);
3177 		}
3178 	} else {
3179 		WL_INFORM_MEM(("ACTION FRAME SCAN DONE\n"));
3180 		wl_clr_p2p_status(cfg, SCANNING);
3181 		wl_clr_drv_status(cfg, SCANNING, cfg->afx_hdl->dev);
3182 		if (cfg->afx_hdl->peer_chan == WL_INVALID)
3183 			complete(&cfg->act_frm_scan);
3184 	}
3185 
3186 	return ret;
3187 }
3188 
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)3189 static s32 wl_escan_without_scan_cache(struct bcm_cfg80211 *cfg, wl_escan_result_t *escan_result,
3190 	struct net_device *ndev, const wl_event_msg_t *e, s32 status)
3191 {
3192 	s32 err = BCME_OK;
3193 	wl_bss_info_t *bi;
3194 	u32 bi_length;
3195 	bool aborted = false;
3196 	bool fw_abort = false;
3197 	bool notify_escan_complete = false;
3198 
3199 	if (wl_escan_check_sync_id(cfg, status, escan_result->sync_id,
3200 		cfg->escan_info.cur_sync_id) < 0) {
3201 		goto exit;
3202 	}
3203 
3204 	if (!(status == WLC_E_STATUS_TIMEOUT) || !(status == WLC_E_STATUS_PARTIAL)) {
3205 		cfg->escan_info.escan_state = WL_ESCAN_STATE_IDLE;
3206 	}
3207 
3208 	if ((likely(cfg->scan_request)) || (cfg->sched_scan_running)) {
3209 		notify_escan_complete = true;
3210 	}
3211 
3212 	if (status == WLC_E_STATUS_PARTIAL) {
3213 		WL_DBG(("WLC_E_STATUS_PARTIAL \n"));
3214 		DBG_EVENT_LOG((dhd_pub_t *)cfg->pub, WIFI_EVENT_DRIVER_SCAN_RESULT_FOUND);
3215 		if ((!escan_result) || (dtoh16(escan_result->bss_count) != 1)) {
3216 			WL_ERR(("Invalid escan result (NULL pointer) or invalid bss_count\n"));
3217 			goto exit;
3218 		}
3219 
3220 		bi = escan_result->bss_info;
3221 		bi_length = dtoh32(bi->length);
3222 		if ((!bi) ||
3223 		(bi_length != (dtoh32(escan_result->buflen) - WL_ESCAN_RESULTS_FIXED_SIZE))) {
3224 			WL_ERR(("Invalid escan bss info (NULL pointer)"
3225 				"or invalid bss_info length\n"));
3226 			goto exit;
3227 		}
3228 
3229 		if (!(bcmcfg_to_wiphy(cfg)->interface_modes & BIT(NL80211_IFTYPE_ADHOC))) {
3230 			if (dtoh16(bi->capability) & DOT11_CAP_IBSS) {
3231 				WL_DBG(("Ignoring IBSS result\n"));
3232 				goto exit;
3233 			}
3234 		}
3235 
3236 		if (wl_p2p_find_peer_channel(cfg, status, bi, bi_length)) {
3237 			goto exit;
3238 		} else {
3239 			if (scan_req_match(cfg)) {
3240 				/* p2p scan && allow only probe response */
3241 				if ((cfg->p2p->search_state != WL_P2P_DISC_ST_SCAN) &&
3242 					(bi->flags & WL_BSS_FLAGS_FROM_BEACON))
3243 					goto exit;
3244 			}
3245 #ifdef ROAM_CHANNEL_CACHE
3246 			add_roam_cache(cfg, bi);
3247 #endif /* ROAM_CHANNEL_CACHE */
3248 			err = wl_inform_single_bss(cfg, bi, false);
3249 #ifdef ROAM_CHANNEL_CACHE
3250 			/* print_roam_cache(); */
3251 			update_roam_cache(cfg, ioctl_version);
3252 #endif /* ROAM_CHANNEL_CACHE */
3253 
3254 			/*
3255 			 * !Broadcast && number of ssid = 1 && number of channels =1
3256 			 * means specific scan to association
3257 			 */
3258 			if (wl_cfgp2p_is_p2p_specific_scan(cfg->scan_request)) {
3259 				WL_ERR(("P2P assoc scan fast aborted.\n"));
3260 				aborted = false;
3261 				fw_abort = true;
3262 			}
3263 			/* Directly exit from function here and
3264 			* avoid sending notify completion to cfg80211
3265 			*/
3266 			goto exit;
3267 		}
3268 	} else if (status == WLC_E_STATUS_SUCCESS) {
3269 		if (wl_p2p_find_peer_channel(cfg, status, NULL, 0)) {
3270 			goto exit;
3271 		}
3272 		WL_INFORM_MEM(("ESCAN COMPLETED\n"));
3273 		DBG_EVENT_LOG((dhd_pub_t *)cfg->pub, WIFI_EVENT_DRIVER_SCAN_COMPLETE);
3274 
3275 		/* Update escan complete status */
3276 		aborted = false;
3277 		fw_abort = false;
3278 
3279 #ifdef CUSTOMER_HW4_DEBUG
3280 		if (wl_scan_timeout_dbg_enabled)
3281 			wl_scan_timeout_dbg_clear();
3282 #endif /* CUSTOMER_HW4_DEBUG */
3283 	} else if ((status == WLC_E_STATUS_ABORT) || (status == WLC_E_STATUS_NEWSCAN) ||
3284 		(status == WLC_E_STATUS_11HQUIET) || (status == WLC_E_STATUS_CS_ABORT) ||
3285 		(status == WLC_E_STATUS_NEWASSOC)) {
3286 		/* Handle all cases of scan abort */
3287 
3288 		WL_DBG(("ESCAN ABORT reason: %d\n", status));
3289 		if (wl_p2p_find_peer_channel(cfg, status, NULL, 0)) {
3290 			goto exit;
3291 		}
3292 		WL_INFORM_MEM(("ESCAN ABORTED\n"));
3293 
3294 		/* Update escan complete status */
3295 		aborted = true;
3296 		fw_abort = false;
3297 
3298 	} else if (status == WLC_E_STATUS_TIMEOUT) {
3299 		WL_ERR(("WLC_E_STATUS_TIMEOUT : scan_request[%p]\n", cfg->scan_request));
3300 		WL_ERR(("reason[0x%x]\n", e->reason));
3301 		if (e->reason == 0xFFFFFFFF) {
3302 			/* Update escan complete status */
3303 			aborted = true;
3304 			fw_abort = true;
3305 		}
3306 	} else {
3307 		WL_ERR(("unexpected Escan Event %d : abort\n", status));
3308 
3309 		if (wl_p2p_find_peer_channel(cfg, status, NULL, 0)) {
3310 			goto exit;
3311 		}
3312 		/* Update escan complete status */
3313 		aborted = true;
3314 		fw_abort = false;
3315 	}
3316 
3317 	/* Notify escan complete status */
3318 	if (notify_escan_complete) {
3319 		if (fw_abort == true) {
3320 			wl_cfgscan_cancel_scan(cfg);
3321 		} else {
3322 			wl_notify_escan_complete(cfg, ndev, aborted);
3323 		}
3324 	}
3325 
3326 exit:
3327 	return err;
3328 
3329 }
3330 #endif /* WL_DRV_AVOID_SCANCACHE */
3331 
3332 s32
wl_notify_scan_status(struct bcm_cfg80211 * cfg,bcm_struct_cfgdev * cfgdev,const wl_event_msg_t * e,void * data)3333 wl_notify_scan_status(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev,
3334 	const wl_event_msg_t *e, void *data)
3335 {
3336 	struct channel_info channel_inform;
3337 	wl_scan_results_t *bss_list;
3338 	struct net_device *ndev = NULL;
3339 	u32 len = WL_SCAN_BUF_MAX;
3340 	s32 err = 0;
3341 	unsigned long flags;
3342 
3343 	WL_DBG(("Enter \n"));
3344 	if (!wl_get_drv_status(cfg, SCANNING, ndev)) {
3345 		WL_DBG(("scan is not ready \n"));
3346 		return err;
3347 	}
3348 	ndev = cfgdev_to_wlc_ndev(cfgdev, cfg);
3349 
3350 	mutex_lock(&cfg->scan_sync);
3351 	wl_clr_drv_status(cfg, SCANNING, ndev);
3352 	bzero(&channel_inform, sizeof(channel_inform));
3353 	err = wldev_ioctl_get(ndev, WLC_GET_CHANNEL, &channel_inform,
3354 		sizeof(channel_inform));
3355 	if (unlikely(err)) {
3356 		WL_ERR(("scan busy (%d)\n", err));
3357 		goto scan_done_out;
3358 	}
3359 	channel_inform.scan_channel = dtoh32(channel_inform.scan_channel);
3360 	if (unlikely(channel_inform.scan_channel)) {
3361 
3362 		WL_DBG(("channel_inform.scan_channel (%d)\n",
3363 			channel_inform.scan_channel));
3364 	}
3365 	cfg->bss_list = cfg->scan_results;
3366 	bss_list = cfg->bss_list;
3367 	bzero(bss_list, len);
3368 	bss_list->buflen = htod32(len);
3369 	err = wldev_ioctl_get(ndev, WLC_SCAN_RESULTS, bss_list, len);
3370 	if (unlikely(err) && unlikely(!cfg->scan_suppressed)) {
3371 		WL_ERR(("%s Scan_results error (%d)\n", ndev->name, err));
3372 		err = -EINVAL;
3373 		goto scan_done_out;
3374 	}
3375 	bss_list->buflen = dtoh32(bss_list->buflen);
3376 	bss_list->version = dtoh32(bss_list->version);
3377 	bss_list->count = dtoh32(bss_list->count);
3378 
3379 	err = wl_inform_bss(cfg);
3380 
3381 scan_done_out:
3382 	del_timer_sync(&cfg->scan_timeout);
3383 	WL_CFG_DRV_LOCK(&cfg->cfgdrv_lock, flags);
3384 	if (cfg->scan_request) {
3385 		_wl_notify_scan_done(cfg, false);
3386 		cfg->scan_request = NULL;
3387 	}
3388 	WL_CFG_DRV_UNLOCK(&cfg->cfgdrv_lock, flags);
3389 	WL_DBG(("cfg80211_scan_done\n"));
3390 	mutex_unlock(&cfg->scan_sync);
3391 	return err;
3392 }
3393 
wl_notify_scan_done(struct bcm_cfg80211 * cfg,bool aborted)3394 void wl_notify_scan_done(struct bcm_cfg80211 *cfg, bool aborted)
3395 {
3396 #if defined(CONFIG_TIZEN)
3397 	struct net_device *ndev = NULL;
3398 #endif /* CONFIG_TIZEN */
3399 
3400 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 8, 0))
3401 	struct cfg80211_scan_info info;
3402 
3403 	bzero(&info, sizeof(struct cfg80211_scan_info));
3404 	info.aborted = aborted;
3405 	cfg80211_scan_done(cfg->scan_request, &info);
3406 #else
3407 	cfg80211_scan_done(cfg->scan_request, aborted);
3408 #endif
3409 
3410 #if defined(CONFIG_TIZEN)
3411 	ndev = bcmcfg_to_prmry_ndev(cfg);
3412 	if (aborted)
3413 		net_stat_tizen_update_wifi(ndev, WIFISTAT_SCAN_ABORT);
3414 	else
3415 		net_stat_tizen_update_wifi(ndev, WIFISTAT_SCAN_DONE);
3416 #endif /* CONFIG_TIZEN */
3417 }
3418 
3419 #if defined(SUPPORT_RANDOM_MAC_SCAN)
3420 int
wl_cfg80211_set_random_mac(struct net_device * dev,bool enable)3421 wl_cfg80211_set_random_mac(struct net_device *dev, bool enable)
3422 {
3423 	struct bcm_cfg80211 *cfg = wl_get_cfg(dev);
3424 	int ret;
3425 
3426 	if (cfg->random_mac_enabled == enable) {
3427 		WL_ERR(("Random MAC already %s\n", enable ? "Enabled" : "Disabled"));
3428 		return BCME_OK;
3429 	}
3430 
3431 	if (enable) {
3432 		ret = wl_cfg80211_random_mac_enable(dev);
3433 	} else {
3434 		ret = wl_cfg80211_random_mac_disable(dev);
3435 	}
3436 
3437 	if (!ret) {
3438 		cfg->random_mac_enabled = enable;
3439 	}
3440 
3441 	return ret;
3442 }
3443 
3444 int
wl_cfg80211_random_mac_enable(struct net_device * dev)3445 wl_cfg80211_random_mac_enable(struct net_device *dev)
3446 {
3447 	u8 random_mac[ETH_ALEN] = {0, };
3448 	u8 rand_bytes[3] = {0, };
3449 	s32 err = BCME_ERROR;
3450 	struct bcm_cfg80211 *cfg = wl_get_cfg(dev);
3451 #if !defined(LEGACY_RANDOM_MAC)
3452 	uint8 buffer[WLC_IOCTL_SMLEN] = {0, };
3453 	wl_scanmac_t *sm = NULL;
3454 	int len = 0;
3455 	wl_scanmac_enable_t *sm_enable = NULL;
3456 	wl_scanmac_config_t *sm_config = NULL;
3457 #endif /* !LEGACY_RANDOM_MAC */
3458 
3459 	if (wl_get_drv_status_all(cfg, CONNECTED) || wl_get_drv_status_all(cfg, CONNECTING) ||
3460 	    wl_get_drv_status_all(cfg, AP_CREATED) || wl_get_drv_status_all(cfg, AP_CREATING)) {
3461 		WL_ERR(("fail to Set random mac, current state is wrong\n"));
3462 		return err;
3463 	}
3464 
3465 	(void)memcpy_s(random_mac, ETH_ALEN, bcmcfg_to_prmry_ndev(cfg)->dev_addr, ETH_ALEN);
3466 	get_random_bytes(&rand_bytes, sizeof(rand_bytes));
3467 
3468 	if (rand_bytes[2] == 0x0 || rand_bytes[2] == 0xff) {
3469 		rand_bytes[2] = 0xf0;
3470 	}
3471 
3472 #if defined(LEGACY_RANDOM_MAC)
3473 	/* of the six bytes of random_mac the bytes 3, 4, 5 are copied with contents of rand_bytes
3474 	* So while copying 3 bytes of content no overflow would be seen. Hence returning void.
3475 	*/
3476 	(void)memcpy_s(&random_mac[3], (sizeof(u8) * 3), rand_bytes, sizeof(rand_bytes));
3477 
3478 	err = wldev_iovar_setbuf_bsscfg(bcmcfg_to_prmry_ndev(cfg), "cur_etheraddr",
3479 		random_mac, ETH_ALEN, cfg->ioctl_buf, WLC_IOCTL_SMLEN, 0, &cfg->ioctl_buf_sync);
3480 
3481 	if (err != BCME_OK) {
3482 		WL_ERR(("failed to set random generate MAC address\n"));
3483 	} else {
3484 		WL_ERR(("set mac " MACDBG " to " MACDBG "\n",
3485 			MAC2STRDBG((const u8 *)bcmcfg_to_prmry_ndev(cfg)->dev_addr),
3486 			MAC2STRDBG((const u8 *)&random_mac)));
3487 		WL_ERR(("random MAC enable done"));
3488 	}
3489 #else
3490 	/* Enable scan mac */
3491 	sm = (wl_scanmac_t *)buffer;
3492 	sm_enable = (wl_scanmac_enable_t *)sm->data;
3493 	sm->len = sizeof(*sm_enable);
3494 	sm_enable->enable = 1;
3495 	len = OFFSETOF(wl_scanmac_t, data) + sm->len;
3496 	sm->subcmd_id = WL_SCANMAC_SUBCMD_ENABLE;
3497 
3498 	err = wldev_iovar_setbuf_bsscfg(dev, "scanmac",
3499 		sm, len, cfg->ioctl_buf, WLC_IOCTL_SMLEN, 0, &cfg->ioctl_buf_sync);
3500 
3501 	/* For older chip which which does not have scanmac support can still use
3502 	 * cur_etheraddr to set the randmac. rand_mask and rand_mac comes from upper
3503 	 * cfg80211 layer. If rand_mask and rand_mac is not passed then fallback
3504 	 * to default cur_etheraddr and default mask.
3505 	 */
3506 	if (err == BCME_UNSUPPORTED) {
3507 		/* In case of host based legacy randomization, random address is
3508 		 * generated by mixing 3 bytes of cur_etheraddr and 3 bytes of
3509 		 * random bytes generated.In that case rand_mask is nothing but
3510 		 * random bytes.
3511 		 */
3512 		(void)memcpy_s(&random_mac[3], (sizeof(u8) * 3), rand_bytes, sizeof(rand_bytes));
3513 		err = wldev_iovar_setbuf_bsscfg(bcmcfg_to_prmry_ndev(cfg), "cur_etheraddr",
3514 				random_mac, ETH_ALEN, cfg->ioctl_buf,
3515 				WLC_IOCTL_SMLEN, 0, &cfg->ioctl_buf_sync);
3516 		if (err != BCME_OK) {
3517 			WL_ERR(("failed to set random generate MAC address\n"));
3518 		} else {
3519 			WL_ERR(("set mac " MACDBG " to " MACDBG "\n",
3520 				MAC2STRDBG((const u8 *)bcmcfg_to_prmry_ndev(cfg)->dev_addr),
3521 				MAC2STRDBG((const u8 *)&random_mac)));
3522 			WL_ERR(("random MAC enable done using legacy randmac"));
3523 		}
3524 	} else if (err == BCME_OK) {
3525 		/* Configure scanmac */
3526 		(void)memset_s(buffer, sizeof(buffer), 0x0, sizeof(buffer));
3527 		sm_config = (wl_scanmac_config_t *)sm->data;
3528 		sm->len = sizeof(*sm_config);
3529 		sm->subcmd_id = WL_SCANMAC_SUBCMD_CONFIG;
3530 		sm_config->scan_bitmap = WL_SCANMAC_SCAN_UNASSOC;
3531 
3532 		/* Set randomize mac address recv from upper layer */
3533 		(void)memcpy_s(&sm_config->mac.octet, ETH_ALEN, random_mac, ETH_ALEN);
3534 
3535 		/* Set randomize mask recv from upper layer */
3536 
3537 		/* Currently in samsung case, upper layer does not provide
3538 		 * variable randmask and its using fixed 3 byte randomization
3539 		 */
3540 		(void)memset_s(&sm_config->random_mask.octet, ETH_ALEN, 0x0, ETH_ALEN);
3541 		/* Memsetting the remaining octets 3, 4, 5. So remaining dest length is 3 */
3542 		(void)memset_s(&sm_config->random_mask.octet[3], 3, 0xFF, 3);
3543 
3544 		WL_DBG(("recv random mac addr " MACDBG  " recv rand mask" MACDBG "\n",
3545 			MAC2STRDBG((const u8 *)&sm_config->mac.octet),
3546 			MAC2STRDBG((const u8 *)&sm_config->random_mask)));
3547 
3548 		len = OFFSETOF(wl_scanmac_t, data) + sm->len;
3549 		err = wldev_iovar_setbuf_bsscfg(dev, "scanmac",
3550 			sm, len, cfg->ioctl_buf, WLC_IOCTL_SMLEN, 0, &cfg->ioctl_buf_sync);
3551 
3552 		if (err != BCME_OK) {
3553 			WL_ERR(("failed scanmac configuration\n"));
3554 
3555 			/* Disable scan mac for clean-up */
3556 			wl_cfg80211_random_mac_disable(dev);
3557 			return err;
3558 		}
3559 		WL_DBG(("random MAC enable done using scanmac"));
3560 	} else  {
3561 		WL_ERR(("failed to enable scanmac, err=%d\n", err));
3562 	}
3563 #endif /* LEGACY_RANDOM_MAC */
3564 
3565 	return err;
3566 }
3567 
3568 int
wl_cfg80211_random_mac_disable(struct net_device * dev)3569 wl_cfg80211_random_mac_disable(struct net_device *dev)
3570 {
3571 	s32 err = BCME_ERROR;
3572 	struct bcm_cfg80211 *cfg = wl_get_cfg(dev);
3573 #if !defined(LEGACY_RANDOM_MAC)
3574 	uint8 buffer[WLC_IOCTL_SMLEN] = {0, };
3575 	wl_scanmac_t *sm = NULL;
3576 	int len = 0;
3577 	wl_scanmac_enable_t *sm_enable = NULL;
3578 #endif /* !LEGACY_RANDOM_MAC */
3579 
3580 #if defined(LEGACY_RANDOM_MAC)
3581 	WL_ERR(("set original mac " MACDBG "\n",
3582 		MAC2STRDBG((const u8 *)bcmcfg_to_prmry_ndev(cfg)->dev_addr)));
3583 
3584 	err = wldev_iovar_setbuf_bsscfg(bcmcfg_to_prmry_ndev(cfg), "cur_etheraddr",
3585 		bcmcfg_to_prmry_ndev(cfg)->dev_addr, ETH_ALEN,
3586 		cfg->ioctl_buf, WLC_IOCTL_SMLEN, 0, &cfg->ioctl_buf_sync);
3587 
3588 	if (err != BCME_OK) {
3589 		WL_ERR(("failed to set original MAC address\n"));
3590 	} else {
3591 		WL_ERR(("legacy random MAC disable done \n"));
3592 	}
3593 #else
3594 	sm = (wl_scanmac_t *)buffer;
3595 	sm_enable = (wl_scanmac_enable_t *)sm->data;
3596 	sm->len = sizeof(*sm_enable);
3597 	/* Disable scanmac */
3598 	sm_enable->enable = 0;
3599 	len = OFFSETOF(wl_scanmac_t, data) + sm->len;
3600 
3601 	sm->subcmd_id = WL_SCANMAC_SUBCMD_ENABLE;
3602 
3603 	err = wldev_iovar_setbuf_bsscfg(dev, "scanmac",
3604 		sm, len, cfg->ioctl_buf, WLC_IOCTL_SMLEN, 0, &cfg->ioctl_buf_sync);
3605 
3606 	if (err != BCME_OK) {
3607 		WL_ERR(("failed to disable scanmac, err=%d\n", err));
3608 		return err;
3609 	}
3610 	/* Clear scanmac enabled status */
3611 	cfg->scanmac_enabled = 0;
3612 	WL_DBG(("random MAC disable done\n"));
3613 #endif /* LEGACY_RANDOM_MAC */
3614 
3615 	return err;
3616 }
3617 
wl_cfg80211_scan_mac_enable(struct net_device * dev)3618 int wl_cfg80211_scan_mac_enable(struct net_device *dev)
3619 {
3620 	struct bcm_cfg80211 *cfg = wl_get_cfg(dev);
3621 	s32 err = BCME_ERROR;
3622 	uint8 buffer[WLC_IOCTL_SMLEN] = {0};
3623 	wl_scanmac_t *sm = NULL;
3624 	int len = 0;
3625 	wl_scanmac_enable_t *sm_enable = NULL;
3626 
3627 	/* Enable scan mac */
3628 	sm = (wl_scanmac_t *)buffer;
3629 	sm_enable = (wl_scanmac_enable_t *)sm->data;
3630 	sm->len = sizeof(*sm_enable);
3631 	sm_enable->enable = 1;
3632 	len = OFFSETOF(wl_scanmac_t, data) + sm->len;
3633 	sm->subcmd_id = WL_SCANMAC_SUBCMD_ENABLE;
3634 
3635 	err = wldev_iovar_setbuf_bsscfg(dev, "scanmac",
3636 		sm, len, cfg->ioctl_buf, WLC_IOCTL_SMLEN, 0, &cfg->ioctl_buf_sync);
3637 	if (unlikely(err)) {
3638 		WL_ERR(("scanmac enable failed\n"));
3639 	} else {
3640 		/* Mark scanmac configured */
3641 		cfg->scanmac_enabled = 1;
3642 	}
3643 
3644 	return err;
3645 }
3646 /*
3647  * This is new interface for mac randomization. It takes randmac and randmask
3648  * as arg and it uses scanmac iovar to offload the mac randomization to firmware.
3649  */
wl_cfg80211_scan_mac_config(struct net_device * dev,uint8 * rand_mac,uint8 * rand_mask)3650 int wl_cfg80211_scan_mac_config(struct net_device *dev, uint8 *rand_mac, uint8 *rand_mask)
3651 {
3652 	int byte_index = 0;
3653 	s32 err = BCME_ERROR;
3654 	uint8 buffer[WLC_IOCTL_SMLEN] = {0};
3655 	wl_scanmac_t *sm = NULL;
3656 	int len = 0;
3657 	wl_scanmac_config_t *sm_config = NULL;
3658 	struct bcm_cfg80211 *cfg = wl_get_cfg(dev);
3659 	uint8 random_mask_46_bits[ETHER_ADDR_LEN] = {0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
3660 
3661 	if (rand_mac == NULL) {
3662 		err = BCME_BADARG;
3663 		WL_ERR(("fail to Set random mac, bad argument\n"));
3664 		/* Disable the current scanmac config */
3665 		return err;
3666 	}
3667 
3668 	if (ETHER_ISNULLADDR(rand_mac)) {
3669 		WL_DBG(("fail to Set random mac, Invalid rand mac\n"));
3670 		/* Disable the current scanmac config */
3671 		return err;
3672 	}
3673 
3674 	/* Configure scanmac */
3675 	(void)memset_s(buffer, sizeof(buffer), 0x0, sizeof(buffer));
3676 	sm = (wl_scanmac_t *)buffer;
3677 	sm_config = (wl_scanmac_config_t *)sm->data;
3678 	sm->len = sizeof(*sm_config);
3679 	sm->subcmd_id = WL_SCANMAC_SUBCMD_CONFIG;
3680 	sm_config->scan_bitmap = WL_SCANMAC_SCAN_UNASSOC;
3681 #ifdef WL_USE_RANDOMIZED_SCAN
3682 	sm_config->scan_bitmap |= WL_SCANMAC_SCAN_ASSOC_HOST;
3683 #endif /* WL_USE_RANDOMIZED_SCAN */
3684 	/* Set randomize mac address recv from upper layer */
3685 	(void)memcpy_s(&sm_config->mac.octet, ETH_ALEN, rand_mac, ETH_ALEN);
3686 
3687 	/* Set randomize mask recv from upper layer */
3688 
3689 	/* There is a difference in how to interpret rand_mask between
3690 	 * upperlayer and firmware. If the byte is set as FF then for
3691 	 * upper layer it  means keep that byte and do not randomize whereas
3692 	 * for firmware it means randomize those bytes and vice versa. Hence
3693 	 * conversion is needed before setting the iovar
3694 	 */
3695 	(void)memset_s(&sm_config->random_mask.octet, ETH_ALEN, 0x0, ETH_ALEN);
3696 	/* Only byte randomization is supported currently. If mask recv is 0x0F
3697 	 * for a particular byte then it will be treated as no randomization
3698 	 * for that byte.
3699 	 */
3700 	if (!rand_mask) {
3701 		/* If rand_mask not provided, use 46_bits_mask */
3702 		(void)memcpy_s(&sm_config->random_mask.octet, ETH_ALEN,
3703 			random_mask_46_bits, ETH_ALEN);
3704 	} else {
3705 		while (byte_index < ETH_ALEN) {
3706 			if (rand_mask[byte_index] == 0xFF) {
3707 				sm_config->random_mask.octet[byte_index] = 0x00;
3708 			} else if (rand_mask[byte_index] == 0x00) {
3709 				sm_config->random_mask.octet[byte_index] = 0xFF;
3710 			}
3711 			byte_index++;
3712 		}
3713 	}
3714 
3715 	WL_DBG(("recv random mac addr " MACDBG  "recv rand mask" MACDBG "\n",
3716 		MAC2STRDBG((const u8 *)&sm_config->mac.octet),
3717 		MAC2STRDBG((const u8 *)&sm_config->random_mask)));
3718 
3719 	len = OFFSETOF(wl_scanmac_t, data) + sm->len;
3720 	err = wldev_iovar_setbuf_bsscfg(dev, "scanmac",
3721 		sm, len, cfg->ioctl_buf, WLC_IOCTL_SMLEN, 0, &cfg->ioctl_buf_sync);
3722 
3723 	if (err != BCME_OK) {
3724 		WL_ERR(("failed scanmac configuration\n"));
3725 
3726 		/* Disable scan mac for clean-up */
3727 		return err;
3728 	}
3729 	WL_INFORM_MEM(("scanmac configured"));
3730 	cfg->scanmac_config = true;
3731 
3732 	return err;
3733 }
3734 
3735 int
wl_cfg80211_scan_mac_disable(struct net_device * dev)3736 wl_cfg80211_scan_mac_disable(struct net_device *dev)
3737 {
3738 	s32 err = BCME_ERROR;
3739 
3740 	err = wl_cfg80211_random_mac_disable(dev);
3741 
3742 	return err;
3743 }
3744 #endif /* SUPPORT_RANDOM_MAC_SCAN */
3745 
3746 #ifdef WL_SCHED_SCAN
3747 #define PNO_TIME                    30
3748 #define PNO_REPEAT                  4
3749 #define PNO_FREQ_EXPO_MAX           2
3750 #define PNO_ADAPTIVE_SCAN_LIMIT     60
3751 static bool
is_ssid_in_list(struct cfg80211_ssid * ssid,struct cfg80211_ssid * ssid_list,int count)3752 is_ssid_in_list(struct cfg80211_ssid *ssid, struct cfg80211_ssid *ssid_list, int count)
3753 {
3754 	int i;
3755 
3756 	if (!ssid || !ssid_list)
3757 		return FALSE;
3758 
3759 	for (i = 0; i < count; i++) {
3760 		if (ssid->ssid_len == ssid_list[i].ssid_len) {
3761 			if (strncmp(ssid->ssid, ssid_list[i].ssid, ssid->ssid_len) == 0)
3762 				return TRUE;
3763 		}
3764 	}
3765 	return FALSE;
3766 }
3767 
3768 int
wl_cfg80211_sched_scan_start(struct wiphy * wiphy,struct net_device * dev,struct cfg80211_sched_scan_request * request)3769 wl_cfg80211_sched_scan_start(struct wiphy *wiphy,
3770                              struct net_device *dev,
3771                              struct cfg80211_sched_scan_request *request)
3772 {
3773 	u16 chan_list[WL_NUMCHANNELS] = {0};
3774 	u32 num_channels = 0;
3775 	ushort pno_time;
3776 	int pno_repeat = PNO_REPEAT;
3777 	int pno_freq_expo_max = PNO_FREQ_EXPO_MAX;
3778 	wlc_ssid_ext_t ssids_local[MAX_PFN_LIST_COUNT];
3779 	struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
3780 	dhd_pub_t *dhdp = (dhd_pub_t *)(cfg->pub);
3781 	struct cfg80211_ssid *ssid = NULL;
3782 	struct cfg80211_ssid *hidden_ssid_list = NULL;
3783 	log_conn_event_t *event_data = NULL;
3784 	tlv_log *tlv_data = NULL;
3785 	u32 alloc_len = 0;
3786 	u32 payload_len;
3787 	int ssid_cnt = 0;
3788 	int i;
3789 	int ret = 0;
3790 	unsigned long flags;
3791 
3792 	if (!request) {
3793 		WL_ERR(("Sched scan request was NULL\n"));
3794 		return -EINVAL;
3795 	}
3796 
3797 	if ((request->n_scan_plans == 1) && request->scan_plans &&
3798 			(request->scan_plans->interval > PNO_ADAPTIVE_SCAN_LIMIT)) {
3799 		/* If the host gives a high value for scan interval, then
3800 		 * doing adaptive scan doesn't make sense. Better stick to the
3801 		 * scan interval that host gives.
3802 		 */
3803 		pno_time = request->scan_plans->interval;
3804 		pno_repeat = 0;
3805 		pno_freq_expo_max = 0;
3806 	} else {
3807 		/* Run adaptive PNO */
3808 		pno_time = PNO_TIME;
3809 	}
3810 
3811 	WL_DBG(("Enter. ssids:%d match_sets:%d pno_time:%d pno_repeat:%d channels:%d\n",
3812 		request->n_ssids, request->n_match_sets,
3813 		pno_time, pno_repeat, request->n_channels));
3814 
3815 	if (!request->n_ssids || !request->n_match_sets) {
3816 		WL_ERR(("Invalid sched scan req!! n_ssids:%d \n", request->n_ssids));
3817 		return -EINVAL;
3818 	}
3819 
3820 	bzero(&ssids_local, sizeof(ssids_local));
3821 
3822 	if (request->n_ssids > 0) {
3823 		hidden_ssid_list = request->ssids;
3824 	}
3825 
3826 	if (request->n_channels && request->n_channels < WL_NUMCHANNELS) {
3827 		/* get channel list. Note PNO uses channels and not chanspecs */
3828 		wl_cfgscan_populate_scan_channels(cfg,
3829 				request->channels, request->n_channels,
3830 				chan_list, &num_channels, false, false);
3831 	}
3832 
3833 	if (DBG_RING_ACTIVE(dhdp, DHD_EVENT_RING_ID)) {
3834 		alloc_len = sizeof(log_conn_event_t) + sizeof(tlv_log) + DOT11_MAX_SSID_LEN;
3835 		event_data = (log_conn_event_t *)MALLOCZ(cfg->osh, alloc_len);
3836 		if (!event_data) {
3837 			WL_ERR(("%s: failed to allocate log_conn_event_t with "
3838 						"length(%d)\n", __func__, alloc_len));
3839 			return -ENOMEM;
3840 		}
3841 	}
3842 	for (i = 0; i < request->n_match_sets && ssid_cnt < MAX_PFN_LIST_COUNT; i++) {
3843 		ssid = &request->match_sets[i].ssid;
3844 		/* No need to include null ssid */
3845 		if (ssid->ssid_len) {
3846 			ssids_local[ssid_cnt].SSID_len = MIN(ssid->ssid_len,
3847 				(uint32)DOT11_MAX_SSID_LEN);
3848 			/* In previous step max SSID_len is limited to DOT11_MAX_SSID_LEN,
3849 			* returning void
3850 			*/
3851 			(void)memcpy_s(ssids_local[ssid_cnt].SSID, DOT11_MAX_SSID_LEN, ssid->ssid,
3852 				ssids_local[ssid_cnt].SSID_len);
3853 			if (is_ssid_in_list(ssid, hidden_ssid_list, request->n_ssids)) {
3854 				ssids_local[ssid_cnt].hidden = TRUE;
3855 				WL_PNO((">>> PNO hidden SSID (%s) \n", ssid->ssid));
3856 			} else {
3857 				ssids_local[ssid_cnt].hidden = FALSE;
3858 				WL_PNO((">>> PNO non-hidden SSID (%s) \n", ssid->ssid));
3859 			}
3860 #if (LINUX_VERSION_CODE > KERNEL_VERSION(3, 15, 0))
3861 			if (request->match_sets[i].rssi_thold != NL80211_SCAN_RSSI_THOLD_OFF) {
3862 				ssids_local[ssid_cnt].rssi_thresh =
3863 				      (int8)request->match_sets[i].rssi_thold;
3864 			}
3865 #endif /* (LINUX_VERSION_CODE > KERNEL_VERSION(3, 15, 0)) */
3866 			ssid_cnt++;
3867 		}
3868 	}
3869 
3870 	if (ssid_cnt) {
3871 #if defined(BCMDONGLEHOST)
3872 		if ((ret = dhd_dev_pno_set_for_ssid(dev, ssids_local, ssid_cnt,
3873 			pno_time, pno_repeat, pno_freq_expo_max,
3874 			(num_channels ? chan_list : NULL), num_channels)) < 0) {
3875 			WL_ERR(("PNO setup failed!! ret=%d \n", ret));
3876 			ret = -EINVAL;
3877 			goto exit;
3878 		}
3879 #endif /* BCMDONGLEHOST */
3880 
3881 		if (DBG_RING_ACTIVE(dhdp, DHD_EVENT_RING_ID)) {
3882 			/*
3883 			 * purposefully logging here to make sure that
3884 			 * firmware configuration was successful
3885 			 */
3886 			for (i = 0; i < ssid_cnt; i++) {
3887 				payload_len = sizeof(log_conn_event_t);
3888 				event_data->event = WIFI_EVENT_DRIVER_PNO_ADD;
3889 				tlv_data = event_data->tlvs;
3890 				/* ssid */
3891 				tlv_data->tag = WIFI_TAG_SSID;
3892 				tlv_data->len = ssids_local[i].SSID_len;
3893 				(void)memcpy_s(tlv_data->value, DOT11_MAX_SSID_LEN,
3894 					ssids_local[i].SSID, ssids_local[i].SSID_len);
3895 				payload_len += TLV_LOG_SIZE(tlv_data);
3896 
3897 				dhd_os_push_push_ring_data(dhdp, DHD_EVENT_RING_ID,
3898 					event_data, payload_len);
3899 			}
3900 		}
3901 
3902 		WL_CFG_DRV_LOCK(&cfg->cfgdrv_lock, flags);
3903 		cfg->sched_scan_req = request;
3904 		WL_CFG_DRV_UNLOCK(&cfg->cfgdrv_lock, flags);
3905 	} else {
3906 		ret = -EINVAL;
3907 	}
3908 
3909 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 19, 0)) && defined(SUPPORT_RANDOM_MAC_SCAN)
3910 	if ((ret = wl_config_scan_macaddr(cfg, dev,
3911 		(request->flags & NL80211_SCAN_FLAG_RANDOM_ADDR),
3912 		request->mac_addr, request->mac_addr_mask)) != BCME_OK) {
3913 		WL_ERR(("scanmac addr config failed\n"));
3914 		/* Cleanup the states and stop the pno */
3915 		if (dhd_dev_pno_stop_for_ssid(dev) < 0) {
3916 			WL_ERR(("PNO Stop for SSID failed"));
3917 		}
3918 		WL_CFG_DRV_LOCK(&cfg->cfgdrv_lock, flags);
3919 		cfg->sched_scan_req = NULL;
3920 		cfg->sched_scan_running = FALSE;
3921 		WL_CFG_DRV_UNLOCK(&cfg->cfgdrv_lock, flags);
3922 		goto exit;
3923 	}
3924 #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 19, 0)) && (defined(SUPPORT_RANDOM_MAC_SCAN)) */
3925 
3926 exit:
3927 	if (event_data) {
3928 		MFREE(cfg->osh, event_data, alloc_len);
3929 	}
3930 	return ret;
3931 }
3932 
3933 int
3934 #if (LINUX_VERSION_CODE > KERNEL_VERSION(4, 11, 0))
wl_cfg80211_sched_scan_stop(struct wiphy * wiphy,struct net_device * dev,u64 reqid)3935 wl_cfg80211_sched_scan_stop(struct wiphy *wiphy, struct net_device *dev, u64 reqid)
3936 #else
3937 wl_cfg80211_sched_scan_stop(struct wiphy *wiphy, struct net_device *dev)
3938 #endif /* LINUX_VER > 4.11 */
3939 {
3940 	struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
3941 #if defined (WL_SCHED_SCAN) && !defined (SCHED_SCAN_DELAYED_WORK)
3942 	dhd_pub_t *dhdp = (dhd_pub_t *)(cfg->pub);
3943 #endif
3944 
3945 #if defined (WL_SCHED_SCAN) && defined (SCHED_SCAN_DELAYED_WORK)
3946 	struct net_device *pri_ndev;
3947 #endif
3948 
3949 	WL_DBG(("Enter \n"));
3950 	WL_PNO((">>> SCHED SCAN STOP\n"));
3951 
3952 #if defined (WL_SCHED_SCAN) && defined (SCHED_SCAN_DELAYED_WORK)
3953 	pri_ndev = bcmcfg_to_prmry_ndev(cfg);
3954 	wl_cfg80211_stop_pno(cfg, dev);
3955 
3956 	cancel_delayed_work(&cfg->sched_scan_stop_work);
3957 #else
3958 
3959 #if defined(BCMDONGLEHOST)
3960 	if (dhd_dev_pno_stop_for_ssid(dev) < 0) {
3961 		WL_ERR(("PNO Stop for SSID failed"));
3962 	} else {
3963 		/*
3964 		 * purposefully logging here to make sure that
3965 		 * firmware configuration was successful
3966 		 */
3967 		DBG_EVENT_LOG(dhdp, WIFI_EVENT_DRIVER_PNO_REMOVE);
3968 	}
3969 #endif /* BCMDONGLEHOST */
3970 
3971 #endif
3972 
3973 	mutex_lock(&cfg->scan_sync);
3974 	if (cfg->sched_scan_req) {
3975 #if defined (WL_SCHED_SCAN) && defined (SCHED_SCAN_DELAYED_WORK)
3976 		if (cfg->sched_scan_running && wl_get_drv_status(cfg, SCANNING, pri_ndev)) {
3977 			/* If targetted escan for PNO is running, abort it */
3978 			WL_INFORM_MEM(("abort targetted escan\n"));
3979 			_wl_cfgscan_cancel_scan(cfg);
3980 			wl_clr_drv_status(cfg, SCANNING, pri_ndev);
3981 		} else {
3982 			WL_INFORM_MEM(("pno escan state:%d\n",
3983 				cfg->sched_scan_running));
3984 		}
3985 #else
3986 		WL_PNO((">>> Sched scan running. Aborting it..\n"));
3987 		_wl_cfgscan_cancel_scan(cfg);
3988 #endif
3989 	}
3990 	cfg->sched_scan_req = NULL;
3991 	cfg->sched_scan_running = FALSE;
3992 	mutex_unlock(&cfg->scan_sync);
3993 
3994 	return 0;
3995 }
3996 #if defined (WL_SCHED_SCAN) && defined (SCHED_SCAN_DELAYED_WORK)
3997 void
wl_cfgscan_sched_scan_stop_work(struct work_struct * work)3998 wl_cfgscan_sched_scan_stop_work(struct work_struct *work)
3999 {
4000 	struct bcm_cfg80211 *cfg = NULL;
4001 	struct wiphy *wiphy = NULL;
4002 	struct delayed_work *dw = to_delayed_work(work);
4003 
4004 	GCC_DIAGNOSTIC_PUSH_SUPPRESS_CAST();
4005 	cfg = container_of(dw, struct bcm_cfg80211, sched_scan_stop_work);
4006 	GCC_DIAGNOSTIC_POP();
4007 
4008 	/* Hold rtnl_lock -> scan_sync lock to be in sync with cfg80211_ops path */
4009 	rtnl_lock();
4010 	mutex_lock(&cfg->scan_sync);
4011 	if (cfg->sched_scan_req) {
4012 		wiphy = cfg->sched_scan_req->wiphy;
4013 		/* Indicate sched scan stopped so that user space
4014 		 * can do a full scan incase found match is empty.
4015 		 */
4016 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0))
4017 		cfg80211_sched_scan_stopped_rtnl(wiphy, cfg->sched_scan_req->reqid);
4018 #else
4019 		cfg80211_sched_scan_stopped_rtnl(wiphy);
4020 #endif /* KERNEL > 4.12.0 */
4021 		cfg->sched_scan_req = NULL;
4022 	}
4023 	mutex_unlock(&cfg->scan_sync);
4024 	rtnl_unlock();
4025 }
4026 #endif
4027 #endif /* WL_SCHED_SCAN */
4028 
4029 #if defined (WL_SCHED_SCAN) && defined (SCHED_SCAN_DELAYED_WORK)
4030 void
wl_cfg80211_stop_pno(struct bcm_cfg80211 * cfg,struct net_device * dev)4031 wl_cfg80211_stop_pno(struct bcm_cfg80211 *cfg, struct net_device *dev)
4032 {
4033 #if defined(BCMDONGLEHOST)
4034 	dhd_pub_t *dhdp = (dhd_pub_t *)(cfg->pub);
4035 
4036 	if (dhd_dev_pno_stop_for_ssid(dev) < 0) {
4037 		WL_ERR(("PNO Stop for SSID failed"));
4038 	} else {
4039 		/*
4040 		 * purposefully logging here to make sure that
4041 		 * firmware configuration was successful
4042 		 */
4043 		DBG_EVENT_LOG(dhdp, WIFI_EVENT_DRIVER_PNO_REMOVE);
4044 	}
4045 #endif /* BCMDONGLEHOST */
4046 }
4047 #endif /* WL_SCHED_SCAN */
4048 
4049 #ifdef WES_SUPPORT
4050 #ifdef CUSTOMER_SCAN_TIMEOUT_SETTING
wl_cfg80211_custom_scan_time(struct net_device * dev,enum wl_custom_scan_time_type type,int time)4051 s32 wl_cfg80211_custom_scan_time(struct net_device *dev,
4052 		enum wl_custom_scan_time_type type, int time)
4053 {
4054 	struct bcm_cfg80211 *cfg = wl_get_cfg(dev);
4055 
4056 	if (cfg == NULL) {
4057 		return FALSE;
4058 	}
4059 
4060 	switch (type) {
4061 		case WL_CUSTOM_SCAN_CHANNEL_TIME :
4062 			WL_ERR(("Scan Channel Time %d\n", time));
4063 			cfg->custom_scan_channel_time = time;
4064 			break;
4065 		case WL_CUSTOM_SCAN_UNASSOC_TIME :
4066 			WL_ERR(("Scan Unassoc Time %d\n", time));
4067 			cfg->custom_scan_unassoc_time = time;
4068 			break;
4069 		case WL_CUSTOM_SCAN_PASSIVE_TIME :
4070 			WL_ERR(("Scan Passive Time %d\n", time));
4071 			cfg->custom_scan_passive_time = time;
4072 			break;
4073 		case WL_CUSTOM_SCAN_HOME_TIME :
4074 			WL_ERR(("Scan Home Time %d\n", time));
4075 			cfg->custom_scan_home_time = time;
4076 			break;
4077 		case WL_CUSTOM_SCAN_HOME_AWAY_TIME :
4078 			WL_ERR(("Scan Home Away Time %d\n", time));
4079 			cfg->custom_scan_home_away_time = time;
4080 			break;
4081 		default:
4082 			return FALSE;
4083 	}
4084 	return TRUE;
4085 }
4086 #endif /* CUSTOMER_SCAN_TIMEOUT_SETTING */
4087 #endif /* WES_SUPPORT */
4088 
4089 #ifdef CUSTOMER_HW4_DEBUG
4090 uint prev_dhd_console_ms = 0;
4091 u32 prev_wl_dbg_level = 0;
4092 static void wl_scan_timeout_dbg_set(void);
4093 
wl_scan_timeout_dbg_set(void)4094 static void wl_scan_timeout_dbg_set(void)
4095 {
4096 	WL_ERR(("Enter \n"));
4097 	prev_dhd_console_ms = dhd_console_ms;
4098 	prev_wl_dbg_level = wl_dbg_level;
4099 
4100 	dhd_console_ms = 1;
4101 	wl_dbg_level |= (WL_DBG_ERR | WL_DBG_P2P_ACTION | WL_DBG_SCAN);
4102 
4103 	wl_scan_timeout_dbg_enabled = 1;
4104 }
wl_scan_timeout_dbg_clear(void)4105 void wl_scan_timeout_dbg_clear(void)
4106 {
4107 	WL_ERR(("Enter \n"));
4108 	dhd_console_ms = prev_dhd_console_ms;
4109 	wl_dbg_level = prev_wl_dbg_level;
4110 
4111 	wl_scan_timeout_dbg_enabled = 0;
4112 }
4113 #endif /* CUSTOMER_HW4_DEBUG */
4114 
wl_scan_timeout(unsigned long data)4115 static void wl_scan_timeout(unsigned long data)
4116 {
4117 	wl_event_msg_t msg;
4118 	struct bcm_cfg80211 *cfg = (struct bcm_cfg80211 *)data;
4119 	struct wireless_dev *wdev = NULL;
4120 	struct net_device *ndev = NULL;
4121 #if 0
4122 	wl_scan_results_t *bss_list;
4123 	wl_bss_info_t *bi = NULL;
4124 	s32 i;
4125 	u32 channel;
4126 #endif
4127 	u64 cur_time = OSL_LOCALTIME_NS();
4128 #ifdef BCMDONGLEHOST
4129 	dhd_pub_t *dhdp = (dhd_pub_t *)(cfg->pub);
4130 #endif /* BCMDONGLEHOST */
4131 	unsigned long flags;
4132 #ifdef RTT_SUPPORT
4133 	rtt_status_info_t *rtt_status = NULL;
4134 	UNUSED_PARAMETER(rtt_status);
4135 #endif /* RTT_SUPPORT */
4136 
4137 	UNUSED_PARAMETER(cur_time);
4138 	WL_CFG_DRV_LOCK(&cfg->cfgdrv_lock, flags);
4139 	if (!(cfg->scan_request)) {
4140 		WL_ERR(("timer expired but no scan request\n"));
4141 		WL_CFG_DRV_UNLOCK(&cfg->cfgdrv_lock, flags);
4142 		return;
4143 	}
4144 
4145 	wdev = GET_SCAN_WDEV(cfg->scan_request);
4146 	WL_CFG_DRV_UNLOCK(&cfg->cfgdrv_lock, flags);
4147 
4148 	if (!wdev) {
4149 		WL_ERR(("No wireless_dev present\n"));
4150 		return;
4151 	}
4152 
4153 #ifdef BCMDONGLEHOST
4154 	if (dhd_query_bus_erros(dhdp)) {
4155 		return;
4156 	}
4157 #if defined(DHD_KERNEL_SCHED_DEBUG) && defined(DHD_FW_COREDUMP)
4158 	/* DHD triggers Kernel panic if the SCAN timeout occurrs
4159 	 * due to tasklet or workqueue scheduling problems in the Linux Kernel.
4160 	 * Customer informs that it is hard to find any clue from the
4161 	 * host memory dump since the important tasklet or workqueue information
4162 	 * is already disappered due the latency while printing out the timestamp
4163 	 * logs for debugging scan timeout issue.
4164 	 * For this reason, customer requestes us to trigger Kernel Panic rather than
4165 	 * taking a SOCRAM dump.
4166 	 */
4167 	if (dhdp->memdump_enabled == DUMP_MEMFILE_BUGON &&
4168 		((cfg->tsinfo.scan_deq < cfg->tsinfo.scan_enq) ||
4169 		dhd_bus_query_dpc_sched_errors(dhdp))) {
4170 		WL_ERR(("****SCAN event timeout due to scheduling problem\n"));
4171 		/* change g_assert_type to trigger Kernel panic */
4172 		g_assert_type = 2;
4173 #ifdef RTT_SUPPORT
4174 		rtt_status = GET_RTTSTATE(dhdp);
4175 #endif /* RTT_SUPPORT */
4176 		WL_ERR(("***SCAN event timeout. WQ state:0x%x scan_enq_time:"SEC_USEC_FMT
4177 			" evt_hdlr_entry_time:"SEC_USEC_FMT" evt_deq_time:"SEC_USEC_FMT
4178 			"\nscan_deq_time:"SEC_USEC_FMT" scan_hdlr_cmplt_time:"SEC_USEC_FMT
4179 			" scan_cmplt_time:"SEC_USEC_FMT" evt_hdlr_exit_time:"SEC_USEC_FMT
4180 			"\ncurrent_time:"SEC_USEC_FMT"\n", work_busy(&cfg->event_work),
4181 			GET_SEC_USEC(cfg->tsinfo.scan_enq),
4182 			GET_SEC_USEC(cfg->tsinfo.wl_evt_hdlr_entry),
4183 			GET_SEC_USEC(cfg->tsinfo.wl_evt_deq),
4184 			GET_SEC_USEC(cfg->tsinfo.scan_deq),
4185 			GET_SEC_USEC(cfg->tsinfo.scan_hdlr_cmplt),
4186 			GET_SEC_USEC(cfg->tsinfo.scan_cmplt),
4187 			GET_SEC_USEC(cfg->tsinfo.wl_evt_hdlr_exit), GET_SEC_USEC(cur_time)));
4188 		if (cfg->tsinfo.scan_enq) {
4189 			WL_ERR(("Elapsed time(ns): %llu\n", (cur_time - cfg->tsinfo.scan_enq)));
4190 		}
4191 		WL_ERR(("lock_states:[%d:%d:%d:%d:%d:%d]\n",
4192 			mutex_is_locked(&cfg->if_sync),
4193 			mutex_is_locked(&cfg->usr_sync),
4194 			mutex_is_locked(&cfg->pm_sync),
4195 			mutex_is_locked(&cfg->scan_sync),
4196 			spin_is_locked(&cfg->cfgdrv_lock),
4197 			spin_is_locked(&cfg->eq_lock)));
4198 #ifdef RTT_SUPPORT
4199 		WL_ERR(("RTT lock_state:[%d]\n",
4200 			mutex_is_locked(&rtt_status->rtt_mutex)));
4201 #ifdef WL_NAN
4202 		WL_ERR(("RTT and Geofence lock_states:[%d:%d]\n",
4203 			mutex_is_locked(&cfg->nancfg->nan_sync),
4204 			mutex_is_locked(&(rtt_status)->geofence_mutex)));
4205 #endif /* WL_NAN */
4206 #endif /* RTT_SUPPORT */
4207 
4208 		/* use ASSERT() to trigger panic */
4209 		ASSERT(0);
4210 	}
4211 #endif /* DHD_KERNEL_SCHED_DEBUG && DHD_FW_COREDUMP */
4212 	dhd_bus_intr_count_dump(dhdp);
4213 #endif /* BCMDONGLEHOST */
4214 
4215 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0)) && !defined(CONFIG_MODULES)
4216 	/* Print WQ states. Enable only for in-built drivers as the symbol is not exported  */
4217 	show_workqueue_state();
4218 #endif /* LINUX_VER >= 4.1 && !CONFIG_MODULES */
4219 
4220 #if 0
4221 	bss_list = wl_escan_get_buf(cfg, FALSE);
4222 	if (!bss_list) {
4223 		WL_ERR(("bss_list is null. Didn't receive any partial scan results\n"));
4224 	} else {
4225 		WL_ERR(("Dump scan buffer:\n"
4226 			"scanned AP count (%d)\n", bss_list->count));
4227 
4228 		bi = next_bss(bss_list, bi);
4229 		for_each_bss(bss_list, bi, i) {
4230 			channel = wf_chspec_ctlchan(wl_chspec_driver_to_host(bi->chanspec));
4231 			WL_ERR(("SSID :%s  Channel :%d\n", bi->SSID, channel));
4232 		}
4233 	}
4234 #endif
4235 
4236 	ndev = wdev_to_wlc_ndev(wdev, cfg);
4237 	bzero(&msg, sizeof(wl_event_msg_t));
4238 	WL_ERR(("timer expired\n"));
4239 #ifdef BCMDONGLEHOST
4240 	dhdp->scan_timeout_occurred = TRUE;
4241 #ifdef BCMPCIE
4242 	if (!dhd_pcie_dump_int_regs(dhdp)) {
4243 		WL_ERR(("%s : PCIe link might be down\n", __FUNCTION__));
4244 		dhd_bus_set_linkdown(dhdp, TRUE);
4245 		dhdp->hang_reason = HANG_REASON_PCIE_LINK_DOWN_EP_DETECT;
4246 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && defined(OEM_ANDROID)
4247 		dhd_os_send_hang_message(dhdp);
4248 #else
4249 		WL_ERR(("%s: HANG event is unsupported\n", __FUNCTION__));
4250 #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27) && OEM_ANDROID */
4251 	}
4252 
4253 	dhd_pcie_dump_rc_conf_space_cap(dhdp);
4254 #endif /* BCMPCIE */
4255 #if 0
4256 	if (!dhd_bus_get_linkdown(dhdp) && dhdp->memdump_enabled) {
4257 		dhdp->memdump_type = DUMP_TYPE_SCAN_TIMEOUT;
4258 		dhd_bus_mem_dump(dhdp);
4259 	}
4260 #endif /* DHD_FW_COREDUMP */
4261 	/*
4262 	 * For the memdump sanity, blocking bus transactions for a while
4263 	 * Keeping it TRUE causes the sequential private cmd error
4264 	 */
4265 	dhdp->scan_timeout_occurred = FALSE;
4266 #endif /* BCMDONGLEHOST */
4267 	msg.event_type = hton32(WLC_E_ESCAN_RESULT);
4268 	msg.status = hton32(WLC_E_STATUS_TIMEOUT);
4269 	msg.reason = 0xFFFFFFFF;
4270 	wl_cfg80211_event(ndev, &msg, NULL);
4271 #ifdef CUSTOMER_HW4_DEBUG
4272 	if (!wl_scan_timeout_dbg_enabled)
4273 		wl_scan_timeout_dbg_set();
4274 #endif /* CUSTOMER_HW4_DEBUG */
4275 
4276 #if defined(BCMDONGLEHOST) && defined(OEM_ANDROID)
4277 	DHD_ENABLE_RUNTIME_PM(dhdp);
4278 #endif /* BCMDONGLEHOST && OEM_ANDROID */
4279 
4280 }
4281 
wl_init_scan(struct bcm_cfg80211 * cfg)4282 s32 wl_init_scan(struct bcm_cfg80211 *cfg)
4283 {
4284 	int err = 0;
4285 
4286 	cfg->evt_handler[WLC_E_ESCAN_RESULT] = wl_escan_handler;
4287 	cfg->escan_info.escan_state = WL_ESCAN_STATE_IDLE;
4288 	wl_escan_init_sync_id(cfg);
4289 
4290 	/* Init scan_timeout timer */
4291 	init_timer_compat(&cfg->scan_timeout, wl_scan_timeout, cfg);
4292 
4293 	wl_cfg80211_set_bcmcfg(cfg);
4294 
4295 	return err;
4296 }
4297 
4298 #ifdef WL_SCHED_SCAN
4299 static s32
wl_cfgscan_init_pno_escan(struct bcm_cfg80211 * cfg,struct net_device * ndev,struct cfg80211_scan_request * request)4300 wl_cfgscan_init_pno_escan(struct bcm_cfg80211 *cfg, struct net_device *ndev,
4301 	struct cfg80211_scan_request *request)
4302 {
4303 	struct wiphy *wiphy = bcmcfg_to_wiphy(cfg);
4304 	dhd_pub_t *dhdp = (dhd_pub_t *)(cfg->pub);
4305 	int err = 0;
4306 
4307 	mutex_lock(&cfg->scan_sync);
4308 	LOG_TS(cfg, scan_start);
4309 
4310 	if (wl_get_drv_status_all(cfg, SCANNING)) {
4311 		_wl_cfgscan_cancel_scan(cfg);
4312 	}
4313 
4314 	wl_set_drv_status(cfg, SCANNING, ndev);
4315 	WL_PNO((">>> Doing targeted ESCAN on PNO event\n"));
4316 
4317 	err = wl_do_escan(cfg, wiphy, ndev, request);
4318 	if (err) {
4319 		wl_clr_drv_status(cfg, SCANNING, ndev);
4320 		mutex_unlock(&cfg->scan_sync);
4321 		WL_ERR(("targeted escan failed. err:%d\n", err));
4322 		return err;
4323 	}
4324 
4325 	DBG_EVENT_LOG(dhdp, WIFI_EVENT_DRIVER_PNO_SCAN_REQUESTED);
4326 
4327 	cfg->sched_scan_running = TRUE;
4328 	mutex_unlock(&cfg->scan_sync);
4329 
4330 	return err;
4331 }
4332 
4333 static s32
wl_cfgscan_update_v3_schedscan_results(struct bcm_cfg80211 * cfg,struct net_device * ndev,wl_pfn_scanresults_v3_t * pfn_result,uint32 event_type)4334 wl_cfgscan_update_v3_schedscan_results(struct bcm_cfg80211 *cfg, struct net_device *ndev,
4335 	wl_pfn_scanresults_v3_t *pfn_result, uint32 event_type)
4336 {
4337 	int err = 0;
4338 	wl_pfn_net_info_v3_t *netinfo, *pnetinfo;
4339 	struct cfg80211_scan_request *request = NULL;
4340 	struct cfg80211_ssid ssid[MAX_PFN_LIST_COUNT];
4341 	struct ieee80211_channel *channel = NULL;
4342 	struct wiphy *wiphy	= bcmcfg_to_wiphy(cfg);
4343 	dhd_pub_t *dhdp = (dhd_pub_t *)(cfg->pub);
4344 	log_conn_event_t *event_data = NULL;
4345 	tlv_log *tlv_data = NULL;
4346 	u32 alloc_len = 0;
4347 	int channel_req = 0;
4348 	u32 payload_len;
4349 
4350 	if (event_type == WLC_E_PFN_NET_LOST) {
4351 		WL_PNO(("Do Nothing %d\n", event_type));
4352 		return 0;
4353 	}
4354 
4355 	WL_INFORM_MEM(("PFN NET FOUND event. count:%d \n", pfn_result->count));
4356 
4357 	pnetinfo = (wl_pfn_net_info_v3_t *)pfn_result->netinfo;
4358 	if (pfn_result->count > 0) {
4359 		int i;
4360 
4361 		if (pfn_result->count > MAX_PFN_LIST_COUNT) {
4362 			pfn_result->count = MAX_PFN_LIST_COUNT;
4363 		}
4364 
4365 		bzero(&ssid, sizeof(ssid));
4366 
4367 		request = (struct cfg80211_scan_request *)MALLOCZ(cfg->osh,
4368 			sizeof(*request) + sizeof(*request->channels) * pfn_result->count);
4369 		channel = (struct ieee80211_channel *)MALLOCZ(cfg->osh,
4370 			(sizeof(struct ieee80211_channel) * pfn_result->count));
4371 		if (!request || !channel) {
4372 			WL_ERR(("No memory"));
4373 			err = -ENOMEM;
4374 			goto out_err;
4375 		}
4376 
4377 		request->wiphy = wiphy;
4378 
4379 		if (DBG_RING_ACTIVE(dhdp, DHD_EVENT_RING_ID)) {
4380 			alloc_len = sizeof(log_conn_event_t) + (3 * sizeof(tlv_log)) +
4381 				DOT11_MAX_SSID_LEN + sizeof(uint16) + sizeof(int16);
4382 			event_data = (log_conn_event_t *)MALLOCZ(cfg->osh, alloc_len);
4383 			if (!event_data) {
4384 				WL_ERR(("%s: failed to allocate the log_conn_event_t with "
4385 					"length(%d)\n", __func__, alloc_len));
4386 				err = -ENOMEM;
4387 				goto out_err;
4388 			}
4389 		}
4390 
4391 		for (i = 0; i < pfn_result->count; i++) {
4392 			u16 ssid_len;
4393 			u8 ssid_buf[DOT11_MAX_SSID_LEN + 1] = {0};
4394 			netinfo = &pnetinfo[i];
4395 
4396 			/* PFN result doesn't have all the info which are required by the
4397 			 * supplicant. (For e.g IEs) Do a target Escan so that sched scan
4398 			 * results are reported via wl_inform_single_bss in the required
4399 			 * format. Escan does require the scan request in the form of
4400 			 * cfg80211_scan_request. For timebeing, create
4401 			 * cfg80211_scan_request one out of the received PNO event.
4402 			 */
4403 			ssid[i].ssid_len = ssid_len = MIN(DOT11_MAX_SSID_LEN,
4404 				netinfo->pfnsubnet.SSID_len);
4405 			/* max ssid_len as in previous step DOT11_MAX_SSID_LEN is same
4406 			* as DOT11_MAX_SSID_LEN = 32
4407 			*/
4408 			(void)memcpy_s(ssid[i].ssid, IEEE80211_MAX_SSID_LEN,
4409 				netinfo->pfnsubnet.u.SSID, ssid_len);
4410 			request->n_ssids++;
4411 
4412 			channel_req = netinfo->pfnsubnet.chanspec;
4413 			channel[i].center_freq = wl_channel_to_frequency(
4414 				wf_chspec_ctlchan(netinfo->pfnsubnet.chanspec),
4415 				CHSPEC_BAND(netinfo->pfnsubnet.chanspec));
4416 			channel[i].band =
4417 				wl_get_nl80211_band(CHSPEC_BAND(netinfo->pfnsubnet.chanspec));
4418 			channel[i].flags |= IEEE80211_CHAN_NO_HT40;
4419 			request->channels[i] = &channel[i];
4420 			request->n_channels++;
4421 
4422 			(void)memcpy_s(ssid_buf, IEEE80211_MAX_SSID_LEN,
4423 				ssid[i].ssid, ssid_len);
4424 			ssid_buf[ssid_len] = '\0';
4425 			WL_INFORM_MEM(("[PNO] SSID:%s chanspec:0x%x freq:%d band:%d\n",
4426 				ssid_buf, netinfo->pfnsubnet.chanspec,
4427 				channel[i].center_freq, channel[i].band));
4428 			if (DBG_RING_ACTIVE(dhdp, DHD_EVENT_RING_ID)) {
4429 				payload_len = sizeof(log_conn_event_t);
4430 				event_data->event = WIFI_EVENT_DRIVER_PNO_NETWORK_FOUND;
4431 				tlv_data = event_data->tlvs;
4432 
4433 				/* ssid */
4434 				tlv_data->tag = WIFI_TAG_SSID;
4435 				tlv_data->len = netinfo->pfnsubnet.SSID_len;
4436 				(void)memcpy_s(tlv_data->value, DOT11_MAX_SSID_LEN,
4437 					ssid[i].ssid, ssid[i].ssid_len);
4438 				payload_len += TLV_LOG_SIZE(tlv_data);
4439 				tlv_data = TLV_LOG_NEXT(tlv_data);
4440 
4441 				/* channel */
4442 				tlv_data->tag = WIFI_TAG_CHANNEL;
4443 				tlv_data->len = sizeof(uint16);
4444 				(void)memcpy_s(tlv_data->value, sizeof(uint16),
4445 					&channel_req, sizeof(uint16));
4446 				payload_len += TLV_LOG_SIZE(tlv_data);
4447 				tlv_data = TLV_LOG_NEXT(tlv_data);
4448 
4449 				/* rssi */
4450 				tlv_data->tag = WIFI_TAG_RSSI;
4451 				tlv_data->len = sizeof(int16);
4452 				(void)memcpy_s(tlv_data->value, sizeof(uint16),
4453 					&netinfo->RSSI, sizeof(int16));
4454 				payload_len += TLV_LOG_SIZE(tlv_data);
4455 				tlv_data = TLV_LOG_NEXT(tlv_data);
4456 
4457 				dhd_os_push_push_ring_data(dhdp, DHD_EVENT_RING_ID,
4458 					&event_data->event, payload_len);
4459 			}
4460 		}
4461 
4462 		/* assign parsed ssid array */
4463 		if (request->n_ssids)
4464 			request->ssids = &ssid[0];
4465 
4466 		if (wl_get_p2p_status(cfg, DISCOVERY_ON)) {
4467 			WL_PNO((">>> P2P discovery was ON. Disabling it\n"));
4468 			err = wl_cfgp2p_discover_enable_search(cfg, false);
4469 			if (unlikely(err)) {
4470 				wl_clr_drv_status(cfg, SCANNING, ndev);
4471 				return err;
4472 			}
4473 			p2p_scan(cfg) = false;
4474 		}
4475 
4476 		err = wl_cfgscan_init_pno_escan(cfg, ndev, request);
4477 		if (err) {
4478 			goto out_err;
4479 		}
4480 	}
4481 	else {
4482 		WL_ERR(("FALSE PNO Event. (pfn_count == 0) \n"));
4483 	}
4484 
4485 out_err:
4486 	if (request) {
4487 		MFREE(cfg->osh, request,
4488 			sizeof(*request) + sizeof(*request->channels) * pfn_result->count);
4489 	}
4490 	if (channel) {
4491 		MFREE(cfg->osh, channel,
4492 			(sizeof(struct ieee80211_channel) * pfn_result->count));
4493 	}
4494 
4495 	if (event_data) {
4496 		MFREE(cfg->osh, event_data, alloc_len);
4497 	}
4498 
4499 	return err;
4500 }
4501 /* If target scan is not reliable, set the below define to "1" to do a
4502  * full escan
4503  */
4504 static s32
wl_notify_sched_scan_results(struct bcm_cfg80211 * cfg,struct net_device * ndev,const wl_event_msg_t * e,void * data)4505 wl_notify_sched_scan_results(struct bcm_cfg80211 *cfg, struct net_device *ndev,
4506 	const wl_event_msg_t *e, void *data)
4507 {
4508 	wl_pfn_net_info_v1_t *netinfo, *pnetinfo;
4509 	wl_pfn_net_info_v2_t *netinfo_v2, *pnetinfo_v2;
4510 	struct wiphy *wiphy	= bcmcfg_to_wiphy(cfg);
4511 	dhd_pub_t *dhdp = (dhd_pub_t *)(cfg->pub);
4512 	int err = 0;
4513 	struct cfg80211_scan_request *request = NULL;
4514 	struct cfg80211_ssid ssid[MAX_PFN_LIST_COUNT];
4515 	struct ieee80211_channel *channel = NULL;
4516 	int channel_req = 0;
4517 	int band = 0;
4518 	wl_pfn_scanresults_v1_t *pfn_result_v1 = (wl_pfn_scanresults_v1_t *)data;
4519 	wl_pfn_scanresults_v2_t *pfn_result_v2 = (wl_pfn_scanresults_v2_t *)data;
4520 	wl_pfn_scanresults_v3_t *pfn_result_v3 = (wl_pfn_scanresults_v3_t *)data;
4521 	int n_pfn_results = 0;
4522 	log_conn_event_t *event_data = NULL;
4523 	tlv_log *tlv_data = NULL;
4524 	u32 alloc_len = 0;
4525 	u32 payload_len;
4526 	u8 tmp_buf[DOT11_MAX_SSID_LEN + 1];
4527 
4528 	WL_DBG(("Enter\n"));
4529 
4530 	/* These static asserts guarantee v1/v2 net_info and subnet_info are compatible
4531 	 * in size and SSID offset, allowing v1 to be used below except for the results
4532 	 * fields themselves (status, count, offset to netinfo).
4533 	 */
4534 	STATIC_ASSERT(sizeof(wl_pfn_net_info_v1_t) == sizeof(wl_pfn_net_info_v2_t));
4535 	STATIC_ASSERT(sizeof(wl_pfn_lnet_info_v1_t) == sizeof(wl_pfn_lnet_info_v2_t));
4536 	STATIC_ASSERT(sizeof(wl_pfn_subnet_info_v1_t) == sizeof(wl_pfn_subnet_info_v2_t));
4537 	STATIC_ASSERT(OFFSETOF(wl_pfn_subnet_info_v1_t, SSID) ==
4538 	              OFFSETOF(wl_pfn_subnet_info_v2_t, u.SSID));
4539 
4540 	/* Extract the version-specific items */
4541 	if (pfn_result_v1->version == PFN_SCANRESULT_VERSION_V1) {
4542 		n_pfn_results = pfn_result_v1->count;
4543 		pnetinfo = pfn_result_v1->netinfo;
4544 		WL_INFORM_MEM(("PFN NET FOUND event. count:%d \n", n_pfn_results));
4545 
4546 		if (n_pfn_results > 0) {
4547 			int i;
4548 
4549 			if (n_pfn_results > MAX_PFN_LIST_COUNT)
4550 				n_pfn_results = MAX_PFN_LIST_COUNT;
4551 
4552 			bzero(&ssid, sizeof(ssid));
4553 
4554 			request = (struct cfg80211_scan_request *)MALLOCZ(cfg->osh,
4555 				sizeof(*request) + sizeof(*request->channels) * n_pfn_results);
4556 			channel = (struct ieee80211_channel *)MALLOCZ(cfg->osh,
4557 				(sizeof(struct ieee80211_channel) * n_pfn_results));
4558 			if (!request || !channel) {
4559 				WL_ERR(("No memory"));
4560 				err = -ENOMEM;
4561 				goto out_err;
4562 			}
4563 
4564 			request->wiphy = wiphy;
4565 
4566 			if (DBG_RING_ACTIVE(dhdp, DHD_EVENT_RING_ID)) {
4567 				alloc_len = sizeof(log_conn_event_t) + (3 * sizeof(tlv_log)) +
4568 					DOT11_MAX_SSID_LEN + sizeof(uint16) + sizeof(int16);
4569 				event_data = (log_conn_event_t *)MALLOCZ(cfg->osh, alloc_len);
4570 				if (!event_data) {
4571 					WL_ERR(("%s: failed to allocate the log_conn_event_t with "
4572 						"length(%d)\n", __func__, alloc_len));
4573 					goto out_err;
4574 				}
4575 			}
4576 
4577 			for (i = 0; i < n_pfn_results; i++) {
4578 				netinfo = &pnetinfo[i];
4579 				/* This looks useless, shouldn't Coverity complain? */
4580 				if (!netinfo) {
4581 					WL_ERR(("Invalid netinfo ptr. index:%d", i));
4582 					err = -EINVAL;
4583 					goto out_err;
4584 				}
4585 				if (netinfo->pfnsubnet.SSID_len > DOT11_MAX_SSID_LEN) {
4586 					WL_ERR(("Wrong SSID length:%d\n",
4587 						netinfo->pfnsubnet.SSID_len));
4588 					err = -EINVAL;
4589 					goto out_err;
4590 				}
4591 				/* In previous step max SSID_len limited to DOT11_MAX_SSID_LEN
4592 				* and tmp_buf size is DOT11_MAX_SSID_LEN+1
4593 				*/
4594 				(void)memcpy_s(tmp_buf, DOT11_MAX_SSID_LEN,
4595 					netinfo->pfnsubnet.SSID, netinfo->pfnsubnet.SSID_len);
4596 				tmp_buf[netinfo->pfnsubnet.SSID_len] = '\0';
4597 				WL_PNO((">>> SSID:%s Channel:%d \n",
4598 					tmp_buf, netinfo->pfnsubnet.channel));
4599 				/* PFN result doesn't have all the info which are required by
4600 				 * the supplicant. (For e.g IEs) Do a target Escan so that
4601 				 * sched scan results are reported via wl_inform_single_bss in
4602 				 * the required format. Escan does require the scan request in
4603 				 * the form of cfg80211_scan_request. For timebeing, create
4604 				 * cfg80211_scan_request one out of the received PNO event.
4605 				 */
4606 
4607 				ssid[i].ssid_len = netinfo->pfnsubnet.SSID_len;
4608 				/* Returning void as ssid[i].ssid_len is limited to max of
4609 				* DOT11_MAX_SSID_LEN
4610 				*/
4611 				(void)memcpy_s(ssid[i].ssid, IEEE80211_MAX_SSID_LEN,
4612 					netinfo->pfnsubnet.SSID, ssid[i].ssid_len);
4613 				request->n_ssids++;
4614 
4615 				channel_req = netinfo->pfnsubnet.channel;
4616 				band = (channel_req <= CH_MAX_2G_CHANNEL) ? NL80211_BAND_2GHZ
4617 					: NL80211_BAND_5GHZ;
4618 				channel[i].center_freq =
4619 					ieee80211_channel_to_frequency(channel_req, band);
4620 				channel[i].band = band;
4621 				channel[i].flags |= IEEE80211_CHAN_NO_HT40;
4622 				request->channels[i] = &channel[i];
4623 				request->n_channels++;
4624 
4625 				if (DBG_RING_ACTIVE(dhdp, DHD_EVENT_RING_ID)) {
4626 					payload_len = sizeof(log_conn_event_t);
4627 					event_data->event = WIFI_EVENT_DRIVER_PNO_NETWORK_FOUND;
4628 					tlv_data = event_data->tlvs;
4629 
4630 					/* ssid */
4631 					tlv_data->tag = WIFI_TAG_SSID;
4632 					tlv_data->len = ssid[i].ssid_len;
4633 					(void)memcpy_s(tlv_data->value, DOT11_MAX_SSID_LEN,
4634 						ssid[i].ssid, ssid[i].ssid_len);
4635 					payload_len += TLV_LOG_SIZE(tlv_data);
4636 					tlv_data = TLV_LOG_NEXT(tlv_data);
4637 
4638 					/* channel */
4639 					tlv_data->tag = WIFI_TAG_CHANNEL;
4640 					tlv_data->len = sizeof(uint16);
4641 					(void)memcpy_s(tlv_data->value, sizeof(uint16),
4642 						&channel_req, sizeof(uint16));
4643 					payload_len += TLV_LOG_SIZE(tlv_data);
4644 					tlv_data = TLV_LOG_NEXT(tlv_data);
4645 
4646 					/* rssi */
4647 					tlv_data->tag = WIFI_TAG_RSSI;
4648 					tlv_data->len = sizeof(int16);
4649 					(void)memcpy_s(tlv_data->value, sizeof(int16),
4650 						&netinfo->RSSI, sizeof(int16));
4651 					payload_len += TLV_LOG_SIZE(tlv_data);
4652 					tlv_data = TLV_LOG_NEXT(tlv_data);
4653 
4654 					dhd_os_push_push_ring_data(dhdp, DHD_EVENT_RING_ID,
4655 						&event_data->event, payload_len);
4656 				}
4657 			}
4658 
4659 			/* assign parsed ssid array */
4660 			if (request->n_ssids)
4661 				request->ssids = &ssid[0];
4662 
4663 			if (wl_get_p2p_status(cfg, DISCOVERY_ON)) {
4664 				WL_PNO((">>> P2P discovery was ON. Disabling it\n"));
4665 				err = wl_cfgp2p_discover_enable_search(cfg, false);
4666 				if (unlikely(err)) {
4667 					wl_clr_drv_status(cfg, SCANNING, ndev);
4668 					goto out_err;
4669 				}
4670 				p2p_scan(cfg) = false;
4671 			}
4672 			err = wl_cfgscan_init_pno_escan(cfg, ndev, request);
4673 			if (err) {
4674 				goto out_err;
4675 			}
4676 		}
4677 		else {
4678 			WL_ERR(("FALSE PNO Event. (pfn_count == 0) \n"));
4679 		}
4680 
4681 	} else if (pfn_result_v2->version == PFN_SCANRESULT_VERSION_V2) {
4682 		n_pfn_results = pfn_result_v2->count;
4683 		pnetinfo_v2 = (wl_pfn_net_info_v2_t *)pfn_result_v2->netinfo;
4684 
4685 		if (e->event_type == WLC_E_PFN_NET_LOST) {
4686 			WL_PNO(("Do Nothing %d\n", e->event_type));
4687 			return 0;
4688 		}
4689 
4690 		WL_INFORM_MEM(("PFN NET FOUND event. count:%d \n", n_pfn_results));
4691 
4692 		if (n_pfn_results > 0) {
4693 			int i;
4694 
4695 			if (n_pfn_results > MAX_PFN_LIST_COUNT)
4696 				n_pfn_results = MAX_PFN_LIST_COUNT;
4697 
4698 			bzero(&ssid, sizeof(ssid));
4699 
4700 			request = (struct cfg80211_scan_request *)MALLOCZ(cfg->osh,
4701 				sizeof(*request) + sizeof(*request->channels) * n_pfn_results);
4702 			channel = (struct ieee80211_channel *)MALLOCZ(cfg->osh,
4703 				(sizeof(struct ieee80211_channel) * n_pfn_results));
4704 			if (!request || !channel) {
4705 				WL_ERR(("No memory"));
4706 				err = -ENOMEM;
4707 				goto out_err;
4708 			}
4709 
4710 			request->wiphy = wiphy;
4711 
4712 			if (DBG_RING_ACTIVE(dhdp, DHD_EVENT_RING_ID)) {
4713 				alloc_len = sizeof(log_conn_event_t) + (3 * sizeof(tlv_log)) +
4714 					DOT11_MAX_SSID_LEN + sizeof(uint16) + sizeof(int16);
4715 				event_data = (log_conn_event_t *)MALLOC(cfg->osh, alloc_len);
4716 				if (!event_data) {
4717 					WL_ERR(("%s: failed to allocate the log_conn_event_t with "
4718 						"length(%d)\n", __func__, alloc_len));
4719 					goto out_err;
4720 				}
4721 			}
4722 
4723 			for (i = 0; i < n_pfn_results; i++) {
4724 				netinfo_v2 = &pnetinfo_v2[i];
4725 				/* This looks useless, shouldn't Coverity complain? */
4726 				if (!netinfo_v2) {
4727 					WL_ERR(("Invalid netinfo ptr. index:%d", i));
4728 					err = -EINVAL;
4729 					goto out_err;
4730 				}
4731 				WL_PNO((">>> SSID:%s Channel:%d \n",
4732 					netinfo_v2->pfnsubnet.u.SSID,
4733 					netinfo_v2->pfnsubnet.channel));
4734 				/* PFN result doesn't have all the info which are required by the
4735 				 * supplicant. (For e.g IEs) Do a target Escan so that sched scan
4736 				 * results are reported via wl_inform_single_bss in the required
4737 				 * format. Escan does require the scan request in the form of
4738 				 * cfg80211_scan_request. For timebeing, create
4739 				 * cfg80211_scan_request one out of the received PNO event.
4740 				 */
4741 				ssid[i].ssid_len = MIN(DOT11_MAX_SSID_LEN,
4742 					netinfo_v2->pfnsubnet.SSID_len);
4743 				/* max ssid_len as in previous step DOT11_MAX_SSID_LEN is same
4744 				* as DOT11_MAX_SSID_LEN = 32
4745 				*/
4746 				(void)memcpy_s(ssid[i].ssid, IEEE80211_MAX_SSID_LEN,
4747 					netinfo_v2->pfnsubnet.u.SSID, ssid[i].ssid_len);
4748 				request->n_ssids++;
4749 
4750 				channel_req = netinfo_v2->pfnsubnet.channel;
4751 				band = (channel_req <= CH_MAX_2G_CHANNEL) ? NL80211_BAND_2GHZ
4752 					: NL80211_BAND_5GHZ;
4753 				channel[i].center_freq =
4754 					ieee80211_channel_to_frequency(channel_req, band);
4755 				channel[i].band = band;
4756 				channel[i].flags |= IEEE80211_CHAN_NO_HT40;
4757 				request->channels[i] = &channel[i];
4758 				request->n_channels++;
4759 
4760 				if (DBG_RING_ACTIVE(dhdp, DHD_EVENT_RING_ID)) {
4761 					payload_len = sizeof(log_conn_event_t);
4762 					event_data->event = WIFI_EVENT_DRIVER_PNO_NETWORK_FOUND;
4763 					tlv_data = event_data->tlvs;
4764 
4765 					/* ssid */
4766 					tlv_data->tag = WIFI_TAG_SSID;
4767 					tlv_data->len = netinfo_v2->pfnsubnet.SSID_len;
4768 					(void)memcpy_s(tlv_data->value, DOT11_MAX_SSID_LEN,
4769 						ssid[i].ssid, ssid[i].ssid_len);
4770 					payload_len += TLV_LOG_SIZE(tlv_data);
4771 					tlv_data = TLV_LOG_NEXT(tlv_data);
4772 
4773 					/* channel */
4774 					tlv_data->tag = WIFI_TAG_CHANNEL;
4775 					tlv_data->len = sizeof(uint16);
4776 					(void)memcpy_s(tlv_data->value, sizeof(uint16),
4777 						&channel_req, sizeof(uint16));
4778 					payload_len += TLV_LOG_SIZE(tlv_data);
4779 					tlv_data = TLV_LOG_NEXT(tlv_data);
4780 
4781 					/* rssi */
4782 					tlv_data->tag = WIFI_TAG_RSSI;
4783 					tlv_data->len = sizeof(int16);
4784 					(void)memcpy_s(tlv_data->value, sizeof(uint16),
4785 						&netinfo_v2->RSSI, sizeof(int16));
4786 					payload_len += TLV_LOG_SIZE(tlv_data);
4787 					tlv_data = TLV_LOG_NEXT(tlv_data);
4788 
4789 					dhd_os_push_push_ring_data(dhdp, DHD_EVENT_RING_ID,
4790 						&event_data->event, payload_len);
4791 				}
4792 			}
4793 
4794 			/* assign parsed ssid array */
4795 			if (request->n_ssids)
4796 				request->ssids = &ssid[0];
4797 
4798 			if (wl_get_p2p_status(cfg, DISCOVERY_ON)) {
4799 				WL_PNO((">>> P2P discovery was ON. Disabling it\n"));
4800 				err = wl_cfgp2p_discover_enable_search(cfg, false);
4801 				if (unlikely(err)) {
4802 					wl_clr_drv_status(cfg, SCANNING, ndev);
4803 					goto out_err;
4804 				}
4805 				p2p_scan(cfg) = false;
4806 			}
4807 
4808 			err = wl_cfgscan_init_pno_escan(cfg, ndev, request);
4809 			if (err) {
4810 				goto out_err;
4811 			}
4812 		}
4813 		else {
4814 			WL_ERR(("FALSE PNO Event. (pfn_count == 0) \n"));
4815 		}
4816 	} else if (pfn_result_v3->version == PFN_SCANRESULT_VERSION_V3) {
4817 		err = wl_cfgscan_update_v3_schedscan_results(cfg, ndev,
4818 			pfn_result_v3, e->event_type);
4819 		if (err) {
4820 			goto out_err;
4821 		}
4822 	} else {
4823 		WL_ERR(("Unsupported version %d, expected %d or %d\n", pfn_result_v1->version,
4824 			PFN_SCANRESULT_VERSION_V1, PFN_SCANRESULT_VERSION_V2));
4825 		err = -EINVAL;
4826 	}
4827 
4828 out_err:
4829 
4830 	mutex_lock(&cfg->scan_sync);
4831 	if (err) {
4832 		/* Notify upper layer that sched scan has stopped so that
4833 		 * upper layer can attempt fresh scan.
4834 		 */
4835 		if (cfg->sched_scan_req) {
4836 			WL_ERR(("sched_scan stopped\n"));
4837 #if defined (WL_SCHED_SCAN) && defined (SCHED_SCAN_DELAYED_WORK)
4838 			wl_cfg80211_stop_pno(cfg,  bcmcfg_to_prmry_ndev(cfg));
4839 			/* schedule the work to indicate sched scan stop to cfg layer */
4840 			schedule_delayed_work(&cfg->sched_scan_stop_work, 0);
4841 #else
4842 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0))
4843 			cfg80211_sched_scan_stopped(wiphy, cfg->sched_scan_req->reqid);
4844 #else
4845 			cfg80211_sched_scan_stopped(wiphy);
4846 #endif /* KERNEL > 4.11.0 */
4847 			cfg->sched_scan_req = NULL;
4848 #endif
4849 		} else {
4850 			WL_ERR(("sched scan req null!\n"));
4851 		}
4852 		cfg->sched_scan_running = FALSE;
4853 		CLR_TS(cfg, scan_start);
4854 	}
4855 	mutex_unlock(&cfg->scan_sync);
4856 
4857 	if (request) {
4858 		MFREE(cfg->osh, request,
4859 			sizeof(*request) + sizeof(*request->channels) * n_pfn_results);
4860 	}
4861 	if (channel) {
4862 		MFREE(cfg->osh, channel,
4863 			(sizeof(struct ieee80211_channel) * n_pfn_results));
4864 	}
4865 
4866 	if (event_data) {
4867 		MFREE(cfg->osh, event_data, alloc_len);
4868 	}
4869 	return err;
4870 }
4871 #endif /* WL_SCHED_SCAN */
4872 
4873 #ifdef PNO_SUPPORT
4874 s32
wl_notify_pfn_status(struct bcm_cfg80211 * cfg,bcm_struct_cfgdev * cfgdev,const wl_event_msg_t * e,void * data)4875 wl_notify_pfn_status(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev,
4876 	const wl_event_msg_t *e, void *data)
4877 {
4878 	struct net_device *ndev = NULL;
4879 #ifdef GSCAN_SUPPORT
4880 	void *ptr;
4881 	int send_evt_bytes = 0;
4882 	u32 event = be32_to_cpu(e->event_type);
4883 	struct wiphy *wiphy = bcmcfg_to_wiphy(cfg);
4884 #endif /* GSCAN_SUPPORT */
4885 
4886 	WL_INFORM_MEM((">>> PNO Event\n"));
4887 
4888 	if (!data) {
4889 		WL_ERR(("Data received is NULL!\n"));
4890 		return 0;
4891 	}
4892 
4893 	ndev = cfgdev_to_wlc_ndev(cfgdev, cfg);
4894 #ifdef GSCAN_SUPPORT
4895 	ptr = dhd_dev_process_epno_result(ndev, data, event, &send_evt_bytes);
4896 	if (ptr) {
4897 		wl_cfgvendor_send_async_event(wiphy, ndev,
4898 			GOOGLE_SCAN_EPNO_EVENT, ptr, send_evt_bytes);
4899 		MFREE(cfg->osh, ptr, send_evt_bytes);
4900 	}
4901 	if (!dhd_dev_is_legacy_pno_enabled(ndev))
4902 		return 0;
4903 #endif /* GSCAN_SUPPORT */
4904 
4905 #ifndef WL_SCHED_SCAN
4906 	/* CUSTOMER_HW4 has other PNO wakelock time by RB:5911 */
4907 	mutex_lock(&cfg->usr_sync);
4908 	/* TODO: Use cfg80211_sched_scan_results(wiphy); */
4909 	/* GregG : WAR as to supplicant busy and not allowed Kernel to suspend */
4910 	CFG80211_DISCONNECTED(ndev, 0, NULL, 0, false, GFP_KERNEL);
4911 	mutex_unlock(&cfg->usr_sync);
4912 #else
4913 	/* If cfg80211 scheduled scan is supported, report the pno results via sched
4914 	 * scan results
4915 	 */
4916 	wl_notify_sched_scan_results(cfg, ndev, e, data);
4917 #endif /* WL_SCHED_SCAN */
4918 	return 0;
4919 }
4920 #endif /* PNO_SUPPORT */
4921 
4922 #ifdef GSCAN_SUPPORT
4923 s32
wl_notify_gscan_event(struct bcm_cfg80211 * cfg,bcm_struct_cfgdev * cfgdev,const wl_event_msg_t * e,void * data)4924 wl_notify_gscan_event(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev,
4925 	const wl_event_msg_t *e, void *data)
4926 {
4927 	s32 err = 0;
4928 	u32 event = be32_to_cpu(e->event_type);
4929 	void *ptr = NULL;
4930 	int send_evt_bytes = 0;
4931 	int event_type;
4932 	struct net_device *ndev = cfgdev_to_wlc_ndev(cfgdev, cfg);
4933 	struct wiphy *wiphy = bcmcfg_to_wiphy(cfg);
4934 	u32 len = ntoh32(e->datalen);
4935 	u32 buf_len = 0;
4936 
4937 	switch (event) {
4938 		case WLC_E_PFN_BEST_BATCHING:
4939 			err = dhd_dev_retrieve_batch_scan(ndev);
4940 			if (err < 0) {
4941 				WL_ERR(("Batch retrieval already in progress %d\n", err));
4942 			} else {
4943 				event_type = WIFI_SCAN_THRESHOLD_NUM_SCANS;
4944 				if (data && len) {
4945 					event_type = *((int *)data);
4946 				}
4947 				wl_cfgvendor_send_async_event(wiphy, ndev,
4948 				    GOOGLE_GSCAN_BATCH_SCAN_EVENT,
4949 				     &event_type, sizeof(int));
4950 			}
4951 			break;
4952 		case WLC_E_PFN_SCAN_COMPLETE:
4953 			event_type = WIFI_SCAN_COMPLETE;
4954 			wl_cfgvendor_send_async_event(wiphy, ndev,
4955 				GOOGLE_SCAN_COMPLETE_EVENT,
4956 				&event_type, sizeof(int));
4957 			break;
4958 		case WLC_E_PFN_BSSID_NET_FOUND:
4959 			ptr = dhd_dev_hotlist_scan_event(ndev, data, &send_evt_bytes,
4960 			      HOTLIST_FOUND, &buf_len);
4961 			if (ptr) {
4962 				wl_cfgvendor_send_hotlist_event(wiphy, ndev,
4963 				 ptr, send_evt_bytes, GOOGLE_GSCAN_GEOFENCE_FOUND_EVENT);
4964 				dhd_dev_gscan_hotlist_cache_cleanup(ndev, HOTLIST_FOUND);
4965 				MFREE(cfg->osh, ptr, send_evt_bytes);
4966 			} else {
4967 				err = -ENOMEM;
4968 			}
4969 			break;
4970 		case WLC_E_PFN_BSSID_NET_LOST:
4971 			/* WLC_E_PFN_BSSID_NET_LOST is conflict shared with WLC_E_PFN_SCAN_ALLGONE
4972 			 * We currently do not use WLC_E_PFN_SCAN_ALLGONE, so if we get it, ignore
4973 			 */
4974 			if (len) {
4975 				ptr = dhd_dev_hotlist_scan_event(ndev, data, &send_evt_bytes,
4976 				                                 HOTLIST_LOST, &buf_len);
4977 				if (ptr) {
4978 					wl_cfgvendor_send_hotlist_event(wiphy, ndev,
4979 					 ptr, send_evt_bytes, GOOGLE_GSCAN_GEOFENCE_LOST_EVENT);
4980 					dhd_dev_gscan_hotlist_cache_cleanup(ndev, HOTLIST_LOST);
4981 					MFREE(cfg->osh, ptr, send_evt_bytes);
4982 				} else {
4983 					err = -ENOMEM;
4984 				}
4985 			} else {
4986 				err = -EINVAL;
4987 			}
4988 			break;
4989 		case WLC_E_PFN_GSCAN_FULL_RESULT:
4990 			ptr = dhd_dev_process_full_gscan_result(ndev, data, len, &send_evt_bytes);
4991 			if (ptr) {
4992 				wl_cfgvendor_send_async_event(wiphy, ndev,
4993 				    GOOGLE_SCAN_FULL_RESULTS_EVENT, ptr, send_evt_bytes);
4994 				MFREE(cfg->osh, ptr, send_evt_bytes);
4995 			} else {
4996 				err = -ENOMEM;
4997 			}
4998 			break;
4999 		case WLC_E_PFN_SSID_EXT:
5000 			ptr = dhd_dev_process_epno_result(ndev, data, event, &send_evt_bytes);
5001 			if (ptr) {
5002 				wl_cfgvendor_send_async_event(wiphy, ndev,
5003 				    GOOGLE_SCAN_EPNO_EVENT, ptr, send_evt_bytes);
5004 				MFREE(cfg->osh, ptr, send_evt_bytes);
5005 			} else {
5006 				err = -ENOMEM;
5007 			}
5008 			break;
5009 		default:
5010 			WL_ERR(("Unknown event %d\n", event));
5011 			break;
5012 	}
5013 	return err;
5014 }
5015 #endif /* GSCAN_SUPPORT */
5016 
wl_cfg80211_set_passive_scan(struct net_device * dev,char * command)5017 void wl_cfg80211_set_passive_scan(struct net_device *dev, char *command)
5018 {
5019 	struct bcm_cfg80211 *cfg = wl_get_cfg(dev);
5020 
5021 	if (strcmp(command, "SCAN-ACTIVE") == 0) {
5022 		cfg->active_scan = 1;
5023 	} else if (strcmp(command, "SCAN-PASSIVE") == 0) {
5024 		cfg->active_scan = 0;
5025 	} else
5026 		WL_ERR(("Unknown command \n"));
5027 	return;
5028 }
5029 
5030 void
wl_cfgscan_listen_complete_work(struct work_struct * work)5031 wl_cfgscan_listen_complete_work(struct work_struct *work)
5032 {
5033 	struct bcm_cfg80211 *cfg = NULL;
5034 	BCM_SET_CONTAINER_OF(cfg, work, struct bcm_cfg80211, loc.work.work);
5035 
5036 	WL_ERR(("listen timeout\n"));
5037 	/* listen not completed. Do recovery */
5038 	if (!cfg->loc.in_progress) {
5039 		WL_ERR(("No listen in progress!\n"));
5040 		return;
5041 	}
5042 	wl_cfgscan_notify_listen_complete(cfg);
5043 }
5044 
5045 s32
wl_cfgscan_notify_listen_complete(struct bcm_cfg80211 * cfg)5046 wl_cfgscan_notify_listen_complete(struct bcm_cfg80211 *cfg)
5047 {
5048 	WL_DBG(("listen on channel complete! cookie:%llu\n", cfg->last_roc_id));
5049 	if (cfg->loc.wdev && cfg->loc.in_progress) {
5050 #if defined(WL_CFG80211_P2P_DEV_IF)
5051 		cfg80211_remain_on_channel_expired(cfg->loc.wdev, cfg->last_roc_id,
5052 			&cfg->remain_on_chan, GFP_KERNEL);
5053 #else
5054 		cfg80211_remain_on_channel_expired(cfg->loc.wdev->netdev, cfg->last_roc_id,
5055 			&cfg->remain_on_chan, cfg->remain_on_chan_type, GFP_KERNEL);
5056 #endif
5057 		cfg->loc.in_progress = false;
5058 		cfg->loc.wdev = NULL;
5059 	}
5060 	return BCME_OK;
5061 }
5062 
5063 static void
wl_init_scan_params(struct bcm_cfg80211 * cfg,u8 * params,u16 params_size,u32 scan_type,u32 action,u32 passive_time)5064 wl_init_scan_params(struct bcm_cfg80211 *cfg, u8 *params, u16 params_size,
5065 	u32 scan_type, u32 action, u32 passive_time)
5066 {
5067 	u32 sync_id = 0;
5068 	wl_escan_params_t *eparams = NULL;
5069 	wl_escan_params_v2_t *eparams_v2 = NULL;
5070 	wl_scan_params_t *scanparams = NULL;
5071 	wl_scan_params_v2_t *scanparams_v2 = NULL;
5072 
5073 	wl_escan_set_sync_id(sync_id, cfg);
5074 	if (cfg->scan_params_v2) {
5075 		eparams_v2 = (wl_escan_params_v2_t *)params;
5076 		eparams_v2->version = htod32(ESCAN_REQ_VERSION_V2);
5077 		eparams_v2->action =  htod16(action);
5078 		eparams_v2->sync_id = sync_id;
5079 		scanparams_v2 = (wl_scan_params_v2_t *)&eparams_v2->params;
5080 		(void)memcpy_s(&scanparams_v2->bssid, ETHER_ADDR_LEN, &ether_bcast, ETHER_ADDR_LEN);
5081 		scanparams_v2->version = htod16(WL_SCAN_PARAMS_VERSION_V2);
5082 		scanparams_v2->length = htod16(sizeof(wl_scan_params_v2_t));
5083 		scanparams_v2->bss_type = DOT11_BSSTYPE_ANY;
5084 		scanparams_v2->scan_type = htod32(scan_type);
5085 		scanparams_v2->nprobes = htod32(-1);
5086 		scanparams_v2->active_time = htod32(-1);
5087 		scanparams_v2->passive_time = htod32(passive_time);
5088 		scanparams_v2->home_time = htod32(-1);
5089 		bzero(&scanparams_v2->ssid, sizeof(wlc_ssid_t));
5090 	} else {
5091 		eparams = (wl_escan_params_t *)params;
5092 		eparams->version = htod32(ESCAN_REQ_VERSION);
5093 		eparams->action =  htod16(action);
5094 		eparams->sync_id = sync_id;
5095 		scanparams = (wl_scan_params_t *)&eparams->params;
5096 		(void)memcpy_s(&scanparams->bssid, ETHER_ADDR_LEN, &ether_bcast, ETHER_ADDR_LEN);
5097 		scanparams->bss_type = DOT11_BSSTYPE_ANY;
5098 		scanparams->scan_type = 0;
5099 		scanparams->nprobes = htod32(-1);
5100 		scanparams->active_time = htod32(-1);
5101 		scanparams->passive_time = htod32(passive_time);
5102 		scanparams->home_time = htod32(-1);
5103 		bzero(&scanparams->ssid, sizeof(wlc_ssid_t));
5104 	}
5105 }
5106 
5107 /* timeout for recoverying upper layer statemachine */
5108 #define WL_LISTEN_TIMEOUT    3000u
5109 
5110 s32
wl_cfgscan_cancel_listen_on_channel(struct bcm_cfg80211 * cfg,bool notify_user)5111 wl_cfgscan_cancel_listen_on_channel(struct bcm_cfg80211 *cfg, bool notify_user)
5112 {
5113 	WL_DBG(("Enter\n"));
5114 
5115 	mutex_lock(&cfg->scan_sync);
5116 	if (!cfg->loc.in_progress) {
5117 		WL_ERR(("listen not in progress. do nothing\n"));
5118 		goto exit;
5119 	}
5120 
5121 	if (delayed_work_pending(&cfg->loc.work)) {
5122 		cancel_delayed_work_sync(&cfg->loc.work);
5123 	}
5124 
5125 	/* abort scan listen */
5126 	_wl_cfgscan_cancel_scan(cfg);
5127 
5128 	if (notify_user) {
5129 		wl_cfgscan_notify_listen_complete(cfg);
5130 	}
5131 	cfg->loc.in_progress = false;
5132 	cfg->loc.wdev = NULL;
5133 exit:
5134 	mutex_unlock(&cfg->scan_sync);
5135 	return 0;
5136 }
5137 
5138 s32
wl_cfgscan_listen_on_channel(struct bcm_cfg80211 * cfg,struct wireless_dev * wdev,struct ieee80211_channel * channel,unsigned int duration)5139 wl_cfgscan_listen_on_channel(struct bcm_cfg80211 *cfg, struct wireless_dev *wdev,
5140 	struct ieee80211_channel *channel, unsigned int duration)
5141 {
5142 	u32 dwell = duration;
5143 	u32 chanspec, params_size;
5144 	u16 chanspec_num = 0;
5145 	s32 bssidx = -1;
5146 	s32 err = 0;
5147 	struct net_device *ndev = NULL;
5148 	u8 *params = NULL;
5149 	wl_escan_params_t *eparams = NULL;
5150 	wl_escan_params_v2_t *eparams_v2 = NULL;
5151 	wl_scan_params_t *scanparams = NULL;
5152 	wl_scan_params_v2_t *scanparams_v2 = NULL;
5153 	u16 *chanspec_list = NULL;
5154 	u32 channel_num = 0, scan_type = 0;
5155 
5156 	WL_DBG(("Enter \n"));
5157 	if (!wdev) {
5158 	  WL_ERR(("wdev null!\n"));
5159 	  return -EINVAL;
5160 	}
5161 
5162 	mutex_lock(&cfg->scan_sync);
5163 	if (wl_get_drv_status_all(cfg, SCANNING)) {
5164 		WL_ERR(("Scanning in progress avoid listen on channel\n"));
5165 		err = -EBUSY;
5166 		goto exit;
5167 	}
5168 	if (cfg->loc.in_progress == true) {
5169 		WL_ERR(("Listen in progress\n"));
5170 		err = -EAGAIN;
5171 		goto exit;
5172 	}
5173 	bssidx = wl_get_bssidx_by_wdev(cfg, wdev);
5174 	if (bssidx < 0) {
5175 		WL_ERR(("invalid bssidx!\n"));
5176 		err = -EINVAL;
5177 		goto exit;
5178 	}
5179 
5180 	/* Use primary ndev for netless dev. BSSIDX will point to right I/F */
5181 	ndev = wdev->netdev ? wdev->netdev : bcmcfg_to_prmry_ndev(cfg);
5182 
5183 	if (cfg->scan_params_v2) {
5184 		params_size = (WL_SCAN_PARAMS_V2_FIXED_SIZE +
5185 			OFFSETOF(wl_escan_params_v2_t, params));
5186 	} else {
5187 		params_size = (WL_SCAN_PARAMS_FIXED_SIZE + OFFSETOF(wl_escan_params_t, params));
5188 	}
5189 
5190 	/* Single channel for listen case. Add a padd of u16 for alignment */
5191 	chanspec_num = 1;
5192 	params_size += (chanspec_num + 1);
5193 
5194 	/* Allocate space for populating single ssid in wl_escan_params_t struct */
5195 	params_size += ((u32) sizeof(struct wlc_ssid));
5196 
5197 	params = MALLOCZ(cfg->osh, params_size);
5198 	if (params == NULL) {
5199 		err = -ENOMEM;
5200 		WL_ERR(("listen fail. no mem.\n"));
5201 		goto exit;
5202 	}
5203 
5204 	scan_type = WL_SCANFLAGS_PASSIVE | WL_SCANFLAGS_LISTEN;
5205 
5206 	wl_init_scan_params(cfg, params, params_size,
5207 		scan_type, WL_SCAN_ACTION_START, dwell);
5208 
5209 	channel_num = (chanspec_num & WL_SCAN_PARAMS_COUNT_MASK);
5210 	if (cfg->scan_params_v2) {
5211 		eparams_v2 = (wl_escan_params_v2_t *)params;
5212 		scanparams_v2 = (wl_scan_params_v2_t *)&eparams_v2->params;
5213 		chanspec_list = scanparams_v2->channel_list;
5214 		scanparams_v2->channel_num = channel_num;
5215 	} else {
5216 		eparams = (wl_escan_params_t *)params;
5217 		scanparams = (wl_scan_params_t *)&eparams->params;
5218 		chanspec_list = scanparams->channel_list;
5219 		scanparams->channel_num = channel_num;
5220 	}
5221 
5222 	/* Copy the single listen channel */
5223 	chanspec = wl_freq_to_chanspec(channel->center_freq);
5224 	chanspec_list[0] = chanspec;
5225 
5226 	err = wldev_iovar_setbuf_bsscfg(ndev, "escan", params, params_size,
5227 		cfg->escan_ioctl_buf, WLC_IOCTL_MEDLEN, bssidx, &cfg->ioctl_buf_sync);
5228 	if (unlikely(err)) {
5229 		if (err == BCME_EPERM) {
5230 			/* Scan Not permitted at this point of time */
5231 			WL_DBG((" listen not permitted at this time (%d)\n", err));
5232 		} else {
5233 			WL_ERR((" listen set error (%d)\n", err));
5234 		}
5235 		goto exit;
5236 	} else {
5237 		unsigned long listen_timeout = dwell + WL_LISTEN_TIMEOUT;
5238 		WL_DBG(("listen started. chanspec:%x\n", chanspec));
5239 		cfg->loc.in_progress = true;
5240 		cfg->loc.wdev = wdev;
5241 
5242 		if (schedule_delayed_work(&cfg->loc.work,
5243 				msecs_to_jiffies(listen_timeout))) {
5244 
5245 #if defined(BCMDONGLEHOST) && defined(OEM_ANDROID)
5246 			DHD_PM_WAKE_LOCK_TIMEOUT(cfg->pub, listen_timeout);
5247 #endif /* BCMDONGLEHOST && OEM_ANDROID */
5248 
5249 		} else {
5250 			WL_ERR(("Can't schedule listen work handler\n"));
5251 		}
5252 	}
5253 
5254 exit:
5255 	if (params) {
5256 		MFREE(cfg->osh, params, params_size);
5257 	}
5258 	mutex_unlock(&cfg->scan_sync);
5259 	return err;
5260 }
5261 
5262 #define LONG_LISTEN_TIME 2000
5263 #ifdef WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST
5264 static void
wl_priortize_scan_over_listen(struct bcm_cfg80211 * cfg,struct net_device * ndev,unsigned int duration)5265 wl_priortize_scan_over_listen(struct bcm_cfg80211 *cfg,
5266 	struct net_device *ndev, unsigned int duration)
5267 {
5268 	WL_DBG(("scan is running. go to fake listen state\n"));
5269 	wl_set_drv_status(cfg, FAKE_REMAINING_ON_CHANNEL, ndev);
5270 
5271 	WL_DBG(("cancel current listen timer \n"));
5272 	del_timer_sync(&cfg->p2p->listen_timer);
5273 
5274 	wl_clr_p2p_status(cfg, LISTEN_EXPIRED);
5275 
5276 	INIT_TIMER(&cfg->p2p->listen_timer,
5277 		wl_cfgp2p_listen_expired, duration, 0);
5278 }
5279 #endif /* WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST */
5280 
5281 /* Few vendors use hard coded static ndev p2p0 for p2p disc */
5282 #define IS_P2P_DISC_NDEV(wdev) \
5283 	(wdev->netdev ? (strncmp(wdev->netdev->name, "p2p0", strlen("p2p0")) == 0) : false)
5284 
5285 s32
wl_cfgscan_remain_on_channel(struct wiphy * wiphy,bcm_struct_cfgdev * cfgdev,struct ieee80211_channel * channel,enum nl80211_channel_type channel_type,unsigned int duration,u64 * cookie)5286 wl_cfgscan_remain_on_channel(struct wiphy *wiphy, bcm_struct_cfgdev *cfgdev,
5287 	struct ieee80211_channel *channel,
5288 #if !defined(WL_CFG80211_P2P_DEV_IF)
5289 	enum nl80211_channel_type channel_type,
5290 #endif /* WL_CFG80211_P2P_DEV_IF */
5291 	unsigned int duration, u64 *cookie)
5292 {
5293 	s32 target_channel;
5294 	u32 id;
5295 	s32 err = BCME_OK;
5296 	struct net_device *ndev = NULL;
5297 	struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
5298 	struct wireless_dev *wdev;
5299 
5300 	RETURN_EIO_IF_NOT_UP(cfg);
5301 
5302 	mutex_lock(&cfg->usr_sync);
5303 	ndev = cfgdev_to_wlc_ndev(cfgdev, cfg);
5304 #if defined(WL_CFG80211_P2P_DEV_IF)
5305 	wdev = cfgdev;
5306 #else
5307 	wdev = ndev_to_wdev(ndev);
5308 #endif
5309 	if (!wdev) {
5310 		WL_ERR(("wdev null\n"));
5311 		err = -EINVAL;
5312 		goto exit;
5313 	}
5314 
5315 	target_channel = ieee80211_frequency_to_channel(channel->center_freq);
5316 
5317 	WL_DBG(("Enter, channel: %d, duration ms (%d) scan_state:%d\n",
5318 		target_channel, duration,
5319 		(wl_get_drv_status(cfg, SCANNING, ndev)) ? TRUE : FALSE));
5320 
5321 #ifdef WL_BCNRECV
5322 	/* check fakeapscan in progress then abort */
5323 	wl_android_bcnrecv_stop(ndev, WL_BCNRECV_LISTENBUSY);
5324 #endif /* WL_BCNRECV */
5325 
5326 #if defined(WL_CFG80211_P2P_DEV_IF)
5327 	if ((wdev->iftype == NL80211_IFTYPE_P2P_DEVICE) || IS_P2P_DISC_NDEV(wdev))
5328 #else
5329 	if (cfg->p2p)
5330 #endif
5331 	{
5332 		/* p2p discovery */
5333 		if (!cfg->p2p) {
5334 			WL_ERR(("cfg->p2p is not initialized\n"));
5335 			err = BCME_ERROR;
5336 			goto exit;
5337 		}
5338 
5339 #ifdef P2P_LISTEN_OFFLOADING
5340 		if (wl_get_p2p_status(cfg, DISC_IN_PROGRESS)) {
5341 			WL_ERR(("P2P_FIND: Discovery offload is in progress\n"));
5342 			err = -EAGAIN;
5343 			goto exit;
5344 		}
5345 #endif /* P2P_LISTEN_OFFLOADING */
5346 
5347 		if (wl_get_drv_status_all(cfg, SCANNING)) {
5348 #ifdef WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST
5349 			if (duration > LONG_LISTEN_TIME) {
5350 				wl_cfgscan_cancel_scan(cfg);
5351 			} else {
5352 				wl_priortize_scan_over_listen(cfg, ndev, duration);
5353 				err = BCME_OK;
5354 				goto exit;
5355 			}
5356 #else
5357 			wl_cfgscan_cancel_scan(cfg);
5358 #endif /* WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST */
5359 		}
5360 
5361 #ifdef WL_CFG80211_SYNC_GON
5362 		if (wl_get_drv_status_all(cfg, WAITING_NEXT_ACT_FRM_LISTEN)) {
5363 			/* Do not enter listen mode again if we are in listen mode already
5364 			* for next af. Remain on channel completion will be returned by
5365 			* af completion.
5366 			*/
5367 #ifdef WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST
5368 			wl_set_drv_status(cfg, FAKE_REMAINING_ON_CHANNEL, ndev);
5369 #else
5370 			wl_set_drv_status(cfg, REMAINING_ON_CHANNEL, ndev);
5371 #endif
5372 			goto exit;
5373 		}
5374 #endif /* WL_CFG80211_SYNC_GON */
5375 
5376 		if (!cfg->p2p->on) {
5377 		/* In case of p2p_listen command, supplicant may send
5378 		* remain_on_channel without turning on P2P
5379 		*/
5380 			p2p_on(cfg) = true;
5381 		}
5382 
5383 		err = wl_cfgp2p_enable_discovery(cfg, ndev, NULL, 0);
5384 		if (unlikely(err)) {
5385 			goto exit;
5386 		}
5387 		err = wl_cfgp2p_discover_listen(cfg, target_channel, duration);
5388 		if (err == BCME_OK) {
5389 			wl_set_drv_status(cfg, REMAINING_ON_CHANNEL, ndev);
5390 		} else {
5391 #ifdef WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST
5392 			if (err == BCME_BUSY) {
5393 				/* if failed, firmware may be internal scanning state.
5394 				* so other scan request shall not abort it
5395 				*/
5396 				wl_set_drv_status(cfg, FAKE_REMAINING_ON_CHANNEL, ndev);
5397 				/* WAR: set err = ok to prevent cookie mismatch in wpa_supplicant
5398 				* and expire timer will send a completion to the upper layer
5399 				*/
5400 				err = BCME_OK;
5401 			}
5402 #endif /* WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST */
5403 		}
5404 	} else if (wdev->iftype == NL80211_IFTYPE_STATION ||
5405 		wdev->iftype == NL80211_IFTYPE_AP) {
5406 		WL_DBG(("LISTEN ON CHANNEL\n"));
5407 		err = wl_cfgscan_listen_on_channel(cfg, wdev, channel, duration);
5408 	}
5409 
5410 exit:
5411 	if (err == BCME_OK) {
5412 		WL_DBG(("Success\n"));
5413 		(void)memcpy_s(&cfg->remain_on_chan, sizeof(struct ieee80211_channel),
5414 			channel, sizeof(struct ieee80211_channel));
5415 #if defined(WL_ENABLE_P2P_IF)
5416 		cfg->remain_on_chan_type = channel_type;
5417 #endif /* WL_ENABLE_P2P_IF */
5418 		id = ++cfg->last_roc_id;
5419 		if (id == 0) {
5420 			id = ++cfg->last_roc_id;
5421 		}
5422 		*cookie = id;
5423 
5424 		/* Notify userspace that listen has started */
5425 		CFG80211_READY_ON_CHANNEL(cfgdev, *cookie, channel, channel_type, duration, flags);
5426 		WL_INFORM_MEM(("listen started on channel:%d duration (ms):%d cookie:%llu\n",
5427 				target_channel, duration, *cookie));
5428 	} else {
5429 		WL_ERR(("Fail to Set (err=%d cookie:%llu)\n", err, *cookie));
5430 		wl_flush_fw_log_buffer(ndev, FW_LOGSET_MASK_ALL);
5431 	}
5432 	mutex_unlock(&cfg->usr_sync);
5433 	return err;
5434 }
5435 
5436 s32
wl_cfgscan_cancel_remain_on_channel(struct wiphy * wiphy,bcm_struct_cfgdev * cfgdev,u64 cookie)5437 wl_cfgscan_cancel_remain_on_channel(struct wiphy *wiphy,
5438 	bcm_struct_cfgdev *cfgdev, u64 cookie)
5439 {
5440 	s32 err = 0;
5441 	struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
5442 #ifdef P2PLISTEN_AP_SAMECHN
5443 	struct net_device *dev;
5444 #endif /* P2PLISTEN_AP_SAMECHN */
5445 
5446 	RETURN_EIO_IF_NOT_UP(cfg);
5447 
5448 #ifdef DHD_IFDEBUG
5449 	PRINT_WDEV_INFO(cfgdev);
5450 #endif /* DHD_IFDEBUG */
5451 
5452 	mutex_lock(&cfg->usr_sync);
5453 #if defined(WL_CFG80211_P2P_DEV_IF)
5454 	WL_DBG(("cancel listen for iftype:%d\n", cfgdev->iftype));
5455 	if ((cfgdev->iftype != NL80211_IFTYPE_P2P_DEVICE) &&
5456 		!IS_P2P_DISC_NDEV(cfgdev)) {
5457 		/* Handle non-p2p cases here */
5458 		err = wl_cfgscan_cancel_listen_on_channel(cfg, false);
5459 		goto exit;
5460 	}
5461 #else
5462 	WL_DBG(("cancel listen for netdev_ifidx: %d \n", cfgdev->ifindex));
5463 #endif /* WL_CFG80211_P2P_DEV_IF */
5464 
5465 #ifdef P2PLISTEN_AP_SAMECHN
5466 	if (cfg && cfg->p2p_resp_apchn_status) {
5467 		dev = bcmcfg_to_prmry_ndev(cfg);
5468 		wl_cfg80211_set_p2p_resp_ap_chn(dev, 0);
5469 		cfg->p2p_resp_apchn_status = false;
5470 		WL_DBG(("p2p_resp_apchn_status Turn OFF \n"));
5471 	}
5472 #endif /* P2PLISTEN_AP_SAMECHN */
5473 
5474 	if (cfg->last_roc_id == cookie) {
5475 		WL_DBG(("cancel p2p listen. cookie:%llu\n", cookie));
5476 		wl_cfgp2p_set_p2p_mode(cfg, WL_P2P_DISC_ST_SCAN, 0, 0,
5477 			wl_to_p2p_bss_bssidx(cfg, P2PAPI_BSSCFG_DEVICE));
5478 	} else {
5479 		WL_ERR(("wl_cfg80211_cancel_remain_on_channel: ignore, request cookie(%llu)"
5480 			" is not matched. (cur : %llu)\n",
5481 			cookie, cfg->last_roc_id));
5482 	}
5483 
5484 #if defined(WL_CFG80211_P2P_DEV_IF)
5485 exit:
5486 #endif
5487 	mutex_unlock(&cfg->usr_sync);
5488 	return err;
5489 }
5490 
5491 #ifdef WL_GET_RCC
5492 int
wl_android_get_roam_scan_chanlist(struct bcm_cfg80211 * cfg)5493 wl_android_get_roam_scan_chanlist(struct bcm_cfg80211 *cfg)
5494 {
5495 	s32 err = BCME_OK;
5496 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0))
5497 	struct sk_buff *skb;
5498 	gfp_t kflags;
5499 	struct net_device *ndev;
5500 	struct wiphy *wiphy;
5501 	wlc_ssid_t *ssid = NULL;
5502 	wl_roam_channel_list_t channel_list;
5503 	uint16 channels[MAX_ROAM_CHANNEL] = {0};
5504 	int i = 0;
5505 
5506 	ndev = bcmcfg_to_prmry_ndev(cfg);
5507 	wiphy = bcmcfg_to_wiphy(cfg);
5508 
5509 	kflags = in_atomic() ? GFP_ATOMIC : GFP_KERNEL;
5510 	skb = CFG80211_VENDOR_EVENT_ALLOC(wiphy, ndev_to_wdev(ndev),
5511 		BRCM_VENDOR_GET_RCC_EVENT_BUF_LEN, BRCM_VENDOR_EVENT_RCC_INFO, kflags);
5512 
5513 	if (!skb) {
5514 		WL_ERR(("skb alloc failed"));
5515 		return BCME_NOMEM;
5516 	}
5517 
5518 	/* Get Current SSID */
5519 	ssid = (struct wlc_ssid *)wl_read_prof(cfg, ndev, WL_PROF_SSID);
5520 	if (!ssid) {
5521 		WL_ERR(("No SSID found in the saved profile\n"));
5522 		err = BCME_ERROR;
5523 		goto fail;
5524 	}
5525 
5526 	/* Get Current RCC List */
5527 	err = wldev_iovar_getbuf(ndev, "roamscan_channels", 0, 0,
5528 		(void *)&channel_list, sizeof(channel_list), NULL);
5529 	if (err) {
5530 		WL_ERR(("Failed to get roamscan channels, err = %d\n", err));
5531 		goto fail;
5532 	}
5533 	if (channel_list.n > MAX_ROAM_CHANNEL) {
5534 		WL_ERR(("Invalid roamscan channels count(%d)\n", channel_list.n));
5535 		goto fail;
5536 	}
5537 
5538 	WL_DBG(("SSID %s(%d), RCC(%d)\n", ssid->SSID, ssid->SSID_len, channel_list.n));
5539 	for (i = 0; i < channel_list.n; i++) {
5540 		channels[i] = CHSPEC_CHANNEL(channel_list.channels[i]);
5541 		WL_DBG(("Chanspec[%d] CH:%03d(0x%04x)\n",
5542 			i, channels[i], channel_list.channels[i]));
5543 	}
5544 
5545 	err = nla_put_string(skb, RCC_ATTRIBUTE_SSID, ssid->SSID);
5546 	if (unlikely(err)) {
5547 		WL_ERR(("nla_put_string RCC_ATTRIBUTE_SSID failed\n"));
5548 		goto fail;
5549 	}
5550 
5551 	err = nla_put_u32(skb, RCC_ATTRIBUTE_SSID_LEN, ssid->SSID_len);
5552 	if (unlikely(err)) {
5553 		WL_ERR(("nla_put_u32 RCC_ATTRIBUTE_SSID_LEN failed\n"));
5554 		goto fail;
5555 	}
5556 
5557 	err = nla_put_u32(skb, RCC_ATTRIBUTE_NUM_CHANNELS, channel_list.n);
5558 	if (unlikely(err)) {
5559 		WL_ERR(("nla_put_u32 RCC_ATTRIBUTE_NUM_CHANNELS failed\n"));
5560 		goto fail;
5561 	}
5562 
5563 	err = nla_put(skb, RCC_ATTRIBUTE_CHANNEL_LIST,
5564 		sizeof(uint16) * MAX_ROAM_CHANNEL, channels);
5565 	if (unlikely(err)) {
5566 		WL_ERR(("nla_put RCC_ATTRIBUTE_CHANNEL_LIST failed\n"));
5567 		goto fail;
5568 	}
5569 
5570 	cfg80211_vendor_event(skb, kflags);
5571 
5572 	return err;
5573 
5574 fail:
5575 	if (skb) {
5576 		nlmsg_free(skb);
5577 	}
5578 #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0) */
5579 	return err;
5580 }
5581 #endif /* WL_GET_RCC */
5582 
5583 /*
5584  * This function prepares assoc channel/s
5585  */
5586 s32
wl_get_assoc_channels(struct bcm_cfg80211 * cfg,struct net_device * dev,wlcfg_assoc_info_t * info)5587 wl_get_assoc_channels(struct bcm_cfg80211 *cfg,
5588 	struct net_device *dev, wlcfg_assoc_info_t *info)
5589 {
5590 #ifdef ESCAN_CHANNEL_CACHE
5591 	s32 err;
5592 	u32 max_channels = MAX_ROAM_CHANNEL;
5593 	u16 rcc_chan_cnt = 0;
5594 
5595 	/*
5596 	 * If bcast join 'OR' no channel information is provided by user space,
5597 	 * then use channels from ESCAN_CHANNEL_CACHE. For other cases where target
5598 	 * channel is available, update RCC via iovar.
5599 	 *
5600 	 * For a given SSID there might multiple APs on different channels and FW
5601 	 * would scan all those channels before deciding up on the AP.
5602 	 */
5603 	if (cfg->rcc_enabled) {
5604 		wlc_ssid_t ssid;
5605 		int band;
5606 		chanspec_t chanspecs[MAX_ROAM_CHANNEL] = {0};
5607 		chanspec_t target_chspec;
5608 
5609 		err = wldev_get_band(dev, &band);
5610 		if (!err) {
5611 			set_roam_band(band);
5612 		}
5613 
5614 		if (memcpy_s(ssid.SSID, sizeof(ssid.SSID), info->ssid, info->ssid_len) != BCME_OK) {
5615 			WL_ERR(("ssid copy failed\n"));
5616 			return -EINVAL;
5617 		}
5618 		ssid.SSID_len = (uint32)info->ssid_len;
5619 
5620 		if (info->targeted_join && info->chanspecs[0]) {
5621 			target_chspec = info->chanspecs[0];
5622 		} else {
5623 			target_chspec = INVCHANSPEC;
5624 		}
5625 		rcc_chan_cnt = get_roam_channel_list(cfg, target_chspec, chanspecs,
5626 				max_channels, &ssid, ioctl_version);
5627 		if ((!info->targeted_join) || (info->bssid_hint) ||
5628 				(info->chan_cnt == 0)) {
5629 #if !defined(DISABLE_FW_NW_SEL_FOR_6G) && defined(WL_6G_BAND)
5630 			int i;
5631 			/* If 6G AP is present, override bssid_hint with our fw nw
5632 			 * selection. Supplicant bssid_hint logic doesn't have support for
5633 			 * 6G, HE, OCE load IE support
5634 			 */
5635 			for (i = 0; i < rcc_chan_cnt; i++) {
5636 				if (CHSPEC_IS6G(chanspecs[i])) {
5637 					WL_INFORM_MEM(("6G channel in rcc. use fw nw sel\n"));
5638 					/* skip bssid hint inclusion and provide bcast bssid */
5639 					info->bssid_hint = false;
5640 					(void)memcpy_s(&info->bssid,
5641 							ETH_ALEN, &ether_bcast, ETH_ALEN);
5642 					break;
5643 				}
5644 			}
5645 #endif /* !DISABLE_FW_NW_SEL_FOR_6G && WL_6G_BAND */
5646 			/* Use RCC channels as part of join params */
5647 			info->chan_cnt = rcc_chan_cnt;
5648 			if (memcpy_s(info->chanspecs, sizeof(info->chanspecs), chanspecs,
5649 					(sizeof(chanspec_t) * rcc_chan_cnt)) != BCME_OK) {
5650 				WL_ERR(("chanspec copy failed!\n"));
5651 				return -EINVAL;
5652 			}
5653 		}
5654 	}
5655 #endif /* ESCAN_CHANNEL_CACHE */
5656 
5657 	WL_DBG_MEM(("channel cnt:%d\n", info->chan_cnt));
5658 	return BCME_OK;
5659 }
5660 
5661 #ifdef DHD_GET_VALID_CHANNELS
5662 bool
wl_cfgscan_is_dfs_set(wifi_band band)5663 wl_cfgscan_is_dfs_set(wifi_band band)
5664 {
5665 	switch (band) {
5666 		case WIFI_BAND_A_DFS:
5667 		case WIFI_BAND_A_WITH_DFS:
5668 		case WIFI_BAND_ABG_WITH_DFS:
5669 		case WIFI_BAND_24GHZ_5GHZ_WITH_DFS_6GHZ:
5670 			return true;
5671 		default:
5672 			return false;
5673 	}
5674 	return false;
5675 }
5676 
5677 s32
wl_cfgscan_get_band_freq_list(struct bcm_cfg80211 * cfg,int band,uint16 * list,uint32 * num_channels)5678 wl_cfgscan_get_band_freq_list(struct bcm_cfg80211 *cfg, int band,
5679 	uint16 *list, uint32 *num_channels)
5680 {
5681 	s32 err = BCME_OK;
5682 	uint32 i, freq, list_count, count = 0;
5683 	struct net_device *dev = bcmcfg_to_prmry_ndev(cfg);
5684 	uint32 chspec, chaninfo;
5685 	bool dfs_set = false;
5686 
5687 	dfs_set = wl_cfgscan_is_dfs_set(band);
5688 	err = wldev_iovar_getbuf_bsscfg(dev, "chan_info_list", NULL,
5689 			0, list, CHANINFO_LIST_BUF_SIZE, 0, &cfg->ioctl_buf_sync);
5690 	if (err == BCME_UNSUPPORTED) {
5691 		WL_INFORM(("get chan_info_list, UNSUPPORTED\n"));
5692 		return err;
5693 	} else if (err != BCME_OK) {
5694 		WL_ERR(("get chan_info_list err(%d)\n", err));
5695 		return err;
5696 	}
5697 
5698 	list_count = ((wl_chanspec_list_v1_t *)list)->count;
5699 	for (i = 0; i < list_count; i++) {
5700 		chspec = dtoh32(((wl_chanspec_list_v1_t *)list)->chspecs[i].chanspec);
5701 		chaninfo = dtoh32(((wl_chanspec_list_v1_t *)list)->chspecs[i].chaninfo);
5702 		freq = wl_channel_to_frequency(wf_chspec_ctlchan(chspec),
5703 			CHSPEC_BAND(chspec));
5704 		if (((band & WIFI_BAND_BG) && CHSPEC_IS2G(chspec)) ||
5705 				((band & WIFI_BAND_6GHZ) && CHSPEC_IS6G(chspec))) {
5706 			/* add 2g/6g channels */
5707 			list[i] = freq;
5708 			count++;
5709 		}
5710 		/* handle 5g separately */
5711 		if (CHSPEC_IS5G(chspec)) {
5712 			if (!((band == WIFI_BAND_A_DFS) && IS_DFS(chaninfo)) &&
5713 				!(band & WIFI_BAND_A)) {
5714 				/* Not DFS only case nor 5G case */
5715 				continue;
5716 			}
5717 
5718 			if ((band & WIFI_BAND_A) && !dfs_set && IS_DFS(chaninfo)) {
5719 				continue;
5720 			}
5721 
5722 			list[i] = freq;
5723 			count++;
5724 		}
5725 	}
5726 	*num_channels = count;
5727 	return err;
5728 }
5729 #endif /* DHD_GET_VALID_CHANNELS */
5730