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