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