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