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