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