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