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