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