Merge tag 'arc-5.2-rc7' of git://git.kernel.org/pub/scm/linux/kernel/git/vgupta/arc
[linux-2.6-microblaze.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                         if (element_len + 2 < sizeof(vendor_ie->vend_hdr))
1365                                 return -EINVAL;
1366
1367                         vendor_ie = (struct ieee_types_vendor_specific *)
1368                                         current_ptr;
1369
1370                         if (!memcmp
1371                             (vendor_ie->vend_hdr.oui, wpa_oui,
1372                              sizeof(wpa_oui))) {
1373                                 bss_entry->bcn_wpa_ie =
1374                                         (struct ieee_types_vendor_specific *)
1375                                         current_ptr;
1376                                 bss_entry->wpa_offset = (u16)
1377                                         (current_ptr - bss_entry->beacon_buf);
1378                         } else if (!memcmp(vendor_ie->vend_hdr.oui, wmm_oui,
1379                                     sizeof(wmm_oui))) {
1380                                 if (total_ie_len ==
1381                                     sizeof(struct ieee_types_wmm_parameter) ||
1382                                     total_ie_len ==
1383                                     sizeof(struct ieee_types_wmm_info))
1384                                         /*
1385                                          * Only accept and copy the WMM IE if
1386                                          * it matches the size expected for the
1387                                          * WMM Info IE or the WMM Parameter IE.
1388                                          */
1389                                         memcpy((u8 *) &bss_entry->wmm_ie,
1390                                                current_ptr, total_ie_len);
1391                         }
1392                         break;
1393                 case WLAN_EID_RSN:
1394                         bss_entry->bcn_rsn_ie =
1395                                 (struct ieee_types_generic *) current_ptr;
1396                         bss_entry->rsn_offset = (u16) (current_ptr -
1397                                                         bss_entry->beacon_buf);
1398                         break;
1399                 case WLAN_EID_BSS_AC_ACCESS_DELAY:
1400                         bss_entry->bcn_wapi_ie =
1401                                 (struct ieee_types_generic *) current_ptr;
1402                         bss_entry->wapi_offset = (u16) (current_ptr -
1403                                                         bss_entry->beacon_buf);
1404                         break;
1405                 case WLAN_EID_HT_CAPABILITY:
1406                         bss_entry->bcn_ht_cap = (struct ieee80211_ht_cap *)
1407                                         (current_ptr +
1408                                         sizeof(struct ieee_types_header));
1409                         bss_entry->ht_cap_offset = (u16) (current_ptr +
1410                                         sizeof(struct ieee_types_header) -
1411                                         bss_entry->beacon_buf);
1412                         break;
1413                 case WLAN_EID_HT_OPERATION:
1414                         bss_entry->bcn_ht_oper =
1415                                 (struct ieee80211_ht_operation *)(current_ptr +
1416                                         sizeof(struct ieee_types_header));
1417                         bss_entry->ht_info_offset = (u16) (current_ptr +
1418                                         sizeof(struct ieee_types_header) -
1419                                         bss_entry->beacon_buf);
1420                         break;
1421                 case WLAN_EID_VHT_CAPABILITY:
1422                         bss_entry->disable_11ac = false;
1423                         bss_entry->bcn_vht_cap =
1424                                 (void *)(current_ptr +
1425                                          sizeof(struct ieee_types_header));
1426                         bss_entry->vht_cap_offset =
1427                                         (u16)((u8 *)bss_entry->bcn_vht_cap -
1428                                               bss_entry->beacon_buf);
1429                         break;
1430                 case WLAN_EID_VHT_OPERATION:
1431                         bss_entry->bcn_vht_oper =
1432                                 (void *)(current_ptr +
1433                                          sizeof(struct ieee_types_header));
1434                         bss_entry->vht_info_offset =
1435                                         (u16)((u8 *)bss_entry->bcn_vht_oper -
1436                                               bss_entry->beacon_buf);
1437                         break;
1438                 case WLAN_EID_BSS_COEX_2040:
1439                         bss_entry->bcn_bss_co_2040 = current_ptr;
1440                         bss_entry->bss_co_2040_offset =
1441                                 (u16) (current_ptr - bss_entry->beacon_buf);
1442                         break;
1443                 case WLAN_EID_EXT_CAPABILITY:
1444                         bss_entry->bcn_ext_cap = current_ptr;
1445                         bss_entry->ext_cap_offset =
1446                                 (u16) (current_ptr - bss_entry->beacon_buf);
1447                         break;
1448                 case WLAN_EID_OPMODE_NOTIF:
1449                         bss_entry->oper_mode = (void *)current_ptr;
1450                         bss_entry->oper_mode_offset =
1451                                         (u16)((u8 *)bss_entry->oper_mode -
1452                                               bss_entry->beacon_buf);
1453                         break;
1454                 default:
1455                         break;
1456                 }
1457
1458                 current_ptr += element_len + 2;
1459
1460                 /* Need to account for IE ID and IE Len */
1461                 bytes_left -= (element_len + 2);
1462
1463         }       /* while (bytes_left > 2) */
1464         return ret;
1465 }
1466
1467 /*
1468  * This function converts radio type scan parameter to a band configuration
1469  * to be used in join command.
1470  */
1471 static u8
1472 mwifiex_radio_type_to_band(u8 radio_type)
1473 {
1474         switch (radio_type) {
1475         case HostCmd_SCAN_RADIO_TYPE_A:
1476                 return BAND_A;
1477         case HostCmd_SCAN_RADIO_TYPE_BG:
1478         default:
1479                 return BAND_G;
1480         }
1481 }
1482
1483 /*
1484  * This is an internal function used to start a scan based on an input
1485  * configuration.
1486  *
1487  * This uses the input user scan configuration information when provided in
1488  * order to send the appropriate scan commands to firmware to populate or
1489  * update the internal driver scan table.
1490  */
1491 int mwifiex_scan_networks(struct mwifiex_private *priv,
1492                           const struct mwifiex_user_scan_cfg *user_scan_in)
1493 {
1494         int ret;
1495         struct mwifiex_adapter *adapter = priv->adapter;
1496         struct cmd_ctrl_node *cmd_node;
1497         union mwifiex_scan_cmd_config_tlv *scan_cfg_out;
1498         struct mwifiex_ie_types_chan_list_param_set *chan_list_out;
1499         struct mwifiex_chan_scan_param_set *scan_chan_list;
1500         u8 filtered_scan;
1501         u8 scan_current_chan_only;
1502         u8 max_chan_per_scan;
1503         unsigned long flags;
1504
1505         if (adapter->scan_processing) {
1506                 mwifiex_dbg(adapter, WARN,
1507                             "cmd: Scan already in process...\n");
1508                 return -EBUSY;
1509         }
1510
1511         if (priv->scan_block) {
1512                 mwifiex_dbg(adapter, WARN,
1513                             "cmd: Scan is blocked during association...\n");
1514                 return -EBUSY;
1515         }
1516
1517         if (test_bit(MWIFIEX_SURPRISE_REMOVED, &adapter->work_flags) ||
1518             test_bit(MWIFIEX_IS_CMD_TIMEDOUT, &adapter->work_flags)) {
1519                 mwifiex_dbg(adapter, ERROR,
1520                             "Ignore scan. Card removed or firmware in bad state\n");
1521                 return -EFAULT;
1522         }
1523
1524         spin_lock_irqsave(&adapter->mwifiex_cmd_lock, flags);
1525         adapter->scan_processing = true;
1526         spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, flags);
1527
1528         scan_cfg_out = kzalloc(sizeof(union mwifiex_scan_cmd_config_tlv),
1529                                GFP_KERNEL);
1530         if (!scan_cfg_out) {
1531                 ret = -ENOMEM;
1532                 goto done;
1533         }
1534
1535         scan_chan_list = kcalloc(MWIFIEX_USER_SCAN_CHAN_MAX,
1536                                  sizeof(struct mwifiex_chan_scan_param_set),
1537                                  GFP_KERNEL);
1538         if (!scan_chan_list) {
1539                 kfree(scan_cfg_out);
1540                 ret = -ENOMEM;
1541                 goto done;
1542         }
1543
1544         mwifiex_config_scan(priv, user_scan_in, &scan_cfg_out->config,
1545                             &chan_list_out, scan_chan_list, &max_chan_per_scan,
1546                             &filtered_scan, &scan_current_chan_only);
1547
1548         ret = mwifiex_scan_channel_list(priv, max_chan_per_scan, filtered_scan,
1549                                         &scan_cfg_out->config, chan_list_out,
1550                                         scan_chan_list);
1551
1552         /* Get scan command from scan_pending_q and put to cmd_pending_q */
1553         if (!ret) {
1554                 spin_lock_irqsave(&adapter->scan_pending_q_lock, flags);
1555                 if (!list_empty(&adapter->scan_pending_q)) {
1556                         cmd_node = list_first_entry(&adapter->scan_pending_q,
1557                                                     struct cmd_ctrl_node, list);
1558                         list_del(&cmd_node->list);
1559                         spin_unlock_irqrestore(&adapter->scan_pending_q_lock,
1560                                                flags);
1561                         mwifiex_insert_cmd_to_pending_q(adapter, cmd_node);
1562                         queue_work(adapter->workqueue, &adapter->main_work);
1563
1564                         /* Perform internal scan synchronously */
1565                         if (!priv->scan_request) {
1566                                 mwifiex_dbg(adapter, INFO,
1567                                             "wait internal scan\n");
1568                                 mwifiex_wait_queue_complete(adapter, cmd_node);
1569                         }
1570                 } else {
1571                         spin_unlock_irqrestore(&adapter->scan_pending_q_lock,
1572                                                flags);
1573                 }
1574         }
1575
1576         kfree(scan_cfg_out);
1577         kfree(scan_chan_list);
1578 done:
1579         if (ret) {
1580                 spin_lock_irqsave(&adapter->mwifiex_cmd_lock, flags);
1581                 adapter->scan_processing = false;
1582                 spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, flags);
1583         }
1584         return ret;
1585 }
1586
1587 /*
1588  * This function prepares a scan command to be sent to the firmware.
1589  *
1590  * This uses the scan command configuration sent to the command processing
1591  * module in command preparation stage to configure a scan command structure
1592  * to send to firmware.
1593  *
1594  * The fixed fields specifying the BSS type and BSSID filters as well as a
1595  * variable number/length of TLVs are sent in the command to firmware.
1596  *
1597  * Preparation also includes -
1598  *      - Setting command ID, and proper size
1599  *      - Ensuring correct endian-ness
1600  */
1601 int mwifiex_cmd_802_11_scan(struct host_cmd_ds_command *cmd,
1602                             struct mwifiex_scan_cmd_config *scan_cfg)
1603 {
1604         struct host_cmd_ds_802_11_scan *scan_cmd = &cmd->params.scan;
1605
1606         /* Set fixed field variables in scan command */
1607         scan_cmd->bss_mode = scan_cfg->bss_mode;
1608         memcpy(scan_cmd->bssid, scan_cfg->specific_bssid,
1609                sizeof(scan_cmd->bssid));
1610         memcpy(scan_cmd->tlv_buffer, scan_cfg->tlv_buf, scan_cfg->tlv_buf_len);
1611
1612         cmd->command = cpu_to_le16(HostCmd_CMD_802_11_SCAN);
1613
1614         /* Size is equal to the sizeof(fixed portions) + the TLV len + header */
1615         cmd->size = cpu_to_le16((u16) (sizeof(scan_cmd->bss_mode)
1616                                           + sizeof(scan_cmd->bssid)
1617                                           + scan_cfg->tlv_buf_len + S_DS_GEN));
1618
1619         return 0;
1620 }
1621
1622 /*
1623  * This function checks compatibility of requested network with current
1624  * driver settings.
1625  */
1626 int mwifiex_check_network_compatibility(struct mwifiex_private *priv,
1627                                         struct mwifiex_bssdescriptor *bss_desc)
1628 {
1629         int ret = -1;
1630
1631         if (!bss_desc)
1632                 return -1;
1633
1634         if ((mwifiex_get_cfp(priv, (u8) bss_desc->bss_band,
1635                              (u16) bss_desc->channel, 0))) {
1636                 switch (priv->bss_mode) {
1637                 case NL80211_IFTYPE_STATION:
1638                 case NL80211_IFTYPE_ADHOC:
1639                         ret = mwifiex_is_network_compatible(priv, bss_desc,
1640                                                             priv->bss_mode);
1641                         if (ret)
1642                                 mwifiex_dbg(priv->adapter, ERROR,
1643                                             "Incompatible network settings\n");
1644                         break;
1645                 default:
1646                         ret = 0;
1647                 }
1648         }
1649
1650         return ret;
1651 }
1652
1653 /* This function checks if SSID string contains all zeroes or length is zero */
1654 static bool mwifiex_is_hidden_ssid(struct cfg80211_ssid *ssid)
1655 {
1656         int idx;
1657
1658         for (idx = 0; idx < ssid->ssid_len; idx++) {
1659                 if (ssid->ssid[idx])
1660                         return false;
1661         }
1662
1663         return true;
1664 }
1665
1666 /* This function checks if any hidden SSID found in passive scan channels
1667  * and save those channels for specific SSID active scan
1668  */
1669 static int mwifiex_save_hidden_ssid_channels(struct mwifiex_private *priv,
1670                                              struct cfg80211_bss *bss)
1671 {
1672         struct mwifiex_bssdescriptor *bss_desc;
1673         int ret;
1674         int chid;
1675
1676         /* Allocate and fill new bss descriptor */
1677         bss_desc = kzalloc(sizeof(*bss_desc), GFP_KERNEL);
1678         if (!bss_desc)
1679                 return -ENOMEM;
1680
1681         ret = mwifiex_fill_new_bss_desc(priv, bss, bss_desc);
1682         if (ret)
1683                 goto done;
1684
1685         if (mwifiex_is_hidden_ssid(&bss_desc->ssid)) {
1686                 mwifiex_dbg(priv->adapter, INFO, "found hidden SSID\n");
1687                 for (chid = 0 ; chid < MWIFIEX_USER_SCAN_CHAN_MAX; chid++) {
1688                         if (priv->hidden_chan[chid].chan_number ==
1689                             bss->channel->hw_value)
1690                                 break;
1691
1692                         if (!priv->hidden_chan[chid].chan_number) {
1693                                 priv->hidden_chan[chid].chan_number =
1694                                         bss->channel->hw_value;
1695                                 priv->hidden_chan[chid].radio_type =
1696                                         bss->channel->band;
1697                                 priv->hidden_chan[chid].scan_type =
1698                                         MWIFIEX_SCAN_TYPE_ACTIVE;
1699                                 break;
1700                         }
1701                 }
1702         }
1703
1704 done:
1705         /* beacon_ie buffer was allocated in function
1706          * mwifiex_fill_new_bss_desc(). Free it now.
1707          */
1708         kfree(bss_desc->beacon_buf);
1709         kfree(bss_desc);
1710         return 0;
1711 }
1712
1713 static int mwifiex_update_curr_bss_params(struct mwifiex_private *priv,
1714                                           struct cfg80211_bss *bss)
1715 {
1716         struct mwifiex_bssdescriptor *bss_desc;
1717         int ret;
1718         unsigned long flags;
1719
1720         /* Allocate and fill new bss descriptor */
1721         bss_desc = kzalloc(sizeof(struct mwifiex_bssdescriptor), GFP_KERNEL);
1722         if (!bss_desc)
1723                 return -ENOMEM;
1724
1725         ret = mwifiex_fill_new_bss_desc(priv, bss, bss_desc);
1726         if (ret)
1727                 goto done;
1728
1729         ret = mwifiex_check_network_compatibility(priv, bss_desc);
1730         if (ret)
1731                 goto done;
1732
1733         spin_lock_irqsave(&priv->curr_bcn_buf_lock, flags);
1734         /* Make a copy of current BSSID descriptor */
1735         memcpy(&priv->curr_bss_params.bss_descriptor, bss_desc,
1736                sizeof(priv->curr_bss_params.bss_descriptor));
1737
1738         /* The contents of beacon_ie will be copied to its own buffer
1739          * in mwifiex_save_curr_bcn()
1740          */
1741         mwifiex_save_curr_bcn(priv);
1742         spin_unlock_irqrestore(&priv->curr_bcn_buf_lock, flags);
1743
1744 done:
1745         /* beacon_ie buffer was allocated in function
1746          * mwifiex_fill_new_bss_desc(). Free it now.
1747          */
1748         kfree(bss_desc->beacon_buf);
1749         kfree(bss_desc);
1750         return 0;
1751 }
1752
1753 static int
1754 mwifiex_parse_single_response_buf(struct mwifiex_private *priv, u8 **bss_info,
1755                                   u32 *bytes_left, u64 fw_tsf, u8 *radio_type,
1756                                   bool ext_scan, s32 rssi_val)
1757 {
1758         struct mwifiex_adapter *adapter = priv->adapter;
1759         struct mwifiex_chan_freq_power *cfp;
1760         struct cfg80211_bss *bss;
1761         u8 bssid[ETH_ALEN];
1762         s32 rssi;
1763         const u8 *ie_buf;
1764         size_t ie_len;
1765         u16 channel = 0;
1766         u16 beacon_size = 0;
1767         u32 curr_bcn_bytes;
1768         u32 freq;
1769         u16 beacon_period;
1770         u16 cap_info_bitmap;
1771         u8 *current_ptr;
1772         u64 timestamp;
1773         struct mwifiex_fixed_bcn_param *bcn_param;
1774         struct mwifiex_bss_priv *bss_priv;
1775
1776         if (*bytes_left >= sizeof(beacon_size)) {
1777                 /* Extract & convert beacon size from command buffer */
1778                 beacon_size = get_unaligned_le16((*bss_info));
1779                 *bytes_left -= sizeof(beacon_size);
1780                 *bss_info += sizeof(beacon_size);
1781         }
1782
1783         if (!beacon_size || beacon_size > *bytes_left) {
1784                 *bss_info += *bytes_left;
1785                 *bytes_left = 0;
1786                 return -EFAULT;
1787         }
1788
1789         /* Initialize the current working beacon pointer for this BSS
1790          * iteration
1791          */
1792         current_ptr = *bss_info;
1793
1794         /* Advance the return beacon pointer past the current beacon */
1795         *bss_info += beacon_size;
1796         *bytes_left -= beacon_size;
1797
1798         curr_bcn_bytes = beacon_size;
1799
1800         /* First 5 fields are bssid, RSSI(for legacy scan only),
1801          * time stamp, beacon interval, and capability information
1802          */
1803         if (curr_bcn_bytes < ETH_ALEN + sizeof(u8) +
1804             sizeof(struct mwifiex_fixed_bcn_param)) {
1805                 mwifiex_dbg(adapter, ERROR,
1806                             "InterpretIE: not enough bytes left\n");
1807                 return -EFAULT;
1808         }
1809
1810         memcpy(bssid, current_ptr, ETH_ALEN);
1811         current_ptr += ETH_ALEN;
1812         curr_bcn_bytes -= ETH_ALEN;
1813
1814         if (!ext_scan) {
1815                 rssi = (s32) *current_ptr;
1816                 rssi = (-rssi) * 100;           /* Convert dBm to mBm */
1817                 current_ptr += sizeof(u8);
1818                 curr_bcn_bytes -= sizeof(u8);
1819                 mwifiex_dbg(adapter, INFO,
1820                             "info: InterpretIE: RSSI=%d\n", rssi);
1821         } else {
1822                 rssi = rssi_val;
1823         }
1824
1825         bcn_param = (struct mwifiex_fixed_bcn_param *)current_ptr;
1826         current_ptr += sizeof(*bcn_param);
1827         curr_bcn_bytes -= sizeof(*bcn_param);
1828
1829         timestamp = le64_to_cpu(bcn_param->timestamp);
1830         beacon_period = le16_to_cpu(bcn_param->beacon_period);
1831
1832         cap_info_bitmap = le16_to_cpu(bcn_param->cap_info_bitmap);
1833         mwifiex_dbg(adapter, INFO,
1834                     "info: InterpretIE: capabilities=0x%X\n",
1835                     cap_info_bitmap);
1836
1837         /* Rest of the current buffer are IE's */
1838         ie_buf = current_ptr;
1839         ie_len = curr_bcn_bytes;
1840         mwifiex_dbg(adapter, INFO,
1841                     "info: InterpretIE: IELength for this AP = %d\n",
1842                     curr_bcn_bytes);
1843
1844         while (curr_bcn_bytes >= sizeof(struct ieee_types_header)) {
1845                 u8 element_id, element_len;
1846
1847                 element_id = *current_ptr;
1848                 element_len = *(current_ptr + 1);
1849                 if (curr_bcn_bytes < element_len +
1850                                 sizeof(struct ieee_types_header)) {
1851                         mwifiex_dbg(adapter, ERROR,
1852                                     "%s: bytes left < IE length\n", __func__);
1853                         return -EFAULT;
1854                 }
1855                 if (element_id == WLAN_EID_DS_PARAMS) {
1856                         channel = *(current_ptr +
1857                                     sizeof(struct ieee_types_header));
1858                         break;
1859                 }
1860
1861                 current_ptr += element_len + sizeof(struct ieee_types_header);
1862                 curr_bcn_bytes -= element_len +
1863                                         sizeof(struct ieee_types_header);
1864         }
1865
1866         if (channel) {
1867                 struct ieee80211_channel *chan;
1868                 u8 band;
1869
1870                 /* Skip entry if on csa closed channel */
1871                 if (channel == priv->csa_chan) {
1872                         mwifiex_dbg(adapter, WARN,
1873                                     "Dropping entry on csa closed channel\n");
1874                         return 0;
1875                 }
1876
1877                 band = BAND_G;
1878                 if (radio_type)
1879                         band = mwifiex_radio_type_to_band(*radio_type &
1880                                                           (BIT(0) | BIT(1)));
1881
1882                 cfp = mwifiex_get_cfp(priv, band, channel, 0);
1883
1884                 freq = cfp ? cfp->freq : 0;
1885
1886                 chan = ieee80211_get_channel(priv->wdev.wiphy, freq);
1887
1888                 if (chan && !(chan->flags & IEEE80211_CHAN_DISABLED)) {
1889                         bss = cfg80211_inform_bss(priv->wdev.wiphy,
1890                                             chan, CFG80211_BSS_FTYPE_UNKNOWN,
1891                                             bssid, timestamp,
1892                                             cap_info_bitmap, beacon_period,
1893                                             ie_buf, ie_len, rssi, GFP_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         unsigned long flags;
1997
1998         spin_lock_irqsave(&adapter->scan_pending_q_lock, flags);
1999         if (list_empty(&adapter->scan_pending_q)) {
2000                 spin_unlock_irqrestore(&adapter->scan_pending_q_lock, flags);
2001
2002                 spin_lock_irqsave(&adapter->mwifiex_cmd_lock, flags);
2003                 adapter->scan_processing = false;
2004                 spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, flags);
2005
2006                 mwifiex_active_scan_req_for_passive_chan(priv);
2007
2008                 if (!adapter->ext_scan)
2009                         mwifiex_complete_scan(priv);
2010
2011                 if (priv->scan_request) {
2012                         struct cfg80211_scan_info info = {
2013                                 .aborted = false,
2014                         };
2015
2016                         mwifiex_dbg(adapter, INFO,
2017                                     "info: notifying scan done\n");
2018                         cfg80211_scan_done(priv->scan_request, &info);
2019                         priv->scan_request = NULL;
2020                         priv->scan_aborting = false;
2021                 } else {
2022                         priv->scan_aborting = false;
2023                         mwifiex_dbg(adapter, INFO,
2024                                     "info: scan already aborted\n");
2025                 }
2026         } else if ((priv->scan_aborting && !priv->scan_request) ||
2027                    priv->scan_block) {
2028                 spin_unlock_irqrestore(&adapter->scan_pending_q_lock, flags);
2029
2030                 mwifiex_cancel_pending_scan_cmd(adapter);
2031
2032                 spin_lock_irqsave(&adapter->mwifiex_cmd_lock, flags);
2033                 adapter->scan_processing = false;
2034                 spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, flags);
2035
2036                 if (!adapter->active_scan_triggered) {
2037                         if (priv->scan_request) {
2038                                 struct cfg80211_scan_info info = {
2039                                         .aborted = true,
2040                                 };
2041
2042                                 mwifiex_dbg(adapter, INFO,
2043                                             "info: aborting scan\n");
2044                                 cfg80211_scan_done(priv->scan_request, &info);
2045                                 priv->scan_request = NULL;
2046                                 priv->scan_aborting = false;
2047                         } else {
2048                                 priv->scan_aborting = false;
2049                                 mwifiex_dbg(adapter, INFO,
2050                                             "info: scan already aborted\n");
2051                         }
2052                 }
2053         } else {
2054                 /* Get scan command from scan_pending_q and put to
2055                  * cmd_pending_q
2056                  */
2057                 cmd_node = list_first_entry(&adapter->scan_pending_q,
2058                                             struct cmd_ctrl_node, list);
2059                 list_del(&cmd_node->list);
2060                 spin_unlock_irqrestore(&adapter->scan_pending_q_lock, flags);
2061                 mwifiex_insert_cmd_to_pending_q(adapter, cmd_node);
2062         }
2063
2064         return;
2065 }
2066
2067 void mwifiex_cancel_scan(struct mwifiex_adapter *adapter)
2068 {
2069         struct mwifiex_private *priv;
2070         unsigned long cmd_flags;
2071         int i;
2072
2073         mwifiex_cancel_pending_scan_cmd(adapter);
2074
2075         if (adapter->scan_processing) {
2076                 spin_lock_irqsave(&adapter->mwifiex_cmd_lock, cmd_flags);
2077                 adapter->scan_processing = false;
2078                 spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, cmd_flags);
2079                 for (i = 0; i < adapter->priv_num; i++) {
2080                         priv = adapter->priv[i];
2081                         if (!priv)
2082                                 continue;
2083                         if (priv->scan_request) {
2084                                 struct cfg80211_scan_info info = {
2085                                         .aborted = true,
2086                                 };
2087
2088                                 mwifiex_dbg(adapter, INFO,
2089                                             "info: aborting scan\n");
2090                                 cfg80211_scan_done(priv->scan_request, &info);
2091                                 priv->scan_request = NULL;
2092                                 priv->scan_aborting = false;
2093                         }
2094                 }
2095         }
2096 }
2097
2098 /*
2099  * This function handles the command response of scan.
2100  *
2101  * The response buffer for the scan command has the following
2102  * memory layout:
2103  *
2104  *      .-------------------------------------------------------------.
2105  *      |  Header (4 * sizeof(t_u16)):  Standard command response hdr |
2106  *      .-------------------------------------------------------------.
2107  *      |  BufSize (t_u16) : sizeof the BSS Description data          |
2108  *      .-------------------------------------------------------------.
2109  *      |  NumOfSet (t_u8) : Number of BSS Descs returned             |
2110  *      .-------------------------------------------------------------.
2111  *      |  BSSDescription data (variable, size given in BufSize)      |
2112  *      .-------------------------------------------------------------.
2113  *      |  TLV data (variable, size calculated using Header->Size,    |
2114  *      |            BufSize and sizeof the fixed fields above)       |
2115  *      .-------------------------------------------------------------.
2116  */
2117 int mwifiex_ret_802_11_scan(struct mwifiex_private *priv,
2118                             struct host_cmd_ds_command *resp)
2119 {
2120         int ret = 0;
2121         struct mwifiex_adapter *adapter = priv->adapter;
2122         struct host_cmd_ds_802_11_scan_rsp *scan_rsp;
2123         struct mwifiex_ie_types_data *tlv_data;
2124         struct mwifiex_ie_types_tsf_timestamp *tsf_tlv;
2125         u8 *bss_info;
2126         u32 scan_resp_size;
2127         u32 bytes_left;
2128         u32 idx;
2129         u32 tlv_buf_size;
2130         struct mwifiex_ie_types_chan_band_list_param_set *chan_band_tlv;
2131         struct chan_band_param_set *chan_band;
2132         u8 is_bgscan_resp;
2133         __le64 fw_tsf = 0;
2134         u8 *radio_type;
2135         struct cfg80211_wowlan_nd_match *pmatch;
2136         struct cfg80211_sched_scan_request *nd_config = NULL;
2137
2138         is_bgscan_resp = (le16_to_cpu(resp->command)
2139                           == HostCmd_CMD_802_11_BG_SCAN_QUERY);
2140         if (is_bgscan_resp)
2141                 scan_rsp = &resp->params.bg_scan_query_resp.scan_resp;
2142         else
2143                 scan_rsp = &resp->params.scan_resp;
2144
2145
2146         if (scan_rsp->number_of_sets > MWIFIEX_MAX_AP) {
2147                 mwifiex_dbg(adapter, ERROR,
2148                             "SCAN_RESP: too many AP returned (%d)\n",
2149                             scan_rsp->number_of_sets);
2150                 ret = -1;
2151                 goto check_next_scan;
2152         }
2153
2154         /* Check csa channel expiry before parsing scan response */
2155         mwifiex_11h_get_csa_closed_channel(priv);
2156
2157         bytes_left = le16_to_cpu(scan_rsp->bss_descript_size);
2158         mwifiex_dbg(adapter, INFO,
2159                     "info: SCAN_RESP: bss_descript_size %d\n",
2160                     bytes_left);
2161
2162         scan_resp_size = le16_to_cpu(resp->size);
2163
2164         mwifiex_dbg(adapter, INFO,
2165                     "info: SCAN_RESP: returned %d APs before parsing\n",
2166                     scan_rsp->number_of_sets);
2167
2168         bss_info = scan_rsp->bss_desc_and_tlv_buffer;
2169
2170         /*
2171          * The size of the TLV buffer is equal to the entire command response
2172          *   size (scan_resp_size) minus the fixed fields (sizeof()'s), the
2173          *   BSS Descriptions (bss_descript_size as bytesLef) and the command
2174          *   response header (S_DS_GEN)
2175          */
2176         tlv_buf_size = scan_resp_size - (bytes_left
2177                                          + sizeof(scan_rsp->bss_descript_size)
2178                                          + sizeof(scan_rsp->number_of_sets)
2179                                          + S_DS_GEN);
2180
2181         tlv_data = (struct mwifiex_ie_types_data *) (scan_rsp->
2182                                                  bss_desc_and_tlv_buffer +
2183                                                  bytes_left);
2184
2185         /* Search the TLV buffer space in the scan response for any valid
2186            TLVs */
2187         mwifiex_ret_802_11_scan_get_tlv_ptrs(adapter, tlv_data, tlv_buf_size,
2188                                              TLV_TYPE_TSFTIMESTAMP,
2189                                              (struct mwifiex_ie_types_data **)
2190                                              &tsf_tlv);
2191
2192         /* Search the TLV buffer space in the scan response for any valid
2193            TLVs */
2194         mwifiex_ret_802_11_scan_get_tlv_ptrs(adapter, tlv_data, tlv_buf_size,
2195                                              TLV_TYPE_CHANNELBANDLIST,
2196                                              (struct mwifiex_ie_types_data **)
2197                                              &chan_band_tlv);
2198
2199 #ifdef CONFIG_PM
2200         if (priv->wdev.wiphy->wowlan_config)
2201                 nd_config = priv->wdev.wiphy->wowlan_config->nd_config;
2202 #endif
2203
2204         if (nd_config) {
2205                 adapter->nd_info =
2206                         kzalloc(sizeof(struct cfg80211_wowlan_nd_match) +
2207                                 sizeof(struct cfg80211_wowlan_nd_match *) *
2208                                 scan_rsp->number_of_sets, GFP_ATOMIC);
2209
2210                 if (adapter->nd_info)
2211                         adapter->nd_info->n_matches = scan_rsp->number_of_sets;
2212         }
2213
2214         for (idx = 0; idx < scan_rsp->number_of_sets && bytes_left; idx++) {
2215                 /*
2216                  * If the TSF TLV was appended to the scan results, save this
2217                  * entry's TSF value in the fw_tsf field. It is the firmware's
2218                  * TSF value at the time the beacon or probe response was
2219                  * received.
2220                  */
2221                 if (tsf_tlv)
2222                         memcpy(&fw_tsf, &tsf_tlv->tsf_data[idx * TSF_DATA_SIZE],
2223                                sizeof(fw_tsf));
2224
2225                 if (chan_band_tlv) {
2226                         chan_band = &chan_band_tlv->chan_band_param[idx];
2227                         radio_type = &chan_band->radio_type;
2228                 } else {
2229                         radio_type = NULL;
2230                 }
2231
2232                 if (chan_band_tlv && adapter->nd_info) {
2233                         adapter->nd_info->matches[idx] =
2234                                 kzalloc(sizeof(*pmatch) + sizeof(u32),
2235                                         GFP_ATOMIC);
2236
2237                         pmatch = adapter->nd_info->matches[idx];
2238
2239                         if (pmatch) {
2240                                 pmatch->n_channels = 1;
2241                                 pmatch->channels[0] = chan_band->chan_number;
2242                         }
2243                 }
2244
2245                 ret = mwifiex_parse_single_response_buf(priv, &bss_info,
2246                                                         &bytes_left,
2247                                                         le64_to_cpu(fw_tsf),
2248                                                         radio_type, false, 0);
2249                 if (ret)
2250                         goto check_next_scan;
2251         }
2252
2253 check_next_scan:
2254         mwifiex_check_next_scan_command(priv);
2255         return ret;
2256 }
2257
2258 /*
2259  * This function prepares an extended scan command to be sent to the firmware
2260  *
2261  * This uses the scan command configuration sent to the command processing
2262  * module in command preparation stage to configure a extended scan command
2263  * structure to send to firmware.
2264  */
2265 int mwifiex_cmd_802_11_scan_ext(struct mwifiex_private *priv,
2266                                 struct host_cmd_ds_command *cmd,
2267                                 void *data_buf)
2268 {
2269         struct host_cmd_ds_802_11_scan_ext *ext_scan = &cmd->params.ext_scan;
2270         struct mwifiex_scan_cmd_config *scan_cfg = data_buf;
2271
2272         memcpy(ext_scan->tlv_buffer, scan_cfg->tlv_buf, scan_cfg->tlv_buf_len);
2273
2274         cmd->command = cpu_to_le16(HostCmd_CMD_802_11_SCAN_EXT);
2275
2276         /* Size is equal to the sizeof(fixed portions) + the TLV len + header */
2277         cmd->size = cpu_to_le16((u16)(sizeof(ext_scan->reserved)
2278                                       + scan_cfg->tlv_buf_len + S_DS_GEN));
2279
2280         return 0;
2281 }
2282
2283 /* This function prepares an background scan config command to be sent
2284  * to the firmware
2285  */
2286 int mwifiex_cmd_802_11_bg_scan_config(struct mwifiex_private *priv,
2287                                       struct host_cmd_ds_command *cmd,
2288                                       void *data_buf)
2289 {
2290         struct host_cmd_ds_802_11_bg_scan_config *bgscan_config =
2291                                         &cmd->params.bg_scan_config;
2292         struct mwifiex_bg_scan_cfg *bgscan_cfg_in = data_buf;
2293         u8 *tlv_pos = bgscan_config->tlv;
2294         u8 num_probes;
2295         u32 ssid_len, chan_idx, scan_type, scan_dur, chan_num;
2296         int i;
2297         struct mwifiex_ie_types_num_probes *num_probes_tlv;
2298         struct mwifiex_ie_types_repeat_count *repeat_count_tlv;
2299         struct mwifiex_ie_types_min_rssi_threshold *rssi_threshold_tlv;
2300         struct mwifiex_ie_types_bgscan_start_later *start_later_tlv;
2301         struct mwifiex_ie_types_wildcard_ssid_params *wildcard_ssid_tlv;
2302         struct mwifiex_ie_types_chan_list_param_set *chan_list_tlv;
2303         struct mwifiex_chan_scan_param_set *temp_chan;
2304
2305         cmd->command = cpu_to_le16(HostCmd_CMD_802_11_BG_SCAN_CONFIG);
2306         cmd->size = cpu_to_le16(sizeof(*bgscan_config) + S_DS_GEN);
2307
2308         bgscan_config->action = cpu_to_le16(bgscan_cfg_in->action);
2309         bgscan_config->enable = bgscan_cfg_in->enable;
2310         bgscan_config->bss_type = bgscan_cfg_in->bss_type;
2311         bgscan_config->scan_interval =
2312                 cpu_to_le32(bgscan_cfg_in->scan_interval);
2313         bgscan_config->report_condition =
2314                 cpu_to_le32(bgscan_cfg_in->report_condition);
2315
2316         /*  stop sched scan  */
2317         if (!bgscan_config->enable)
2318                 return 0;
2319
2320         bgscan_config->chan_per_scan = bgscan_cfg_in->chan_per_scan;
2321
2322         num_probes = (bgscan_cfg_in->num_probes ? bgscan_cfg_in->
2323                       num_probes : priv->adapter->scan_probes);
2324
2325         if (num_probes) {
2326                 num_probes_tlv = (struct mwifiex_ie_types_num_probes *)tlv_pos;
2327                 num_probes_tlv->header.type = cpu_to_le16(TLV_TYPE_NUMPROBES);
2328                 num_probes_tlv->header.len =
2329                         cpu_to_le16(sizeof(num_probes_tlv->num_probes));
2330                 num_probes_tlv->num_probes = cpu_to_le16((u16)num_probes);
2331
2332                 tlv_pos += sizeof(num_probes_tlv->header) +
2333                         le16_to_cpu(num_probes_tlv->header.len);
2334         }
2335
2336         if (bgscan_cfg_in->repeat_count) {
2337                 repeat_count_tlv =
2338                         (struct mwifiex_ie_types_repeat_count *)tlv_pos;
2339                 repeat_count_tlv->header.type =
2340                         cpu_to_le16(TLV_TYPE_REPEAT_COUNT);
2341                 repeat_count_tlv->header.len =
2342                         cpu_to_le16(sizeof(repeat_count_tlv->repeat_count));
2343                 repeat_count_tlv->repeat_count =
2344                         cpu_to_le16(bgscan_cfg_in->repeat_count);
2345
2346                 tlv_pos += sizeof(repeat_count_tlv->header) +
2347                         le16_to_cpu(repeat_count_tlv->header.len);
2348         }
2349
2350         if (bgscan_cfg_in->rssi_threshold) {
2351                 rssi_threshold_tlv =
2352                         (struct mwifiex_ie_types_min_rssi_threshold *)tlv_pos;
2353                 rssi_threshold_tlv->header.type =
2354                         cpu_to_le16(TLV_TYPE_RSSI_LOW);
2355                 rssi_threshold_tlv->header.len =
2356                         cpu_to_le16(sizeof(rssi_threshold_tlv->rssi_threshold));
2357                 rssi_threshold_tlv->rssi_threshold =
2358                         cpu_to_le16(bgscan_cfg_in->rssi_threshold);
2359
2360                 tlv_pos += sizeof(rssi_threshold_tlv->header) +
2361                         le16_to_cpu(rssi_threshold_tlv->header.len);
2362         }
2363
2364         for (i = 0; i < bgscan_cfg_in->num_ssids; i++) {
2365                 ssid_len = bgscan_cfg_in->ssid_list[i].ssid.ssid_len;
2366
2367                 wildcard_ssid_tlv =
2368                         (struct mwifiex_ie_types_wildcard_ssid_params *)tlv_pos;
2369                 wildcard_ssid_tlv->header.type =
2370                                 cpu_to_le16(TLV_TYPE_WILDCARDSSID);
2371                 wildcard_ssid_tlv->header.len = cpu_to_le16(
2372                                 (u16)(ssid_len + sizeof(wildcard_ssid_tlv->
2373                                                          max_ssid_length)));
2374
2375                 /* max_ssid_length = 0 tells firmware to perform
2376                  * specific scan for the SSID filled, whereas
2377                  * max_ssid_length = IEEE80211_MAX_SSID_LEN is for
2378                  * wildcard scan.
2379                  */
2380                 if (ssid_len)
2381                         wildcard_ssid_tlv->max_ssid_length = 0;
2382                 else
2383                         wildcard_ssid_tlv->max_ssid_length =
2384                                                 IEEE80211_MAX_SSID_LEN;
2385
2386                 memcpy(wildcard_ssid_tlv->ssid,
2387                        bgscan_cfg_in->ssid_list[i].ssid.ssid, ssid_len);
2388
2389                 tlv_pos += (sizeof(wildcard_ssid_tlv->header)
2390                                 + le16_to_cpu(wildcard_ssid_tlv->header.len));
2391         }
2392
2393         chan_list_tlv = (struct mwifiex_ie_types_chan_list_param_set *)tlv_pos;
2394
2395         if (bgscan_cfg_in->chan_list[0].chan_number) {
2396                 dev_dbg(priv->adapter->dev, "info: bgscan: Using supplied channel list\n");
2397
2398                 chan_list_tlv->header.type = cpu_to_le16(TLV_TYPE_CHANLIST);
2399
2400                 for (chan_idx = 0;
2401                      chan_idx < MWIFIEX_BG_SCAN_CHAN_MAX &&
2402                      bgscan_cfg_in->chan_list[chan_idx].chan_number;
2403                      chan_idx++) {
2404                         temp_chan = chan_list_tlv->chan_scan_param + chan_idx;
2405
2406                         /* Increment the TLV header length by size appended */
2407                         le16_unaligned_add_cpu(&chan_list_tlv->header.len,
2408                                                sizeof(
2409                                                chan_list_tlv->chan_scan_param));
2410
2411                         temp_chan->chan_number =
2412                                 bgscan_cfg_in->chan_list[chan_idx].chan_number;
2413                         temp_chan->radio_type =
2414                                 bgscan_cfg_in->chan_list[chan_idx].radio_type;
2415
2416                         scan_type =
2417                                 bgscan_cfg_in->chan_list[chan_idx].scan_type;
2418
2419                         if (scan_type == MWIFIEX_SCAN_TYPE_PASSIVE)
2420                                 temp_chan->chan_scan_mode_bitmap
2421                                         |= MWIFIEX_PASSIVE_SCAN;
2422                         else
2423                                 temp_chan->chan_scan_mode_bitmap
2424                                         &= ~MWIFIEX_PASSIVE_SCAN;
2425
2426                         if (bgscan_cfg_in->chan_list[chan_idx].scan_time) {
2427                                 scan_dur = (u16)bgscan_cfg_in->
2428                                         chan_list[chan_idx].scan_time;
2429                         } else {
2430                                 scan_dur = (scan_type ==
2431                                             MWIFIEX_SCAN_TYPE_PASSIVE) ?
2432                                             priv->adapter->passive_scan_time :
2433                                             priv->adapter->specific_scan_time;
2434                         }
2435
2436                         temp_chan->min_scan_time = cpu_to_le16(scan_dur);
2437                         temp_chan->max_scan_time = cpu_to_le16(scan_dur);
2438                 }
2439         } else {
2440                 dev_dbg(priv->adapter->dev,
2441                         "info: bgscan: Creating full region channel list\n");
2442                 chan_num =
2443                         mwifiex_bgscan_create_channel_list(priv, bgscan_cfg_in,
2444                                                            chan_list_tlv->
2445                                                            chan_scan_param);
2446                 le16_unaligned_add_cpu(&chan_list_tlv->header.len,
2447                                        chan_num *
2448                              sizeof(chan_list_tlv->chan_scan_param[0]));
2449         }
2450
2451         tlv_pos += (sizeof(chan_list_tlv->header)
2452                         + le16_to_cpu(chan_list_tlv->header.len));
2453
2454         if (bgscan_cfg_in->start_later) {
2455                 start_later_tlv =
2456                         (struct mwifiex_ie_types_bgscan_start_later *)tlv_pos;
2457                 start_later_tlv->header.type =
2458                         cpu_to_le16(TLV_TYPE_BGSCAN_START_LATER);
2459                 start_later_tlv->header.len =
2460                         cpu_to_le16(sizeof(start_later_tlv->start_later));
2461                 start_later_tlv->start_later =
2462                         cpu_to_le16(bgscan_cfg_in->start_later);
2463
2464                 tlv_pos += sizeof(start_later_tlv->header) +
2465                         le16_to_cpu(start_later_tlv->header.len);
2466         }
2467
2468         /* Append vendor specific IE TLV */
2469         mwifiex_cmd_append_vsie_tlv(priv, MWIFIEX_VSIE_MASK_BGSCAN, &tlv_pos);
2470
2471         le16_unaligned_add_cpu(&cmd->size, tlv_pos - bgscan_config->tlv);
2472
2473         return 0;
2474 }
2475
2476 int mwifiex_stop_bg_scan(struct mwifiex_private *priv)
2477 {
2478         struct mwifiex_bg_scan_cfg *bgscan_cfg;
2479
2480         if (!priv->sched_scanning) {
2481                 dev_dbg(priv->adapter->dev, "bgscan already stopped!\n");
2482                 return 0;
2483         }
2484
2485         bgscan_cfg = kzalloc(sizeof(*bgscan_cfg), GFP_KERNEL);
2486         if (!bgscan_cfg)
2487                 return -ENOMEM;
2488
2489         bgscan_cfg->bss_type = MWIFIEX_BSS_MODE_INFRA;
2490         bgscan_cfg->action = MWIFIEX_BGSCAN_ACT_SET;
2491         bgscan_cfg->enable = false;
2492
2493         if (mwifiex_send_cmd(priv, HostCmd_CMD_802_11_BG_SCAN_CONFIG,
2494                              HostCmd_ACT_GEN_SET, 0, bgscan_cfg, true)) {
2495                 kfree(bgscan_cfg);
2496                 return -EFAULT;
2497         }
2498
2499         kfree(bgscan_cfg);
2500         priv->sched_scanning = false;
2501
2502         return 0;
2503 }
2504
2505 static void
2506 mwifiex_update_chan_statistics(struct mwifiex_private *priv,
2507                                struct mwifiex_ietypes_chanstats *tlv_stat)
2508 {
2509         struct mwifiex_adapter *adapter = priv->adapter;
2510         u8 i, num_chan;
2511         struct mwifiex_fw_chan_stats *fw_chan_stats;
2512         struct mwifiex_chan_stats chan_stats;
2513
2514         fw_chan_stats = (void *)((u8 *)tlv_stat +
2515                               sizeof(struct mwifiex_ie_types_header));
2516         num_chan = le16_to_cpu(tlv_stat->header.len) /
2517                                               sizeof(struct mwifiex_chan_stats);
2518
2519         for (i = 0 ; i < num_chan; i++) {
2520                 if (adapter->survey_idx >= adapter->num_in_chan_stats) {
2521                         mwifiex_dbg(adapter, WARN,
2522                                     "FW reported too many channel results (max %d)\n",
2523                                     adapter->num_in_chan_stats);
2524                         return;
2525                 }
2526                 chan_stats.chan_num = fw_chan_stats->chan_num;
2527                 chan_stats.bandcfg = fw_chan_stats->bandcfg;
2528                 chan_stats.flags = fw_chan_stats->flags;
2529                 chan_stats.noise = fw_chan_stats->noise;
2530                 chan_stats.total_bss = le16_to_cpu(fw_chan_stats->total_bss);
2531                 chan_stats.cca_scan_dur =
2532                                        le16_to_cpu(fw_chan_stats->cca_scan_dur);
2533                 chan_stats.cca_busy_dur =
2534                                        le16_to_cpu(fw_chan_stats->cca_busy_dur);
2535                 mwifiex_dbg(adapter, INFO,
2536                             "chan=%d, noise=%d, total_network=%d scan_duration=%d, busy_duration=%d\n",
2537                             chan_stats.chan_num,
2538                             chan_stats.noise,
2539                             chan_stats.total_bss,
2540                             chan_stats.cca_scan_dur,
2541                             chan_stats.cca_busy_dur);
2542                 memcpy(&adapter->chan_stats[adapter->survey_idx++], &chan_stats,
2543                        sizeof(struct mwifiex_chan_stats));
2544                 fw_chan_stats++;
2545         }
2546 }
2547
2548 /* This function handles the command response of extended scan */
2549 int mwifiex_ret_802_11_scan_ext(struct mwifiex_private *priv,
2550                                 struct host_cmd_ds_command *resp)
2551 {
2552         struct mwifiex_adapter *adapter = priv->adapter;
2553         struct host_cmd_ds_802_11_scan_ext *ext_scan_resp;
2554         struct mwifiex_ie_types_header *tlv;
2555         struct mwifiex_ietypes_chanstats *tlv_stat;
2556         u16 buf_left, type, len;
2557
2558         struct host_cmd_ds_command *cmd_ptr;
2559         struct cmd_ctrl_node *cmd_node;
2560         unsigned long cmd_flags, scan_flags;
2561         bool complete_scan = false;
2562
2563         mwifiex_dbg(adapter, INFO, "info: EXT scan returns successfully\n");
2564
2565         ext_scan_resp = &resp->params.ext_scan;
2566
2567         tlv = (void *)ext_scan_resp->tlv_buffer;
2568         buf_left = le16_to_cpu(resp->size) - (sizeof(*ext_scan_resp) + S_DS_GEN
2569                                               - 1);
2570
2571         while (buf_left >= sizeof(struct mwifiex_ie_types_header)) {
2572                 type = le16_to_cpu(tlv->type);
2573                 len = le16_to_cpu(tlv->len);
2574
2575                 if (buf_left < (sizeof(struct mwifiex_ie_types_header) + len)) {
2576                         mwifiex_dbg(adapter, ERROR,
2577                                     "error processing scan response TLVs");
2578                         break;
2579                 }
2580
2581                 switch (type) {
2582                 case TLV_TYPE_CHANNEL_STATS:
2583                         tlv_stat = (void *)tlv;
2584                         mwifiex_update_chan_statistics(priv, tlv_stat);
2585                         break;
2586                 default:
2587                         break;
2588                 }
2589
2590                 buf_left -= len + sizeof(struct mwifiex_ie_types_header);
2591                 tlv = (void *)((u8 *)tlv + len +
2592                                sizeof(struct mwifiex_ie_types_header));
2593         }
2594
2595         spin_lock_irqsave(&adapter->cmd_pending_q_lock, cmd_flags);
2596         spin_lock_irqsave(&adapter->scan_pending_q_lock, scan_flags);
2597         if (list_empty(&adapter->scan_pending_q)) {
2598                 complete_scan = true;
2599                 list_for_each_entry(cmd_node, &adapter->cmd_pending_q, list) {
2600                         cmd_ptr = (void *)cmd_node->cmd_skb->data;
2601                         if (le16_to_cpu(cmd_ptr->command) ==
2602                             HostCmd_CMD_802_11_SCAN_EXT) {
2603                                 mwifiex_dbg(adapter, INFO,
2604                                             "Scan pending in command pending list");
2605                                 complete_scan = false;
2606                                 break;
2607                         }
2608                 }
2609         }
2610         spin_unlock_irqrestore(&adapter->scan_pending_q_lock, scan_flags);
2611         spin_unlock_irqrestore(&adapter->cmd_pending_q_lock, cmd_flags);
2612
2613         if (complete_scan)
2614                 mwifiex_complete_scan(priv);
2615
2616         return 0;
2617 }
2618
2619 /* This function This function handles the event extended scan report. It
2620  * parses extended scan results and informs to cfg80211 stack.
2621  */
2622 int mwifiex_handle_event_ext_scan_report(struct mwifiex_private *priv,
2623                                          void *buf)
2624 {
2625         int ret = 0;
2626         struct mwifiex_adapter *adapter = priv->adapter;
2627         u8 *bss_info;
2628         u32 bytes_left, bytes_left_for_tlv, idx;
2629         u16 type, len;
2630         struct mwifiex_ie_types_data *tlv;
2631         struct mwifiex_ie_types_bss_scan_rsp *scan_rsp_tlv;
2632         struct mwifiex_ie_types_bss_scan_info *scan_info_tlv;
2633         u8 *radio_type;
2634         u64 fw_tsf = 0;
2635         s32 rssi = 0;
2636         struct mwifiex_event_scan_result *event_scan = buf;
2637         u8 num_of_set = event_scan->num_of_set;
2638         u8 *scan_resp = buf + sizeof(struct mwifiex_event_scan_result);
2639         u16 scan_resp_size = le16_to_cpu(event_scan->buf_size);
2640
2641         if (num_of_set > MWIFIEX_MAX_AP) {
2642                 mwifiex_dbg(adapter, ERROR,
2643                             "EXT_SCAN: Invalid number of AP returned (%d)!!\n",
2644                             num_of_set);
2645                 ret = -1;
2646                 goto check_next_scan;
2647         }
2648
2649         bytes_left = scan_resp_size;
2650         mwifiex_dbg(adapter, INFO,
2651                     "EXT_SCAN: size %d, returned %d APs...",
2652                     scan_resp_size, num_of_set);
2653         mwifiex_dbg_dump(adapter, CMD_D, "EXT_SCAN buffer:", buf,
2654                          scan_resp_size +
2655                          sizeof(struct mwifiex_event_scan_result));
2656
2657         tlv = (struct mwifiex_ie_types_data *)scan_resp;
2658
2659         for (idx = 0; idx < num_of_set && bytes_left; idx++) {
2660                 type = le16_to_cpu(tlv->header.type);
2661                 len = le16_to_cpu(tlv->header.len);
2662                 if (bytes_left < sizeof(struct mwifiex_ie_types_header) + len) {
2663                         mwifiex_dbg(adapter, ERROR,
2664                                     "EXT_SCAN: Error bytes left < TLV length\n");
2665                         break;
2666                 }
2667                 scan_rsp_tlv = NULL;
2668                 scan_info_tlv = NULL;
2669                 bytes_left_for_tlv = bytes_left;
2670
2671                 /* BSS response TLV with beacon or probe response buffer
2672                  * at the initial position of each descriptor
2673                  */
2674                 if (type != TLV_TYPE_BSS_SCAN_RSP)
2675                         break;
2676
2677                 bss_info = (u8 *)tlv;
2678                 scan_rsp_tlv = (struct mwifiex_ie_types_bss_scan_rsp *)tlv;
2679                 tlv = (struct mwifiex_ie_types_data *)(tlv->data + len);
2680                 bytes_left_for_tlv -=
2681                                 (len + sizeof(struct mwifiex_ie_types_header));
2682
2683                 while (bytes_left_for_tlv >=
2684                        sizeof(struct mwifiex_ie_types_header) &&
2685                        le16_to_cpu(tlv->header.type) != TLV_TYPE_BSS_SCAN_RSP) {
2686                         type = le16_to_cpu(tlv->header.type);
2687                         len = le16_to_cpu(tlv->header.len);
2688                         if (bytes_left_for_tlv <
2689                             sizeof(struct mwifiex_ie_types_header) + len) {
2690                                 mwifiex_dbg(adapter, ERROR,
2691                                             "EXT_SCAN: Error in processing TLV,\t"
2692                                             "bytes left < TLV length\n");
2693                                 scan_rsp_tlv = NULL;
2694                                 bytes_left_for_tlv = 0;
2695                                 continue;
2696                         }
2697                         switch (type) {
2698                         case TLV_TYPE_BSS_SCAN_INFO:
2699                                 scan_info_tlv =
2700                                   (struct mwifiex_ie_types_bss_scan_info *)tlv;
2701                                 if (len !=
2702                                  sizeof(struct mwifiex_ie_types_bss_scan_info) -
2703                                  sizeof(struct mwifiex_ie_types_header)) {
2704                                         bytes_left_for_tlv = 0;
2705                                         continue;
2706                                 }
2707                                 break;
2708                         default:
2709                                 break;
2710                         }
2711                         tlv = (struct mwifiex_ie_types_data *)(tlv->data + len);
2712                         bytes_left -=
2713                                 (len + sizeof(struct mwifiex_ie_types_header));
2714                         bytes_left_for_tlv -=
2715                                 (len + sizeof(struct mwifiex_ie_types_header));
2716                 }
2717
2718                 if (!scan_rsp_tlv)
2719                         break;
2720
2721                 /* Advance pointer to the beacon buffer length and
2722                  * update the bytes count so that the function
2723                  * wlan_interpret_bss_desc_with_ie() can handle the
2724                  * scan buffer withut any change
2725                  */
2726                 bss_info += sizeof(u16);
2727                 bytes_left -= sizeof(u16);
2728
2729                 if (scan_info_tlv) {
2730                         rssi = (s32)(s16)(le16_to_cpu(scan_info_tlv->rssi));
2731                         rssi *= 100;           /* Convert dBm to mBm */
2732                         mwifiex_dbg(adapter, INFO,
2733                                     "info: InterpretIE: RSSI=%d\n", rssi);
2734                         fw_tsf = le64_to_cpu(scan_info_tlv->tsf);
2735                         radio_type = &scan_info_tlv->radio_type;
2736                 } else {
2737                         radio_type = NULL;
2738                 }
2739                 ret = mwifiex_parse_single_response_buf(priv, &bss_info,
2740                                                         &bytes_left, fw_tsf,
2741                                                         radio_type, true, rssi);
2742                 if (ret)
2743                         goto check_next_scan;
2744         }
2745
2746 check_next_scan:
2747         if (!event_scan->more_event)
2748                 mwifiex_check_next_scan_command(priv);
2749
2750         return ret;
2751 }
2752
2753 /*
2754  * This function prepares command for background scan query.
2755  *
2756  * Preparation includes -
2757  *      - Setting command ID and proper size
2758  *      - Setting background scan flush parameter
2759  *      - Ensuring correct endian-ness
2760  */
2761 int mwifiex_cmd_802_11_bg_scan_query(struct host_cmd_ds_command *cmd)
2762 {
2763         struct host_cmd_ds_802_11_bg_scan_query *bg_query =
2764                 &cmd->params.bg_scan_query;
2765
2766         cmd->command = cpu_to_le16(HostCmd_CMD_802_11_BG_SCAN_QUERY);
2767         cmd->size = cpu_to_le16(sizeof(struct host_cmd_ds_802_11_bg_scan_query)
2768                                 + S_DS_GEN);
2769
2770         bg_query->flush = 1;
2771
2772         return 0;
2773 }
2774
2775 /*
2776  * This function inserts scan command node to the scan pending queue.
2777  */
2778 void
2779 mwifiex_queue_scan_cmd(struct mwifiex_private *priv,
2780                        struct cmd_ctrl_node *cmd_node)
2781 {
2782         struct mwifiex_adapter *adapter = priv->adapter;
2783         unsigned long flags;
2784
2785         cmd_node->wait_q_enabled = true;
2786         cmd_node->condition = &adapter->scan_wait_q_woken;
2787         spin_lock_irqsave(&adapter->scan_pending_q_lock, flags);
2788         list_add_tail(&cmd_node->list, &adapter->scan_pending_q);
2789         spin_unlock_irqrestore(&adapter->scan_pending_q_lock, flags);
2790 }
2791
2792 /*
2793  * This function sends a scan command for all available channels to the
2794  * firmware, filtered on a specific SSID.
2795  */
2796 static int mwifiex_scan_specific_ssid(struct mwifiex_private *priv,
2797                                       struct cfg80211_ssid *req_ssid)
2798 {
2799         struct mwifiex_adapter *adapter = priv->adapter;
2800         int ret;
2801         struct mwifiex_user_scan_cfg *scan_cfg;
2802
2803         if (adapter->scan_processing) {
2804                 mwifiex_dbg(adapter, WARN,
2805                             "cmd: Scan already in process...\n");
2806                 return -EBUSY;
2807         }
2808
2809         if (priv->scan_block) {
2810                 mwifiex_dbg(adapter, WARN,
2811                             "cmd: Scan is blocked during association...\n");
2812                 return -EBUSY;
2813         }
2814
2815         scan_cfg = kzalloc(sizeof(struct mwifiex_user_scan_cfg), GFP_KERNEL);
2816         if (!scan_cfg)
2817                 return -ENOMEM;
2818
2819         scan_cfg->ssid_list = req_ssid;
2820         scan_cfg->num_ssids = 1;
2821
2822         ret = mwifiex_scan_networks(priv, scan_cfg);
2823
2824         kfree(scan_cfg);
2825         return ret;
2826 }
2827
2828 /*
2829  * Sends IOCTL request to start a scan.
2830  *
2831  * This function allocates the IOCTL request buffer, fills it
2832  * with requisite parameters and calls the IOCTL handler.
2833  *
2834  * Scan command can be issued for both normal scan and specific SSID
2835  * scan, depending upon whether an SSID is provided or not.
2836  */
2837 int mwifiex_request_scan(struct mwifiex_private *priv,
2838                          struct cfg80211_ssid *req_ssid)
2839 {
2840         int ret;
2841
2842         if (mutex_lock_interruptible(&priv->async_mutex)) {
2843                 mwifiex_dbg(priv->adapter, ERROR,
2844                             "%s: acquire semaphore fail\n",
2845                             __func__);
2846                 return -1;
2847         }
2848
2849         priv->adapter->scan_wait_q_woken = false;
2850
2851         if (req_ssid && req_ssid->ssid_len != 0)
2852                 /* Specific SSID scan */
2853                 ret = mwifiex_scan_specific_ssid(priv, req_ssid);
2854         else
2855                 /* Normal scan */
2856                 ret = mwifiex_scan_networks(priv, NULL);
2857
2858         mutex_unlock(&priv->async_mutex);
2859
2860         return ret;
2861 }
2862
2863 /*
2864  * This function appends the vendor specific IE TLV to a buffer.
2865  */
2866 int
2867 mwifiex_cmd_append_vsie_tlv(struct mwifiex_private *priv,
2868                             u16 vsie_mask, u8 **buffer)
2869 {
2870         int id, ret_len = 0;
2871         struct mwifiex_ie_types_vendor_param_set *vs_param_set;
2872
2873         if (!buffer)
2874                 return 0;
2875         if (!(*buffer))
2876                 return 0;
2877
2878         /*
2879          * Traverse through the saved vendor specific IE array and append
2880          * the selected(scan/assoc/adhoc) IE as TLV to the command
2881          */
2882         for (id = 0; id < MWIFIEX_MAX_VSIE_NUM; id++) {
2883                 if (priv->vs_ie[id].mask & vsie_mask) {
2884                         vs_param_set =
2885                                 (struct mwifiex_ie_types_vendor_param_set *)
2886                                 *buffer;
2887                         vs_param_set->header.type =
2888                                 cpu_to_le16(TLV_TYPE_PASSTHROUGH);
2889                         vs_param_set->header.len =
2890                                 cpu_to_le16((((u16) priv->vs_ie[id].ie[1])
2891                                 & 0x00FF) + 2);
2892                         memcpy(vs_param_set->ie, priv->vs_ie[id].ie,
2893                                le16_to_cpu(vs_param_set->header.len));
2894                         *buffer += le16_to_cpu(vs_param_set->header.len) +
2895                                    sizeof(struct mwifiex_ie_types_header);
2896                         ret_len += le16_to_cpu(vs_param_set->header.len) +
2897                                    sizeof(struct mwifiex_ie_types_header);
2898                 }
2899         }
2900         return ret_len;
2901 }
2902
2903 /*
2904  * This function saves a beacon buffer of the current BSS descriptor.
2905  *
2906  * The current beacon buffer is saved so that it can be restored in the
2907  * following cases that makes the beacon buffer not to contain the current
2908  * ssid's beacon buffer.
2909  *      - The current ssid was not found somehow in the last scan.
2910  *      - The current ssid was the last entry of the scan table and overloaded.
2911  */
2912 void
2913 mwifiex_save_curr_bcn(struct mwifiex_private *priv)
2914 {
2915         struct mwifiex_bssdescriptor *curr_bss =
2916                 &priv->curr_bss_params.bss_descriptor;
2917
2918         if (!curr_bss->beacon_buf_size)
2919                 return;
2920
2921         /* allocate beacon buffer at 1st time; or if it's size has changed */
2922         if (!priv->curr_bcn_buf ||
2923             priv->curr_bcn_size != curr_bss->beacon_buf_size) {
2924                 priv->curr_bcn_size = curr_bss->beacon_buf_size;
2925
2926                 kfree(priv->curr_bcn_buf);
2927                 priv->curr_bcn_buf = kmalloc(curr_bss->beacon_buf_size,
2928                                              GFP_ATOMIC);
2929                 if (!priv->curr_bcn_buf)
2930                         return;
2931         }
2932
2933         memcpy(priv->curr_bcn_buf, curr_bss->beacon_buf,
2934                curr_bss->beacon_buf_size);
2935         mwifiex_dbg(priv->adapter, INFO,
2936                     "info: current beacon saved %d\n",
2937                     priv->curr_bcn_size);
2938
2939         curr_bss->beacon_buf = priv->curr_bcn_buf;
2940
2941         /* adjust the pointers in the current BSS descriptor */
2942         if (curr_bss->bcn_wpa_ie)
2943                 curr_bss->bcn_wpa_ie =
2944                         (struct ieee_types_vendor_specific *)
2945                         (curr_bss->beacon_buf +
2946                          curr_bss->wpa_offset);
2947
2948         if (curr_bss->bcn_rsn_ie)
2949                 curr_bss->bcn_rsn_ie = (struct ieee_types_generic *)
2950                         (curr_bss->beacon_buf +
2951                          curr_bss->rsn_offset);
2952
2953         if (curr_bss->bcn_ht_cap)
2954                 curr_bss->bcn_ht_cap = (struct ieee80211_ht_cap *)
2955                         (curr_bss->beacon_buf +
2956                          curr_bss->ht_cap_offset);
2957
2958         if (curr_bss->bcn_ht_oper)
2959                 curr_bss->bcn_ht_oper = (struct ieee80211_ht_operation *)
2960                         (curr_bss->beacon_buf +
2961                          curr_bss->ht_info_offset);
2962
2963         if (curr_bss->bcn_vht_cap)
2964                 curr_bss->bcn_vht_cap = (void *)(curr_bss->beacon_buf +
2965                                                  curr_bss->vht_cap_offset);
2966
2967         if (curr_bss->bcn_vht_oper)
2968                 curr_bss->bcn_vht_oper = (void *)(curr_bss->beacon_buf +
2969                                                   curr_bss->vht_info_offset);
2970
2971         if (curr_bss->bcn_bss_co_2040)
2972                 curr_bss->bcn_bss_co_2040 =
2973                         (curr_bss->beacon_buf + curr_bss->bss_co_2040_offset);
2974
2975         if (curr_bss->bcn_ext_cap)
2976                 curr_bss->bcn_ext_cap = curr_bss->beacon_buf +
2977                         curr_bss->ext_cap_offset;
2978
2979         if (curr_bss->oper_mode)
2980                 curr_bss->oper_mode = (void *)(curr_bss->beacon_buf +
2981                                                curr_bss->oper_mode_offset);
2982 }
2983
2984 /*
2985  * This function frees the current BSS descriptor beacon buffer.
2986  */
2987 void
2988 mwifiex_free_curr_bcn(struct mwifiex_private *priv)
2989 {
2990         kfree(priv->curr_bcn_buf);
2991         priv->curr_bcn_buf = NULL;
2992 }