GNU Linux-libre 4.19.286-gnu1
[releases.git] / drivers / net / wireless / marvell / mwifiex / scan.c
1 /*
2  * Marvell Wireless LAN device driver: scan ioctl and command handling
3  *
4  * Copyright (C) 2011-2014, Marvell International Ltd.
5  *
6  * This software file (the "File") is distributed by Marvell International
7  * Ltd. under the terms of the GNU General Public License Version 2, June 1991
8  * (the "License").  You may use, redistribute and/or modify this File in
9  * accordance with the terms and conditions of the License, a copy of which
10  * is available by writing to the Free Software Foundation, Inc.,
11  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
12  * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
13  *
14  * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
16  * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
17  * this warranty disclaimer.
18  */
19
20 #include "decl.h"
21 #include "ioctl.h"
22 #include "util.h"
23 #include "fw.h"
24 #include "main.h"
25 #include "11n.h"
26 #include "cfg80211.h"
27
28 /* The maximum number of channels the firmware can scan per command */
29 #define MWIFIEX_MAX_CHANNELS_PER_SPECIFIC_SCAN   14
30
31 #define MWIFIEX_DEF_CHANNELS_PER_SCAN_CMD       4
32
33 /* Memory needed to store a max sized Channel List TLV for a firmware scan */
34 #define CHAN_TLV_MAX_SIZE  (sizeof(struct mwifiex_ie_types_header)         \
35                                 + (MWIFIEX_MAX_CHANNELS_PER_SPECIFIC_SCAN     \
36                                 *sizeof(struct mwifiex_chan_scan_param_set)))
37
38 /* Memory needed to store supported rate */
39 #define RATE_TLV_MAX_SIZE   (sizeof(struct mwifiex_ie_types_rates_param_set) \
40                                 + HOSTCMD_SUPPORTED_RATES)
41
42 /* Memory needed to store a max number/size WildCard SSID TLV for a firmware
43         scan */
44 #define WILDCARD_SSID_TLV_MAX_SIZE  \
45         (MWIFIEX_MAX_SSID_LIST_LENGTH *                                 \
46                 (sizeof(struct mwifiex_ie_types_wildcard_ssid_params)   \
47                         + IEEE80211_MAX_SSID_LEN))
48
49 /* Maximum memory needed for a mwifiex_scan_cmd_config with all TLVs at max */
50 #define MAX_SCAN_CFG_ALLOC (sizeof(struct mwifiex_scan_cmd_config)        \
51                                 + sizeof(struct mwifiex_ie_types_num_probes)   \
52                                 + sizeof(struct mwifiex_ie_types_htcap)       \
53                                 + CHAN_TLV_MAX_SIZE                 \
54                                 + RATE_TLV_MAX_SIZE                 \
55                                 + WILDCARD_SSID_TLV_MAX_SIZE)
56
57
58 union mwifiex_scan_cmd_config_tlv {
59         /* Scan configuration (variable length) */
60         struct mwifiex_scan_cmd_config config;
61         /* Max allocated block */
62         u8 config_alloc_buf[MAX_SCAN_CFG_ALLOC];
63 };
64
65 enum cipher_suite {
66         CIPHER_SUITE_TKIP,
67         CIPHER_SUITE_CCMP,
68         CIPHER_SUITE_MAX
69 };
70 static u8 mwifiex_wpa_oui[CIPHER_SUITE_MAX][4] = {
71         { 0x00, 0x50, 0xf2, 0x02 },     /* TKIP */
72         { 0x00, 0x50, 0xf2, 0x04 },     /* AES  */
73 };
74 static u8 mwifiex_rsn_oui[CIPHER_SUITE_MAX][4] = {
75         { 0x00, 0x0f, 0xac, 0x02 },     /* TKIP */
76         { 0x00, 0x0f, 0xac, 0x04 },     /* AES  */
77 };
78
79 static void
80 _dbg_security_flags(int log_level, const char *func, const char *desc,
81                     struct mwifiex_private *priv,
82                     struct mwifiex_bssdescriptor *bss_desc)
83 {
84         _mwifiex_dbg(priv->adapter, log_level,
85                      "info: %s: %s:\twpa_ie=%#x wpa2_ie=%#x WEP=%s WPA=%s WPA2=%s\tEncMode=%#x privacy=%#x\n",
86                      func, desc,
87                      bss_desc->bcn_wpa_ie ?
88                      bss_desc->bcn_wpa_ie->vend_hdr.element_id : 0,
89                      bss_desc->bcn_rsn_ie ?
90                      bss_desc->bcn_rsn_ie->ieee_hdr.element_id : 0,
91                      priv->sec_info.wep_enabled ? "e" : "d",
92                      priv->sec_info.wpa_enabled ? "e" : "d",
93                      priv->sec_info.wpa2_enabled ? "e" : "d",
94                      priv->sec_info.encryption_mode,
95                      bss_desc->privacy);
96 }
97 #define dbg_security_flags(mask, desc, priv, bss_desc) \
98         _dbg_security_flags(MWIFIEX_DBG_##mask, desc, __func__, priv, bss_desc)
99
100 static bool
101 has_ieee_hdr(struct ieee_types_generic *ie, u8 key)
102 {
103         return (ie && ie->ieee_hdr.element_id == key);
104 }
105
106 static bool
107 has_vendor_hdr(struct ieee_types_vendor_specific *ie, u8 key)
108 {
109         return (ie && ie->vend_hdr.element_id == key);
110 }
111
112 /*
113  * This function parses a given IE for a given OUI.
114  *
115  * This is used to parse a WPA/RSN IE to find if it has
116  * a given oui in PTK.
117  */
118 static u8
119 mwifiex_search_oui_in_ie(struct ie_body *iebody, u8 *oui)
120 {
121         u8 count;
122
123         count = iebody->ptk_cnt[0];
124
125         /* There could be multiple OUIs for PTK hence
126            1) Take the length.
127            2) Check all the OUIs for AES.
128            3) If one of them is AES then pass success. */
129         while (count) {
130                 if (!memcmp(iebody->ptk_body, oui, sizeof(iebody->ptk_body)))
131                         return MWIFIEX_OUI_PRESENT;
132
133                 --count;
134                 if (count)
135                         iebody = (struct ie_body *) ((u8 *) iebody +
136                                                 sizeof(iebody->ptk_body));
137         }
138
139         pr_debug("info: %s: OUI is not found in PTK\n", __func__);
140         return MWIFIEX_OUI_NOT_PRESENT;
141 }
142
143 /*
144  * This function checks if a given OUI is present in a RSN IE.
145  *
146  * The function first checks if a RSN IE is present or not in the
147  * BSS descriptor. It tries to locate the OUI only if such an IE is
148  * present.
149  */
150 static u8
151 mwifiex_is_rsn_oui_present(struct mwifiex_bssdescriptor *bss_desc, u32 cipher)
152 {
153         u8 *oui;
154         struct ie_body *iebody;
155         u8 ret = MWIFIEX_OUI_NOT_PRESENT;
156
157         if (has_ieee_hdr(bss_desc->bcn_rsn_ie, WLAN_EID_RSN)) {
158                 iebody = (struct ie_body *)
159                          (((u8 *) bss_desc->bcn_rsn_ie->data) +
160                           RSN_GTK_OUI_OFFSET);
161                 oui = &mwifiex_rsn_oui[cipher][0];
162                 ret = mwifiex_search_oui_in_ie(iebody, oui);
163                 if (ret)
164                         return ret;
165         }
166         return ret;
167 }
168
169 /*
170  * This function checks if a given OUI is present in a WPA IE.
171  *
172  * The function first checks if a WPA IE is present or not in the
173  * BSS descriptor. It tries to locate the OUI only if such an IE is
174  * present.
175  */
176 static u8
177 mwifiex_is_wpa_oui_present(struct mwifiex_bssdescriptor *bss_desc, u32 cipher)
178 {
179         u8 *oui;
180         struct ie_body *iebody;
181         u8 ret = MWIFIEX_OUI_NOT_PRESENT;
182
183         if (has_vendor_hdr(bss_desc->bcn_wpa_ie, WLAN_EID_VENDOR_SPECIFIC)) {
184                 iebody = (struct ie_body *)((u8 *)bss_desc->bcn_wpa_ie->data +
185                                             WPA_GTK_OUI_OFFSET);
186                 oui = &mwifiex_wpa_oui[cipher][0];
187                 ret = mwifiex_search_oui_in_ie(iebody, oui);
188                 if (ret)
189                         return ret;
190         }
191         return ret;
192 }
193
194 /*
195  * This function compares two SSIDs and checks if they match.
196  */
197 s32
198 mwifiex_ssid_cmp(struct cfg80211_ssid *ssid1, struct cfg80211_ssid *ssid2)
199 {
200         if (!ssid1 || !ssid2 || (ssid1->ssid_len != ssid2->ssid_len))
201                 return -1;
202         return memcmp(ssid1->ssid, ssid2->ssid, ssid1->ssid_len);
203 }
204
205 /*
206  * This function checks if wapi is enabled in driver and scanned network is
207  * compatible with it.
208  */
209 static bool
210 mwifiex_is_bss_wapi(struct mwifiex_private *priv,
211                     struct mwifiex_bssdescriptor *bss_desc)
212 {
213         if (priv->sec_info.wapi_enabled &&
214             has_ieee_hdr(bss_desc->bcn_wapi_ie, WLAN_EID_BSS_AC_ACCESS_DELAY))
215                 return true;
216         return false;
217 }
218
219 /*
220  * This function checks if driver is configured with no security mode and
221  * scanned network is compatible with it.
222  */
223 static bool
224 mwifiex_is_bss_no_sec(struct mwifiex_private *priv,
225                       struct mwifiex_bssdescriptor *bss_desc)
226 {
227         if (!priv->sec_info.wep_enabled && !priv->sec_info.wpa_enabled &&
228             !priv->sec_info.wpa2_enabled &&
229             !has_vendor_hdr(bss_desc->bcn_wpa_ie, WLAN_EID_VENDOR_SPECIFIC) &&
230             !has_ieee_hdr(bss_desc->bcn_rsn_ie, WLAN_EID_RSN) &&
231             !priv->sec_info.encryption_mode && !bss_desc->privacy) {
232                 return true;
233         }
234         return false;
235 }
236
237 /*
238  * This function checks if static WEP is enabled in driver and scanned network
239  * is compatible with it.
240  */
241 static bool
242 mwifiex_is_bss_static_wep(struct mwifiex_private *priv,
243                           struct mwifiex_bssdescriptor *bss_desc)
244 {
245         if (priv->sec_info.wep_enabled && !priv->sec_info.wpa_enabled &&
246             !priv->sec_info.wpa2_enabled && bss_desc->privacy) {
247                 return true;
248         }
249         return false;
250 }
251
252 /*
253  * This function checks if wpa is enabled in driver and scanned network is
254  * compatible with it.
255  */
256 static bool
257 mwifiex_is_bss_wpa(struct mwifiex_private *priv,
258                    struct mwifiex_bssdescriptor *bss_desc)
259 {
260         if (!priv->sec_info.wep_enabled && priv->sec_info.wpa_enabled &&
261             !priv->sec_info.wpa2_enabled &&
262             has_vendor_hdr(bss_desc->bcn_wpa_ie, WLAN_EID_VENDOR_SPECIFIC)
263            /*
264             * Privacy bit may NOT be set in some APs like
265             * LinkSys WRT54G && bss_desc->privacy
266             */
267          ) {
268                 dbg_security_flags(INFO, "WPA", priv, bss_desc);
269                 return true;
270         }
271         return false;
272 }
273
274 /*
275  * This function checks if wpa2 is enabled in driver and scanned network is
276  * compatible with it.
277  */
278 static bool
279 mwifiex_is_bss_wpa2(struct mwifiex_private *priv,
280                     struct mwifiex_bssdescriptor *bss_desc)
281 {
282         if (!priv->sec_info.wep_enabled && !priv->sec_info.wpa_enabled &&
283             priv->sec_info.wpa2_enabled &&
284             has_ieee_hdr(bss_desc->bcn_rsn_ie, WLAN_EID_RSN)) {
285                 /*
286                  * Privacy bit may NOT be set in some APs like
287                  * LinkSys WRT54G && bss_desc->privacy
288                  */
289                 dbg_security_flags(INFO, "WAP2", priv, bss_desc);
290                 return true;
291         }
292         return false;
293 }
294
295 /*
296  * This function checks if adhoc AES is enabled in driver and scanned network is
297  * compatible with it.
298  */
299 static bool
300 mwifiex_is_bss_adhoc_aes(struct mwifiex_private *priv,
301                          struct mwifiex_bssdescriptor *bss_desc)
302 {
303         if (!priv->sec_info.wep_enabled && !priv->sec_info.wpa_enabled &&
304             !priv->sec_info.wpa2_enabled &&
305             !has_vendor_hdr(bss_desc->bcn_wpa_ie, WLAN_EID_VENDOR_SPECIFIC) &&
306             !has_ieee_hdr(bss_desc->bcn_rsn_ie, WLAN_EID_RSN) &&
307             !priv->sec_info.encryption_mode && bss_desc->privacy) {
308                 return true;
309         }
310         return false;
311 }
312
313 /*
314  * This function checks if dynamic WEP is enabled in driver and scanned network
315  * is compatible with it.
316  */
317 static bool
318 mwifiex_is_bss_dynamic_wep(struct mwifiex_private *priv,
319                            struct mwifiex_bssdescriptor *bss_desc)
320 {
321         if (!priv->sec_info.wep_enabled && !priv->sec_info.wpa_enabled &&
322             !priv->sec_info.wpa2_enabled &&
323             !has_vendor_hdr(bss_desc->bcn_wpa_ie, WLAN_EID_VENDOR_SPECIFIC) &&
324             !has_ieee_hdr(bss_desc->bcn_rsn_ie, WLAN_EID_RSN) &&
325             priv->sec_info.encryption_mode && bss_desc->privacy) {
326                 dbg_security_flags(INFO, "dynamic", priv, bss_desc);
327                 return true;
328         }
329         return false;
330 }
331
332 /*
333  * This function checks if a scanned network is compatible with the driver
334  * settings.
335  *
336  *   WEP     WPA    WPA2   ad-hoc encrypt                  Network
337  * enabled enabled enabled  AES    mode   Privacy WPA WPA2 Compatible
338  *    0       0       0      0     NONE      0     0   0   yes No security
339  *    0       1       0      0      x        1x    1   x   yes WPA (disable
340  *                                                         HT if no AES)
341  *    0       0       1      0      x        1x    x   1   yes WPA2 (disable
342  *                                                         HT if no AES)
343  *    0       0       0      1     NONE      1     0   0   yes Ad-hoc AES
344  *    1       0       0      0     NONE      1     0   0   yes Static WEP
345  *                                                         (disable HT)
346  *    0       0       0      0    !=NONE     1     0   0   yes Dynamic WEP
347  *
348  * Compatibility is not matched while roaming, except for mode.
349  */
350 static s32
351 mwifiex_is_network_compatible(struct mwifiex_private *priv,
352                               struct mwifiex_bssdescriptor *bss_desc, u32 mode)
353 {
354         struct mwifiex_adapter *adapter = priv->adapter;
355
356         bss_desc->disable_11n = false;
357
358         /* Don't check for compatibility if roaming */
359         if (priv->media_connected &&
360             (priv->bss_mode == NL80211_IFTYPE_STATION) &&
361             (bss_desc->bss_mode == NL80211_IFTYPE_STATION))
362                 return 0;
363
364         if (priv->wps.session_enable) {
365                 mwifiex_dbg(adapter, IOCTL,
366                             "info: return success directly in WPS period\n");
367                 return 0;
368         }
369
370         if (bss_desc->chan_sw_ie_present) {
371                 mwifiex_dbg(adapter, INFO,
372                             "Don't connect to AP with WLAN_EID_CHANNEL_SWITCH\n");
373                 return -1;
374         }
375
376         if (mwifiex_is_bss_wapi(priv, bss_desc)) {
377                 mwifiex_dbg(adapter, INFO,
378                             "info: return success for WAPI AP\n");
379                 return 0;
380         }
381
382         if (bss_desc->bss_mode == mode) {
383                 if (mwifiex_is_bss_no_sec(priv, bss_desc)) {
384                         /* No security */
385                         return 0;
386                 } else if (mwifiex_is_bss_static_wep(priv, bss_desc)) {
387                         /* Static WEP enabled */
388                         mwifiex_dbg(adapter, INFO,
389                                     "info: Disable 11n in WEP mode.\n");
390                         bss_desc->disable_11n = true;
391                         return 0;
392                 } else if (mwifiex_is_bss_wpa(priv, bss_desc)) {
393                         /* WPA enabled */
394                         if (((priv->adapter->config_bands & BAND_GN ||
395                               priv->adapter->config_bands & BAND_AN) &&
396                              bss_desc->bcn_ht_cap) &&
397                             !mwifiex_is_wpa_oui_present(bss_desc,
398                                                          CIPHER_SUITE_CCMP)) {
399
400                                 if (mwifiex_is_wpa_oui_present
401                                                 (bss_desc, CIPHER_SUITE_TKIP)) {
402                                         mwifiex_dbg(adapter, INFO,
403                                                     "info: Disable 11n if AES\t"
404                                                     "is not supported by AP\n");
405                                         bss_desc->disable_11n = true;
406                                 } else {
407                                         return -1;
408                                 }
409                         }
410                         return 0;
411                 } else if (mwifiex_is_bss_wpa2(priv, bss_desc)) {
412                         /* WPA2 enabled */
413                         if (((priv->adapter->config_bands & BAND_GN ||
414                               priv->adapter->config_bands & BAND_AN) &&
415                              bss_desc->bcn_ht_cap) &&
416                             !mwifiex_is_rsn_oui_present(bss_desc,
417                                                         CIPHER_SUITE_CCMP)) {
418
419                                 if (mwifiex_is_rsn_oui_present
420                                                 (bss_desc, CIPHER_SUITE_TKIP)) {
421                                         mwifiex_dbg(adapter, INFO,
422                                                     "info: Disable 11n if AES\t"
423                                                     "is not supported by AP\n");
424                                         bss_desc->disable_11n = true;
425                                 } else {
426                                         return -1;
427                                 }
428                         }
429                         return 0;
430                 } else if (mwifiex_is_bss_adhoc_aes(priv, bss_desc)) {
431                         /* Ad-hoc AES enabled */
432                         return 0;
433                 } else if (mwifiex_is_bss_dynamic_wep(priv, bss_desc)) {
434                         /* Dynamic WEP enabled */
435                         return 0;
436                 }
437
438                 /* Security doesn't match */
439                 dbg_security_flags(ERROR, "failed", priv, bss_desc);
440                 return -1;
441         }
442
443         /* Mode doesn't match */
444         return -1;
445 }
446
447 /*
448  * This function creates a channel list for the driver to scan, based
449  * on region/band information.
450  *
451  * This routine is used for any scan that is not provided with a
452  * specific channel list to scan.
453  */
454 static int
455 mwifiex_scan_create_channel_list(struct mwifiex_private *priv,
456                                  const struct mwifiex_user_scan_cfg
457                                                         *user_scan_in,
458                                  struct mwifiex_chan_scan_param_set
459                                                         *scan_chan_list,
460                                  u8 filtered_scan)
461 {
462         enum nl80211_band band;
463         struct ieee80211_supported_band *sband;
464         struct ieee80211_channel *ch;
465         struct mwifiex_adapter *adapter = priv->adapter;
466         int chan_idx = 0, i;
467
468         for (band = 0; (band < NUM_NL80211_BANDS) ; band++) {
469
470                 if (!priv->wdev.wiphy->bands[band])
471                         continue;
472
473                 sband = priv->wdev.wiphy->bands[band];
474
475                 for (i = 0; (i < sband->n_channels) ; i++) {
476                         ch = &sband->channels[i];
477                         if (ch->flags & IEEE80211_CHAN_DISABLED)
478                                 continue;
479                         scan_chan_list[chan_idx].radio_type = band;
480
481                         if (user_scan_in &&
482                             user_scan_in->chan_list[0].scan_time)
483                                 scan_chan_list[chan_idx].max_scan_time =
484                                         cpu_to_le16((u16) user_scan_in->
485                                         chan_list[0].scan_time);
486                         else if ((ch->flags & IEEE80211_CHAN_NO_IR) ||
487                                  (ch->flags & IEEE80211_CHAN_RADAR))
488                                 scan_chan_list[chan_idx].max_scan_time =
489                                         cpu_to_le16(adapter->passive_scan_time);
490                         else
491                                 scan_chan_list[chan_idx].max_scan_time =
492                                         cpu_to_le16(adapter->active_scan_time);
493
494                         if (ch->flags & IEEE80211_CHAN_NO_IR)
495                                 scan_chan_list[chan_idx].chan_scan_mode_bitmap
496                                         |= (MWIFIEX_PASSIVE_SCAN |
497                                             MWIFIEX_HIDDEN_SSID_REPORT);
498                         else
499                                 scan_chan_list[chan_idx].chan_scan_mode_bitmap
500                                         &= ~MWIFIEX_PASSIVE_SCAN;
501                         scan_chan_list[chan_idx].chan_number =
502                                                         (u32) ch->hw_value;
503
504                         scan_chan_list[chan_idx].chan_scan_mode_bitmap
505                                         |= MWIFIEX_DISABLE_CHAN_FILT;
506
507                         if (filtered_scan &&
508                             !((ch->flags & IEEE80211_CHAN_NO_IR) ||
509                               (ch->flags & IEEE80211_CHAN_RADAR)))
510                                 scan_chan_list[chan_idx].max_scan_time =
511                                 cpu_to_le16(adapter->specific_scan_time);
512
513                         chan_idx++;
514                 }
515
516         }
517         return chan_idx;
518 }
519
520 /* This function creates a channel list tlv for bgscan config, based
521  * on region/band information.
522  */
523 static int
524 mwifiex_bgscan_create_channel_list(struct mwifiex_private *priv,
525                                    const struct mwifiex_bg_scan_cfg
526                                                 *bgscan_cfg_in,
527                                    struct mwifiex_chan_scan_param_set
528                                                 *scan_chan_list)
529 {
530         enum nl80211_band band;
531         struct ieee80211_supported_band *sband;
532         struct ieee80211_channel *ch;
533         struct mwifiex_adapter *adapter = priv->adapter;
534         int chan_idx = 0, i;
535
536         for (band = 0; (band < NUM_NL80211_BANDS); band++) {
537                 if (!priv->wdev.wiphy->bands[band])
538                         continue;
539
540                 sband = priv->wdev.wiphy->bands[band];
541
542                 for (i = 0; (i < sband->n_channels) ; i++) {
543                         ch = &sband->channels[i];
544                         if (ch->flags & IEEE80211_CHAN_DISABLED)
545                                 continue;
546                         scan_chan_list[chan_idx].radio_type = band;
547
548                         if (bgscan_cfg_in->chan_list[0].scan_time)
549                                 scan_chan_list[chan_idx].max_scan_time =
550                                         cpu_to_le16((u16)bgscan_cfg_in->
551                                         chan_list[0].scan_time);
552                         else if (ch->flags & IEEE80211_CHAN_NO_IR)
553                                 scan_chan_list[chan_idx].max_scan_time =
554                                         cpu_to_le16(adapter->passive_scan_time);
555                         else
556                                 scan_chan_list[chan_idx].max_scan_time =
557                                         cpu_to_le16(adapter->
558                                                     specific_scan_time);
559
560                         if (ch->flags & IEEE80211_CHAN_NO_IR)
561                                 scan_chan_list[chan_idx].chan_scan_mode_bitmap
562                                         |= MWIFIEX_PASSIVE_SCAN;
563                         else
564                                 scan_chan_list[chan_idx].chan_scan_mode_bitmap
565                                         &= ~MWIFIEX_PASSIVE_SCAN;
566
567                         scan_chan_list[chan_idx].chan_number =
568                                                         (u32)ch->hw_value;
569                         chan_idx++;
570                 }
571         }
572         return chan_idx;
573 }
574
575 /* This function appends rate TLV to scan config command. */
576 static int
577 mwifiex_append_rate_tlv(struct mwifiex_private *priv,
578                         struct mwifiex_scan_cmd_config *scan_cfg_out,
579                         u8 radio)
580 {
581         struct mwifiex_ie_types_rates_param_set *rates_tlv;
582         u8 rates[MWIFIEX_SUPPORTED_RATES], *tlv_pos;
583         u32 rates_size;
584
585         memset(rates, 0, sizeof(rates));
586
587         tlv_pos = (u8 *)scan_cfg_out->tlv_buf + scan_cfg_out->tlv_buf_len;
588
589         if (priv->scan_request)
590                 rates_size = mwifiex_get_rates_from_cfg80211(priv, rates,
591                                                              radio);
592         else
593                 rates_size = mwifiex_get_supported_rates(priv, rates);
594
595         mwifiex_dbg(priv->adapter, CMD,
596                     "info: SCAN_CMD: Rates size = %d\n",
597                 rates_size);
598         rates_tlv = (struct mwifiex_ie_types_rates_param_set *)tlv_pos;
599         rates_tlv->header.type = cpu_to_le16(WLAN_EID_SUPP_RATES);
600         rates_tlv->header.len = cpu_to_le16((u16) rates_size);
601         memcpy(rates_tlv->rates, rates, rates_size);
602         scan_cfg_out->tlv_buf_len += sizeof(rates_tlv->header) + rates_size;
603
604         return rates_size;
605 }
606
607 /*
608  * This function constructs and sends multiple scan config commands to
609  * the firmware.
610  *
611  * Previous routines in the code flow have created a scan command configuration
612  * with any requested TLVs.  This function splits the channel TLV into maximum
613  * channels supported per scan lists and sends the portion of the channel TLV,
614  * along with the other TLVs, to the firmware.
615  */
616 static int
617 mwifiex_scan_channel_list(struct mwifiex_private *priv,
618                           u32 max_chan_per_scan, u8 filtered_scan,
619                           struct mwifiex_scan_cmd_config *scan_cfg_out,
620                           struct mwifiex_ie_types_chan_list_param_set
621                           *chan_tlv_out,
622                           struct mwifiex_chan_scan_param_set *scan_chan_list)
623 {
624         struct mwifiex_adapter *adapter = priv->adapter;
625         int ret = 0;
626         struct mwifiex_chan_scan_param_set *tmp_chan_list;
627         struct mwifiex_chan_scan_param_set *start_chan;
628         u32 tlv_idx, rates_size, cmd_no;
629         u32 total_scan_time;
630         u32 done_early;
631         u8 radio_type;
632
633         if (!scan_cfg_out || !chan_tlv_out || !scan_chan_list) {
634                 mwifiex_dbg(priv->adapter, ERROR,
635                             "info: Scan: Null detect: %p, %p, %p\n",
636                             scan_cfg_out, chan_tlv_out, scan_chan_list);
637                 return -1;
638         }
639
640         /* Check csa channel expiry before preparing scan list */
641         mwifiex_11h_get_csa_closed_channel(priv);
642
643         chan_tlv_out->header.type = cpu_to_le16(TLV_TYPE_CHANLIST);
644
645         /* Set the temp channel struct pointer to the start of the desired
646            list */
647         tmp_chan_list = scan_chan_list;
648
649         /* Loop through the desired channel list, sending a new firmware scan
650            commands for each max_chan_per_scan channels (or for 1,6,11
651            individually if configured accordingly) */
652         while (tmp_chan_list->chan_number) {
653
654                 tlv_idx = 0;
655                 total_scan_time = 0;
656                 radio_type = 0;
657                 chan_tlv_out->header.len = 0;
658                 start_chan = tmp_chan_list;
659                 done_early = false;
660
661                 /*
662                  * Construct the Channel TLV for the scan command.  Continue to
663                  * insert channel TLVs until:
664                  *   - the tlv_idx hits the maximum configured per scan command
665                  *   - the next channel to insert is 0 (end of desired channel
666                  *     list)
667                  *   - done_early is set (controlling individual scanning of
668                  *     1,6,11)
669                  */
670                 while (tlv_idx < max_chan_per_scan &&
671                        tmp_chan_list->chan_number && !done_early) {
672
673                         if (tmp_chan_list->chan_number == priv->csa_chan) {
674                                 tmp_chan_list++;
675                                 continue;
676                         }
677
678                         radio_type = tmp_chan_list->radio_type;
679                         mwifiex_dbg(priv->adapter, INFO,
680                                     "info: Scan: Chan(%3d), Radio(%d),\t"
681                                     "Mode(%d, %d), Dur(%d)\n",
682                                     tmp_chan_list->chan_number,
683                                     tmp_chan_list->radio_type,
684                                     tmp_chan_list->chan_scan_mode_bitmap
685                                     & MWIFIEX_PASSIVE_SCAN,
686                                     (tmp_chan_list->chan_scan_mode_bitmap
687                                     & MWIFIEX_DISABLE_CHAN_FILT) >> 1,
688                                     le16_to_cpu(tmp_chan_list->max_scan_time));
689
690                         /* Copy the current channel TLV to the command being
691                            prepared */
692                         memcpy(chan_tlv_out->chan_scan_param + tlv_idx,
693                                tmp_chan_list,
694                                sizeof(chan_tlv_out->chan_scan_param));
695
696                         /* Increment the TLV header length by the size
697                            appended */
698                         le16_unaligned_add_cpu(&chan_tlv_out->header.len,
699                                                sizeof(
700                                                 chan_tlv_out->chan_scan_param));
701
702                         /*
703                          * The tlv buffer length is set to the number of bytes
704                          * of the between the channel tlv pointer and the start
705                          * of the tlv buffer.  This compensates for any TLVs
706                          * that were appended before the channel list.
707                          */
708                         scan_cfg_out->tlv_buf_len = (u32) ((u8 *) chan_tlv_out -
709                                                         scan_cfg_out->tlv_buf);
710
711                         /* Add the size of the channel tlv header and the data
712                            length */
713                         scan_cfg_out->tlv_buf_len +=
714                                 (sizeof(chan_tlv_out->header)
715                                  + le16_to_cpu(chan_tlv_out->header.len));
716
717                         /* Increment the index to the channel tlv we are
718                            constructing */
719                         tlv_idx++;
720
721                         /* Count the total scan time per command */
722                         total_scan_time +=
723                                 le16_to_cpu(tmp_chan_list->max_scan_time);
724
725                         done_early = false;
726
727                         /* Stop the loop if the *current* channel is in the
728                            1,6,11 set and we are not filtering on a BSSID
729                            or SSID. */
730                         if (!filtered_scan &&
731                             (tmp_chan_list->chan_number == 1 ||
732                              tmp_chan_list->chan_number == 6 ||
733                              tmp_chan_list->chan_number == 11))
734                                 done_early = true;
735
736                         /* Increment the tmp pointer to the next channel to
737                            be scanned */
738                         tmp_chan_list++;
739
740                         /* Stop the loop if the *next* channel is in the 1,6,11
741                            set.  This will cause it to be the only channel
742                            scanned on the next interation */
743                         if (!filtered_scan &&
744                             (tmp_chan_list->chan_number == 1 ||
745                              tmp_chan_list->chan_number == 6 ||
746                              tmp_chan_list->chan_number == 11))
747                                 done_early = true;
748                 }
749
750                 /* The total scan time should be less than scan command timeout
751                    value */
752                 if (total_scan_time > MWIFIEX_MAX_TOTAL_SCAN_TIME) {
753                         mwifiex_dbg(priv->adapter, ERROR,
754                                     "total scan time %dms\t"
755                                     "is over limit (%dms), scan skipped\n",
756                                     total_scan_time,
757                                     MWIFIEX_MAX_TOTAL_SCAN_TIME);
758                         ret = -1;
759                         break;
760                 }
761
762                 rates_size = mwifiex_append_rate_tlv(priv, scan_cfg_out,
763                                                      radio_type);
764
765                 priv->adapter->scan_channels = start_chan;
766
767                 /* Send the scan command to the firmware with the specified
768                    cfg */
769                 if (priv->adapter->ext_scan)
770                         cmd_no = HostCmd_CMD_802_11_SCAN_EXT;
771                 else
772                         cmd_no = HostCmd_CMD_802_11_SCAN;
773
774                 ret = mwifiex_send_cmd(priv, cmd_no, HostCmd_ACT_GEN_SET,
775                                        0, scan_cfg_out, false);
776
777                 /* rate IE is updated per scan command but same starting
778                  * pointer is used each time so that rate IE from earlier
779                  * scan_cfg_out->buf is overwritten with new one.
780                  */
781                 scan_cfg_out->tlv_buf_len -=
782                             sizeof(struct mwifiex_ie_types_header) + rates_size;
783
784                 if (ret) {
785                         mwifiex_cancel_pending_scan_cmd(adapter);
786                         break;
787                 }
788         }
789
790         if (ret)
791                 return -1;
792
793         return 0;
794 }
795
796 /*
797  * This function constructs a scan command configuration structure to use
798  * in scan commands.
799  *
800  * Application layer or other functions can invoke network scanning
801  * with a scan configuration supplied in a user scan configuration structure.
802  * This structure is used as the basis of one or many scan command configuration
803  * commands that are sent to the command processing module and eventually to the
804  * firmware.
805  *
806  * This function creates a scan command configuration structure  based on the
807  * following user supplied parameters (if present):
808  *      - SSID filter
809  *      - BSSID filter
810  *      - Number of Probes to be sent
811  *      - Channel list
812  *
813  * If the SSID or BSSID filter is not present, the filter is disabled/cleared.
814  * If the number of probes is not set, adapter default setting is used.
815  */
816 static void
817 mwifiex_config_scan(struct mwifiex_private *priv,
818                     const struct mwifiex_user_scan_cfg *user_scan_in,
819                     struct mwifiex_scan_cmd_config *scan_cfg_out,
820                     struct mwifiex_ie_types_chan_list_param_set **chan_list_out,
821                     struct mwifiex_chan_scan_param_set *scan_chan_list,
822                     u8 *max_chan_per_scan, u8 *filtered_scan,
823                     u8 *scan_current_only)
824 {
825         struct mwifiex_adapter *adapter = priv->adapter;
826         struct mwifiex_ie_types_num_probes *num_probes_tlv;
827         struct mwifiex_ie_types_scan_chan_gap *chan_gap_tlv;
828         struct mwifiex_ie_types_random_mac *random_mac_tlv;
829         struct mwifiex_ie_types_wildcard_ssid_params *wildcard_ssid_tlv;
830         struct mwifiex_ie_types_bssid_list *bssid_tlv;
831         u8 *tlv_pos;
832         u32 num_probes;
833         u32 ssid_len;
834         u32 chan_idx;
835         u32 scan_type;
836         u16 scan_dur;
837         u8 channel;
838         u8 radio_type;
839         int i;
840         u8 ssid_filter;
841         struct mwifiex_ie_types_htcap *ht_cap;
842         struct mwifiex_ie_types_bss_mode *bss_mode;
843         const u8 zero_mac[6] = {0, 0, 0, 0, 0, 0};
844
845         /* The tlv_buf_len is calculated for each scan command.  The TLVs added
846            in this routine will be preserved since the routine that sends the
847            command will append channelTLVs at *chan_list_out.  The difference
848            between the *chan_list_out and the tlv_buf start will be used to
849            calculate the size of anything we add in this routine. */
850         scan_cfg_out->tlv_buf_len = 0;
851
852         /* Running tlv pointer.  Assigned to chan_list_out at end of function
853            so later routines know where channels can be added to the command
854            buf */
855         tlv_pos = scan_cfg_out->tlv_buf;
856
857         /* Initialize the scan as un-filtered; the flag is later set to TRUE
858            below if a SSID or BSSID filter is sent in the command */
859         *filtered_scan = false;
860
861         /* Initialize the scan as not being only on the current channel.  If
862            the channel list is customized, only contains one channel, and is
863            the active channel, this is set true and data flow is not halted. */
864         *scan_current_only = false;
865
866         if (user_scan_in) {
867                 u8 tmpaddr[ETH_ALEN];
868
869                 /* Default the ssid_filter flag to TRUE, set false under
870                    certain wildcard conditions and qualified by the existence
871                    of an SSID list before marking the scan as filtered */
872                 ssid_filter = true;
873
874                 /* Set the BSS type scan filter, use Adapter setting if
875                    unset */
876                 scan_cfg_out->bss_mode =
877                         (u8)(user_scan_in->bss_mode ?: adapter->scan_mode);
878
879                 /* Set the number of probes to send, use Adapter setting
880                    if unset */
881                 num_probes = user_scan_in->num_probes ?: adapter->scan_probes;
882
883                 /*
884                  * Set the BSSID filter to the incoming configuration,
885                  * if non-zero.  If not set, it will remain disabled
886                  * (all zeros).
887                  */
888                 memcpy(scan_cfg_out->specific_bssid,
889                        user_scan_in->specific_bssid,
890                        sizeof(scan_cfg_out->specific_bssid));
891
892                 memcpy(tmpaddr, scan_cfg_out->specific_bssid, ETH_ALEN);
893
894                 if (adapter->ext_scan &&
895                     !is_zero_ether_addr(tmpaddr)) {
896                         bssid_tlv =
897                                 (struct mwifiex_ie_types_bssid_list *)tlv_pos;
898                         bssid_tlv->header.type = cpu_to_le16(TLV_TYPE_BSSID);
899                         bssid_tlv->header.len = cpu_to_le16(ETH_ALEN);
900                         memcpy(bssid_tlv->bssid, user_scan_in->specific_bssid,
901                                ETH_ALEN);
902                         tlv_pos += sizeof(struct mwifiex_ie_types_bssid_list);
903                 }
904
905                 for (i = 0; i < user_scan_in->num_ssids; i++) {
906                         ssid_len = user_scan_in->ssid_list[i].ssid_len;
907
908                         wildcard_ssid_tlv =
909                                 (struct mwifiex_ie_types_wildcard_ssid_params *)
910                                 tlv_pos;
911                         wildcard_ssid_tlv->header.type =
912                                 cpu_to_le16(TLV_TYPE_WILDCARDSSID);
913                         wildcard_ssid_tlv->header.len = cpu_to_le16(
914                                 (u16) (ssid_len + sizeof(wildcard_ssid_tlv->
915                                                          max_ssid_length)));
916
917                         /*
918                          * max_ssid_length = 0 tells firmware to perform
919                          * specific scan for the SSID filled, whereas
920                          * max_ssid_length = IEEE80211_MAX_SSID_LEN is for
921                          * wildcard scan.
922                          */
923                         if (ssid_len)
924                                 wildcard_ssid_tlv->max_ssid_length = 0;
925                         else
926                                 wildcard_ssid_tlv->max_ssid_length =
927                                                         IEEE80211_MAX_SSID_LEN;
928
929                         if (!memcmp(user_scan_in->ssid_list[i].ssid,
930                                     "DIRECT-", 7))
931                                 wildcard_ssid_tlv->max_ssid_length = 0xfe;
932
933                         memcpy(wildcard_ssid_tlv->ssid,
934                                user_scan_in->ssid_list[i].ssid, ssid_len);
935
936                         tlv_pos += (sizeof(wildcard_ssid_tlv->header)
937                                 + le16_to_cpu(wildcard_ssid_tlv->header.len));
938
939                         mwifiex_dbg(adapter, INFO,
940                                     "info: scan: ssid[%d]: %s, %d\n",
941                                     i, wildcard_ssid_tlv->ssid,
942                                     wildcard_ssid_tlv->max_ssid_length);
943
944                         /* Empty wildcard ssid with a maxlen will match many or
945                            potentially all SSIDs (maxlen == 32), therefore do
946                            not treat the scan as
947                            filtered. */
948                         if (!ssid_len && wildcard_ssid_tlv->max_ssid_length)
949                                 ssid_filter = false;
950                 }
951
952                 /*
953                  *  The default number of channels sent in the command is low to
954                  *  ensure the response buffer from the firmware does not
955                  *  truncate scan results.  That is not an issue with an SSID
956                  *  or BSSID filter applied to the scan results in the firmware.
957                  */
958                 memcpy(tmpaddr, scan_cfg_out->specific_bssid, ETH_ALEN);
959                 if ((i && ssid_filter) ||
960                     !is_zero_ether_addr(tmpaddr))
961                         *filtered_scan = true;
962
963                 if (user_scan_in->scan_chan_gap) {
964                         mwifiex_dbg(adapter, INFO,
965                                     "info: scan: channel gap = %d\n",
966                                     user_scan_in->scan_chan_gap);
967                         *max_chan_per_scan =
968                                         MWIFIEX_MAX_CHANNELS_PER_SPECIFIC_SCAN;
969
970                         chan_gap_tlv = (void *)tlv_pos;
971                         chan_gap_tlv->header.type =
972                                          cpu_to_le16(TLV_TYPE_SCAN_CHANNEL_GAP);
973                         chan_gap_tlv->header.len =
974                                     cpu_to_le16(sizeof(chan_gap_tlv->chan_gap));
975                         chan_gap_tlv->chan_gap =
976                                      cpu_to_le16((user_scan_in->scan_chan_gap));
977                         tlv_pos +=
978                                   sizeof(struct mwifiex_ie_types_scan_chan_gap);
979                 }
980
981                 if (!ether_addr_equal(user_scan_in->random_mac, zero_mac)) {
982                         random_mac_tlv = (void *)tlv_pos;
983                         random_mac_tlv->header.type =
984                                          cpu_to_le16(TLV_TYPE_RANDOM_MAC);
985                         random_mac_tlv->header.len =
986                                     cpu_to_le16(sizeof(random_mac_tlv->mac));
987                         ether_addr_copy(random_mac_tlv->mac,
988                                         user_scan_in->random_mac);
989                         tlv_pos +=
990                                   sizeof(struct mwifiex_ie_types_random_mac);
991                 }
992         } else {
993                 scan_cfg_out->bss_mode = (u8) adapter->scan_mode;
994                 num_probes = adapter->scan_probes;
995         }
996
997         /*
998          *  If a specific BSSID or SSID is used, the number of channels in the
999          *  scan command will be increased to the absolute maximum.
1000          */
1001         if (*filtered_scan) {
1002                 *max_chan_per_scan = MWIFIEX_MAX_CHANNELS_PER_SPECIFIC_SCAN;
1003         } else {
1004                 if (!priv->media_connected)
1005                         *max_chan_per_scan = MWIFIEX_DEF_CHANNELS_PER_SCAN_CMD;
1006                 else
1007                         *max_chan_per_scan =
1008                                         MWIFIEX_DEF_CHANNELS_PER_SCAN_CMD / 2;
1009         }
1010
1011         if (adapter->ext_scan) {
1012                 bss_mode = (struct mwifiex_ie_types_bss_mode *)tlv_pos;
1013                 bss_mode->header.type = cpu_to_le16(TLV_TYPE_BSS_MODE);
1014                 bss_mode->header.len = cpu_to_le16(sizeof(bss_mode->bss_mode));
1015                 bss_mode->bss_mode = scan_cfg_out->bss_mode;
1016                 tlv_pos += sizeof(bss_mode->header) +
1017                            le16_to_cpu(bss_mode->header.len);
1018         }
1019
1020         /* If the input config or adapter has the number of Probes set,
1021            add tlv */
1022         if (num_probes) {
1023
1024                 mwifiex_dbg(adapter, INFO,
1025                             "info: scan: num_probes = %d\n",
1026                             num_probes);
1027
1028                 num_probes_tlv = (struct mwifiex_ie_types_num_probes *) tlv_pos;
1029                 num_probes_tlv->header.type = cpu_to_le16(TLV_TYPE_NUMPROBES);
1030                 num_probes_tlv->header.len =
1031                         cpu_to_le16(sizeof(num_probes_tlv->num_probes));
1032                 num_probes_tlv->num_probes = cpu_to_le16((u16) num_probes);
1033
1034                 tlv_pos += sizeof(num_probes_tlv->header) +
1035                         le16_to_cpu(num_probes_tlv->header.len);
1036
1037         }
1038
1039         if (ISSUPP_11NENABLED(priv->adapter->fw_cap_info) &&
1040             (priv->adapter->config_bands & BAND_GN ||
1041              priv->adapter->config_bands & BAND_AN)) {
1042                 ht_cap = (struct mwifiex_ie_types_htcap *) tlv_pos;
1043                 memset(ht_cap, 0, sizeof(struct mwifiex_ie_types_htcap));
1044                 ht_cap->header.type = cpu_to_le16(WLAN_EID_HT_CAPABILITY);
1045                 ht_cap->header.len =
1046                                 cpu_to_le16(sizeof(struct ieee80211_ht_cap));
1047                 radio_type =
1048                         mwifiex_band_to_radio_type(priv->adapter->config_bands);
1049                 mwifiex_fill_cap_info(priv, radio_type, &ht_cap->ht_cap);
1050                 tlv_pos += sizeof(struct mwifiex_ie_types_htcap);
1051         }
1052
1053         /* Append vendor specific IE TLV */
1054         mwifiex_cmd_append_vsie_tlv(priv, MWIFIEX_VSIE_MASK_SCAN, &tlv_pos);
1055
1056         /*
1057          * Set the output for the channel TLV to the address in the tlv buffer
1058          *   past any TLVs that were added in this function (SSID, num_probes).
1059          *   Channel TLVs will be added past this for each scan command,
1060          *   preserving the TLVs that were previously added.
1061          */
1062         *chan_list_out =
1063                 (struct mwifiex_ie_types_chan_list_param_set *) tlv_pos;
1064
1065         if (user_scan_in && user_scan_in->chan_list[0].chan_number) {
1066
1067                 mwifiex_dbg(adapter, INFO,
1068                             "info: Scan: Using supplied channel list\n");
1069
1070                 for (chan_idx = 0;
1071                      chan_idx < MWIFIEX_USER_SCAN_CHAN_MAX &&
1072                      user_scan_in->chan_list[chan_idx].chan_number;
1073                      chan_idx++) {
1074
1075                         channel = user_scan_in->chan_list[chan_idx].chan_number;
1076                         scan_chan_list[chan_idx].chan_number = channel;
1077
1078                         radio_type =
1079                                 user_scan_in->chan_list[chan_idx].radio_type;
1080                         scan_chan_list[chan_idx].radio_type = radio_type;
1081
1082                         scan_type = user_scan_in->chan_list[chan_idx].scan_type;
1083
1084                         if (scan_type == MWIFIEX_SCAN_TYPE_PASSIVE)
1085                                 scan_chan_list[chan_idx].chan_scan_mode_bitmap
1086                                         |= (MWIFIEX_PASSIVE_SCAN |
1087                                             MWIFIEX_HIDDEN_SSID_REPORT);
1088                         else
1089                                 scan_chan_list[chan_idx].chan_scan_mode_bitmap
1090                                         &= ~MWIFIEX_PASSIVE_SCAN;
1091
1092                         scan_chan_list[chan_idx].chan_scan_mode_bitmap
1093                                 |= MWIFIEX_DISABLE_CHAN_FILT;
1094
1095                         if (user_scan_in->chan_list[chan_idx].scan_time) {
1096                                 scan_dur = (u16) user_scan_in->
1097                                         chan_list[chan_idx].scan_time;
1098                         } else {
1099                                 if (scan_type == MWIFIEX_SCAN_TYPE_PASSIVE)
1100                                         scan_dur = adapter->passive_scan_time;
1101                                 else if (*filtered_scan)
1102                                         scan_dur = adapter->specific_scan_time;
1103                                 else
1104                                         scan_dur = adapter->active_scan_time;
1105                         }
1106
1107                         scan_chan_list[chan_idx].min_scan_time =
1108                                 cpu_to_le16(scan_dur);
1109                         scan_chan_list[chan_idx].max_scan_time =
1110                                 cpu_to_le16(scan_dur);
1111                 }
1112
1113                 /* Check if we are only scanning the current channel */
1114                 if ((chan_idx == 1) &&
1115                     (user_scan_in->chan_list[0].chan_number ==
1116                      priv->curr_bss_params.bss_descriptor.channel)) {
1117                         *scan_current_only = true;
1118                         mwifiex_dbg(adapter, INFO,
1119                                     "info: Scan: Scanning current channel only\n");
1120                 }
1121         } else {
1122                 mwifiex_dbg(adapter, INFO,
1123                             "info: Scan: Creating full region channel list\n");
1124                 mwifiex_scan_create_channel_list(priv, user_scan_in,
1125                                                  scan_chan_list,
1126                                                  *filtered_scan);
1127         }
1128
1129 }
1130
1131 /*
1132  * This function inspects the scan response buffer for pointers to
1133  * expected TLVs.
1134  *
1135  * TLVs can be included at the end of the scan response BSS information.
1136  *
1137  * Data in the buffer is parsed pointers to TLVs that can potentially
1138  * be passed back in the response.
1139  */
1140 static void
1141 mwifiex_ret_802_11_scan_get_tlv_ptrs(struct mwifiex_adapter *adapter,
1142                                      struct mwifiex_ie_types_data *tlv,
1143                                      u32 tlv_buf_size, u32 req_tlv_type,
1144                                      struct mwifiex_ie_types_data **tlv_data)
1145 {
1146         struct mwifiex_ie_types_data *current_tlv;
1147         u32 tlv_buf_left;
1148         u32 tlv_type;
1149         u32 tlv_len;
1150
1151         current_tlv = tlv;
1152         tlv_buf_left = tlv_buf_size;
1153         *tlv_data = NULL;
1154
1155         mwifiex_dbg(adapter, INFO,
1156                     "info: SCAN_RESP: tlv_buf_size = %d\n",
1157                     tlv_buf_size);
1158
1159         while (tlv_buf_left >= sizeof(struct mwifiex_ie_types_header)) {
1160
1161                 tlv_type = le16_to_cpu(current_tlv->header.type);
1162                 tlv_len = le16_to_cpu(current_tlv->header.len);
1163
1164                 if (sizeof(tlv->header) + tlv_len > tlv_buf_left) {
1165                         mwifiex_dbg(adapter, ERROR,
1166                                     "SCAN_RESP: TLV buffer corrupt\n");
1167                         break;
1168                 }
1169
1170                 if (req_tlv_type == tlv_type) {
1171                         switch (tlv_type) {
1172                         case TLV_TYPE_TSFTIMESTAMP:
1173                                 mwifiex_dbg(adapter, INFO,
1174                                             "info: SCAN_RESP: TSF\t"
1175                                             "timestamp TLV, len = %d\n",
1176                                             tlv_len);
1177                                 *tlv_data = current_tlv;
1178                                 break;
1179                         case TLV_TYPE_CHANNELBANDLIST:
1180                                 mwifiex_dbg(adapter, INFO,
1181                                             "info: SCAN_RESP: channel\t"
1182                                             "band list TLV, len = %d\n",
1183                                             tlv_len);
1184                                 *tlv_data = current_tlv;
1185                                 break;
1186                         default:
1187                                 mwifiex_dbg(adapter, ERROR,
1188                                             "SCAN_RESP: unhandled TLV = %d\n",
1189                                             tlv_type);
1190                                 /* Give up, this seems corrupted */
1191                                 return;
1192                         }
1193                 }
1194
1195                 if (*tlv_data)
1196                         break;
1197
1198
1199                 tlv_buf_left -= (sizeof(tlv->header) + tlv_len);
1200                 current_tlv =
1201                         (struct mwifiex_ie_types_data *) (current_tlv->data +
1202                                                           tlv_len);
1203
1204         }                       /* while */
1205 }
1206
1207 /*
1208  * This function parses provided beacon buffer and updates
1209  * respective fields in bss descriptor structure.
1210  */
1211 int mwifiex_update_bss_desc_with_ie(struct mwifiex_adapter *adapter,
1212                                     struct mwifiex_bssdescriptor *bss_entry)
1213 {
1214         int ret = 0;
1215         u8 element_id;
1216         struct ieee_types_fh_param_set *fh_param_set;
1217         struct ieee_types_ds_param_set *ds_param_set;
1218         struct ieee_types_cf_param_set *cf_param_set;
1219         struct ieee_types_ibss_param_set *ibss_param_set;
1220         u8 *current_ptr;
1221         u8 *rate;
1222         u8 element_len;
1223         u16 total_ie_len;
1224         u8 bytes_to_copy;
1225         u8 rate_size;
1226         u8 found_data_rate_ie;
1227         u32 bytes_left;
1228         struct ieee_types_vendor_specific *vendor_ie;
1229         const u8 wpa_oui[4] = { 0x00, 0x50, 0xf2, 0x01 };
1230         const u8 wmm_oui[4] = { 0x00, 0x50, 0xf2, 0x02 };
1231
1232         found_data_rate_ie = false;
1233         rate_size = 0;
1234         current_ptr = bss_entry->beacon_buf;
1235         bytes_left = bss_entry->beacon_buf_size;
1236
1237         /* Process variable IE */
1238         while (bytes_left >= 2) {
1239                 element_id = *current_ptr;
1240                 element_len = *(current_ptr + 1);
1241                 total_ie_len = element_len + sizeof(struct ieee_types_header);
1242
1243                 if (bytes_left < total_ie_len) {
1244                         mwifiex_dbg(adapter, ERROR,
1245                                     "err: InterpretIE: in processing\t"
1246                                     "IE, bytes left < IE length\n");
1247                         return -1;
1248                 }
1249                 switch (element_id) {
1250                 case WLAN_EID_SSID:
1251                         if (element_len > IEEE80211_MAX_SSID_LEN)
1252                                 return -EINVAL;
1253                         bss_entry->ssid.ssid_len = element_len;
1254                         memcpy(bss_entry->ssid.ssid, (current_ptr + 2),
1255                                element_len);
1256                         mwifiex_dbg(adapter, INFO,
1257                                     "info: InterpretIE: ssid: %-32s\n",
1258                                     bss_entry->ssid.ssid);
1259                         break;
1260
1261                 case WLAN_EID_SUPP_RATES:
1262                         if (element_len > MWIFIEX_SUPPORTED_RATES)
1263                                 return -EINVAL;
1264                         memcpy(bss_entry->data_rates, current_ptr + 2,
1265                                element_len);
1266                         memcpy(bss_entry->supported_rates, current_ptr + 2,
1267                                element_len);
1268                         rate_size = element_len;
1269                         found_data_rate_ie = true;
1270                         break;
1271
1272                 case WLAN_EID_FH_PARAMS:
1273                         if (element_len + 2 < sizeof(*fh_param_set))
1274                                 return -EINVAL;
1275                         fh_param_set =
1276                                 (struct ieee_types_fh_param_set *) current_ptr;
1277                         memcpy(&bss_entry->phy_param_set.fh_param_set,
1278                                fh_param_set,
1279                                sizeof(struct ieee_types_fh_param_set));
1280                         break;
1281
1282                 case WLAN_EID_DS_PARAMS:
1283                         if (element_len + 2 < sizeof(*ds_param_set))
1284                                 return -EINVAL;
1285                         ds_param_set =
1286                                 (struct ieee_types_ds_param_set *) current_ptr;
1287
1288                         bss_entry->channel = ds_param_set->current_chan;
1289
1290                         memcpy(&bss_entry->phy_param_set.ds_param_set,
1291                                ds_param_set,
1292                                sizeof(struct ieee_types_ds_param_set));
1293                         break;
1294
1295                 case WLAN_EID_CF_PARAMS:
1296                         if (element_len + 2 < sizeof(*cf_param_set))
1297                                 return -EINVAL;
1298                         cf_param_set =
1299                                 (struct ieee_types_cf_param_set *) current_ptr;
1300                         memcpy(&bss_entry->ss_param_set.cf_param_set,
1301                                cf_param_set,
1302                                sizeof(struct ieee_types_cf_param_set));
1303                         break;
1304
1305                 case WLAN_EID_IBSS_PARAMS:
1306                         if (element_len + 2 < sizeof(*ibss_param_set))
1307                                 return -EINVAL;
1308                         ibss_param_set =
1309                                 (struct ieee_types_ibss_param_set *)
1310                                 current_ptr;
1311                         memcpy(&bss_entry->ss_param_set.ibss_param_set,
1312                                ibss_param_set,
1313                                sizeof(struct ieee_types_ibss_param_set));
1314                         break;
1315
1316                 case WLAN_EID_ERP_INFO:
1317                         if (!element_len)
1318                                 return -EINVAL;
1319                         bss_entry->erp_flags = *(current_ptr + 2);
1320                         break;
1321
1322                 case WLAN_EID_PWR_CONSTRAINT:
1323                         if (!element_len)
1324                                 return -EINVAL;
1325                         bss_entry->local_constraint = *(current_ptr + 2);
1326                         bss_entry->sensed_11h = true;
1327                         break;
1328
1329                 case WLAN_EID_CHANNEL_SWITCH:
1330                         bss_entry->chan_sw_ie_present = true;
1331                         /* fall through */
1332                 case WLAN_EID_PWR_CAPABILITY:
1333                 case WLAN_EID_TPC_REPORT:
1334                 case WLAN_EID_QUIET:
1335                         bss_entry->sensed_11h = true;
1336                     break;
1337
1338                 case WLAN_EID_EXT_SUPP_RATES:
1339                         /*
1340                          * Only process extended supported rate
1341                          * if data rate is already found.
1342                          * Data rate IE should come before
1343                          * extended supported rate IE
1344                          */
1345                         if (found_data_rate_ie) {
1346                                 if ((element_len + rate_size) >
1347                                     MWIFIEX_SUPPORTED_RATES)
1348                                         bytes_to_copy =
1349                                                 (MWIFIEX_SUPPORTED_RATES -
1350                                                  rate_size);
1351                                 else
1352                                         bytes_to_copy = element_len;
1353
1354                                 rate = (u8 *) bss_entry->data_rates;
1355                                 rate += rate_size;
1356                                 memcpy(rate, current_ptr + 2, bytes_to_copy);
1357
1358                                 rate = (u8 *) bss_entry->supported_rates;
1359                                 rate += rate_size;
1360                                 memcpy(rate, current_ptr + 2, bytes_to_copy);
1361                         }
1362                         break;
1363
1364                 case WLAN_EID_VENDOR_SPECIFIC:
1365                         vendor_ie = (struct ieee_types_vendor_specific *)
1366                                         current_ptr;
1367
1368                         /* 802.11 requires at least 3-byte OUI. */
1369                         if (element_len < sizeof(vendor_ie->vend_hdr.oui.oui))
1370                                 return -EINVAL;
1371
1372                         /* Not long enough for a match? Skip it. */
1373                         if (element_len < sizeof(wpa_oui))
1374                                 break;
1375
1376                         if (!memcmp(&vendor_ie->vend_hdr.oui, wpa_oui,
1377                                     sizeof(wpa_oui))) {
1378                                 bss_entry->bcn_wpa_ie =
1379                                         (struct ieee_types_vendor_specific *)
1380                                         current_ptr;
1381                                 bss_entry->wpa_offset = (u16)
1382                                         (current_ptr - bss_entry->beacon_buf);
1383                         } else if (!memcmp(&vendor_ie->vend_hdr.oui, wmm_oui,
1384                                     sizeof(wmm_oui))) {
1385                                 if (total_ie_len ==
1386                                     sizeof(struct ieee_types_wmm_parameter) ||
1387                                     total_ie_len ==
1388                                     sizeof(struct ieee_types_wmm_info))
1389                                         /*
1390                                          * Only accept and copy the WMM IE if
1391                                          * it matches the size expected for the
1392                                          * WMM Info IE or the WMM Parameter IE.
1393                                          */
1394                                         memcpy((u8 *) &bss_entry->wmm_ie,
1395                                                current_ptr, total_ie_len);
1396                         }
1397                         break;
1398                 case WLAN_EID_RSN:
1399                         bss_entry->bcn_rsn_ie =
1400                                 (struct ieee_types_generic *) current_ptr;
1401                         bss_entry->rsn_offset = (u16) (current_ptr -
1402                                                         bss_entry->beacon_buf);
1403                         break;
1404                 case WLAN_EID_BSS_AC_ACCESS_DELAY:
1405                         bss_entry->bcn_wapi_ie =
1406                                 (struct ieee_types_generic *) current_ptr;
1407                         bss_entry->wapi_offset = (u16) (current_ptr -
1408                                                         bss_entry->beacon_buf);
1409                         break;
1410                 case WLAN_EID_HT_CAPABILITY:
1411                         bss_entry->bcn_ht_cap = (struct ieee80211_ht_cap *)
1412                                         (current_ptr +
1413                                         sizeof(struct ieee_types_header));
1414                         bss_entry->ht_cap_offset = (u16) (current_ptr +
1415                                         sizeof(struct ieee_types_header) -
1416                                         bss_entry->beacon_buf);
1417                         break;
1418                 case WLAN_EID_HT_OPERATION:
1419                         bss_entry->bcn_ht_oper =
1420                                 (struct ieee80211_ht_operation *)(current_ptr +
1421                                         sizeof(struct ieee_types_header));
1422                         bss_entry->ht_info_offset = (u16) (current_ptr +
1423                                         sizeof(struct ieee_types_header) -
1424                                         bss_entry->beacon_buf);
1425                         break;
1426                 case WLAN_EID_VHT_CAPABILITY:
1427                         bss_entry->disable_11ac = false;
1428                         bss_entry->bcn_vht_cap =
1429                                 (void *)(current_ptr +
1430                                          sizeof(struct ieee_types_header));
1431                         bss_entry->vht_cap_offset =
1432                                         (u16)((u8 *)bss_entry->bcn_vht_cap -
1433                                               bss_entry->beacon_buf);
1434                         break;
1435                 case WLAN_EID_VHT_OPERATION:
1436                         bss_entry->bcn_vht_oper =
1437                                 (void *)(current_ptr +
1438                                          sizeof(struct ieee_types_header));
1439                         bss_entry->vht_info_offset =
1440                                         (u16)((u8 *)bss_entry->bcn_vht_oper -
1441                                               bss_entry->beacon_buf);
1442                         break;
1443                 case WLAN_EID_BSS_COEX_2040:
1444                         bss_entry->bcn_bss_co_2040 = current_ptr;
1445                         bss_entry->bss_co_2040_offset =
1446                                 (u16) (current_ptr - bss_entry->beacon_buf);
1447                         break;
1448                 case WLAN_EID_EXT_CAPABILITY:
1449                         bss_entry->bcn_ext_cap = current_ptr;
1450                         bss_entry->ext_cap_offset =
1451                                 (u16) (current_ptr - bss_entry->beacon_buf);
1452                         break;
1453                 case WLAN_EID_OPMODE_NOTIF:
1454                         bss_entry->oper_mode = (void *)current_ptr;
1455                         bss_entry->oper_mode_offset =
1456                                         (u16)((u8 *)bss_entry->oper_mode -
1457                                               bss_entry->beacon_buf);
1458                         break;
1459                 default:
1460                         break;
1461                 }
1462
1463                 current_ptr += element_len + 2;
1464
1465                 /* Need to account for IE ID and IE Len */
1466                 bytes_left -= (element_len + 2);
1467
1468         }       /* while (bytes_left > 2) */
1469         return ret;
1470 }
1471
1472 /*
1473  * This function converts radio type scan parameter to a band configuration
1474  * to be used in join command.
1475  */
1476 static u8
1477 mwifiex_radio_type_to_band(u8 radio_type)
1478 {
1479         switch (radio_type) {
1480         case HostCmd_SCAN_RADIO_TYPE_A:
1481                 return BAND_A;
1482         case HostCmd_SCAN_RADIO_TYPE_BG:
1483         default:
1484                 return BAND_G;
1485         }
1486 }
1487
1488 /*
1489  * This is an internal function used to start a scan based on an input
1490  * configuration.
1491  *
1492  * This uses the input user scan configuration information when provided in
1493  * order to send the appropriate scan commands to firmware to populate or
1494  * update the internal driver scan table.
1495  */
1496 int mwifiex_scan_networks(struct mwifiex_private *priv,
1497                           const struct mwifiex_user_scan_cfg *user_scan_in)
1498 {
1499         int ret;
1500         struct mwifiex_adapter *adapter = priv->adapter;
1501         struct cmd_ctrl_node *cmd_node;
1502         union mwifiex_scan_cmd_config_tlv *scan_cfg_out;
1503         struct mwifiex_ie_types_chan_list_param_set *chan_list_out;
1504         struct mwifiex_chan_scan_param_set *scan_chan_list;
1505         u8 filtered_scan;
1506         u8 scan_current_chan_only;
1507         u8 max_chan_per_scan;
1508         unsigned long flags;
1509
1510         if (adapter->scan_processing) {
1511                 mwifiex_dbg(adapter, WARN,
1512                             "cmd: Scan already in process...\n");
1513                 return -EBUSY;
1514         }
1515
1516         if (priv->scan_block) {
1517                 mwifiex_dbg(adapter, WARN,
1518                             "cmd: Scan is blocked during association...\n");
1519                 return -EBUSY;
1520         }
1521
1522         if (test_bit(MWIFIEX_SURPRISE_REMOVED, &adapter->work_flags) ||
1523             test_bit(MWIFIEX_IS_CMD_TIMEDOUT, &adapter->work_flags)) {
1524                 mwifiex_dbg(adapter, ERROR,
1525                             "Ignore scan. Card removed or firmware in bad state\n");
1526                 return -EFAULT;
1527         }
1528
1529         spin_lock_irqsave(&adapter->mwifiex_cmd_lock, flags);
1530         adapter->scan_processing = true;
1531         spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, flags);
1532
1533         scan_cfg_out = kzalloc(sizeof(union mwifiex_scan_cmd_config_tlv),
1534                                GFP_KERNEL);
1535         if (!scan_cfg_out) {
1536                 ret = -ENOMEM;
1537                 goto done;
1538         }
1539
1540         scan_chan_list = kcalloc(MWIFIEX_USER_SCAN_CHAN_MAX,
1541                                  sizeof(struct mwifiex_chan_scan_param_set),
1542                                  GFP_KERNEL);
1543         if (!scan_chan_list) {
1544                 kfree(scan_cfg_out);
1545                 ret = -ENOMEM;
1546                 goto done;
1547         }
1548
1549         mwifiex_config_scan(priv, user_scan_in, &scan_cfg_out->config,
1550                             &chan_list_out, scan_chan_list, &max_chan_per_scan,
1551                             &filtered_scan, &scan_current_chan_only);
1552
1553         ret = mwifiex_scan_channel_list(priv, max_chan_per_scan, filtered_scan,
1554                                         &scan_cfg_out->config, chan_list_out,
1555                                         scan_chan_list);
1556
1557         /* Get scan command from scan_pending_q and put to cmd_pending_q */
1558         if (!ret) {
1559                 spin_lock_irqsave(&adapter->scan_pending_q_lock, flags);
1560                 if (!list_empty(&adapter->scan_pending_q)) {
1561                         cmd_node = list_first_entry(&adapter->scan_pending_q,
1562                                                     struct cmd_ctrl_node, list);
1563                         list_del(&cmd_node->list);
1564                         spin_unlock_irqrestore(&adapter->scan_pending_q_lock,
1565                                                flags);
1566                         mwifiex_insert_cmd_to_pending_q(adapter, cmd_node);
1567                         queue_work(adapter->workqueue, &adapter->main_work);
1568
1569                         /* Perform internal scan synchronously */
1570                         if (!priv->scan_request) {
1571                                 mwifiex_dbg(adapter, INFO,
1572                                             "wait internal scan\n");
1573                                 mwifiex_wait_queue_complete(adapter, cmd_node);
1574                         }
1575                 } else {
1576                         spin_unlock_irqrestore(&adapter->scan_pending_q_lock,
1577                                                flags);
1578                 }
1579         }
1580
1581         kfree(scan_cfg_out);
1582         kfree(scan_chan_list);
1583 done:
1584         if (ret) {
1585                 spin_lock_irqsave(&adapter->mwifiex_cmd_lock, flags);
1586                 adapter->scan_processing = false;
1587                 spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, flags);
1588         }
1589         return ret;
1590 }
1591
1592 /*
1593  * This function prepares a scan command to be sent to the firmware.
1594  *
1595  * This uses the scan command configuration sent to the command processing
1596  * module in command preparation stage to configure a scan command structure
1597  * to send to firmware.
1598  *
1599  * The fixed fields specifying the BSS type and BSSID filters as well as a
1600  * variable number/length of TLVs are sent in the command to firmware.
1601  *
1602  * Preparation also includes -
1603  *      - Setting command ID, and proper size
1604  *      - Ensuring correct endian-ness
1605  */
1606 int mwifiex_cmd_802_11_scan(struct host_cmd_ds_command *cmd,
1607                             struct mwifiex_scan_cmd_config *scan_cfg)
1608 {
1609         struct host_cmd_ds_802_11_scan *scan_cmd = &cmd->params.scan;
1610
1611         /* Set fixed field variables in scan command */
1612         scan_cmd->bss_mode = scan_cfg->bss_mode;
1613         memcpy(scan_cmd->bssid, scan_cfg->specific_bssid,
1614                sizeof(scan_cmd->bssid));
1615         memcpy(scan_cmd->tlv_buffer, scan_cfg->tlv_buf, scan_cfg->tlv_buf_len);
1616
1617         cmd->command = cpu_to_le16(HostCmd_CMD_802_11_SCAN);
1618
1619         /* Size is equal to the sizeof(fixed portions) + the TLV len + header */
1620         cmd->size = cpu_to_le16((u16) (sizeof(scan_cmd->bss_mode)
1621                                           + sizeof(scan_cmd->bssid)
1622                                           + scan_cfg->tlv_buf_len + S_DS_GEN));
1623
1624         return 0;
1625 }
1626
1627 /*
1628  * This function checks compatibility of requested network with current
1629  * driver settings.
1630  */
1631 int mwifiex_check_network_compatibility(struct mwifiex_private *priv,
1632                                         struct mwifiex_bssdescriptor *bss_desc)
1633 {
1634         int ret = -1;
1635
1636         if (!bss_desc)
1637                 return -1;
1638
1639         if ((mwifiex_get_cfp(priv, (u8) bss_desc->bss_band,
1640                              (u16) bss_desc->channel, 0))) {
1641                 switch (priv->bss_mode) {
1642                 case NL80211_IFTYPE_STATION:
1643                 case NL80211_IFTYPE_ADHOC:
1644                         ret = mwifiex_is_network_compatible(priv, bss_desc,
1645                                                             priv->bss_mode);
1646                         if (ret)
1647                                 mwifiex_dbg(priv->adapter, ERROR,
1648                                             "Incompatible network settings\n");
1649                         break;
1650                 default:
1651                         ret = 0;
1652                 }
1653         }
1654
1655         return ret;
1656 }
1657
1658 /* This function checks if SSID string contains all zeroes or length is zero */
1659 static bool mwifiex_is_hidden_ssid(struct cfg80211_ssid *ssid)
1660 {
1661         int idx;
1662
1663         for (idx = 0; idx < ssid->ssid_len; idx++) {
1664                 if (ssid->ssid[idx])
1665                         return false;
1666         }
1667
1668         return true;
1669 }
1670
1671 /* This function checks if any hidden SSID found in passive scan channels
1672  * and save those channels for specific SSID active scan
1673  */
1674 static int mwifiex_save_hidden_ssid_channels(struct mwifiex_private *priv,
1675                                              struct cfg80211_bss *bss)
1676 {
1677         struct mwifiex_bssdescriptor *bss_desc;
1678         int ret;
1679         int chid;
1680
1681         /* Allocate and fill new bss descriptor */
1682         bss_desc = kzalloc(sizeof(*bss_desc), GFP_KERNEL);
1683         if (!bss_desc)
1684                 return -ENOMEM;
1685
1686         ret = mwifiex_fill_new_bss_desc(priv, bss, bss_desc);
1687         if (ret)
1688                 goto done;
1689
1690         if (mwifiex_is_hidden_ssid(&bss_desc->ssid)) {
1691                 mwifiex_dbg(priv->adapter, INFO, "found hidden SSID\n");
1692                 for (chid = 0 ; chid < MWIFIEX_USER_SCAN_CHAN_MAX; chid++) {
1693                         if (priv->hidden_chan[chid].chan_number ==
1694                             bss->channel->hw_value)
1695                                 break;
1696
1697                         if (!priv->hidden_chan[chid].chan_number) {
1698                                 priv->hidden_chan[chid].chan_number =
1699                                         bss->channel->hw_value;
1700                                 priv->hidden_chan[chid].radio_type =
1701                                         bss->channel->band;
1702                                 priv->hidden_chan[chid].scan_type =
1703                                         MWIFIEX_SCAN_TYPE_ACTIVE;
1704                                 break;
1705                         }
1706                 }
1707         }
1708
1709 done:
1710         /* beacon_ie buffer was allocated in function
1711          * mwifiex_fill_new_bss_desc(). Free it now.
1712          */
1713         kfree(bss_desc->beacon_buf);
1714         kfree(bss_desc);
1715         return 0;
1716 }
1717
1718 static int mwifiex_update_curr_bss_params(struct mwifiex_private *priv,
1719                                           struct cfg80211_bss *bss)
1720 {
1721         struct mwifiex_bssdescriptor *bss_desc;
1722         int ret;
1723         unsigned long flags;
1724
1725         /* Allocate and fill new bss descriptor */
1726         bss_desc = kzalloc(sizeof(struct mwifiex_bssdescriptor), GFP_KERNEL);
1727         if (!bss_desc)
1728                 return -ENOMEM;
1729
1730         ret = mwifiex_fill_new_bss_desc(priv, bss, bss_desc);
1731         if (ret)
1732                 goto done;
1733
1734         ret = mwifiex_check_network_compatibility(priv, bss_desc);
1735         if (ret)
1736                 goto done;
1737
1738         spin_lock_irqsave(&priv->curr_bcn_buf_lock, flags);
1739         /* Make a copy of current BSSID descriptor */
1740         memcpy(&priv->curr_bss_params.bss_descriptor, bss_desc,
1741                sizeof(priv->curr_bss_params.bss_descriptor));
1742
1743         /* The contents of beacon_ie will be copied to its own buffer
1744          * in mwifiex_save_curr_bcn()
1745          */
1746         mwifiex_save_curr_bcn(priv);
1747         spin_unlock_irqrestore(&priv->curr_bcn_buf_lock, flags);
1748
1749 done:
1750         /* beacon_ie buffer was allocated in function
1751          * mwifiex_fill_new_bss_desc(). Free it now.
1752          */
1753         kfree(bss_desc->beacon_buf);
1754         kfree(bss_desc);
1755         return 0;
1756 }
1757
1758 static int
1759 mwifiex_parse_single_response_buf(struct mwifiex_private *priv, u8 **bss_info,
1760                                   u32 *bytes_left, u64 fw_tsf, u8 *radio_type,
1761                                   bool ext_scan, s32 rssi_val)
1762 {
1763         struct mwifiex_adapter *adapter = priv->adapter;
1764         struct mwifiex_chan_freq_power *cfp;
1765         struct cfg80211_bss *bss;
1766         u8 bssid[ETH_ALEN];
1767         s32 rssi;
1768         const u8 *ie_buf;
1769         size_t ie_len;
1770         u16 channel = 0;
1771         u16 beacon_size = 0;
1772         u32 curr_bcn_bytes;
1773         u32 freq;
1774         u16 beacon_period;
1775         u16 cap_info_bitmap;
1776         u8 *current_ptr;
1777         u64 timestamp;
1778         struct mwifiex_fixed_bcn_param *bcn_param;
1779         struct mwifiex_bss_priv *bss_priv;
1780
1781         if (*bytes_left >= sizeof(beacon_size)) {
1782                 /* Extract & convert beacon size from command buffer */
1783                 beacon_size = get_unaligned_le16((*bss_info));
1784                 *bytes_left -= sizeof(beacon_size);
1785                 *bss_info += sizeof(beacon_size);
1786         }
1787
1788         if (!beacon_size || beacon_size > *bytes_left) {
1789                 *bss_info += *bytes_left;
1790                 *bytes_left = 0;
1791                 return -EFAULT;
1792         }
1793
1794         /* Initialize the current working beacon pointer for this BSS
1795          * iteration
1796          */
1797         current_ptr = *bss_info;
1798
1799         /* Advance the return beacon pointer past the current beacon */
1800         *bss_info += beacon_size;
1801         *bytes_left -= beacon_size;
1802
1803         curr_bcn_bytes = beacon_size;
1804
1805         /* First 5 fields are bssid, RSSI(for legacy scan only),
1806          * time stamp, beacon interval, and capability information
1807          */
1808         if (curr_bcn_bytes < ETH_ALEN + sizeof(u8) +
1809             sizeof(struct mwifiex_fixed_bcn_param)) {
1810                 mwifiex_dbg(adapter, ERROR,
1811                             "InterpretIE: not enough bytes left\n");
1812                 return -EFAULT;
1813         }
1814
1815         memcpy(bssid, current_ptr, ETH_ALEN);
1816         current_ptr += ETH_ALEN;
1817         curr_bcn_bytes -= ETH_ALEN;
1818
1819         if (!ext_scan) {
1820                 rssi = (s32) *current_ptr;
1821                 rssi = (-rssi) * 100;           /* Convert dBm to mBm */
1822                 current_ptr += sizeof(u8);
1823                 curr_bcn_bytes -= sizeof(u8);
1824                 mwifiex_dbg(adapter, INFO,
1825                             "info: InterpretIE: RSSI=%d\n", rssi);
1826         } else {
1827                 rssi = rssi_val;
1828         }
1829
1830         bcn_param = (struct mwifiex_fixed_bcn_param *)current_ptr;
1831         current_ptr += sizeof(*bcn_param);
1832         curr_bcn_bytes -= sizeof(*bcn_param);
1833
1834         timestamp = le64_to_cpu(bcn_param->timestamp);
1835         beacon_period = le16_to_cpu(bcn_param->beacon_period);
1836
1837         cap_info_bitmap = le16_to_cpu(bcn_param->cap_info_bitmap);
1838         mwifiex_dbg(adapter, INFO,
1839                     "info: InterpretIE: capabilities=0x%X\n",
1840                     cap_info_bitmap);
1841
1842         /* Rest of the current buffer are IE's */
1843         ie_buf = current_ptr;
1844         ie_len = curr_bcn_bytes;
1845         mwifiex_dbg(adapter, INFO,
1846                     "info: InterpretIE: IELength for this AP = %d\n",
1847                     curr_bcn_bytes);
1848
1849         while (curr_bcn_bytes >= sizeof(struct ieee_types_header)) {
1850                 u8 element_id, element_len;
1851
1852                 element_id = *current_ptr;
1853                 element_len = *(current_ptr + 1);
1854                 if (curr_bcn_bytes < element_len +
1855                                 sizeof(struct ieee_types_header)) {
1856                         mwifiex_dbg(adapter, ERROR,
1857                                     "%s: bytes left < IE length\n", __func__);
1858                         return -EFAULT;
1859                 }
1860                 if (element_id == WLAN_EID_DS_PARAMS) {
1861                         channel = *(current_ptr +
1862                                     sizeof(struct ieee_types_header));
1863                         break;
1864                 }
1865
1866                 current_ptr += element_len + sizeof(struct ieee_types_header);
1867                 curr_bcn_bytes -= element_len +
1868                                         sizeof(struct ieee_types_header);
1869         }
1870
1871         if (channel) {
1872                 struct ieee80211_channel *chan;
1873                 u8 band;
1874
1875                 /* Skip entry if on csa closed channel */
1876                 if (channel == priv->csa_chan) {
1877                         mwifiex_dbg(adapter, WARN,
1878                                     "Dropping entry on csa closed channel\n");
1879                         return 0;
1880                 }
1881
1882                 band = BAND_G;
1883                 if (radio_type)
1884                         band = mwifiex_radio_type_to_band(*radio_type &
1885                                                           (BIT(0) | BIT(1)));
1886
1887                 cfp = mwifiex_get_cfp(priv, band, channel, 0);
1888
1889                 freq = cfp ? cfp->freq : 0;
1890
1891                 chan = ieee80211_get_channel(priv->wdev.wiphy, freq);
1892
1893                 if (chan && !(chan->flags & IEEE80211_CHAN_DISABLED)) {
1894                         bss = cfg80211_inform_bss(priv->wdev.wiphy,
1895                                             chan, CFG80211_BSS_FTYPE_UNKNOWN,
1896                                             bssid, timestamp,
1897                                             cap_info_bitmap, beacon_period,
1898                                             ie_buf, ie_len, rssi, GFP_ATOMIC);
1899                         if (bss) {
1900                                 bss_priv = (struct mwifiex_bss_priv *)bss->priv;
1901                                 bss_priv->band = band;
1902                                 bss_priv->fw_tsf = fw_tsf;
1903                                 if (priv->media_connected &&
1904                                     !memcmp(bssid, priv->curr_bss_params.
1905                                             bss_descriptor.mac_address,
1906                                             ETH_ALEN))
1907                                         mwifiex_update_curr_bss_params(priv,
1908                                                                        bss);
1909
1910                                 if ((chan->flags & IEEE80211_CHAN_RADAR) ||
1911                                     (chan->flags & IEEE80211_CHAN_NO_IR)) {
1912                                         mwifiex_dbg(adapter, INFO,
1913                                                     "radar or passive channel %d\n",
1914                                                     channel);
1915                                         mwifiex_save_hidden_ssid_channels(priv,
1916                                                                           bss);
1917                                 }
1918
1919                                 cfg80211_put_bss(priv->wdev.wiphy, bss);
1920                         }
1921                 }
1922         } else {
1923                 mwifiex_dbg(adapter, WARN, "missing BSS channel IE\n");
1924         }
1925
1926         return 0;
1927 }
1928
1929 static void mwifiex_complete_scan(struct mwifiex_private *priv)
1930 {
1931         struct mwifiex_adapter *adapter = priv->adapter;
1932
1933         adapter->survey_idx = 0;
1934         if (adapter->curr_cmd->wait_q_enabled) {
1935                 adapter->cmd_wait_q.status = 0;
1936                 if (!priv->scan_request) {
1937                         mwifiex_dbg(adapter, INFO,
1938                                     "complete internal scan\n");
1939                         mwifiex_complete_cmd(adapter, adapter->curr_cmd);
1940                 }
1941         }
1942 }
1943
1944 /* This function checks if any hidden SSID found in passive scan channels
1945  * and do specific SSID active scan for those channels
1946  */
1947 static int
1948 mwifiex_active_scan_req_for_passive_chan(struct mwifiex_private *priv)
1949 {
1950         int ret;
1951         struct mwifiex_adapter *adapter = priv->adapter;
1952         u8 id = 0;
1953         struct mwifiex_user_scan_cfg  *user_scan_cfg;
1954
1955         if (adapter->active_scan_triggered || !priv->scan_request ||
1956             priv->scan_aborting) {
1957                 adapter->active_scan_triggered = false;
1958                 return 0;
1959         }
1960
1961         if (!priv->hidden_chan[0].chan_number) {
1962                 mwifiex_dbg(adapter, INFO, "No BSS with hidden SSID found on DFS channels\n");
1963                 return 0;
1964         }
1965         user_scan_cfg = kzalloc(sizeof(*user_scan_cfg), GFP_KERNEL);
1966
1967         if (!user_scan_cfg)
1968                 return -ENOMEM;
1969
1970         for (id = 0; id < MWIFIEX_USER_SCAN_CHAN_MAX; id++) {
1971                 if (!priv->hidden_chan[id].chan_number)
1972                         break;
1973                 memcpy(&user_scan_cfg->chan_list[id],
1974                        &priv->hidden_chan[id],
1975                        sizeof(struct mwifiex_user_scan_chan));
1976         }
1977
1978         adapter->active_scan_triggered = true;
1979         if (priv->scan_request->flags & NL80211_SCAN_FLAG_RANDOM_ADDR)
1980                 ether_addr_copy(user_scan_cfg->random_mac,
1981                                 priv->scan_request->mac_addr);
1982         user_scan_cfg->num_ssids = priv->scan_request->n_ssids;
1983         user_scan_cfg->ssid_list = priv->scan_request->ssids;
1984
1985         ret = mwifiex_scan_networks(priv, user_scan_cfg);
1986         kfree(user_scan_cfg);
1987
1988         memset(&priv->hidden_chan, 0, sizeof(priv->hidden_chan));
1989
1990         if (ret) {
1991                 dev_err(priv->adapter->dev, "scan failed: %d\n", ret);
1992                 return ret;
1993         }
1994
1995         return 0;
1996 }
1997 static void mwifiex_check_next_scan_command(struct mwifiex_private *priv)
1998 {
1999         struct mwifiex_adapter *adapter = priv->adapter;
2000         struct cmd_ctrl_node *cmd_node;
2001         unsigned long flags;
2002
2003         spin_lock_irqsave(&adapter->scan_pending_q_lock, flags);
2004         if (list_empty(&adapter->scan_pending_q)) {
2005                 spin_unlock_irqrestore(&adapter->scan_pending_q_lock, flags);
2006
2007                 spin_lock_irqsave(&adapter->mwifiex_cmd_lock, flags);
2008                 adapter->scan_processing = false;
2009                 spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, flags);
2010
2011                 mwifiex_active_scan_req_for_passive_chan(priv);
2012
2013                 if (!adapter->ext_scan)
2014                         mwifiex_complete_scan(priv);
2015
2016                 if (priv->scan_request) {
2017                         struct cfg80211_scan_info info = {
2018                                 .aborted = false,
2019                         };
2020
2021                         mwifiex_dbg(adapter, INFO,
2022                                     "info: notifying scan done\n");
2023                         cfg80211_scan_done(priv->scan_request, &info);
2024                         priv->scan_request = NULL;
2025                         priv->scan_aborting = false;
2026                 } else {
2027                         priv->scan_aborting = false;
2028                         mwifiex_dbg(adapter, INFO,
2029                                     "info: scan already aborted\n");
2030                 }
2031         } else if ((priv->scan_aborting && !priv->scan_request) ||
2032                    priv->scan_block) {
2033                 spin_unlock_irqrestore(&adapter->scan_pending_q_lock, flags);
2034
2035                 mwifiex_cancel_pending_scan_cmd(adapter);
2036
2037                 spin_lock_irqsave(&adapter->mwifiex_cmd_lock, flags);
2038                 adapter->scan_processing = false;
2039                 spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, flags);
2040
2041                 if (!adapter->active_scan_triggered) {
2042                         if (priv->scan_request) {
2043                                 struct cfg80211_scan_info info = {
2044                                         .aborted = true,
2045                                 };
2046
2047                                 mwifiex_dbg(adapter, INFO,
2048                                             "info: aborting scan\n");
2049                                 cfg80211_scan_done(priv->scan_request, &info);
2050                                 priv->scan_request = NULL;
2051                                 priv->scan_aborting = false;
2052                         } else {
2053                                 priv->scan_aborting = false;
2054                                 mwifiex_dbg(adapter, INFO,
2055                                             "info: scan already aborted\n");
2056                         }
2057                 }
2058         } else {
2059                 /* Get scan command from scan_pending_q and put to
2060                  * cmd_pending_q
2061                  */
2062                 cmd_node = list_first_entry(&adapter->scan_pending_q,
2063                                             struct cmd_ctrl_node, list);
2064                 list_del(&cmd_node->list);
2065                 spin_unlock_irqrestore(&adapter->scan_pending_q_lock, flags);
2066                 mwifiex_insert_cmd_to_pending_q(adapter, cmd_node);
2067         }
2068
2069         return;
2070 }
2071
2072 void mwifiex_cancel_scan(struct mwifiex_adapter *adapter)
2073 {
2074         struct mwifiex_private *priv;
2075         unsigned long cmd_flags;
2076         int i;
2077
2078         mwifiex_cancel_pending_scan_cmd(adapter);
2079
2080         if (adapter->scan_processing) {
2081                 spin_lock_irqsave(&adapter->mwifiex_cmd_lock, cmd_flags);
2082                 adapter->scan_processing = false;
2083                 spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, cmd_flags);
2084                 for (i = 0; i < adapter->priv_num; i++) {
2085                         priv = adapter->priv[i];
2086                         if (!priv)
2087                                 continue;
2088                         if (priv->scan_request) {
2089                                 struct cfg80211_scan_info info = {
2090                                         .aborted = true,
2091                                 };
2092
2093                                 mwifiex_dbg(adapter, INFO,
2094                                             "info: aborting scan\n");
2095                                 cfg80211_scan_done(priv->scan_request, &info);
2096                                 priv->scan_request = NULL;
2097                                 priv->scan_aborting = false;
2098                         }
2099                 }
2100         }
2101 }
2102
2103 /*
2104  * This function handles the command response of scan.
2105  *
2106  * The response buffer for the scan command has the following
2107  * memory layout:
2108  *
2109  *      .-------------------------------------------------------------.
2110  *      |  Header (4 * sizeof(t_u16)):  Standard command response hdr |
2111  *      .-------------------------------------------------------------.
2112  *      |  BufSize (t_u16) : sizeof the BSS Description data          |
2113  *      .-------------------------------------------------------------.
2114  *      |  NumOfSet (t_u8) : Number of BSS Descs returned             |
2115  *      .-------------------------------------------------------------.
2116  *      |  BSSDescription data (variable, size given in BufSize)      |
2117  *      .-------------------------------------------------------------.
2118  *      |  TLV data (variable, size calculated using Header->Size,    |
2119  *      |            BufSize and sizeof the fixed fields above)       |
2120  *      .-------------------------------------------------------------.
2121  */
2122 int mwifiex_ret_802_11_scan(struct mwifiex_private *priv,
2123                             struct host_cmd_ds_command *resp)
2124 {
2125         int ret = 0;
2126         struct mwifiex_adapter *adapter = priv->adapter;
2127         struct host_cmd_ds_802_11_scan_rsp *scan_rsp;
2128         struct mwifiex_ie_types_data *tlv_data;
2129         struct mwifiex_ie_types_tsf_timestamp *tsf_tlv;
2130         u8 *bss_info;
2131         u32 scan_resp_size;
2132         u32 bytes_left;
2133         u32 idx;
2134         u32 tlv_buf_size;
2135         struct mwifiex_ie_types_chan_band_list_param_set *chan_band_tlv;
2136         struct chan_band_param_set *chan_band;
2137         u8 is_bgscan_resp;
2138         __le64 fw_tsf = 0;
2139         u8 *radio_type;
2140         struct cfg80211_wowlan_nd_match *pmatch;
2141         struct cfg80211_sched_scan_request *nd_config = NULL;
2142
2143         is_bgscan_resp = (le16_to_cpu(resp->command)
2144                           == HostCmd_CMD_802_11_BG_SCAN_QUERY);
2145         if (is_bgscan_resp)
2146                 scan_rsp = &resp->params.bg_scan_query_resp.scan_resp;
2147         else
2148                 scan_rsp = &resp->params.scan_resp;
2149
2150
2151         if (scan_rsp->number_of_sets > MWIFIEX_MAX_AP) {
2152                 mwifiex_dbg(adapter, ERROR,
2153                             "SCAN_RESP: too many AP returned (%d)\n",
2154                             scan_rsp->number_of_sets);
2155                 ret = -1;
2156                 goto check_next_scan;
2157         }
2158
2159         /* Check csa channel expiry before parsing scan response */
2160         mwifiex_11h_get_csa_closed_channel(priv);
2161
2162         bytes_left = le16_to_cpu(scan_rsp->bss_descript_size);
2163         mwifiex_dbg(adapter, INFO,
2164                     "info: SCAN_RESP: bss_descript_size %d\n",
2165                     bytes_left);
2166
2167         scan_resp_size = le16_to_cpu(resp->size);
2168
2169         mwifiex_dbg(adapter, INFO,
2170                     "info: SCAN_RESP: returned %d APs before parsing\n",
2171                     scan_rsp->number_of_sets);
2172
2173         bss_info = scan_rsp->bss_desc_and_tlv_buffer;
2174
2175         /*
2176          * The size of the TLV buffer is equal to the entire command response
2177          *   size (scan_resp_size) minus the fixed fields (sizeof()'s), the
2178          *   BSS Descriptions (bss_descript_size as bytesLef) and the command
2179          *   response header (S_DS_GEN)
2180          */
2181         tlv_buf_size = scan_resp_size - (bytes_left
2182                                          + sizeof(scan_rsp->bss_descript_size)
2183                                          + sizeof(scan_rsp->number_of_sets)
2184                                          + S_DS_GEN);
2185
2186         tlv_data = (struct mwifiex_ie_types_data *) (scan_rsp->
2187                                                  bss_desc_and_tlv_buffer +
2188                                                  bytes_left);
2189
2190         /* Search the TLV buffer space in the scan response for any valid
2191            TLVs */
2192         mwifiex_ret_802_11_scan_get_tlv_ptrs(adapter, tlv_data, tlv_buf_size,
2193                                              TLV_TYPE_TSFTIMESTAMP,
2194                                              (struct mwifiex_ie_types_data **)
2195                                              &tsf_tlv);
2196
2197         /* Search the TLV buffer space in the scan response for any valid
2198            TLVs */
2199         mwifiex_ret_802_11_scan_get_tlv_ptrs(adapter, tlv_data, tlv_buf_size,
2200                                              TLV_TYPE_CHANNELBANDLIST,
2201                                              (struct mwifiex_ie_types_data **)
2202                                              &chan_band_tlv);
2203
2204 #ifdef CONFIG_PM
2205         if (priv->wdev.wiphy->wowlan_config)
2206                 nd_config = priv->wdev.wiphy->wowlan_config->nd_config;
2207 #endif
2208
2209         if (nd_config) {
2210                 adapter->nd_info =
2211                         kzalloc(sizeof(struct cfg80211_wowlan_nd_match) +
2212                                 sizeof(struct cfg80211_wowlan_nd_match *) *
2213                                 scan_rsp->number_of_sets, GFP_ATOMIC);
2214
2215                 if (adapter->nd_info)
2216                         adapter->nd_info->n_matches = scan_rsp->number_of_sets;
2217         }
2218
2219         for (idx = 0; idx < scan_rsp->number_of_sets && bytes_left; idx++) {
2220                 /*
2221                  * If the TSF TLV was appended to the scan results, save this
2222                  * entry's TSF value in the fw_tsf field. It is the firmware's
2223                  * TSF value at the time the beacon or probe response was
2224                  * received.
2225                  */
2226                 if (tsf_tlv)
2227                         memcpy(&fw_tsf, &tsf_tlv->tsf_data[idx * TSF_DATA_SIZE],
2228                                sizeof(fw_tsf));
2229
2230                 if (chan_band_tlv) {
2231                         chan_band = &chan_band_tlv->chan_band_param[idx];
2232                         radio_type = &chan_band->radio_type;
2233                 } else {
2234                         radio_type = NULL;
2235                 }
2236
2237                 if (chan_band_tlv && adapter->nd_info) {
2238                         adapter->nd_info->matches[idx] =
2239                                 kzalloc(sizeof(*pmatch) + sizeof(u32),
2240                                         GFP_ATOMIC);
2241
2242                         pmatch = adapter->nd_info->matches[idx];
2243
2244                         if (pmatch) {
2245                                 pmatch->n_channels = 1;
2246                                 pmatch->channels[0] = chan_band->chan_number;
2247                         }
2248                 }
2249
2250                 ret = mwifiex_parse_single_response_buf(priv, &bss_info,
2251                                                         &bytes_left,
2252                                                         le64_to_cpu(fw_tsf),
2253                                                         radio_type, false, 0);
2254                 if (ret)
2255                         goto check_next_scan;
2256         }
2257
2258 check_next_scan:
2259         mwifiex_check_next_scan_command(priv);
2260         return ret;
2261 }
2262
2263 /*
2264  * This function prepares an extended scan command to be sent to the firmware
2265  *
2266  * This uses the scan command configuration sent to the command processing
2267  * module in command preparation stage to configure a extended scan command
2268  * structure to send to firmware.
2269  */
2270 int mwifiex_cmd_802_11_scan_ext(struct mwifiex_private *priv,
2271                                 struct host_cmd_ds_command *cmd,
2272                                 void *data_buf)
2273 {
2274         struct host_cmd_ds_802_11_scan_ext *ext_scan = &cmd->params.ext_scan;
2275         struct mwifiex_scan_cmd_config *scan_cfg = data_buf;
2276
2277         memcpy(ext_scan->tlv_buffer, scan_cfg->tlv_buf, scan_cfg->tlv_buf_len);
2278
2279         cmd->command = cpu_to_le16(HostCmd_CMD_802_11_SCAN_EXT);
2280
2281         /* Size is equal to the sizeof(fixed portions) + the TLV len + header */
2282         cmd->size = cpu_to_le16((u16)(sizeof(ext_scan->reserved)
2283                                       + scan_cfg->tlv_buf_len + S_DS_GEN));
2284
2285         return 0;
2286 }
2287
2288 /* This function prepares an background scan config command to be sent
2289  * to the firmware
2290  */
2291 int mwifiex_cmd_802_11_bg_scan_config(struct mwifiex_private *priv,
2292                                       struct host_cmd_ds_command *cmd,
2293                                       void *data_buf)
2294 {
2295         struct host_cmd_ds_802_11_bg_scan_config *bgscan_config =
2296                                         &cmd->params.bg_scan_config;
2297         struct mwifiex_bg_scan_cfg *bgscan_cfg_in = data_buf;
2298         u8 *tlv_pos = bgscan_config->tlv;
2299         u8 num_probes;
2300         u32 ssid_len, chan_idx, scan_type, scan_dur, chan_num;
2301         int i;
2302         struct mwifiex_ie_types_num_probes *num_probes_tlv;
2303         struct mwifiex_ie_types_repeat_count *repeat_count_tlv;
2304         struct mwifiex_ie_types_min_rssi_threshold *rssi_threshold_tlv;
2305         struct mwifiex_ie_types_bgscan_start_later *start_later_tlv;
2306         struct mwifiex_ie_types_wildcard_ssid_params *wildcard_ssid_tlv;
2307         struct mwifiex_ie_types_chan_list_param_set *chan_list_tlv;
2308         struct mwifiex_chan_scan_param_set *temp_chan;
2309
2310         cmd->command = cpu_to_le16(HostCmd_CMD_802_11_BG_SCAN_CONFIG);
2311         cmd->size = cpu_to_le16(sizeof(*bgscan_config) + S_DS_GEN);
2312
2313         bgscan_config->action = cpu_to_le16(bgscan_cfg_in->action);
2314         bgscan_config->enable = bgscan_cfg_in->enable;
2315         bgscan_config->bss_type = bgscan_cfg_in->bss_type;
2316         bgscan_config->scan_interval =
2317                 cpu_to_le32(bgscan_cfg_in->scan_interval);
2318         bgscan_config->report_condition =
2319                 cpu_to_le32(bgscan_cfg_in->report_condition);
2320
2321         /*  stop sched scan  */
2322         if (!bgscan_config->enable)
2323                 return 0;
2324
2325         bgscan_config->chan_per_scan = bgscan_cfg_in->chan_per_scan;
2326
2327         num_probes = (bgscan_cfg_in->num_probes ? bgscan_cfg_in->
2328                       num_probes : priv->adapter->scan_probes);
2329
2330         if (num_probes) {
2331                 num_probes_tlv = (struct mwifiex_ie_types_num_probes *)tlv_pos;
2332                 num_probes_tlv->header.type = cpu_to_le16(TLV_TYPE_NUMPROBES);
2333                 num_probes_tlv->header.len =
2334                         cpu_to_le16(sizeof(num_probes_tlv->num_probes));
2335                 num_probes_tlv->num_probes = cpu_to_le16((u16)num_probes);
2336
2337                 tlv_pos += sizeof(num_probes_tlv->header) +
2338                         le16_to_cpu(num_probes_tlv->header.len);
2339         }
2340
2341         if (bgscan_cfg_in->repeat_count) {
2342                 repeat_count_tlv =
2343                         (struct mwifiex_ie_types_repeat_count *)tlv_pos;
2344                 repeat_count_tlv->header.type =
2345                         cpu_to_le16(TLV_TYPE_REPEAT_COUNT);
2346                 repeat_count_tlv->header.len =
2347                         cpu_to_le16(sizeof(repeat_count_tlv->repeat_count));
2348                 repeat_count_tlv->repeat_count =
2349                         cpu_to_le16(bgscan_cfg_in->repeat_count);
2350
2351                 tlv_pos += sizeof(repeat_count_tlv->header) +
2352                         le16_to_cpu(repeat_count_tlv->header.len);
2353         }
2354
2355         if (bgscan_cfg_in->rssi_threshold) {
2356                 rssi_threshold_tlv =
2357                         (struct mwifiex_ie_types_min_rssi_threshold *)tlv_pos;
2358                 rssi_threshold_tlv->header.type =
2359                         cpu_to_le16(TLV_TYPE_RSSI_LOW);
2360                 rssi_threshold_tlv->header.len =
2361                         cpu_to_le16(sizeof(rssi_threshold_tlv->rssi_threshold));
2362                 rssi_threshold_tlv->rssi_threshold =
2363                         cpu_to_le16(bgscan_cfg_in->rssi_threshold);
2364
2365                 tlv_pos += sizeof(rssi_threshold_tlv->header) +
2366                         le16_to_cpu(rssi_threshold_tlv->header.len);
2367         }
2368
2369         for (i = 0; i < bgscan_cfg_in->num_ssids; i++) {
2370                 ssid_len = bgscan_cfg_in->ssid_list[i].ssid.ssid_len;
2371
2372                 wildcard_ssid_tlv =
2373                         (struct mwifiex_ie_types_wildcard_ssid_params *)tlv_pos;
2374                 wildcard_ssid_tlv->header.type =
2375                                 cpu_to_le16(TLV_TYPE_WILDCARDSSID);
2376                 wildcard_ssid_tlv->header.len = cpu_to_le16(
2377                                 (u16)(ssid_len + sizeof(wildcard_ssid_tlv->
2378                                                          max_ssid_length)));
2379
2380                 /* max_ssid_length = 0 tells firmware to perform
2381                  * specific scan for the SSID filled, whereas
2382                  * max_ssid_length = IEEE80211_MAX_SSID_LEN is for
2383                  * wildcard scan.
2384                  */
2385                 if (ssid_len)
2386                         wildcard_ssid_tlv->max_ssid_length = 0;
2387                 else
2388                         wildcard_ssid_tlv->max_ssid_length =
2389                                                 IEEE80211_MAX_SSID_LEN;
2390
2391                 memcpy(wildcard_ssid_tlv->ssid,
2392                        bgscan_cfg_in->ssid_list[i].ssid.ssid, ssid_len);
2393
2394                 tlv_pos += (sizeof(wildcard_ssid_tlv->header)
2395                                 + le16_to_cpu(wildcard_ssid_tlv->header.len));
2396         }
2397
2398         chan_list_tlv = (struct mwifiex_ie_types_chan_list_param_set *)tlv_pos;
2399
2400         if (bgscan_cfg_in->chan_list[0].chan_number) {
2401                 dev_dbg(priv->adapter->dev, "info: bgscan: Using supplied channel list\n");
2402
2403                 chan_list_tlv->header.type = cpu_to_le16(TLV_TYPE_CHANLIST);
2404
2405                 for (chan_idx = 0;
2406                      chan_idx < MWIFIEX_BG_SCAN_CHAN_MAX &&
2407                      bgscan_cfg_in->chan_list[chan_idx].chan_number;
2408                      chan_idx++) {
2409                         temp_chan = chan_list_tlv->chan_scan_param + chan_idx;
2410
2411                         /* Increment the TLV header length by size appended */
2412                         le16_unaligned_add_cpu(&chan_list_tlv->header.len,
2413                                                sizeof(
2414                                                chan_list_tlv->chan_scan_param));
2415
2416                         temp_chan->chan_number =
2417                                 bgscan_cfg_in->chan_list[chan_idx].chan_number;
2418                         temp_chan->radio_type =
2419                                 bgscan_cfg_in->chan_list[chan_idx].radio_type;
2420
2421                         scan_type =
2422                                 bgscan_cfg_in->chan_list[chan_idx].scan_type;
2423
2424                         if (scan_type == MWIFIEX_SCAN_TYPE_PASSIVE)
2425                                 temp_chan->chan_scan_mode_bitmap
2426                                         |= MWIFIEX_PASSIVE_SCAN;
2427                         else
2428                                 temp_chan->chan_scan_mode_bitmap
2429                                         &= ~MWIFIEX_PASSIVE_SCAN;
2430
2431                         if (bgscan_cfg_in->chan_list[chan_idx].scan_time) {
2432                                 scan_dur = (u16)bgscan_cfg_in->
2433                                         chan_list[chan_idx].scan_time;
2434                         } else {
2435                                 scan_dur = (scan_type ==
2436                                             MWIFIEX_SCAN_TYPE_PASSIVE) ?
2437                                             priv->adapter->passive_scan_time :
2438                                             priv->adapter->specific_scan_time;
2439                         }
2440
2441                         temp_chan->min_scan_time = cpu_to_le16(scan_dur);
2442                         temp_chan->max_scan_time = cpu_to_le16(scan_dur);
2443                 }
2444         } else {
2445                 dev_dbg(priv->adapter->dev,
2446                         "info: bgscan: Creating full region channel list\n");
2447                 chan_num =
2448                         mwifiex_bgscan_create_channel_list(priv, bgscan_cfg_in,
2449                                                            chan_list_tlv->
2450                                                            chan_scan_param);
2451                 le16_unaligned_add_cpu(&chan_list_tlv->header.len,
2452                                        chan_num *
2453                              sizeof(chan_list_tlv->chan_scan_param[0]));
2454         }
2455
2456         tlv_pos += (sizeof(chan_list_tlv->header)
2457                         + le16_to_cpu(chan_list_tlv->header.len));
2458
2459         if (bgscan_cfg_in->start_later) {
2460                 start_later_tlv =
2461                         (struct mwifiex_ie_types_bgscan_start_later *)tlv_pos;
2462                 start_later_tlv->header.type =
2463                         cpu_to_le16(TLV_TYPE_BGSCAN_START_LATER);
2464                 start_later_tlv->header.len =
2465                         cpu_to_le16(sizeof(start_later_tlv->start_later));
2466                 start_later_tlv->start_later =
2467                         cpu_to_le16(bgscan_cfg_in->start_later);
2468
2469                 tlv_pos += sizeof(start_later_tlv->header) +
2470                         le16_to_cpu(start_later_tlv->header.len);
2471         }
2472
2473         /* Append vendor specific IE TLV */
2474         mwifiex_cmd_append_vsie_tlv(priv, MWIFIEX_VSIE_MASK_BGSCAN, &tlv_pos);
2475
2476         le16_unaligned_add_cpu(&cmd->size, tlv_pos - bgscan_config->tlv);
2477
2478         return 0;
2479 }
2480
2481 int mwifiex_stop_bg_scan(struct mwifiex_private *priv)
2482 {
2483         struct mwifiex_bg_scan_cfg *bgscan_cfg;
2484
2485         if (!priv->sched_scanning) {
2486                 dev_dbg(priv->adapter->dev, "bgscan already stopped!\n");
2487                 return 0;
2488         }
2489
2490         bgscan_cfg = kzalloc(sizeof(*bgscan_cfg), GFP_KERNEL);
2491         if (!bgscan_cfg)
2492                 return -ENOMEM;
2493
2494         bgscan_cfg->bss_type = MWIFIEX_BSS_MODE_INFRA;
2495         bgscan_cfg->action = MWIFIEX_BGSCAN_ACT_SET;
2496         bgscan_cfg->enable = false;
2497
2498         if (mwifiex_send_cmd(priv, HostCmd_CMD_802_11_BG_SCAN_CONFIG,
2499                              HostCmd_ACT_GEN_SET, 0, bgscan_cfg, true)) {
2500                 kfree(bgscan_cfg);
2501                 return -EFAULT;
2502         }
2503
2504         kfree(bgscan_cfg);
2505         priv->sched_scanning = false;
2506
2507         return 0;
2508 }
2509
2510 static void
2511 mwifiex_update_chan_statistics(struct mwifiex_private *priv,
2512                                struct mwifiex_ietypes_chanstats *tlv_stat)
2513 {
2514         struct mwifiex_adapter *adapter = priv->adapter;
2515         u8 i, num_chan;
2516         struct mwifiex_fw_chan_stats *fw_chan_stats;
2517         struct mwifiex_chan_stats chan_stats;
2518
2519         fw_chan_stats = (void *)((u8 *)tlv_stat +
2520                               sizeof(struct mwifiex_ie_types_header));
2521         num_chan = le16_to_cpu(tlv_stat->header.len) /
2522                                               sizeof(struct mwifiex_chan_stats);
2523
2524         for (i = 0 ; i < num_chan; i++) {
2525                 if (adapter->survey_idx >= adapter->num_in_chan_stats) {
2526                         mwifiex_dbg(adapter, WARN,
2527                                     "FW reported too many channel results (max %d)\n",
2528                                     adapter->num_in_chan_stats);
2529                         return;
2530                 }
2531                 chan_stats.chan_num = fw_chan_stats->chan_num;
2532                 chan_stats.bandcfg = fw_chan_stats->bandcfg;
2533                 chan_stats.flags = fw_chan_stats->flags;
2534                 chan_stats.noise = fw_chan_stats->noise;
2535                 chan_stats.total_bss = le16_to_cpu(fw_chan_stats->total_bss);
2536                 chan_stats.cca_scan_dur =
2537                                        le16_to_cpu(fw_chan_stats->cca_scan_dur);
2538                 chan_stats.cca_busy_dur =
2539                                        le16_to_cpu(fw_chan_stats->cca_busy_dur);
2540                 mwifiex_dbg(adapter, INFO,
2541                             "chan=%d, noise=%d, total_network=%d scan_duration=%d, busy_duration=%d\n",
2542                             chan_stats.chan_num,
2543                             chan_stats.noise,
2544                             chan_stats.total_bss,
2545                             chan_stats.cca_scan_dur,
2546                             chan_stats.cca_busy_dur);
2547                 memcpy(&adapter->chan_stats[adapter->survey_idx++], &chan_stats,
2548                        sizeof(struct mwifiex_chan_stats));
2549                 fw_chan_stats++;
2550         }
2551 }
2552
2553 /* This function handles the command response of extended scan */
2554 int mwifiex_ret_802_11_scan_ext(struct mwifiex_private *priv,
2555                                 struct host_cmd_ds_command *resp)
2556 {
2557         struct mwifiex_adapter *adapter = priv->adapter;
2558         struct host_cmd_ds_802_11_scan_ext *ext_scan_resp;
2559         struct mwifiex_ie_types_header *tlv;
2560         struct mwifiex_ietypes_chanstats *tlv_stat;
2561         u16 buf_left, type, len;
2562
2563         struct host_cmd_ds_command *cmd_ptr;
2564         struct cmd_ctrl_node *cmd_node;
2565         unsigned long cmd_flags, scan_flags;
2566         bool complete_scan = false;
2567
2568         mwifiex_dbg(adapter, INFO, "info: EXT scan returns successfully\n");
2569
2570         ext_scan_resp = &resp->params.ext_scan;
2571
2572         tlv = (void *)ext_scan_resp->tlv_buffer;
2573         buf_left = le16_to_cpu(resp->size) - (sizeof(*ext_scan_resp) + S_DS_GEN
2574                                               - 1);
2575
2576         while (buf_left >= sizeof(struct mwifiex_ie_types_header)) {
2577                 type = le16_to_cpu(tlv->type);
2578                 len = le16_to_cpu(tlv->len);
2579
2580                 if (buf_left < (sizeof(struct mwifiex_ie_types_header) + len)) {
2581                         mwifiex_dbg(adapter, ERROR,
2582                                     "error processing scan response TLVs");
2583                         break;
2584                 }
2585
2586                 switch (type) {
2587                 case TLV_TYPE_CHANNEL_STATS:
2588                         tlv_stat = (void *)tlv;
2589                         mwifiex_update_chan_statistics(priv, tlv_stat);
2590                         break;
2591                 default:
2592                         break;
2593                 }
2594
2595                 buf_left -= len + sizeof(struct mwifiex_ie_types_header);
2596                 tlv = (void *)((u8 *)tlv + len +
2597                                sizeof(struct mwifiex_ie_types_header));
2598         }
2599
2600         spin_lock_irqsave(&adapter->cmd_pending_q_lock, cmd_flags);
2601         spin_lock_irqsave(&adapter->scan_pending_q_lock, scan_flags);
2602         if (list_empty(&adapter->scan_pending_q)) {
2603                 complete_scan = true;
2604                 list_for_each_entry(cmd_node, &adapter->cmd_pending_q, list) {
2605                         cmd_ptr = (void *)cmd_node->cmd_skb->data;
2606                         if (le16_to_cpu(cmd_ptr->command) ==
2607                             HostCmd_CMD_802_11_SCAN_EXT) {
2608                                 mwifiex_dbg(adapter, INFO,
2609                                             "Scan pending in command pending list");
2610                                 complete_scan = false;
2611                                 break;
2612                         }
2613                 }
2614         }
2615         spin_unlock_irqrestore(&adapter->scan_pending_q_lock, scan_flags);
2616         spin_unlock_irqrestore(&adapter->cmd_pending_q_lock, cmd_flags);
2617
2618         if (complete_scan)
2619                 mwifiex_complete_scan(priv);
2620
2621         return 0;
2622 }
2623
2624 /* This function This function handles the event extended scan report. It
2625  * parses extended scan results and informs to cfg80211 stack.
2626  */
2627 int mwifiex_handle_event_ext_scan_report(struct mwifiex_private *priv,
2628                                          void *buf)
2629 {
2630         int ret = 0;
2631         struct mwifiex_adapter *adapter = priv->adapter;
2632         u8 *bss_info;
2633         u32 bytes_left, bytes_left_for_tlv, idx;
2634         u16 type, len;
2635         struct mwifiex_ie_types_data *tlv;
2636         struct mwifiex_ie_types_bss_scan_rsp *scan_rsp_tlv;
2637         struct mwifiex_ie_types_bss_scan_info *scan_info_tlv;
2638         u8 *radio_type;
2639         u64 fw_tsf = 0;
2640         s32 rssi = 0;
2641         struct mwifiex_event_scan_result *event_scan = buf;
2642         u8 num_of_set = event_scan->num_of_set;
2643         u8 *scan_resp = buf + sizeof(struct mwifiex_event_scan_result);
2644         u16 scan_resp_size = le16_to_cpu(event_scan->buf_size);
2645
2646         if (num_of_set > MWIFIEX_MAX_AP) {
2647                 mwifiex_dbg(adapter, ERROR,
2648                             "EXT_SCAN: Invalid number of AP returned (%d)!!\n",
2649                             num_of_set);
2650                 ret = -1;
2651                 goto check_next_scan;
2652         }
2653
2654         bytes_left = scan_resp_size;
2655         mwifiex_dbg(adapter, INFO,
2656                     "EXT_SCAN: size %d, returned %d APs...",
2657                     scan_resp_size, num_of_set);
2658         mwifiex_dbg_dump(adapter, CMD_D, "EXT_SCAN buffer:", buf,
2659                          scan_resp_size +
2660                          sizeof(struct mwifiex_event_scan_result));
2661
2662         tlv = (struct mwifiex_ie_types_data *)scan_resp;
2663
2664         for (idx = 0; idx < num_of_set && bytes_left; idx++) {
2665                 type = le16_to_cpu(tlv->header.type);
2666                 len = le16_to_cpu(tlv->header.len);
2667                 if (bytes_left < sizeof(struct mwifiex_ie_types_header) + len) {
2668                         mwifiex_dbg(adapter, ERROR,
2669                                     "EXT_SCAN: Error bytes left < TLV length\n");
2670                         break;
2671                 }
2672                 scan_rsp_tlv = NULL;
2673                 scan_info_tlv = NULL;
2674                 bytes_left_for_tlv = bytes_left;
2675
2676                 /* BSS response TLV with beacon or probe response buffer
2677                  * at the initial position of each descriptor
2678                  */
2679                 if (type != TLV_TYPE_BSS_SCAN_RSP)
2680                         break;
2681
2682                 bss_info = (u8 *)tlv;
2683                 scan_rsp_tlv = (struct mwifiex_ie_types_bss_scan_rsp *)tlv;
2684                 tlv = (struct mwifiex_ie_types_data *)(tlv->data + len);
2685                 bytes_left_for_tlv -=
2686                                 (len + sizeof(struct mwifiex_ie_types_header));
2687
2688                 while (bytes_left_for_tlv >=
2689                        sizeof(struct mwifiex_ie_types_header) &&
2690                        le16_to_cpu(tlv->header.type) != TLV_TYPE_BSS_SCAN_RSP) {
2691                         type = le16_to_cpu(tlv->header.type);
2692                         len = le16_to_cpu(tlv->header.len);
2693                         if (bytes_left_for_tlv <
2694                             sizeof(struct mwifiex_ie_types_header) + len) {
2695                                 mwifiex_dbg(adapter, ERROR,
2696                                             "EXT_SCAN: Error in processing TLV,\t"
2697                                             "bytes left < TLV length\n");
2698                                 scan_rsp_tlv = NULL;
2699                                 bytes_left_for_tlv = 0;
2700                                 continue;
2701                         }
2702                         switch (type) {
2703                         case TLV_TYPE_BSS_SCAN_INFO:
2704                                 scan_info_tlv =
2705                                   (struct mwifiex_ie_types_bss_scan_info *)tlv;
2706                                 if (len !=
2707                                  sizeof(struct mwifiex_ie_types_bss_scan_info) -
2708                                  sizeof(struct mwifiex_ie_types_header)) {
2709                                         bytes_left_for_tlv = 0;
2710                                         continue;
2711                                 }
2712                                 break;
2713                         default:
2714                                 break;
2715                         }
2716                         tlv = (struct mwifiex_ie_types_data *)(tlv->data + len);
2717                         bytes_left -=
2718                                 (len + sizeof(struct mwifiex_ie_types_header));
2719                         bytes_left_for_tlv -=
2720                                 (len + sizeof(struct mwifiex_ie_types_header));
2721                 }
2722
2723                 if (!scan_rsp_tlv)
2724                         break;
2725
2726                 /* Advance pointer to the beacon buffer length and
2727                  * update the bytes count so that the function
2728                  * wlan_interpret_bss_desc_with_ie() can handle the
2729                  * scan buffer withut any change
2730                  */
2731                 bss_info += sizeof(u16);
2732                 bytes_left -= sizeof(u16);
2733
2734                 if (scan_info_tlv) {
2735                         rssi = (s32)(s16)(le16_to_cpu(scan_info_tlv->rssi));
2736                         rssi *= 100;           /* Convert dBm to mBm */
2737                         mwifiex_dbg(adapter, INFO,
2738                                     "info: InterpretIE: RSSI=%d\n", rssi);
2739                         fw_tsf = le64_to_cpu(scan_info_tlv->tsf);
2740                         radio_type = &scan_info_tlv->radio_type;
2741                 } else {
2742                         radio_type = NULL;
2743                 }
2744                 ret = mwifiex_parse_single_response_buf(priv, &bss_info,
2745                                                         &bytes_left, fw_tsf,
2746                                                         radio_type, true, rssi);
2747                 if (ret)
2748                         goto check_next_scan;
2749         }
2750
2751 check_next_scan:
2752         if (!event_scan->more_event)
2753                 mwifiex_check_next_scan_command(priv);
2754
2755         return ret;
2756 }
2757
2758 /*
2759  * This function prepares command for background scan query.
2760  *
2761  * Preparation includes -
2762  *      - Setting command ID and proper size
2763  *      - Setting background scan flush parameter
2764  *      - Ensuring correct endian-ness
2765  */
2766 int mwifiex_cmd_802_11_bg_scan_query(struct host_cmd_ds_command *cmd)
2767 {
2768         struct host_cmd_ds_802_11_bg_scan_query *bg_query =
2769                 &cmd->params.bg_scan_query;
2770
2771         cmd->command = cpu_to_le16(HostCmd_CMD_802_11_BG_SCAN_QUERY);
2772         cmd->size = cpu_to_le16(sizeof(struct host_cmd_ds_802_11_bg_scan_query)
2773                                 + S_DS_GEN);
2774
2775         bg_query->flush = 1;
2776
2777         return 0;
2778 }
2779
2780 /*
2781  * This function inserts scan command node to the scan pending queue.
2782  */
2783 void
2784 mwifiex_queue_scan_cmd(struct mwifiex_private *priv,
2785                        struct cmd_ctrl_node *cmd_node)
2786 {
2787         struct mwifiex_adapter *adapter = priv->adapter;
2788         unsigned long flags;
2789
2790         cmd_node->wait_q_enabled = true;
2791         cmd_node->condition = &adapter->scan_wait_q_woken;
2792         spin_lock_irqsave(&adapter->scan_pending_q_lock, flags);
2793         list_add_tail(&cmd_node->list, &adapter->scan_pending_q);
2794         spin_unlock_irqrestore(&adapter->scan_pending_q_lock, flags);
2795 }
2796
2797 /*
2798  * This function sends a scan command for all available channels to the
2799  * firmware, filtered on a specific SSID.
2800  */
2801 static int mwifiex_scan_specific_ssid(struct mwifiex_private *priv,
2802                                       struct cfg80211_ssid *req_ssid)
2803 {
2804         struct mwifiex_adapter *adapter = priv->adapter;
2805         int ret;
2806         struct mwifiex_user_scan_cfg *scan_cfg;
2807
2808         if (adapter->scan_processing) {
2809                 mwifiex_dbg(adapter, WARN,
2810                             "cmd: Scan already in process...\n");
2811                 return -EBUSY;
2812         }
2813
2814         if (priv->scan_block) {
2815                 mwifiex_dbg(adapter, WARN,
2816                             "cmd: Scan is blocked during association...\n");
2817                 return -EBUSY;
2818         }
2819
2820         scan_cfg = kzalloc(sizeof(struct mwifiex_user_scan_cfg), GFP_KERNEL);
2821         if (!scan_cfg)
2822                 return -ENOMEM;
2823
2824         scan_cfg->ssid_list = req_ssid;
2825         scan_cfg->num_ssids = 1;
2826
2827         ret = mwifiex_scan_networks(priv, scan_cfg);
2828
2829         kfree(scan_cfg);
2830         return ret;
2831 }
2832
2833 /*
2834  * Sends IOCTL request to start a scan.
2835  *
2836  * This function allocates the IOCTL request buffer, fills it
2837  * with requisite parameters and calls the IOCTL handler.
2838  *
2839  * Scan command can be issued for both normal scan and specific SSID
2840  * scan, depending upon whether an SSID is provided or not.
2841  */
2842 int mwifiex_request_scan(struct mwifiex_private *priv,
2843                          struct cfg80211_ssid *req_ssid)
2844 {
2845         int ret;
2846
2847         if (mutex_lock_interruptible(&priv->async_mutex)) {
2848                 mwifiex_dbg(priv->adapter, ERROR,
2849                             "%s: acquire semaphore fail\n",
2850                             __func__);
2851                 return -1;
2852         }
2853
2854         priv->adapter->scan_wait_q_woken = false;
2855
2856         if (req_ssid && req_ssid->ssid_len != 0)
2857                 /* Specific SSID scan */
2858                 ret = mwifiex_scan_specific_ssid(priv, req_ssid);
2859         else
2860                 /* Normal scan */
2861                 ret = mwifiex_scan_networks(priv, NULL);
2862
2863         mutex_unlock(&priv->async_mutex);
2864
2865         return ret;
2866 }
2867
2868 /*
2869  * This function appends the vendor specific IE TLV to a buffer.
2870  */
2871 int
2872 mwifiex_cmd_append_vsie_tlv(struct mwifiex_private *priv,
2873                             u16 vsie_mask, u8 **buffer)
2874 {
2875         int id, ret_len = 0;
2876         struct mwifiex_ie_types_vendor_param_set *vs_param_set;
2877
2878         if (!buffer)
2879                 return 0;
2880         if (!(*buffer))
2881                 return 0;
2882
2883         /*
2884          * Traverse through the saved vendor specific IE array and append
2885          * the selected(scan/assoc/adhoc) IE as TLV to the command
2886          */
2887         for (id = 0; id < MWIFIEX_MAX_VSIE_NUM; id++) {
2888                 if (priv->vs_ie[id].mask & vsie_mask) {
2889                         vs_param_set =
2890                                 (struct mwifiex_ie_types_vendor_param_set *)
2891                                 *buffer;
2892                         vs_param_set->header.type =
2893                                 cpu_to_le16(TLV_TYPE_PASSTHROUGH);
2894                         vs_param_set->header.len =
2895                                 cpu_to_le16((((u16) priv->vs_ie[id].ie[1])
2896                                 & 0x00FF) + 2);
2897                         if (le16_to_cpu(vs_param_set->header.len) >
2898                                 MWIFIEX_MAX_VSIE_LEN) {
2899                                 mwifiex_dbg(priv->adapter, ERROR,
2900                                             "Invalid param length!\n");
2901                                 break;
2902                         }
2903
2904                         memcpy(vs_param_set->ie, priv->vs_ie[id].ie,
2905                                le16_to_cpu(vs_param_set->header.len));
2906                         *buffer += le16_to_cpu(vs_param_set->header.len) +
2907                                    sizeof(struct mwifiex_ie_types_header);
2908                         ret_len += le16_to_cpu(vs_param_set->header.len) +
2909                                    sizeof(struct mwifiex_ie_types_header);
2910                 }
2911         }
2912         return ret_len;
2913 }
2914
2915 /*
2916  * This function saves a beacon buffer of the current BSS descriptor.
2917  *
2918  * The current beacon buffer is saved so that it can be restored in the
2919  * following cases that makes the beacon buffer not to contain the current
2920  * ssid's beacon buffer.
2921  *      - The current ssid was not found somehow in the last scan.
2922  *      - The current ssid was the last entry of the scan table and overloaded.
2923  */
2924 void
2925 mwifiex_save_curr_bcn(struct mwifiex_private *priv)
2926 {
2927         struct mwifiex_bssdescriptor *curr_bss =
2928                 &priv->curr_bss_params.bss_descriptor;
2929
2930         if (!curr_bss->beacon_buf_size)
2931                 return;
2932
2933         /* allocate beacon buffer at 1st time; or if it's size has changed */
2934         if (!priv->curr_bcn_buf ||
2935             priv->curr_bcn_size != curr_bss->beacon_buf_size) {
2936                 priv->curr_bcn_size = curr_bss->beacon_buf_size;
2937
2938                 kfree(priv->curr_bcn_buf);
2939                 priv->curr_bcn_buf = kmalloc(curr_bss->beacon_buf_size,
2940                                              GFP_ATOMIC);
2941                 if (!priv->curr_bcn_buf)
2942                         return;
2943         }
2944
2945         memcpy(priv->curr_bcn_buf, curr_bss->beacon_buf,
2946                curr_bss->beacon_buf_size);
2947         mwifiex_dbg(priv->adapter, INFO,
2948                     "info: current beacon saved %d\n",
2949                     priv->curr_bcn_size);
2950
2951         curr_bss->beacon_buf = priv->curr_bcn_buf;
2952
2953         /* adjust the pointers in the current BSS descriptor */
2954         if (curr_bss->bcn_wpa_ie)
2955                 curr_bss->bcn_wpa_ie =
2956                         (struct ieee_types_vendor_specific *)
2957                         (curr_bss->beacon_buf +
2958                          curr_bss->wpa_offset);
2959
2960         if (curr_bss->bcn_rsn_ie)
2961                 curr_bss->bcn_rsn_ie = (struct ieee_types_generic *)
2962                         (curr_bss->beacon_buf +
2963                          curr_bss->rsn_offset);
2964
2965         if (curr_bss->bcn_ht_cap)
2966                 curr_bss->bcn_ht_cap = (struct ieee80211_ht_cap *)
2967                         (curr_bss->beacon_buf +
2968                          curr_bss->ht_cap_offset);
2969
2970         if (curr_bss->bcn_ht_oper)
2971                 curr_bss->bcn_ht_oper = (struct ieee80211_ht_operation *)
2972                         (curr_bss->beacon_buf +
2973                          curr_bss->ht_info_offset);
2974
2975         if (curr_bss->bcn_vht_cap)
2976                 curr_bss->bcn_vht_cap = (void *)(curr_bss->beacon_buf +
2977                                                  curr_bss->vht_cap_offset);
2978
2979         if (curr_bss->bcn_vht_oper)
2980                 curr_bss->bcn_vht_oper = (void *)(curr_bss->beacon_buf +
2981                                                   curr_bss->vht_info_offset);
2982
2983         if (curr_bss->bcn_bss_co_2040)
2984                 curr_bss->bcn_bss_co_2040 =
2985                         (curr_bss->beacon_buf + curr_bss->bss_co_2040_offset);
2986
2987         if (curr_bss->bcn_ext_cap)
2988                 curr_bss->bcn_ext_cap = curr_bss->beacon_buf +
2989                         curr_bss->ext_cap_offset;
2990
2991         if (curr_bss->oper_mode)
2992                 curr_bss->oper_mode = (void *)(curr_bss->beacon_buf +
2993                                                curr_bss->oper_mode_offset);
2994 }
2995
2996 /*
2997  * This function frees the current BSS descriptor beacon buffer.
2998  */
2999 void
3000 mwifiex_free_curr_bcn(struct mwifiex_private *priv)
3001 {
3002         kfree(priv->curr_bcn_buf);
3003         priv->curr_bcn_buf = NULL;
3004 }