GNU Linux-libre 4.14.303-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_unaligned_add_cpu(&chan_tlv_out->header.len,
696                                                sizeof(
697                                                 chan_tlv_out->chan_scan_param));
698
699                         /*
700                          * The tlv buffer length is set to the number of bytes
701                          * of the between the channel tlv pointer and the start
702                          * of the tlv buffer.  This compensates for any TLVs
703                          * that were appended before the channel list.
704                          */
705                         scan_cfg_out->tlv_buf_len = (u32) ((u8 *) chan_tlv_out -
706                                                         scan_cfg_out->tlv_buf);
707
708                         /* Add the size of the channel tlv header and the data
709                            length */
710                         scan_cfg_out->tlv_buf_len +=
711                                 (sizeof(chan_tlv_out->header)
712                                  + le16_to_cpu(chan_tlv_out->header.len));
713
714                         /* Increment the index to the channel tlv we are
715                            constructing */
716                         tlv_idx++;
717
718                         /* Count the total scan time per command */
719                         total_scan_time +=
720                                 le16_to_cpu(tmp_chan_list->max_scan_time);
721
722                         done_early = false;
723
724                         /* Stop the loop if the *current* channel is in the
725                            1,6,11 set and we are not filtering on a BSSID
726                            or SSID. */
727                         if (!filtered_scan &&
728                             (tmp_chan_list->chan_number == 1 ||
729                              tmp_chan_list->chan_number == 6 ||
730                              tmp_chan_list->chan_number == 11))
731                                 done_early = true;
732
733                         /* Increment the tmp pointer to the next channel to
734                            be scanned */
735                         tmp_chan_list++;
736
737                         /* Stop the loop if the *next* channel is in the 1,6,11
738                            set.  This will cause it to be the only channel
739                            scanned on the next interation */
740                         if (!filtered_scan &&
741                             (tmp_chan_list->chan_number == 1 ||
742                              tmp_chan_list->chan_number == 6 ||
743                              tmp_chan_list->chan_number == 11))
744                                 done_early = true;
745                 }
746
747                 /* The total scan time should be less than scan command timeout
748                    value */
749                 if (total_scan_time > MWIFIEX_MAX_TOTAL_SCAN_TIME) {
750                         mwifiex_dbg(priv->adapter, ERROR,
751                                     "total scan time %dms\t"
752                                     "is over limit (%dms), scan skipped\n",
753                                     total_scan_time,
754                                     MWIFIEX_MAX_TOTAL_SCAN_TIME);
755                         ret = -1;
756                         break;
757                 }
758
759                 rates_size = mwifiex_append_rate_tlv(priv, scan_cfg_out,
760                                                      radio_type);
761
762                 priv->adapter->scan_channels = start_chan;
763
764                 /* Send the scan command to the firmware with the specified
765                    cfg */
766                 if (priv->adapter->ext_scan)
767                         cmd_no = HostCmd_CMD_802_11_SCAN_EXT;
768                 else
769                         cmd_no = HostCmd_CMD_802_11_SCAN;
770
771                 ret = mwifiex_send_cmd(priv, cmd_no, HostCmd_ACT_GEN_SET,
772                                        0, scan_cfg_out, false);
773
774                 /* rate IE is updated per scan command but same starting
775                  * pointer is used each time so that rate IE from earlier
776                  * scan_cfg_out->buf is overwritten with new one.
777                  */
778                 scan_cfg_out->tlv_buf_len -=
779                             sizeof(struct mwifiex_ie_types_header) + rates_size;
780
781                 if (ret) {
782                         mwifiex_cancel_pending_scan_cmd(adapter);
783                         break;
784                 }
785         }
786
787         if (ret)
788                 return -1;
789
790         return 0;
791 }
792
793 /*
794  * This function constructs a scan command configuration structure to use
795  * in scan commands.
796  *
797  * Application layer or other functions can invoke network scanning
798  * with a scan configuration supplied in a user scan configuration structure.
799  * This structure is used as the basis of one or many scan command configuration
800  * commands that are sent to the command processing module and eventually to the
801  * firmware.
802  *
803  * This function creates a scan command configuration structure  based on the
804  * following user supplied parameters (if present):
805  *      - SSID filter
806  *      - BSSID filter
807  *      - Number of Probes to be sent
808  *      - Channel list
809  *
810  * If the SSID or BSSID filter is not present, the filter is disabled/cleared.
811  * If the number of probes is not set, adapter default setting is used.
812  */
813 static void
814 mwifiex_config_scan(struct mwifiex_private *priv,
815                     const struct mwifiex_user_scan_cfg *user_scan_in,
816                     struct mwifiex_scan_cmd_config *scan_cfg_out,
817                     struct mwifiex_ie_types_chan_list_param_set **chan_list_out,
818                     struct mwifiex_chan_scan_param_set *scan_chan_list,
819                     u8 *max_chan_per_scan, u8 *filtered_scan,
820                     u8 *scan_current_only)
821 {
822         struct mwifiex_adapter *adapter = priv->adapter;
823         struct mwifiex_ie_types_num_probes *num_probes_tlv;
824         struct mwifiex_ie_types_scan_chan_gap *chan_gap_tlv;
825         struct mwifiex_ie_types_random_mac *random_mac_tlv;
826         struct mwifiex_ie_types_wildcard_ssid_params *wildcard_ssid_tlv;
827         struct mwifiex_ie_types_bssid_list *bssid_tlv;
828         u8 *tlv_pos;
829         u32 num_probes;
830         u32 ssid_len;
831         u32 chan_idx;
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                 u8 tmpaddr[ETH_ALEN];
865
866                 /* Default the ssid_filter flag to TRUE, set false under
867                    certain wildcard conditions and qualified by the existence
868                    of an SSID list before marking the scan as filtered */
869                 ssid_filter = true;
870
871                 /* Set the BSS type scan filter, use Adapter setting if
872                    unset */
873                 scan_cfg_out->bss_mode =
874                         (u8)(user_scan_in->bss_mode ?: adapter->scan_mode);
875
876                 /* Set the number of probes to send, use Adapter setting
877                    if unset */
878                 num_probes = user_scan_in->num_probes ?: adapter->scan_probes;
879
880                 /*
881                  * Set the BSSID filter to the incoming configuration,
882                  * if non-zero.  If not set, it will remain disabled
883                  * (all zeros).
884                  */
885                 memcpy(scan_cfg_out->specific_bssid,
886                        user_scan_in->specific_bssid,
887                        sizeof(scan_cfg_out->specific_bssid));
888
889                 memcpy(tmpaddr, scan_cfg_out->specific_bssid, ETH_ALEN);
890
891                 if (adapter->ext_scan &&
892                     !is_zero_ether_addr(tmpaddr)) {
893                         bssid_tlv =
894                                 (struct mwifiex_ie_types_bssid_list *)tlv_pos;
895                         bssid_tlv->header.type = cpu_to_le16(TLV_TYPE_BSSID);
896                         bssid_tlv->header.len = cpu_to_le16(ETH_ALEN);
897                         memcpy(bssid_tlv->bssid, user_scan_in->specific_bssid,
898                                ETH_ALEN);
899                         tlv_pos += sizeof(struct mwifiex_ie_types_bssid_list);
900                 }
901
902                 for (i = 0; i < user_scan_in->num_ssids; i++) {
903                         ssid_len = user_scan_in->ssid_list[i].ssid_len;
904
905                         wildcard_ssid_tlv =
906                                 (struct mwifiex_ie_types_wildcard_ssid_params *)
907                                 tlv_pos;
908                         wildcard_ssid_tlv->header.type =
909                                 cpu_to_le16(TLV_TYPE_WILDCARDSSID);
910                         wildcard_ssid_tlv->header.len = cpu_to_le16(
911                                 (u16) (ssid_len + sizeof(wildcard_ssid_tlv->
912                                                          max_ssid_length)));
913
914                         /*
915                          * max_ssid_length = 0 tells firmware to perform
916                          * specific scan for the SSID filled, whereas
917                          * max_ssid_length = IEEE80211_MAX_SSID_LEN is for
918                          * wildcard scan.
919                          */
920                         if (ssid_len)
921                                 wildcard_ssid_tlv->max_ssid_length = 0;
922                         else
923                                 wildcard_ssid_tlv->max_ssid_length =
924                                                         IEEE80211_MAX_SSID_LEN;
925
926                         if (!memcmp(user_scan_in->ssid_list[i].ssid,
927                                     "DIRECT-", 7))
928                                 wildcard_ssid_tlv->max_ssid_length = 0xfe;
929
930                         memcpy(wildcard_ssid_tlv->ssid,
931                                user_scan_in->ssid_list[i].ssid, ssid_len);
932
933                         tlv_pos += (sizeof(wildcard_ssid_tlv->header)
934                                 + le16_to_cpu(wildcard_ssid_tlv->header.len));
935
936                         mwifiex_dbg(adapter, INFO,
937                                     "info: scan: ssid[%d]: %s, %d\n",
938                                     i, wildcard_ssid_tlv->ssid,
939                                     wildcard_ssid_tlv->max_ssid_length);
940
941                         /* Empty wildcard ssid with a maxlen will match many or
942                            potentially all SSIDs (maxlen == 32), therefore do
943                            not treat the scan as
944                            filtered. */
945                         if (!ssid_len && wildcard_ssid_tlv->max_ssid_length)
946                                 ssid_filter = false;
947                 }
948
949                 /*
950                  *  The default number of channels sent in the command is low to
951                  *  ensure the response buffer from the firmware does not
952                  *  truncate scan results.  That is not an issue with an SSID
953                  *  or BSSID filter applied to the scan results in the firmware.
954                  */
955                 memcpy(tmpaddr, scan_cfg_out->specific_bssid, ETH_ALEN);
956                 if ((i && ssid_filter) ||
957                     !is_zero_ether_addr(tmpaddr))
958                         *filtered_scan = true;
959
960                 if (user_scan_in->scan_chan_gap) {
961                         mwifiex_dbg(adapter, INFO,
962                                     "info: scan: channel gap = %d\n",
963                                     user_scan_in->scan_chan_gap);
964                         *max_chan_per_scan =
965                                         MWIFIEX_MAX_CHANNELS_PER_SPECIFIC_SCAN;
966
967                         chan_gap_tlv = (void *)tlv_pos;
968                         chan_gap_tlv->header.type =
969                                          cpu_to_le16(TLV_TYPE_SCAN_CHANNEL_GAP);
970                         chan_gap_tlv->header.len =
971                                     cpu_to_le16(sizeof(chan_gap_tlv->chan_gap));
972                         chan_gap_tlv->chan_gap =
973                                      cpu_to_le16((user_scan_in->scan_chan_gap));
974                         tlv_pos +=
975                                   sizeof(struct mwifiex_ie_types_scan_chan_gap);
976                 }
977
978                 if (!ether_addr_equal(user_scan_in->random_mac, zero_mac)) {
979                         random_mac_tlv = (void *)tlv_pos;
980                         random_mac_tlv->header.type =
981                                          cpu_to_le16(TLV_TYPE_RANDOM_MAC);
982                         random_mac_tlv->header.len =
983                                     cpu_to_le16(sizeof(random_mac_tlv->mac));
984                         ether_addr_copy(random_mac_tlv->mac,
985                                         user_scan_in->random_mac);
986                         tlv_pos +=
987                                   sizeof(struct mwifiex_ie_types_random_mac);
988                 }
989         } else {
990                 scan_cfg_out->bss_mode = (u8) adapter->scan_mode;
991                 num_probes = adapter->scan_probes;
992         }
993
994         /*
995          *  If a specific BSSID or SSID is used, the number of channels in the
996          *  scan command will be increased to the absolute maximum.
997          */
998         if (*filtered_scan) {
999                 *max_chan_per_scan = MWIFIEX_MAX_CHANNELS_PER_SPECIFIC_SCAN;
1000         } else {
1001                 if (!priv->media_connected)
1002                         *max_chan_per_scan = MWIFIEX_DEF_CHANNELS_PER_SCAN_CMD;
1003                 else
1004                         *max_chan_per_scan =
1005                                         MWIFIEX_DEF_CHANNELS_PER_SCAN_CMD / 2;
1006         }
1007
1008         if (adapter->ext_scan) {
1009                 bss_mode = (struct mwifiex_ie_types_bss_mode *)tlv_pos;
1010                 bss_mode->header.type = cpu_to_le16(TLV_TYPE_BSS_MODE);
1011                 bss_mode->header.len = cpu_to_le16(sizeof(bss_mode->bss_mode));
1012                 bss_mode->bss_mode = scan_cfg_out->bss_mode;
1013                 tlv_pos += sizeof(bss_mode->header) +
1014                            le16_to_cpu(bss_mode->header.len);
1015         }
1016
1017         /* If the input config or adapter has the number of Probes set,
1018            add tlv */
1019         if (num_probes) {
1020
1021                 mwifiex_dbg(adapter, INFO,
1022                             "info: scan: num_probes = %d\n",
1023                             num_probes);
1024
1025                 num_probes_tlv = (struct mwifiex_ie_types_num_probes *) tlv_pos;
1026                 num_probes_tlv->header.type = cpu_to_le16(TLV_TYPE_NUMPROBES);
1027                 num_probes_tlv->header.len =
1028                         cpu_to_le16(sizeof(num_probes_tlv->num_probes));
1029                 num_probes_tlv->num_probes = cpu_to_le16((u16) num_probes);
1030
1031                 tlv_pos += sizeof(num_probes_tlv->header) +
1032                         le16_to_cpu(num_probes_tlv->header.len);
1033
1034         }
1035
1036         if (ISSUPP_11NENABLED(priv->adapter->fw_cap_info) &&
1037             (priv->adapter->config_bands & BAND_GN ||
1038              priv->adapter->config_bands & BAND_AN)) {
1039                 ht_cap = (struct mwifiex_ie_types_htcap *) tlv_pos;
1040                 memset(ht_cap, 0, sizeof(struct mwifiex_ie_types_htcap));
1041                 ht_cap->header.type = cpu_to_le16(WLAN_EID_HT_CAPABILITY);
1042                 ht_cap->header.len =
1043                                 cpu_to_le16(sizeof(struct ieee80211_ht_cap));
1044                 radio_type =
1045                         mwifiex_band_to_radio_type(priv->adapter->config_bands);
1046                 mwifiex_fill_cap_info(priv, radio_type, &ht_cap->ht_cap);
1047                 tlv_pos += sizeof(struct mwifiex_ie_types_htcap);
1048         }
1049
1050         /* Append vendor specific IE TLV */
1051         mwifiex_cmd_append_vsie_tlv(priv, MWIFIEX_VSIE_MASK_SCAN, &tlv_pos);
1052
1053         /*
1054          * Set the output for the channel TLV to the address in the tlv buffer
1055          *   past any TLVs that were added in this function (SSID, num_probes).
1056          *   Channel TLVs will be added past this for each scan command,
1057          *   preserving the TLVs that were previously added.
1058          */
1059         *chan_list_out =
1060                 (struct mwifiex_ie_types_chan_list_param_set *) tlv_pos;
1061
1062         if (user_scan_in && user_scan_in->chan_list[0].chan_number) {
1063
1064                 mwifiex_dbg(adapter, INFO,
1065                             "info: Scan: Using supplied channel list\n");
1066
1067                 for (chan_idx = 0;
1068                      chan_idx < MWIFIEX_USER_SCAN_CHAN_MAX &&
1069                      user_scan_in->chan_list[chan_idx].chan_number;
1070                      chan_idx++) {
1071
1072                         channel = user_scan_in->chan_list[chan_idx].chan_number;
1073                         scan_chan_list[chan_idx].chan_number = channel;
1074
1075                         radio_type =
1076                                 user_scan_in->chan_list[chan_idx].radio_type;
1077                         scan_chan_list[chan_idx].radio_type = radio_type;
1078
1079                         scan_type = user_scan_in->chan_list[chan_idx].scan_type;
1080
1081                         if (scan_type == MWIFIEX_SCAN_TYPE_PASSIVE)
1082                                 scan_chan_list[chan_idx].chan_scan_mode_bitmap
1083                                         |= (MWIFIEX_PASSIVE_SCAN |
1084                                             MWIFIEX_HIDDEN_SSID_REPORT);
1085                         else
1086                                 scan_chan_list[chan_idx].chan_scan_mode_bitmap
1087                                         &= ~MWIFIEX_PASSIVE_SCAN;
1088
1089                         scan_chan_list[chan_idx].chan_scan_mode_bitmap
1090                                 |= MWIFIEX_DISABLE_CHAN_FILT;
1091
1092                         if (user_scan_in->chan_list[chan_idx].scan_time) {
1093                                 scan_dur = (u16) user_scan_in->
1094                                         chan_list[chan_idx].scan_time;
1095                         } else {
1096                                 if (scan_type == MWIFIEX_SCAN_TYPE_PASSIVE)
1097                                         scan_dur = adapter->passive_scan_time;
1098                                 else if (*filtered_scan)
1099                                         scan_dur = adapter->specific_scan_time;
1100                                 else
1101                                         scan_dur = adapter->active_scan_time;
1102                         }
1103
1104                         scan_chan_list[chan_idx].min_scan_time =
1105                                 cpu_to_le16(scan_dur);
1106                         scan_chan_list[chan_idx].max_scan_time =
1107                                 cpu_to_le16(scan_dur);
1108                 }
1109
1110                 /* Check if we are only scanning the current channel */
1111                 if ((chan_idx == 1) &&
1112                     (user_scan_in->chan_list[0].chan_number ==
1113                      priv->curr_bss_params.bss_descriptor.channel)) {
1114                         *scan_current_only = true;
1115                         mwifiex_dbg(adapter, INFO,
1116                                     "info: Scan: Scanning current channel only\n");
1117                 }
1118         } else {
1119                 mwifiex_dbg(adapter, INFO,
1120                             "info: Scan: Creating full region channel list\n");
1121                 mwifiex_scan_create_channel_list(priv, user_scan_in,
1122                                                  scan_chan_list,
1123                                                  *filtered_scan);
1124         }
1125
1126 }
1127
1128 /*
1129  * This function inspects the scan response buffer for pointers to
1130  * expected TLVs.
1131  *
1132  * TLVs can be included at the end of the scan response BSS information.
1133  *
1134  * Data in the buffer is parsed pointers to TLVs that can potentially
1135  * be passed back in the response.
1136  */
1137 static void
1138 mwifiex_ret_802_11_scan_get_tlv_ptrs(struct mwifiex_adapter *adapter,
1139                                      struct mwifiex_ie_types_data *tlv,
1140                                      u32 tlv_buf_size, u32 req_tlv_type,
1141                                      struct mwifiex_ie_types_data **tlv_data)
1142 {
1143         struct mwifiex_ie_types_data *current_tlv;
1144         u32 tlv_buf_left;
1145         u32 tlv_type;
1146         u32 tlv_len;
1147
1148         current_tlv = tlv;
1149         tlv_buf_left = tlv_buf_size;
1150         *tlv_data = NULL;
1151
1152         mwifiex_dbg(adapter, INFO,
1153                     "info: SCAN_RESP: tlv_buf_size = %d\n",
1154                     tlv_buf_size);
1155
1156         while (tlv_buf_left >= sizeof(struct mwifiex_ie_types_header)) {
1157
1158                 tlv_type = le16_to_cpu(current_tlv->header.type);
1159                 tlv_len = le16_to_cpu(current_tlv->header.len);
1160
1161                 if (sizeof(tlv->header) + tlv_len > tlv_buf_left) {
1162                         mwifiex_dbg(adapter, ERROR,
1163                                     "SCAN_RESP: TLV buffer corrupt\n");
1164                         break;
1165                 }
1166
1167                 if (req_tlv_type == tlv_type) {
1168                         switch (tlv_type) {
1169                         case TLV_TYPE_TSFTIMESTAMP:
1170                                 mwifiex_dbg(adapter, INFO,
1171                                             "info: SCAN_RESP: TSF\t"
1172                                             "timestamp TLV, len = %d\n",
1173                                             tlv_len);
1174                                 *tlv_data = current_tlv;
1175                                 break;
1176                         case TLV_TYPE_CHANNELBANDLIST:
1177                                 mwifiex_dbg(adapter, INFO,
1178                                             "info: SCAN_RESP: channel\t"
1179                                             "band list TLV, len = %d\n",
1180                                             tlv_len);
1181                                 *tlv_data = current_tlv;
1182                                 break;
1183                         default:
1184                                 mwifiex_dbg(adapter, ERROR,
1185                                             "SCAN_RESP: unhandled TLV = %d\n",
1186                                             tlv_type);
1187                                 /* Give up, this seems corrupted */
1188                                 return;
1189                         }
1190                 }
1191
1192                 if (*tlv_data)
1193                         break;
1194
1195
1196                 tlv_buf_left -= (sizeof(tlv->header) + tlv_len);
1197                 current_tlv =
1198                         (struct mwifiex_ie_types_data *) (current_tlv->data +
1199                                                           tlv_len);
1200
1201         }                       /* while */
1202 }
1203
1204 /*
1205  * This function parses provided beacon buffer and updates
1206  * respective fields in bss descriptor structure.
1207  */
1208 int mwifiex_update_bss_desc_with_ie(struct mwifiex_adapter *adapter,
1209                                     struct mwifiex_bssdescriptor *bss_entry)
1210 {
1211         int ret = 0;
1212         u8 element_id;
1213         struct ieee_types_fh_param_set *fh_param_set;
1214         struct ieee_types_ds_param_set *ds_param_set;
1215         struct ieee_types_cf_param_set *cf_param_set;
1216         struct ieee_types_ibss_param_set *ibss_param_set;
1217         u8 *current_ptr;
1218         u8 *rate;
1219         u8 element_len;
1220         u16 total_ie_len;
1221         u8 bytes_to_copy;
1222         u8 rate_size;
1223         u8 found_data_rate_ie;
1224         u32 bytes_left;
1225         struct ieee_types_vendor_specific *vendor_ie;
1226         const u8 wpa_oui[4] = { 0x00, 0x50, 0xf2, 0x01 };
1227         const u8 wmm_oui[4] = { 0x00, 0x50, 0xf2, 0x02 };
1228
1229         found_data_rate_ie = false;
1230         rate_size = 0;
1231         current_ptr = bss_entry->beacon_buf;
1232         bytes_left = bss_entry->beacon_buf_size;
1233
1234         /* Process variable IE */
1235         while (bytes_left >= 2) {
1236                 element_id = *current_ptr;
1237                 element_len = *(current_ptr + 1);
1238                 total_ie_len = element_len + sizeof(struct ieee_types_header);
1239
1240                 if (bytes_left < total_ie_len) {
1241                         mwifiex_dbg(adapter, ERROR,
1242                                     "err: InterpretIE: in processing\t"
1243                                     "IE, bytes left < IE length\n");
1244                         return -1;
1245                 }
1246                 switch (element_id) {
1247                 case WLAN_EID_SSID:
1248                         if (element_len > IEEE80211_MAX_SSID_LEN)
1249                                 return -EINVAL;
1250                         bss_entry->ssid.ssid_len = element_len;
1251                         memcpy(bss_entry->ssid.ssid, (current_ptr + 2),
1252                                element_len);
1253                         mwifiex_dbg(adapter, INFO,
1254                                     "info: InterpretIE: ssid: %-32s\n",
1255                                     bss_entry->ssid.ssid);
1256                         break;
1257
1258                 case WLAN_EID_SUPP_RATES:
1259                         if (element_len > MWIFIEX_SUPPORTED_RATES)
1260                                 return -EINVAL;
1261                         memcpy(bss_entry->data_rates, current_ptr + 2,
1262                                element_len);
1263                         memcpy(bss_entry->supported_rates, current_ptr + 2,
1264                                element_len);
1265                         rate_size = element_len;
1266                         found_data_rate_ie = true;
1267                         break;
1268
1269                 case WLAN_EID_FH_PARAMS:
1270                         if (element_len + 2 < sizeof(*fh_param_set))
1271                                 return -EINVAL;
1272                         fh_param_set =
1273                                 (struct ieee_types_fh_param_set *) current_ptr;
1274                         memcpy(&bss_entry->phy_param_set.fh_param_set,
1275                                fh_param_set,
1276                                sizeof(struct ieee_types_fh_param_set));
1277                         break;
1278
1279                 case WLAN_EID_DS_PARAMS:
1280                         if (element_len + 2 < sizeof(*ds_param_set))
1281                                 return -EINVAL;
1282                         ds_param_set =
1283                                 (struct ieee_types_ds_param_set *) current_ptr;
1284
1285                         bss_entry->channel = ds_param_set->current_chan;
1286
1287                         memcpy(&bss_entry->phy_param_set.ds_param_set,
1288                                ds_param_set,
1289                                sizeof(struct ieee_types_ds_param_set));
1290                         break;
1291
1292                 case WLAN_EID_CF_PARAMS:
1293                         if (element_len + 2 < sizeof(*cf_param_set))
1294                                 return -EINVAL;
1295                         cf_param_set =
1296                                 (struct ieee_types_cf_param_set *) current_ptr;
1297                         memcpy(&bss_entry->ss_param_set.cf_param_set,
1298                                cf_param_set,
1299                                sizeof(struct ieee_types_cf_param_set));
1300                         break;
1301
1302                 case WLAN_EID_IBSS_PARAMS:
1303                         if (element_len + 2 < sizeof(*ibss_param_set))
1304                                 return -EINVAL;
1305                         ibss_param_set =
1306                                 (struct ieee_types_ibss_param_set *)
1307                                 current_ptr;
1308                         memcpy(&bss_entry->ss_param_set.ibss_param_set,
1309                                ibss_param_set,
1310                                sizeof(struct ieee_types_ibss_param_set));
1311                         break;
1312
1313                 case WLAN_EID_ERP_INFO:
1314                         if (!element_len)
1315                                 return -EINVAL;
1316                         bss_entry->erp_flags = *(current_ptr + 2);
1317                         break;
1318
1319                 case WLAN_EID_PWR_CONSTRAINT:
1320                         if (!element_len)
1321                                 return -EINVAL;
1322                         bss_entry->local_constraint = *(current_ptr + 2);
1323                         bss_entry->sensed_11h = true;
1324                         break;
1325
1326                 case WLAN_EID_CHANNEL_SWITCH:
1327                         bss_entry->chan_sw_ie_present = true;
1328                 case WLAN_EID_PWR_CAPABILITY:
1329                 case WLAN_EID_TPC_REPORT:
1330                 case WLAN_EID_QUIET:
1331                         bss_entry->sensed_11h = true;
1332                     break;
1333
1334                 case WLAN_EID_EXT_SUPP_RATES:
1335                         /*
1336                          * Only process extended supported rate
1337                          * if data rate is already found.
1338                          * Data rate IE should come before
1339                          * extended supported rate IE
1340                          */
1341                         if (found_data_rate_ie) {
1342                                 if ((element_len + rate_size) >
1343                                     MWIFIEX_SUPPORTED_RATES)
1344                                         bytes_to_copy =
1345                                                 (MWIFIEX_SUPPORTED_RATES -
1346                                                  rate_size);
1347                                 else
1348                                         bytes_to_copy = element_len;
1349
1350                                 rate = (u8 *) bss_entry->data_rates;
1351                                 rate += rate_size;
1352                                 memcpy(rate, current_ptr + 2, bytes_to_copy);
1353
1354                                 rate = (u8 *) bss_entry->supported_rates;
1355                                 rate += rate_size;
1356                                 memcpy(rate, current_ptr + 2, bytes_to_copy);
1357                         }
1358                         break;
1359
1360                 case WLAN_EID_VENDOR_SPECIFIC:
1361                         vendor_ie = (struct ieee_types_vendor_specific *)
1362                                         current_ptr;
1363
1364                         /* 802.11 requires at least 3-byte OUI. */
1365                         if (element_len < sizeof(vendor_ie->vend_hdr.oui.oui))
1366                                 return -EINVAL;
1367
1368                         /* Not long enough for a match? Skip it. */
1369                         if (element_len < sizeof(wpa_oui))
1370                                 break;
1371
1372                         if (!memcmp(&vendor_ie->vend_hdr.oui, wpa_oui,
1373                                     sizeof(wpa_oui))) {
1374                                 bss_entry->bcn_wpa_ie =
1375                                         (struct ieee_types_vendor_specific *)
1376                                         current_ptr;
1377                                 bss_entry->wpa_offset = (u16)
1378                                         (current_ptr - bss_entry->beacon_buf);
1379                         } else if (!memcmp(&vendor_ie->vend_hdr.oui, wmm_oui,
1380                                     sizeof(wmm_oui))) {
1381                                 if (total_ie_len ==
1382                                     sizeof(struct ieee_types_wmm_parameter) ||
1383                                     total_ie_len ==
1384                                     sizeof(struct ieee_types_wmm_info))
1385                                         /*
1386                                          * Only accept and copy the WMM IE if
1387                                          * it matches the size expected for the
1388                                          * WMM Info IE or the WMM Parameter IE.
1389                                          */
1390                                         memcpy((u8 *) &bss_entry->wmm_ie,
1391                                                current_ptr, total_ie_len);
1392                         }
1393                         break;
1394                 case WLAN_EID_RSN:
1395                         bss_entry->bcn_rsn_ie =
1396                                 (struct ieee_types_generic *) current_ptr;
1397                         bss_entry->rsn_offset = (u16) (current_ptr -
1398                                                         bss_entry->beacon_buf);
1399                         break;
1400                 case WLAN_EID_BSS_AC_ACCESS_DELAY:
1401                         bss_entry->bcn_wapi_ie =
1402                                 (struct ieee_types_generic *) current_ptr;
1403                         bss_entry->wapi_offset = (u16) (current_ptr -
1404                                                         bss_entry->beacon_buf);
1405                         break;
1406                 case WLAN_EID_HT_CAPABILITY:
1407                         bss_entry->bcn_ht_cap = (struct ieee80211_ht_cap *)
1408                                         (current_ptr +
1409                                         sizeof(struct ieee_types_header));
1410                         bss_entry->ht_cap_offset = (u16) (current_ptr +
1411                                         sizeof(struct ieee_types_header) -
1412                                         bss_entry->beacon_buf);
1413                         break;
1414                 case WLAN_EID_HT_OPERATION:
1415                         bss_entry->bcn_ht_oper =
1416                                 (struct ieee80211_ht_operation *)(current_ptr +
1417                                         sizeof(struct ieee_types_header));
1418                         bss_entry->ht_info_offset = (u16) (current_ptr +
1419                                         sizeof(struct ieee_types_header) -
1420                                         bss_entry->beacon_buf);
1421                         break;
1422                 case WLAN_EID_VHT_CAPABILITY:
1423                         bss_entry->disable_11ac = false;
1424                         bss_entry->bcn_vht_cap =
1425                                 (void *)(current_ptr +
1426                                          sizeof(struct ieee_types_header));
1427                         bss_entry->vht_cap_offset =
1428                                         (u16)((u8 *)bss_entry->bcn_vht_cap -
1429                                               bss_entry->beacon_buf);
1430                         break;
1431                 case WLAN_EID_VHT_OPERATION:
1432                         bss_entry->bcn_vht_oper =
1433                                 (void *)(current_ptr +
1434                                          sizeof(struct ieee_types_header));
1435                         bss_entry->vht_info_offset =
1436                                         (u16)((u8 *)bss_entry->bcn_vht_oper -
1437                                               bss_entry->beacon_buf);
1438                         break;
1439                 case WLAN_EID_BSS_COEX_2040:
1440                         bss_entry->bcn_bss_co_2040 = current_ptr;
1441                         bss_entry->bss_co_2040_offset =
1442                                 (u16) (current_ptr - bss_entry->beacon_buf);
1443                         break;
1444                 case WLAN_EID_EXT_CAPABILITY:
1445                         bss_entry->bcn_ext_cap = current_ptr;
1446                         bss_entry->ext_cap_offset =
1447                                 (u16) (current_ptr - bss_entry->beacon_buf);
1448                         break;
1449                 case WLAN_EID_OPMODE_NOTIF:
1450                         bss_entry->oper_mode = (void *)current_ptr;
1451                         bss_entry->oper_mode_offset =
1452                                         (u16)((u8 *)bss_entry->oper_mode -
1453                                               bss_entry->beacon_buf);
1454                         break;
1455                 default:
1456                         break;
1457                 }
1458
1459                 current_ptr += element_len + 2;
1460
1461                 /* Need to account for IE ID and IE Len */
1462                 bytes_left -= (element_len + 2);
1463
1464         }       /* while (bytes_left > 2) */
1465         return ret;
1466 }
1467
1468 /*
1469  * This function converts radio type scan parameter to a band configuration
1470  * to be used in join command.
1471  */
1472 static u8
1473 mwifiex_radio_type_to_band(u8 radio_type)
1474 {
1475         switch (radio_type) {
1476         case HostCmd_SCAN_RADIO_TYPE_A:
1477                 return BAND_A;
1478         case HostCmd_SCAN_RADIO_TYPE_BG:
1479         default:
1480                 return BAND_G;
1481         }
1482 }
1483
1484 /*
1485  * This is an internal function used to start a scan based on an input
1486  * configuration.
1487  *
1488  * This uses the input user scan configuration information when provided in
1489  * order to send the appropriate scan commands to firmware to populate or
1490  * update the internal driver scan table.
1491  */
1492 int mwifiex_scan_networks(struct mwifiex_private *priv,
1493                           const struct mwifiex_user_scan_cfg *user_scan_in)
1494 {
1495         int ret;
1496         struct mwifiex_adapter *adapter = priv->adapter;
1497         struct cmd_ctrl_node *cmd_node;
1498         union mwifiex_scan_cmd_config_tlv *scan_cfg_out;
1499         struct mwifiex_ie_types_chan_list_param_set *chan_list_out;
1500         struct mwifiex_chan_scan_param_set *scan_chan_list;
1501         u8 filtered_scan;
1502         u8 scan_current_chan_only;
1503         u8 max_chan_per_scan;
1504         unsigned long flags;
1505
1506         if (adapter->scan_processing) {
1507                 mwifiex_dbg(adapter, WARN,
1508                             "cmd: Scan already in process...\n");
1509                 return -EBUSY;
1510         }
1511
1512         if (priv->scan_block) {
1513                 mwifiex_dbg(adapter, WARN,
1514                             "cmd: Scan is blocked during association...\n");
1515                 return -EBUSY;
1516         }
1517
1518         if (adapter->surprise_removed || adapter->is_cmd_timedout) {
1519                 mwifiex_dbg(adapter, ERROR,
1520                             "Ignore scan. Card removed or firmware in bad state\n");
1521                 return -EFAULT;
1522         }
1523
1524         spin_lock_irqsave(&adapter->mwifiex_cmd_lock, flags);
1525         adapter->scan_processing = true;
1526         spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, flags);
1527
1528         scan_cfg_out = kzalloc(sizeof(union mwifiex_scan_cmd_config_tlv),
1529                                GFP_KERNEL);
1530         if (!scan_cfg_out) {
1531                 ret = -ENOMEM;
1532                 goto done;
1533         }
1534
1535         scan_chan_list = kcalloc(MWIFIEX_USER_SCAN_CHAN_MAX,
1536                                  sizeof(struct mwifiex_chan_scan_param_set),
1537                                  GFP_KERNEL);
1538         if (!scan_chan_list) {
1539                 kfree(scan_cfg_out);
1540                 ret = -ENOMEM;
1541                 goto done;
1542         }
1543
1544         mwifiex_config_scan(priv, user_scan_in, &scan_cfg_out->config,
1545                             &chan_list_out, scan_chan_list, &max_chan_per_scan,
1546                             &filtered_scan, &scan_current_chan_only);
1547
1548         ret = mwifiex_scan_channel_list(priv, max_chan_per_scan, filtered_scan,
1549                                         &scan_cfg_out->config, chan_list_out,
1550                                         scan_chan_list);
1551
1552         /* Get scan command from scan_pending_q and put to cmd_pending_q */
1553         if (!ret) {
1554                 spin_lock_irqsave(&adapter->scan_pending_q_lock, flags);
1555                 if (!list_empty(&adapter->scan_pending_q)) {
1556                         cmd_node = list_first_entry(&adapter->scan_pending_q,
1557                                                     struct cmd_ctrl_node, list);
1558                         list_del(&cmd_node->list);
1559                         spin_unlock_irqrestore(&adapter->scan_pending_q_lock,
1560                                                flags);
1561                         mwifiex_insert_cmd_to_pending_q(adapter, cmd_node);
1562                         queue_work(adapter->workqueue, &adapter->main_work);
1563
1564                         /* Perform internal scan synchronously */
1565                         if (!priv->scan_request) {
1566                                 mwifiex_dbg(adapter, INFO,
1567                                             "wait internal scan\n");
1568                                 mwifiex_wait_queue_complete(adapter, cmd_node);
1569                         }
1570                 } else {
1571                         spin_unlock_irqrestore(&adapter->scan_pending_q_lock,
1572                                                flags);
1573                 }
1574         }
1575
1576         kfree(scan_cfg_out);
1577         kfree(scan_chan_list);
1578 done:
1579         if (ret) {
1580                 spin_lock_irqsave(&adapter->mwifiex_cmd_lock, flags);
1581                 adapter->scan_processing = false;
1582                 spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, flags);
1583         }
1584         return ret;
1585 }
1586
1587 /*
1588  * This function prepares a scan command to be sent to the firmware.
1589  *
1590  * This uses the scan command configuration sent to the command processing
1591  * module in command preparation stage to configure a scan command structure
1592  * to send to firmware.
1593  *
1594  * The fixed fields specifying the BSS type and BSSID filters as well as a
1595  * variable number/length of TLVs are sent in the command to firmware.
1596  *
1597  * Preparation also includes -
1598  *      - Setting command ID, and proper size
1599  *      - Ensuring correct endian-ness
1600  */
1601 int mwifiex_cmd_802_11_scan(struct host_cmd_ds_command *cmd,
1602                             struct mwifiex_scan_cmd_config *scan_cfg)
1603 {
1604         struct host_cmd_ds_802_11_scan *scan_cmd = &cmd->params.scan;
1605
1606         /* Set fixed field variables in scan command */
1607         scan_cmd->bss_mode = scan_cfg->bss_mode;
1608         memcpy(scan_cmd->bssid, scan_cfg->specific_bssid,
1609                sizeof(scan_cmd->bssid));
1610         memcpy(scan_cmd->tlv_buffer, scan_cfg->tlv_buf, scan_cfg->tlv_buf_len);
1611
1612         cmd->command = cpu_to_le16(HostCmd_CMD_802_11_SCAN);
1613
1614         /* Size is equal to the sizeof(fixed portions) + the TLV len + header */
1615         cmd->size = cpu_to_le16((u16) (sizeof(scan_cmd->bss_mode)
1616                                           + sizeof(scan_cmd->bssid)
1617                                           + scan_cfg->tlv_buf_len + S_DS_GEN));
1618
1619         return 0;
1620 }
1621
1622 /*
1623  * This function checks compatibility of requested network with current
1624  * driver settings.
1625  */
1626 int mwifiex_check_network_compatibility(struct mwifiex_private *priv,
1627                                         struct mwifiex_bssdescriptor *bss_desc)
1628 {
1629         int ret = -1;
1630
1631         if (!bss_desc)
1632                 return -1;
1633
1634         if ((mwifiex_get_cfp(priv, (u8) bss_desc->bss_band,
1635                              (u16) bss_desc->channel, 0))) {
1636                 switch (priv->bss_mode) {
1637                 case NL80211_IFTYPE_STATION:
1638                 case NL80211_IFTYPE_ADHOC:
1639                         ret = mwifiex_is_network_compatible(priv, bss_desc,
1640                                                             priv->bss_mode);
1641                         if (ret)
1642                                 mwifiex_dbg(priv->adapter, ERROR,
1643                                             "Incompatible network settings\n");
1644                         break;
1645                 default:
1646                         ret = 0;
1647                 }
1648         }
1649
1650         return ret;
1651 }
1652
1653 /* This function checks if SSID string contains all zeroes or length is zero */
1654 static bool mwifiex_is_hidden_ssid(struct cfg80211_ssid *ssid)
1655 {
1656         int idx;
1657
1658         for (idx = 0; idx < ssid->ssid_len; idx++) {
1659                 if (ssid->ssid[idx])
1660                         return false;
1661         }
1662
1663         return true;
1664 }
1665
1666 /* This function checks if any hidden SSID found in passive scan channels
1667  * and save those channels for specific SSID active scan
1668  */
1669 static int mwifiex_save_hidden_ssid_channels(struct mwifiex_private *priv,
1670                                              struct cfg80211_bss *bss)
1671 {
1672         struct mwifiex_bssdescriptor *bss_desc;
1673         int ret;
1674         int chid;
1675
1676         /* Allocate and fill new bss descriptor */
1677         bss_desc = kzalloc(sizeof(*bss_desc), GFP_KERNEL);
1678         if (!bss_desc)
1679                 return -ENOMEM;
1680
1681         ret = mwifiex_fill_new_bss_desc(priv, bss, bss_desc);
1682         if (ret)
1683                 goto done;
1684
1685         if (mwifiex_is_hidden_ssid(&bss_desc->ssid)) {
1686                 mwifiex_dbg(priv->adapter, INFO, "found hidden SSID\n");
1687                 for (chid = 0 ; chid < MWIFIEX_USER_SCAN_CHAN_MAX; chid++) {
1688                         if (priv->hidden_chan[chid].chan_number ==
1689                             bss->channel->hw_value)
1690                                 break;
1691
1692                         if (!priv->hidden_chan[chid].chan_number) {
1693                                 priv->hidden_chan[chid].chan_number =
1694                                         bss->channel->hw_value;
1695                                 priv->hidden_chan[chid].radio_type =
1696                                         bss->channel->band;
1697                                 priv->hidden_chan[chid].scan_type =
1698                                         MWIFIEX_SCAN_TYPE_ACTIVE;
1699                                 break;
1700                         }
1701                 }
1702         }
1703
1704 done:
1705         /* beacon_ie buffer was allocated in function
1706          * mwifiex_fill_new_bss_desc(). Free it now.
1707          */
1708         kfree(bss_desc->beacon_buf);
1709         kfree(bss_desc);
1710         return 0;
1711 }
1712
1713 static int mwifiex_update_curr_bss_params(struct mwifiex_private *priv,
1714                                           struct cfg80211_bss *bss)
1715 {
1716         struct mwifiex_bssdescriptor *bss_desc;
1717         int ret;
1718         unsigned long flags;
1719
1720         /* Allocate and fill new bss descriptor */
1721         bss_desc = kzalloc(sizeof(struct mwifiex_bssdescriptor), GFP_KERNEL);
1722         if (!bss_desc)
1723                 return -ENOMEM;
1724
1725         ret = mwifiex_fill_new_bss_desc(priv, bss, bss_desc);
1726         if (ret)
1727                 goto done;
1728
1729         ret = mwifiex_check_network_compatibility(priv, bss_desc);
1730         if (ret)
1731                 goto done;
1732
1733         spin_lock_irqsave(&priv->curr_bcn_buf_lock, flags);
1734         /* Make a copy of current BSSID descriptor */
1735         memcpy(&priv->curr_bss_params.bss_descriptor, bss_desc,
1736                sizeof(priv->curr_bss_params.bss_descriptor));
1737
1738         /* The contents of beacon_ie will be copied to its own buffer
1739          * in mwifiex_save_curr_bcn()
1740          */
1741         mwifiex_save_curr_bcn(priv);
1742         spin_unlock_irqrestore(&priv->curr_bcn_buf_lock, flags);
1743
1744 done:
1745         /* beacon_ie buffer was allocated in function
1746          * mwifiex_fill_new_bss_desc(). Free it now.
1747          */
1748         kfree(bss_desc->beacon_buf);
1749         kfree(bss_desc);
1750         return 0;
1751 }
1752
1753 static int
1754 mwifiex_parse_single_response_buf(struct mwifiex_private *priv, u8 **bss_info,
1755                                   u32 *bytes_left, u64 fw_tsf, u8 *radio_type,
1756                                   bool ext_scan, s32 rssi_val)
1757 {
1758         struct mwifiex_adapter *adapter = priv->adapter;
1759         struct mwifiex_chan_freq_power *cfp;
1760         struct cfg80211_bss *bss;
1761         u8 bssid[ETH_ALEN];
1762         s32 rssi;
1763         const u8 *ie_buf;
1764         size_t ie_len;
1765         u16 channel = 0;
1766         u16 beacon_size = 0;
1767         u32 curr_bcn_bytes;
1768         u32 freq;
1769         u16 beacon_period;
1770         u16 cap_info_bitmap;
1771         u8 *current_ptr;
1772         u64 timestamp;
1773         struct mwifiex_fixed_bcn_param *bcn_param;
1774         struct mwifiex_bss_priv *bss_priv;
1775
1776         if (*bytes_left >= sizeof(beacon_size)) {
1777                 /* Extract & convert beacon size from command buffer */
1778                 beacon_size = get_unaligned_le16((*bss_info));
1779                 *bytes_left -= sizeof(beacon_size);
1780                 *bss_info += sizeof(beacon_size);
1781         }
1782
1783         if (!beacon_size || beacon_size > *bytes_left) {
1784                 *bss_info += *bytes_left;
1785                 *bytes_left = 0;
1786                 return -EFAULT;
1787         }
1788
1789         /* Initialize the current working beacon pointer for this BSS
1790          * iteration
1791          */
1792         current_ptr = *bss_info;
1793
1794         /* Advance the return beacon pointer past the current beacon */
1795         *bss_info += beacon_size;
1796         *bytes_left -= beacon_size;
1797
1798         curr_bcn_bytes = beacon_size;
1799
1800         /* First 5 fields are bssid, RSSI(for legacy scan only),
1801          * time stamp, beacon interval, and capability information
1802          */
1803         if (curr_bcn_bytes < ETH_ALEN + sizeof(u8) +
1804             sizeof(struct mwifiex_fixed_bcn_param)) {
1805                 mwifiex_dbg(adapter, ERROR,
1806                             "InterpretIE: not enough bytes left\n");
1807                 return -EFAULT;
1808         }
1809
1810         memcpy(bssid, current_ptr, ETH_ALEN);
1811         current_ptr += ETH_ALEN;
1812         curr_bcn_bytes -= ETH_ALEN;
1813
1814         if (!ext_scan) {
1815                 rssi = (s32) *current_ptr;
1816                 rssi = (-rssi) * 100;           /* Convert dBm to mBm */
1817                 current_ptr += sizeof(u8);
1818                 curr_bcn_bytes -= sizeof(u8);
1819                 mwifiex_dbg(adapter, INFO,
1820                             "info: InterpretIE: RSSI=%d\n", rssi);
1821         } else {
1822                 rssi = rssi_val;
1823         }
1824
1825         bcn_param = (struct mwifiex_fixed_bcn_param *)current_ptr;
1826         current_ptr += sizeof(*bcn_param);
1827         curr_bcn_bytes -= sizeof(*bcn_param);
1828
1829         timestamp = le64_to_cpu(bcn_param->timestamp);
1830         beacon_period = le16_to_cpu(bcn_param->beacon_period);
1831
1832         cap_info_bitmap = le16_to_cpu(bcn_param->cap_info_bitmap);
1833         mwifiex_dbg(adapter, INFO,
1834                     "info: InterpretIE: capabilities=0x%X\n",
1835                     cap_info_bitmap);
1836
1837         /* Rest of the current buffer are IE's */
1838         ie_buf = current_ptr;
1839         ie_len = curr_bcn_bytes;
1840         mwifiex_dbg(adapter, INFO,
1841                     "info: InterpretIE: IELength for this AP = %d\n",
1842                     curr_bcn_bytes);
1843
1844         while (curr_bcn_bytes >= sizeof(struct ieee_types_header)) {
1845                 u8 element_id, element_len;
1846
1847                 element_id = *current_ptr;
1848                 element_len = *(current_ptr + 1);
1849                 if (curr_bcn_bytes < element_len +
1850                                 sizeof(struct ieee_types_header)) {
1851                         mwifiex_dbg(adapter, ERROR,
1852                                     "%s: bytes left < IE length\n", __func__);
1853                         return -EFAULT;
1854                 }
1855                 if (element_id == WLAN_EID_DS_PARAMS) {
1856                         channel = *(current_ptr +
1857                                     sizeof(struct ieee_types_header));
1858                         break;
1859                 }
1860
1861                 current_ptr += element_len + sizeof(struct ieee_types_header);
1862                 curr_bcn_bytes -= element_len +
1863                                         sizeof(struct ieee_types_header);
1864         }
1865
1866         if (channel) {
1867                 struct ieee80211_channel *chan;
1868                 u8 band;
1869
1870                 /* Skip entry if on csa closed channel */
1871                 if (channel == priv->csa_chan) {
1872                         mwifiex_dbg(adapter, WARN,
1873                                     "Dropping entry on csa closed channel\n");
1874                         return 0;
1875                 }
1876
1877                 band = BAND_G;
1878                 if (radio_type)
1879                         band = mwifiex_radio_type_to_band(*radio_type &
1880                                                           (BIT(0) | BIT(1)));
1881
1882                 cfp = mwifiex_get_cfp(priv, band, channel, 0);
1883
1884                 freq = cfp ? cfp->freq : 0;
1885
1886                 chan = ieee80211_get_channel(priv->wdev.wiphy, freq);
1887
1888                 if (chan && !(chan->flags & IEEE80211_CHAN_DISABLED)) {
1889                         bss = cfg80211_inform_bss(priv->wdev.wiphy,
1890                                             chan, CFG80211_BSS_FTYPE_UNKNOWN,
1891                                             bssid, timestamp,
1892                                             cap_info_bitmap, beacon_period,
1893                                             ie_buf, ie_len, rssi, GFP_ATOMIC);
1894                         if (bss) {
1895                                 bss_priv = (struct mwifiex_bss_priv *)bss->priv;
1896                                 bss_priv->band = band;
1897                                 bss_priv->fw_tsf = fw_tsf;
1898                                 if (priv->media_connected &&
1899                                     !memcmp(bssid, priv->curr_bss_params.
1900                                             bss_descriptor.mac_address,
1901                                             ETH_ALEN))
1902                                         mwifiex_update_curr_bss_params(priv,
1903                                                                        bss);
1904
1905                                 if ((chan->flags & IEEE80211_CHAN_RADAR) ||
1906                                     (chan->flags & IEEE80211_CHAN_NO_IR)) {
1907                                         mwifiex_dbg(adapter, INFO,
1908                                                     "radar or passive channel %d\n",
1909                                                     channel);
1910                                         mwifiex_save_hidden_ssid_channels(priv,
1911                                                                           bss);
1912                                 }
1913
1914                                 cfg80211_put_bss(priv->wdev.wiphy, bss);
1915                         }
1916                 }
1917         } else {
1918                 mwifiex_dbg(adapter, WARN, "missing BSS channel IE\n");
1919         }
1920
1921         return 0;
1922 }
1923
1924 static void mwifiex_complete_scan(struct mwifiex_private *priv)
1925 {
1926         struct mwifiex_adapter *adapter = priv->adapter;
1927
1928         adapter->survey_idx = 0;
1929         if (adapter->curr_cmd->wait_q_enabled) {
1930                 adapter->cmd_wait_q.status = 0;
1931                 if (!priv->scan_request) {
1932                         mwifiex_dbg(adapter, INFO,
1933                                     "complete internal scan\n");
1934                         mwifiex_complete_cmd(adapter, adapter->curr_cmd);
1935                 }
1936         }
1937 }
1938
1939 /* This function checks if any hidden SSID found in passive scan channels
1940  * and do specific SSID active scan for those channels
1941  */
1942 static int
1943 mwifiex_active_scan_req_for_passive_chan(struct mwifiex_private *priv)
1944 {
1945         int ret;
1946         struct mwifiex_adapter *adapter = priv->adapter;
1947         u8 id = 0;
1948         struct mwifiex_user_scan_cfg  *user_scan_cfg;
1949
1950         if (adapter->active_scan_triggered || !priv->scan_request ||
1951             priv->scan_aborting) {
1952                 adapter->active_scan_triggered = false;
1953                 return 0;
1954         }
1955
1956         if (!priv->hidden_chan[0].chan_number) {
1957                 mwifiex_dbg(adapter, INFO, "No BSS with hidden SSID found on DFS channels\n");
1958                 return 0;
1959         }
1960         user_scan_cfg = kzalloc(sizeof(*user_scan_cfg), GFP_KERNEL);
1961
1962         if (!user_scan_cfg)
1963                 return -ENOMEM;
1964
1965         memset(user_scan_cfg, 0, sizeof(*user_scan_cfg));
1966
1967         for (id = 0; id < MWIFIEX_USER_SCAN_CHAN_MAX; id++) {
1968                 if (!priv->hidden_chan[id].chan_number)
1969                         break;
1970                 memcpy(&user_scan_cfg->chan_list[id],
1971                        &priv->hidden_chan[id],
1972                        sizeof(struct mwifiex_user_scan_chan));
1973         }
1974
1975         adapter->active_scan_triggered = true;
1976         if (priv->scan_request->flags & NL80211_SCAN_FLAG_RANDOM_ADDR)
1977                 ether_addr_copy(user_scan_cfg->random_mac, priv->random_mac);
1978         user_scan_cfg->num_ssids = priv->scan_request->n_ssids;
1979         user_scan_cfg->ssid_list = priv->scan_request->ssids;
1980
1981         ret = mwifiex_scan_networks(priv, user_scan_cfg);
1982         kfree(user_scan_cfg);
1983
1984         memset(&priv->hidden_chan, 0, sizeof(priv->hidden_chan));
1985
1986         if (ret) {
1987                 dev_err(priv->adapter->dev, "scan failed: %d\n", ret);
1988                 return ret;
1989         }
1990
1991         return 0;
1992 }
1993 static void mwifiex_check_next_scan_command(struct mwifiex_private *priv)
1994 {
1995         struct mwifiex_adapter *adapter = priv->adapter;
1996         struct cmd_ctrl_node *cmd_node;
1997         unsigned long flags;
1998
1999         spin_lock_irqsave(&adapter->scan_pending_q_lock, flags);
2000         if (list_empty(&adapter->scan_pending_q)) {
2001                 spin_unlock_irqrestore(&adapter->scan_pending_q_lock, flags);
2002
2003                 spin_lock_irqsave(&adapter->mwifiex_cmd_lock, flags);
2004                 adapter->scan_processing = false;
2005                 spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, flags);
2006
2007                 mwifiex_active_scan_req_for_passive_chan(priv);
2008
2009                 if (!adapter->ext_scan)
2010                         mwifiex_complete_scan(priv);
2011
2012                 if (priv->scan_request) {
2013                         struct cfg80211_scan_info info = {
2014                                 .aborted = false,
2015                         };
2016
2017                         mwifiex_dbg(adapter, INFO,
2018                                     "info: notifying scan done\n");
2019                         cfg80211_scan_done(priv->scan_request, &info);
2020                         priv->scan_request = NULL;
2021                         priv->scan_aborting = false;
2022                 } else {
2023                         priv->scan_aborting = false;
2024                         mwifiex_dbg(adapter, INFO,
2025                                     "info: scan already aborted\n");
2026                 }
2027         } else if ((priv->scan_aborting && !priv->scan_request) ||
2028                    priv->scan_block) {
2029                 spin_unlock_irqrestore(&adapter->scan_pending_q_lock, flags);
2030
2031                 mwifiex_cancel_pending_scan_cmd(adapter);
2032
2033                 spin_lock_irqsave(&adapter->mwifiex_cmd_lock, flags);
2034                 adapter->scan_processing = false;
2035                 spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, flags);
2036
2037                 if (!adapter->active_scan_triggered) {
2038                         if (priv->scan_request) {
2039                                 struct cfg80211_scan_info info = {
2040                                         .aborted = true,
2041                                 };
2042
2043                                 mwifiex_dbg(adapter, INFO,
2044                                             "info: aborting scan\n");
2045                                 cfg80211_scan_done(priv->scan_request, &info);
2046                                 priv->scan_request = NULL;
2047                                 priv->scan_aborting = false;
2048                         } else {
2049                                 priv->scan_aborting = false;
2050                                 mwifiex_dbg(adapter, INFO,
2051                                             "info: scan already aborted\n");
2052                         }
2053                 }
2054         } else {
2055                 /* Get scan command from scan_pending_q and put to
2056                  * cmd_pending_q
2057                  */
2058                 cmd_node = list_first_entry(&adapter->scan_pending_q,
2059                                             struct cmd_ctrl_node, list);
2060                 list_del(&cmd_node->list);
2061                 spin_unlock_irqrestore(&adapter->scan_pending_q_lock, flags);
2062                 mwifiex_insert_cmd_to_pending_q(adapter, cmd_node);
2063         }
2064
2065         return;
2066 }
2067
2068 void mwifiex_cancel_scan(struct mwifiex_adapter *adapter)
2069 {
2070         struct mwifiex_private *priv;
2071         unsigned long cmd_flags;
2072         int i;
2073
2074         mwifiex_cancel_pending_scan_cmd(adapter);
2075
2076         if (adapter->scan_processing) {
2077                 spin_lock_irqsave(&adapter->mwifiex_cmd_lock, cmd_flags);
2078                 adapter->scan_processing = false;
2079                 spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, cmd_flags);
2080                 for (i = 0; i < adapter->priv_num; i++) {
2081                         priv = adapter->priv[i];
2082                         if (!priv)
2083                                 continue;
2084                         if (priv->scan_request) {
2085                                 struct cfg80211_scan_info info = {
2086                                         .aborted = true,
2087                                 };
2088
2089                                 mwifiex_dbg(adapter, INFO,
2090                                             "info: aborting scan\n");
2091                                 cfg80211_scan_done(priv->scan_request, &info);
2092                                 priv->scan_request = NULL;
2093                                 priv->scan_aborting = false;
2094                         }
2095                 }
2096         }
2097 }
2098
2099 /*
2100  * This function handles the command response of scan.
2101  *
2102  * The response buffer for the scan command has the following
2103  * memory layout:
2104  *
2105  *      .-------------------------------------------------------------.
2106  *      |  Header (4 * sizeof(t_u16)):  Standard command response hdr |
2107  *      .-------------------------------------------------------------.
2108  *      |  BufSize (t_u16) : sizeof the BSS Description data          |
2109  *      .-------------------------------------------------------------.
2110  *      |  NumOfSet (t_u8) : Number of BSS Descs returned             |
2111  *      .-------------------------------------------------------------.
2112  *      |  BSSDescription data (variable, size given in BufSize)      |
2113  *      .-------------------------------------------------------------.
2114  *      |  TLV data (variable, size calculated using Header->Size,    |
2115  *      |            BufSize and sizeof the fixed fields above)       |
2116  *      .-------------------------------------------------------------.
2117  */
2118 int mwifiex_ret_802_11_scan(struct mwifiex_private *priv,
2119                             struct host_cmd_ds_command *resp)
2120 {
2121         int ret = 0;
2122         struct mwifiex_adapter *adapter = priv->adapter;
2123         struct host_cmd_ds_802_11_scan_rsp *scan_rsp;
2124         struct mwifiex_ie_types_data *tlv_data;
2125         struct mwifiex_ie_types_tsf_timestamp *tsf_tlv;
2126         u8 *bss_info;
2127         u32 scan_resp_size;
2128         u32 bytes_left;
2129         u32 idx;
2130         u32 tlv_buf_size;
2131         struct mwifiex_ie_types_chan_band_list_param_set *chan_band_tlv;
2132         struct chan_band_param_set *chan_band;
2133         u8 is_bgscan_resp;
2134         __le64 fw_tsf = 0;
2135         u8 *radio_type;
2136         struct cfg80211_wowlan_nd_match *pmatch;
2137         struct cfg80211_sched_scan_request *nd_config = NULL;
2138
2139         is_bgscan_resp = (le16_to_cpu(resp->command)
2140                           == HostCmd_CMD_802_11_BG_SCAN_QUERY);
2141         if (is_bgscan_resp)
2142                 scan_rsp = &resp->params.bg_scan_query_resp.scan_resp;
2143         else
2144                 scan_rsp = &resp->params.scan_resp;
2145
2146
2147         if (scan_rsp->number_of_sets > MWIFIEX_MAX_AP) {
2148                 mwifiex_dbg(adapter, ERROR,
2149                             "SCAN_RESP: too many AP returned (%d)\n",
2150                             scan_rsp->number_of_sets);
2151                 ret = -1;
2152                 goto check_next_scan;
2153         }
2154
2155         /* Check csa channel expiry before parsing scan response */
2156         mwifiex_11h_get_csa_closed_channel(priv);
2157
2158         bytes_left = le16_to_cpu(scan_rsp->bss_descript_size);
2159         mwifiex_dbg(adapter, INFO,
2160                     "info: SCAN_RESP: bss_descript_size %d\n",
2161                     bytes_left);
2162
2163         scan_resp_size = le16_to_cpu(resp->size);
2164
2165         mwifiex_dbg(adapter, INFO,
2166                     "info: SCAN_RESP: returned %d APs before parsing\n",
2167                     scan_rsp->number_of_sets);
2168
2169         bss_info = scan_rsp->bss_desc_and_tlv_buffer;
2170
2171         /*
2172          * The size of the TLV buffer is equal to the entire command response
2173          *   size (scan_resp_size) minus the fixed fields (sizeof()'s), the
2174          *   BSS Descriptions (bss_descript_size as bytesLef) and the command
2175          *   response header (S_DS_GEN)
2176          */
2177         tlv_buf_size = scan_resp_size - (bytes_left
2178                                          + sizeof(scan_rsp->bss_descript_size)
2179                                          + sizeof(scan_rsp->number_of_sets)
2180                                          + S_DS_GEN);
2181
2182         tlv_data = (struct mwifiex_ie_types_data *) (scan_rsp->
2183                                                  bss_desc_and_tlv_buffer +
2184                                                  bytes_left);
2185
2186         /* Search the TLV buffer space in the scan response for any valid
2187            TLVs */
2188         mwifiex_ret_802_11_scan_get_tlv_ptrs(adapter, tlv_data, tlv_buf_size,
2189                                              TLV_TYPE_TSFTIMESTAMP,
2190                                              (struct mwifiex_ie_types_data **)
2191                                              &tsf_tlv);
2192
2193         /* Search the TLV buffer space in the scan response for any valid
2194            TLVs */
2195         mwifiex_ret_802_11_scan_get_tlv_ptrs(adapter, tlv_data, tlv_buf_size,
2196                                              TLV_TYPE_CHANNELBANDLIST,
2197                                              (struct mwifiex_ie_types_data **)
2198                                              &chan_band_tlv);
2199
2200 #ifdef CONFIG_PM
2201         if (priv->wdev.wiphy->wowlan_config)
2202                 nd_config = priv->wdev.wiphy->wowlan_config->nd_config;
2203 #endif
2204
2205         if (nd_config) {
2206                 adapter->nd_info =
2207                         kzalloc(sizeof(struct cfg80211_wowlan_nd_match) +
2208                                 sizeof(struct cfg80211_wowlan_nd_match *) *
2209                                 scan_rsp->number_of_sets, GFP_ATOMIC);
2210
2211                 if (adapter->nd_info)
2212                         adapter->nd_info->n_matches = scan_rsp->number_of_sets;
2213         }
2214
2215         for (idx = 0; idx < scan_rsp->number_of_sets && bytes_left; idx++) {
2216                 /*
2217                  * If the TSF TLV was appended to the scan results, save this
2218                  * entry's TSF value in the fw_tsf field. It is the firmware's
2219                  * TSF value at the time the beacon or probe response was
2220                  * received.
2221                  */
2222                 if (tsf_tlv)
2223                         memcpy(&fw_tsf, &tsf_tlv->tsf_data[idx * TSF_DATA_SIZE],
2224                                sizeof(fw_tsf));
2225
2226                 if (chan_band_tlv) {
2227                         chan_band = &chan_band_tlv->chan_band_param[idx];
2228                         radio_type = &chan_band->radio_type;
2229                 } else {
2230                         radio_type = NULL;
2231                 }
2232
2233                 if (chan_band_tlv && adapter->nd_info) {
2234                         adapter->nd_info->matches[idx] =
2235                                 kzalloc(sizeof(*pmatch) + sizeof(u32),
2236                                         GFP_ATOMIC);
2237
2238                         pmatch = adapter->nd_info->matches[idx];
2239
2240                         if (pmatch) {
2241                                 pmatch->n_channels = 1;
2242                                 pmatch->channels[0] = chan_band->chan_number;
2243                         }
2244                 }
2245
2246                 ret = mwifiex_parse_single_response_buf(priv, &bss_info,
2247                                                         &bytes_left,
2248                                                         le64_to_cpu(fw_tsf),
2249                                                         radio_type, false, 0);
2250                 if (ret)
2251                         goto check_next_scan;
2252         }
2253
2254 check_next_scan:
2255         mwifiex_check_next_scan_command(priv);
2256         return ret;
2257 }
2258
2259 /*
2260  * This function prepares an extended scan command to be sent to the firmware
2261  *
2262  * This uses the scan command configuration sent to the command processing
2263  * module in command preparation stage to configure a extended scan command
2264  * structure to send to firmware.
2265  */
2266 int mwifiex_cmd_802_11_scan_ext(struct mwifiex_private *priv,
2267                                 struct host_cmd_ds_command *cmd,
2268                                 void *data_buf)
2269 {
2270         struct host_cmd_ds_802_11_scan_ext *ext_scan = &cmd->params.ext_scan;
2271         struct mwifiex_scan_cmd_config *scan_cfg = data_buf;
2272
2273         memcpy(ext_scan->tlv_buffer, scan_cfg->tlv_buf, scan_cfg->tlv_buf_len);
2274
2275         cmd->command = cpu_to_le16(HostCmd_CMD_802_11_SCAN_EXT);
2276
2277         /* Size is equal to the sizeof(fixed portions) + the TLV len + header */
2278         cmd->size = cpu_to_le16((u16)(sizeof(ext_scan->reserved)
2279                                       + scan_cfg->tlv_buf_len + S_DS_GEN));
2280
2281         return 0;
2282 }
2283
2284 /* This function prepares an background scan config command to be sent
2285  * to the firmware
2286  */
2287 int mwifiex_cmd_802_11_bg_scan_config(struct mwifiex_private *priv,
2288                                       struct host_cmd_ds_command *cmd,
2289                                       void *data_buf)
2290 {
2291         struct host_cmd_ds_802_11_bg_scan_config *bgscan_config =
2292                                         &cmd->params.bg_scan_config;
2293         struct mwifiex_bg_scan_cfg *bgscan_cfg_in = data_buf;
2294         u8 *tlv_pos = bgscan_config->tlv;
2295         u8 num_probes;
2296         u32 ssid_len, chan_idx, scan_type, scan_dur, chan_num;
2297         int i;
2298         struct mwifiex_ie_types_num_probes *num_probes_tlv;
2299         struct mwifiex_ie_types_repeat_count *repeat_count_tlv;
2300         struct mwifiex_ie_types_min_rssi_threshold *rssi_threshold_tlv;
2301         struct mwifiex_ie_types_bgscan_start_later *start_later_tlv;
2302         struct mwifiex_ie_types_wildcard_ssid_params *wildcard_ssid_tlv;
2303         struct mwifiex_ie_types_chan_list_param_set *chan_list_tlv;
2304         struct mwifiex_chan_scan_param_set *temp_chan;
2305
2306         cmd->command = cpu_to_le16(HostCmd_CMD_802_11_BG_SCAN_CONFIG);
2307         cmd->size = cpu_to_le16(sizeof(*bgscan_config) + S_DS_GEN);
2308
2309         bgscan_config->action = cpu_to_le16(bgscan_cfg_in->action);
2310         bgscan_config->enable = bgscan_cfg_in->enable;
2311         bgscan_config->bss_type = bgscan_cfg_in->bss_type;
2312         bgscan_config->scan_interval =
2313                 cpu_to_le32(bgscan_cfg_in->scan_interval);
2314         bgscan_config->report_condition =
2315                 cpu_to_le32(bgscan_cfg_in->report_condition);
2316
2317         /*  stop sched scan  */
2318         if (!bgscan_config->enable)
2319                 return 0;
2320
2321         bgscan_config->chan_per_scan = bgscan_cfg_in->chan_per_scan;
2322
2323         num_probes = (bgscan_cfg_in->num_probes ? bgscan_cfg_in->
2324                       num_probes : priv->adapter->scan_probes);
2325
2326         if (num_probes) {
2327                 num_probes_tlv = (struct mwifiex_ie_types_num_probes *)tlv_pos;
2328                 num_probes_tlv->header.type = cpu_to_le16(TLV_TYPE_NUMPROBES);
2329                 num_probes_tlv->header.len =
2330                         cpu_to_le16(sizeof(num_probes_tlv->num_probes));
2331                 num_probes_tlv->num_probes = cpu_to_le16((u16)num_probes);
2332
2333                 tlv_pos += sizeof(num_probes_tlv->header) +
2334                         le16_to_cpu(num_probes_tlv->header.len);
2335         }
2336
2337         if (bgscan_cfg_in->repeat_count) {
2338                 repeat_count_tlv =
2339                         (struct mwifiex_ie_types_repeat_count *)tlv_pos;
2340                 repeat_count_tlv->header.type =
2341                         cpu_to_le16(TLV_TYPE_REPEAT_COUNT);
2342                 repeat_count_tlv->header.len =
2343                         cpu_to_le16(sizeof(repeat_count_tlv->repeat_count));
2344                 repeat_count_tlv->repeat_count =
2345                         cpu_to_le16(bgscan_cfg_in->repeat_count);
2346
2347                 tlv_pos += sizeof(repeat_count_tlv->header) +
2348                         le16_to_cpu(repeat_count_tlv->header.len);
2349         }
2350
2351         if (bgscan_cfg_in->rssi_threshold) {
2352                 rssi_threshold_tlv =
2353                         (struct mwifiex_ie_types_min_rssi_threshold *)tlv_pos;
2354                 rssi_threshold_tlv->header.type =
2355                         cpu_to_le16(TLV_TYPE_RSSI_LOW);
2356                 rssi_threshold_tlv->header.len =
2357                         cpu_to_le16(sizeof(rssi_threshold_tlv->rssi_threshold));
2358                 rssi_threshold_tlv->rssi_threshold =
2359                         cpu_to_le16(bgscan_cfg_in->rssi_threshold);
2360
2361                 tlv_pos += sizeof(rssi_threshold_tlv->header) +
2362                         le16_to_cpu(rssi_threshold_tlv->header.len);
2363         }
2364
2365         for (i = 0; i < bgscan_cfg_in->num_ssids; i++) {
2366                 ssid_len = bgscan_cfg_in->ssid_list[i].ssid.ssid_len;
2367
2368                 wildcard_ssid_tlv =
2369                         (struct mwifiex_ie_types_wildcard_ssid_params *)tlv_pos;
2370                 wildcard_ssid_tlv->header.type =
2371                                 cpu_to_le16(TLV_TYPE_WILDCARDSSID);
2372                 wildcard_ssid_tlv->header.len = cpu_to_le16(
2373                                 (u16)(ssid_len + sizeof(wildcard_ssid_tlv->
2374                                                          max_ssid_length)));
2375
2376                 /* max_ssid_length = 0 tells firmware to perform
2377                  * specific scan for the SSID filled, whereas
2378                  * max_ssid_length = IEEE80211_MAX_SSID_LEN is for
2379                  * wildcard scan.
2380                  */
2381                 if (ssid_len)
2382                         wildcard_ssid_tlv->max_ssid_length = 0;
2383                 else
2384                         wildcard_ssid_tlv->max_ssid_length =
2385                                                 IEEE80211_MAX_SSID_LEN;
2386
2387                 memcpy(wildcard_ssid_tlv->ssid,
2388                        bgscan_cfg_in->ssid_list[i].ssid.ssid, ssid_len);
2389
2390                 tlv_pos += (sizeof(wildcard_ssid_tlv->header)
2391                                 + le16_to_cpu(wildcard_ssid_tlv->header.len));
2392         }
2393
2394         chan_list_tlv = (struct mwifiex_ie_types_chan_list_param_set *)tlv_pos;
2395
2396         if (bgscan_cfg_in->chan_list[0].chan_number) {
2397                 dev_dbg(priv->adapter->dev, "info: bgscan: Using supplied channel list\n");
2398
2399                 chan_list_tlv->header.type = cpu_to_le16(TLV_TYPE_CHANLIST);
2400
2401                 for (chan_idx = 0;
2402                      chan_idx < MWIFIEX_BG_SCAN_CHAN_MAX &&
2403                      bgscan_cfg_in->chan_list[chan_idx].chan_number;
2404                      chan_idx++) {
2405                         temp_chan = chan_list_tlv->chan_scan_param + chan_idx;
2406
2407                         /* Increment the TLV header length by size appended */
2408                         le16_unaligned_add_cpu(&chan_list_tlv->header.len,
2409                                                sizeof(
2410                                                chan_list_tlv->chan_scan_param));
2411
2412                         temp_chan->chan_number =
2413                                 bgscan_cfg_in->chan_list[chan_idx].chan_number;
2414                         temp_chan->radio_type =
2415                                 bgscan_cfg_in->chan_list[chan_idx].radio_type;
2416
2417                         scan_type =
2418                                 bgscan_cfg_in->chan_list[chan_idx].scan_type;
2419
2420                         if (scan_type == MWIFIEX_SCAN_TYPE_PASSIVE)
2421                                 temp_chan->chan_scan_mode_bitmap
2422                                         |= MWIFIEX_PASSIVE_SCAN;
2423                         else
2424                                 temp_chan->chan_scan_mode_bitmap
2425                                         &= ~MWIFIEX_PASSIVE_SCAN;
2426
2427                         if (bgscan_cfg_in->chan_list[chan_idx].scan_time) {
2428                                 scan_dur = (u16)bgscan_cfg_in->
2429                                         chan_list[chan_idx].scan_time;
2430                         } else {
2431                                 scan_dur = (scan_type ==
2432                                             MWIFIEX_SCAN_TYPE_PASSIVE) ?
2433                                             priv->adapter->passive_scan_time :
2434                                             priv->adapter->specific_scan_time;
2435                         }
2436
2437                         temp_chan->min_scan_time = cpu_to_le16(scan_dur);
2438                         temp_chan->max_scan_time = cpu_to_le16(scan_dur);
2439                 }
2440         } else {
2441                 dev_dbg(priv->adapter->dev,
2442                         "info: bgscan: Creating full region channel list\n");
2443                 chan_num =
2444                         mwifiex_bgscan_create_channel_list(priv, bgscan_cfg_in,
2445                                                            chan_list_tlv->
2446                                                            chan_scan_param);
2447                 le16_unaligned_add_cpu(&chan_list_tlv->header.len,
2448                                        chan_num *
2449                              sizeof(chan_list_tlv->chan_scan_param[0]));
2450         }
2451
2452         tlv_pos += (sizeof(chan_list_tlv->header)
2453                         + le16_to_cpu(chan_list_tlv->header.len));
2454
2455         if (bgscan_cfg_in->start_later) {
2456                 start_later_tlv =
2457                         (struct mwifiex_ie_types_bgscan_start_later *)tlv_pos;
2458                 start_later_tlv->header.type =
2459                         cpu_to_le16(TLV_TYPE_BGSCAN_START_LATER);
2460                 start_later_tlv->header.len =
2461                         cpu_to_le16(sizeof(start_later_tlv->start_later));
2462                 start_later_tlv->start_later =
2463                         cpu_to_le16(bgscan_cfg_in->start_later);
2464
2465                 tlv_pos += sizeof(start_later_tlv->header) +
2466                         le16_to_cpu(start_later_tlv->header.len);
2467         }
2468
2469         /* Append vendor specific IE TLV */
2470         mwifiex_cmd_append_vsie_tlv(priv, MWIFIEX_VSIE_MASK_BGSCAN, &tlv_pos);
2471
2472         le16_unaligned_add_cpu(&cmd->size, tlv_pos - bgscan_config->tlv);
2473
2474         return 0;
2475 }
2476
2477 int mwifiex_stop_bg_scan(struct mwifiex_private *priv)
2478 {
2479         struct mwifiex_bg_scan_cfg *bgscan_cfg;
2480
2481         if (!priv->sched_scanning) {
2482                 dev_dbg(priv->adapter->dev, "bgscan already stopped!\n");
2483                 return 0;
2484         }
2485
2486         bgscan_cfg = kzalloc(sizeof(*bgscan_cfg), GFP_KERNEL);
2487         if (!bgscan_cfg)
2488                 return -ENOMEM;
2489
2490         bgscan_cfg->bss_type = MWIFIEX_BSS_MODE_INFRA;
2491         bgscan_cfg->action = MWIFIEX_BGSCAN_ACT_SET;
2492         bgscan_cfg->enable = false;
2493
2494         if (mwifiex_send_cmd(priv, HostCmd_CMD_802_11_BG_SCAN_CONFIG,
2495                              HostCmd_ACT_GEN_SET, 0, bgscan_cfg, true)) {
2496                 kfree(bgscan_cfg);
2497                 return -EFAULT;
2498         }
2499
2500         kfree(bgscan_cfg);
2501         priv->sched_scanning = false;
2502
2503         return 0;
2504 }
2505
2506 static void
2507 mwifiex_update_chan_statistics(struct mwifiex_private *priv,
2508                                struct mwifiex_ietypes_chanstats *tlv_stat)
2509 {
2510         struct mwifiex_adapter *adapter = priv->adapter;
2511         u8 i, num_chan;
2512         struct mwifiex_fw_chan_stats *fw_chan_stats;
2513         struct mwifiex_chan_stats chan_stats;
2514
2515         fw_chan_stats = (void *)((u8 *)tlv_stat +
2516                               sizeof(struct mwifiex_ie_types_header));
2517         num_chan = le16_to_cpu(tlv_stat->header.len) /
2518                                               sizeof(struct mwifiex_chan_stats);
2519
2520         for (i = 0 ; i < num_chan; i++) {
2521                 if (adapter->survey_idx >= adapter->num_in_chan_stats) {
2522                         mwifiex_dbg(adapter, WARN,
2523                                     "FW reported too many channel results (max %d)\n",
2524                                     adapter->num_in_chan_stats);
2525                         return;
2526                 }
2527                 chan_stats.chan_num = fw_chan_stats->chan_num;
2528                 chan_stats.bandcfg = fw_chan_stats->bandcfg;
2529                 chan_stats.flags = fw_chan_stats->flags;
2530                 chan_stats.noise = fw_chan_stats->noise;
2531                 chan_stats.total_bss = le16_to_cpu(fw_chan_stats->total_bss);
2532                 chan_stats.cca_scan_dur =
2533                                        le16_to_cpu(fw_chan_stats->cca_scan_dur);
2534                 chan_stats.cca_busy_dur =
2535                                        le16_to_cpu(fw_chan_stats->cca_busy_dur);
2536                 mwifiex_dbg(adapter, INFO,
2537                             "chan=%d, noise=%d, total_network=%d scan_duration=%d, busy_duration=%d\n",
2538                             chan_stats.chan_num,
2539                             chan_stats.noise,
2540                             chan_stats.total_bss,
2541                             chan_stats.cca_scan_dur,
2542                             chan_stats.cca_busy_dur);
2543                 memcpy(&adapter->chan_stats[adapter->survey_idx++], &chan_stats,
2544                        sizeof(struct mwifiex_chan_stats));
2545                 fw_chan_stats++;
2546         }
2547 }
2548
2549 /* This function handles the command response of extended scan */
2550 int mwifiex_ret_802_11_scan_ext(struct mwifiex_private *priv,
2551                                 struct host_cmd_ds_command *resp)
2552 {
2553         struct mwifiex_adapter *adapter = priv->adapter;
2554         struct host_cmd_ds_802_11_scan_ext *ext_scan_resp;
2555         struct mwifiex_ie_types_header *tlv;
2556         struct mwifiex_ietypes_chanstats *tlv_stat;
2557         u16 buf_left, type, len;
2558
2559         struct host_cmd_ds_command *cmd_ptr;
2560         struct cmd_ctrl_node *cmd_node;
2561         unsigned long cmd_flags, scan_flags;
2562         bool complete_scan = false;
2563
2564         mwifiex_dbg(adapter, INFO, "info: EXT scan returns successfully\n");
2565
2566         ext_scan_resp = &resp->params.ext_scan;
2567
2568         tlv = (void *)ext_scan_resp->tlv_buffer;
2569         buf_left = le16_to_cpu(resp->size) - (sizeof(*ext_scan_resp) + S_DS_GEN
2570                                               - 1);
2571
2572         while (buf_left >= sizeof(struct mwifiex_ie_types_header)) {
2573                 type = le16_to_cpu(tlv->type);
2574                 len = le16_to_cpu(tlv->len);
2575
2576                 if (buf_left < (sizeof(struct mwifiex_ie_types_header) + len)) {
2577                         mwifiex_dbg(adapter, ERROR,
2578                                     "error processing scan response TLVs");
2579                         break;
2580                 }
2581
2582                 switch (type) {
2583                 case TLV_TYPE_CHANNEL_STATS:
2584                         tlv_stat = (void *)tlv;
2585                         mwifiex_update_chan_statistics(priv, tlv_stat);
2586                         break;
2587                 default:
2588                         break;
2589                 }
2590
2591                 buf_left -= len + sizeof(struct mwifiex_ie_types_header);
2592                 tlv = (void *)((u8 *)tlv + len +
2593                                sizeof(struct mwifiex_ie_types_header));
2594         }
2595
2596         spin_lock_irqsave(&adapter->cmd_pending_q_lock, cmd_flags);
2597         spin_lock_irqsave(&adapter->scan_pending_q_lock, scan_flags);
2598         if (list_empty(&adapter->scan_pending_q)) {
2599                 complete_scan = true;
2600                 list_for_each_entry(cmd_node, &adapter->cmd_pending_q, list) {
2601                         cmd_ptr = (void *)cmd_node->cmd_skb->data;
2602                         if (le16_to_cpu(cmd_ptr->command) ==
2603                             HostCmd_CMD_802_11_SCAN_EXT) {
2604                                 mwifiex_dbg(adapter, INFO,
2605                                             "Scan pending in command pending list");
2606                                 complete_scan = false;
2607                                 break;
2608                         }
2609                 }
2610         }
2611         spin_unlock_irqrestore(&adapter->scan_pending_q_lock, scan_flags);
2612         spin_unlock_irqrestore(&adapter->cmd_pending_q_lock, cmd_flags);
2613
2614         if (complete_scan)
2615                 mwifiex_complete_scan(priv);
2616
2617         return 0;
2618 }
2619
2620 /* This function This function handles the event extended scan report. It
2621  * parses extended scan results and informs to cfg80211 stack.
2622  */
2623 int mwifiex_handle_event_ext_scan_report(struct mwifiex_private *priv,
2624                                          void *buf)
2625 {
2626         int ret = 0;
2627         struct mwifiex_adapter *adapter = priv->adapter;
2628         u8 *bss_info;
2629         u32 bytes_left, bytes_left_for_tlv, idx;
2630         u16 type, len;
2631         struct mwifiex_ie_types_data *tlv;
2632         struct mwifiex_ie_types_bss_scan_rsp *scan_rsp_tlv;
2633         struct mwifiex_ie_types_bss_scan_info *scan_info_tlv;
2634         u8 *radio_type;
2635         u64 fw_tsf = 0;
2636         s32 rssi = 0;
2637         struct mwifiex_event_scan_result *event_scan = buf;
2638         u8 num_of_set = event_scan->num_of_set;
2639         u8 *scan_resp = buf + sizeof(struct mwifiex_event_scan_result);
2640         u16 scan_resp_size = le16_to_cpu(event_scan->buf_size);
2641
2642         if (num_of_set > MWIFIEX_MAX_AP) {
2643                 mwifiex_dbg(adapter, ERROR,
2644                             "EXT_SCAN: Invalid number of AP returned (%d)!!\n",
2645                             num_of_set);
2646                 ret = -1;
2647                 goto check_next_scan;
2648         }
2649
2650         bytes_left = scan_resp_size;
2651         mwifiex_dbg(adapter, INFO,
2652                     "EXT_SCAN: size %d, returned %d APs...",
2653                     scan_resp_size, num_of_set);
2654         mwifiex_dbg_dump(adapter, CMD_D, "EXT_SCAN buffer:", buf,
2655                          scan_resp_size +
2656                          sizeof(struct mwifiex_event_scan_result));
2657
2658         tlv = (struct mwifiex_ie_types_data *)scan_resp;
2659
2660         for (idx = 0; idx < num_of_set && bytes_left; idx++) {
2661                 type = le16_to_cpu(tlv->header.type);
2662                 len = le16_to_cpu(tlv->header.len);
2663                 if (bytes_left < sizeof(struct mwifiex_ie_types_header) + len) {
2664                         mwifiex_dbg(adapter, ERROR,
2665                                     "EXT_SCAN: Error bytes left < TLV length\n");
2666                         break;
2667                 }
2668                 scan_rsp_tlv = NULL;
2669                 scan_info_tlv = NULL;
2670                 bytes_left_for_tlv = bytes_left;
2671
2672                 /* BSS response TLV with beacon or probe response buffer
2673                  * at the initial position of each descriptor
2674                  */
2675                 if (type != TLV_TYPE_BSS_SCAN_RSP)
2676                         break;
2677
2678                 bss_info = (u8 *)tlv;
2679                 scan_rsp_tlv = (struct mwifiex_ie_types_bss_scan_rsp *)tlv;
2680                 tlv = (struct mwifiex_ie_types_data *)(tlv->data + len);
2681                 bytes_left_for_tlv -=
2682                                 (len + sizeof(struct mwifiex_ie_types_header));
2683
2684                 while (bytes_left_for_tlv >=
2685                        sizeof(struct mwifiex_ie_types_header) &&
2686                        le16_to_cpu(tlv->header.type) != TLV_TYPE_BSS_SCAN_RSP) {
2687                         type = le16_to_cpu(tlv->header.type);
2688                         len = le16_to_cpu(tlv->header.len);
2689                         if (bytes_left_for_tlv <
2690                             sizeof(struct mwifiex_ie_types_header) + len) {
2691                                 mwifiex_dbg(adapter, ERROR,
2692                                             "EXT_SCAN: Error in processing TLV,\t"
2693                                             "bytes left < TLV length\n");
2694                                 scan_rsp_tlv = NULL;
2695                                 bytes_left_for_tlv = 0;
2696                                 continue;
2697                         }
2698                         switch (type) {
2699                         case TLV_TYPE_BSS_SCAN_INFO:
2700                                 scan_info_tlv =
2701                                   (struct mwifiex_ie_types_bss_scan_info *)tlv;
2702                                 if (len !=
2703                                  sizeof(struct mwifiex_ie_types_bss_scan_info) -
2704                                  sizeof(struct mwifiex_ie_types_header)) {
2705                                         bytes_left_for_tlv = 0;
2706                                         continue;
2707                                 }
2708                                 break;
2709                         default:
2710                                 break;
2711                         }
2712                         tlv = (struct mwifiex_ie_types_data *)(tlv->data + len);
2713                         bytes_left -=
2714                                 (len + sizeof(struct mwifiex_ie_types_header));
2715                         bytes_left_for_tlv -=
2716                                 (len + sizeof(struct mwifiex_ie_types_header));
2717                 }
2718
2719                 if (!scan_rsp_tlv)
2720                         break;
2721
2722                 /* Advance pointer to the beacon buffer length and
2723                  * update the bytes count so that the function
2724                  * wlan_interpret_bss_desc_with_ie() can handle the
2725                  * scan buffer withut any change
2726                  */
2727                 bss_info += sizeof(u16);
2728                 bytes_left -= sizeof(u16);
2729
2730                 if (scan_info_tlv) {
2731                         rssi = (s32)(s16)(le16_to_cpu(scan_info_tlv->rssi));
2732                         rssi *= 100;           /* Convert dBm to mBm */
2733                         mwifiex_dbg(adapter, INFO,
2734                                     "info: InterpretIE: RSSI=%d\n", rssi);
2735                         fw_tsf = le64_to_cpu(scan_info_tlv->tsf);
2736                         radio_type = &scan_info_tlv->radio_type;
2737                 } else {
2738                         radio_type = NULL;
2739                 }
2740                 ret = mwifiex_parse_single_response_buf(priv, &bss_info,
2741                                                         &bytes_left, fw_tsf,
2742                                                         radio_type, true, rssi);
2743                 if (ret)
2744                         goto check_next_scan;
2745         }
2746
2747 check_next_scan:
2748         if (!event_scan->more_event)
2749                 mwifiex_check_next_scan_command(priv);
2750
2751         return ret;
2752 }
2753
2754 /*
2755  * This function prepares command for background scan query.
2756  *
2757  * Preparation includes -
2758  *      - Setting command ID and proper size
2759  *      - Setting background scan flush parameter
2760  *      - Ensuring correct endian-ness
2761  */
2762 int mwifiex_cmd_802_11_bg_scan_query(struct host_cmd_ds_command *cmd)
2763 {
2764         struct host_cmd_ds_802_11_bg_scan_query *bg_query =
2765                 &cmd->params.bg_scan_query;
2766
2767         cmd->command = cpu_to_le16(HostCmd_CMD_802_11_BG_SCAN_QUERY);
2768         cmd->size = cpu_to_le16(sizeof(struct host_cmd_ds_802_11_bg_scan_query)
2769                                 + S_DS_GEN);
2770
2771         bg_query->flush = 1;
2772
2773         return 0;
2774 }
2775
2776 /*
2777  * This function inserts scan command node to the scan pending queue.
2778  */
2779 void
2780 mwifiex_queue_scan_cmd(struct mwifiex_private *priv,
2781                        struct cmd_ctrl_node *cmd_node)
2782 {
2783         struct mwifiex_adapter *adapter = priv->adapter;
2784         unsigned long flags;
2785
2786         cmd_node->wait_q_enabled = true;
2787         cmd_node->condition = &adapter->scan_wait_q_woken;
2788         spin_lock_irqsave(&adapter->scan_pending_q_lock, flags);
2789         list_add_tail(&cmd_node->list, &adapter->scan_pending_q);
2790         spin_unlock_irqrestore(&adapter->scan_pending_q_lock, flags);
2791 }
2792
2793 /*
2794  * This function sends a scan command for all available channels to the
2795  * firmware, filtered on a specific SSID.
2796  */
2797 static int mwifiex_scan_specific_ssid(struct mwifiex_private *priv,
2798                                       struct cfg80211_ssid *req_ssid)
2799 {
2800         struct mwifiex_adapter *adapter = priv->adapter;
2801         int ret;
2802         struct mwifiex_user_scan_cfg *scan_cfg;
2803
2804         if (adapter->scan_processing) {
2805                 mwifiex_dbg(adapter, WARN,
2806                             "cmd: Scan already in process...\n");
2807                 return -EBUSY;
2808         }
2809
2810         if (priv->scan_block) {
2811                 mwifiex_dbg(adapter, WARN,
2812                             "cmd: Scan is blocked during association...\n");
2813                 return -EBUSY;
2814         }
2815
2816         scan_cfg = kzalloc(sizeof(struct mwifiex_user_scan_cfg), GFP_KERNEL);
2817         if (!scan_cfg)
2818                 return -ENOMEM;
2819
2820         scan_cfg->ssid_list = req_ssid;
2821         scan_cfg->num_ssids = 1;
2822
2823         ret = mwifiex_scan_networks(priv, scan_cfg);
2824
2825         kfree(scan_cfg);
2826         return ret;
2827 }
2828
2829 /*
2830  * Sends IOCTL request to start a scan.
2831  *
2832  * This function allocates the IOCTL request buffer, fills it
2833  * with requisite parameters and calls the IOCTL handler.
2834  *
2835  * Scan command can be issued for both normal scan and specific SSID
2836  * scan, depending upon whether an SSID is provided or not.
2837  */
2838 int mwifiex_request_scan(struct mwifiex_private *priv,
2839                          struct cfg80211_ssid *req_ssid)
2840 {
2841         int ret;
2842
2843         if (mutex_lock_interruptible(&priv->async_mutex)) {
2844                 mwifiex_dbg(priv->adapter, ERROR,
2845                             "%s: acquire semaphore fail\n",
2846                             __func__);
2847                 return -1;
2848         }
2849
2850         priv->adapter->scan_wait_q_woken = false;
2851
2852         if (req_ssid && req_ssid->ssid_len != 0)
2853                 /* Specific SSID scan */
2854                 ret = mwifiex_scan_specific_ssid(priv, req_ssid);
2855         else
2856                 /* Normal scan */
2857                 ret = mwifiex_scan_networks(priv, NULL);
2858
2859         mutex_unlock(&priv->async_mutex);
2860
2861         return ret;
2862 }
2863
2864 /*
2865  * This function appends the vendor specific IE TLV to a buffer.
2866  */
2867 int
2868 mwifiex_cmd_append_vsie_tlv(struct mwifiex_private *priv,
2869                             u16 vsie_mask, u8 **buffer)
2870 {
2871         int id, ret_len = 0;
2872         struct mwifiex_ie_types_vendor_param_set *vs_param_set;
2873
2874         if (!buffer)
2875                 return 0;
2876         if (!(*buffer))
2877                 return 0;
2878
2879         /*
2880          * Traverse through the saved vendor specific IE array and append
2881          * the selected(scan/assoc/adhoc) IE as TLV to the command
2882          */
2883         for (id = 0; id < MWIFIEX_MAX_VSIE_NUM; id++) {
2884                 if (priv->vs_ie[id].mask & vsie_mask) {
2885                         vs_param_set =
2886                                 (struct mwifiex_ie_types_vendor_param_set *)
2887                                 *buffer;
2888                         vs_param_set->header.type =
2889                                 cpu_to_le16(TLV_TYPE_PASSTHROUGH);
2890                         vs_param_set->header.len =
2891                                 cpu_to_le16((((u16) priv->vs_ie[id].ie[1])
2892                                 & 0x00FF) + 2);
2893                         if (le16_to_cpu(vs_param_set->header.len) >
2894                                 MWIFIEX_MAX_VSIE_LEN) {
2895                                 mwifiex_dbg(priv->adapter, ERROR,
2896                                             "Invalid param length!\n");
2897                                 break;
2898                         }
2899
2900                         memcpy(vs_param_set->ie, priv->vs_ie[id].ie,
2901                                le16_to_cpu(vs_param_set->header.len));
2902                         *buffer += le16_to_cpu(vs_param_set->header.len) +
2903                                    sizeof(struct mwifiex_ie_types_header);
2904                         ret_len += le16_to_cpu(vs_param_set->header.len) +
2905                                    sizeof(struct mwifiex_ie_types_header);
2906                 }
2907         }
2908         return ret_len;
2909 }
2910
2911 /*
2912  * This function saves a beacon buffer of the current BSS descriptor.
2913  *
2914  * The current beacon buffer is saved so that it can be restored in the
2915  * following cases that makes the beacon buffer not to contain the current
2916  * ssid's beacon buffer.
2917  *      - The current ssid was not found somehow in the last scan.
2918  *      - The current ssid was the last entry of the scan table and overloaded.
2919  */
2920 void
2921 mwifiex_save_curr_bcn(struct mwifiex_private *priv)
2922 {
2923         struct mwifiex_bssdescriptor *curr_bss =
2924                 &priv->curr_bss_params.bss_descriptor;
2925
2926         if (!curr_bss->beacon_buf_size)
2927                 return;
2928
2929         /* allocate beacon buffer at 1st time; or if it's size has changed */
2930         if (!priv->curr_bcn_buf ||
2931             priv->curr_bcn_size != curr_bss->beacon_buf_size) {
2932                 priv->curr_bcn_size = curr_bss->beacon_buf_size;
2933
2934                 kfree(priv->curr_bcn_buf);
2935                 priv->curr_bcn_buf = kmalloc(curr_bss->beacon_buf_size,
2936                                              GFP_ATOMIC);
2937                 if (!priv->curr_bcn_buf)
2938                         return;
2939         }
2940
2941         memcpy(priv->curr_bcn_buf, curr_bss->beacon_buf,
2942                curr_bss->beacon_buf_size);
2943         mwifiex_dbg(priv->adapter, INFO,
2944                     "info: current beacon saved %d\n",
2945                     priv->curr_bcn_size);
2946
2947         curr_bss->beacon_buf = priv->curr_bcn_buf;
2948
2949         /* adjust the pointers in the current BSS descriptor */
2950         if (curr_bss->bcn_wpa_ie)
2951                 curr_bss->bcn_wpa_ie =
2952                         (struct ieee_types_vendor_specific *)
2953                         (curr_bss->beacon_buf +
2954                          curr_bss->wpa_offset);
2955
2956         if (curr_bss->bcn_rsn_ie)
2957                 curr_bss->bcn_rsn_ie = (struct ieee_types_generic *)
2958                         (curr_bss->beacon_buf +
2959                          curr_bss->rsn_offset);
2960
2961         if (curr_bss->bcn_ht_cap)
2962                 curr_bss->bcn_ht_cap = (struct ieee80211_ht_cap *)
2963                         (curr_bss->beacon_buf +
2964                          curr_bss->ht_cap_offset);
2965
2966         if (curr_bss->bcn_ht_oper)
2967                 curr_bss->bcn_ht_oper = (struct ieee80211_ht_operation *)
2968                         (curr_bss->beacon_buf +
2969                          curr_bss->ht_info_offset);
2970
2971         if (curr_bss->bcn_vht_cap)
2972                 curr_bss->bcn_vht_cap = (void *)(curr_bss->beacon_buf +
2973                                                  curr_bss->vht_cap_offset);
2974
2975         if (curr_bss->bcn_vht_oper)
2976                 curr_bss->bcn_vht_oper = (void *)(curr_bss->beacon_buf +
2977                                                   curr_bss->vht_info_offset);
2978
2979         if (curr_bss->bcn_bss_co_2040)
2980                 curr_bss->bcn_bss_co_2040 =
2981                         (curr_bss->beacon_buf + curr_bss->bss_co_2040_offset);
2982
2983         if (curr_bss->bcn_ext_cap)
2984                 curr_bss->bcn_ext_cap = curr_bss->beacon_buf +
2985                         curr_bss->ext_cap_offset;
2986
2987         if (curr_bss->oper_mode)
2988                 curr_bss->oper_mode = (void *)(curr_bss->beacon_buf +
2989                                                curr_bss->oper_mode_offset);
2990 }
2991
2992 /*
2993  * This function frees the current BSS descriptor beacon buffer.
2994  */
2995 void
2996 mwifiex_free_curr_bcn(struct mwifiex_private *priv)
2997 {
2998         kfree(priv->curr_bcn_buf);
2999         priv->curr_bcn_buf = NULL;
3000 }