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