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