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