Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wirel...
[pandora-kernel.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             && !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             && 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             && 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 == NL80211_IFTYPE_STATION)
459             && (bss_desc->bss_mode == NL80211_IFTYPE_STATION))
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 NL80211_IFTYPE_STATION:
577                 case NL80211_IFTYPE_ADHOC:
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 NL80211_IFTYPE_UNSPECIFIED:
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         __le16 beacon_interval;
1214         __le16 capabilities;
1215         u8 *current_ptr;
1216         u8 *rate;
1217         u8 element_len;
1218         u16 total_ie_len;
1219         u8 bytes_to_copy;
1220         u8 rate_size;
1221         u16 beacon_size;
1222         u8 found_data_rate_ie;
1223         u32 bytes_left_for_current_beacon;
1224         struct ieee_types_vendor_specific *vendor_ie;
1225         const u8 wpa_oui[4] = { 0x00, 0x50, 0xf2, 0x01 };
1226         const u8 wmm_oui[4] = { 0x00, 0x50, 0xf2, 0x02 };
1227
1228         found_data_rate_ie = false;
1229         rate_size = 0;
1230         beacon_size = 0;
1231
1232         if (*bytes_left >= sizeof(beacon_size)) {
1233                 /* Extract & convert beacon size from the command buffer */
1234                 memcpy(&beacon_size, *beacon_info, sizeof(beacon_size));
1235                 *bytes_left -= sizeof(beacon_size);
1236                 *beacon_info += sizeof(beacon_size);
1237         }
1238
1239         if (!beacon_size || beacon_size > *bytes_left) {
1240                 *beacon_info += *bytes_left;
1241                 *bytes_left = 0;
1242                 return -1;
1243         }
1244
1245         /* Initialize the current working beacon pointer for this BSS
1246            iteration */
1247         current_ptr = *beacon_info;
1248
1249         /* Advance the return beacon pointer past the current beacon */
1250         *beacon_info += beacon_size;
1251         *bytes_left -= beacon_size;
1252
1253         bytes_left_for_current_beacon = beacon_size;
1254
1255         memcpy(bss_entry->mac_address, current_ptr, ETH_ALEN);
1256         dev_dbg(adapter->dev, "info: InterpretIE: AP MAC Addr: %pM\n",
1257                                                 bss_entry->mac_address);
1258
1259         current_ptr += ETH_ALEN;
1260         bytes_left_for_current_beacon -= ETH_ALEN;
1261
1262         if (bytes_left_for_current_beacon < 12) {
1263                 dev_err(adapter->dev, "InterpretIE: not enough bytes left\n");
1264                 return -1;
1265         }
1266
1267         /*
1268          * Next 4 fields are RSSI, time stamp, beacon interval,
1269          *   and capability information
1270          */
1271
1272         /* RSSI is 1 byte long */
1273         bss_entry->rssi = (s32) (*current_ptr);
1274         dev_dbg(adapter->dev, "info: InterpretIE: RSSI=%02X\n", *current_ptr);
1275         current_ptr += 1;
1276         bytes_left_for_current_beacon -= 1;
1277
1278         /*
1279          *  The RSSI is not part of the beacon/probe response.  After we have
1280          *    advanced current_ptr past the RSSI field, save the remaining
1281          *    data for use at the application layer
1282          */
1283         bss_entry->beacon_buf = current_ptr;
1284         bss_entry->beacon_buf_size = bytes_left_for_current_beacon;
1285
1286         /* Time stamp is 8 bytes long */
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(&beacon_interval, current_ptr, 2);
1293         bss_entry->beacon_period = le16_to_cpu(beacon_interval);
1294         current_ptr += 2;
1295         bytes_left_for_current_beacon -= 2;
1296
1297         /* Capability information is 2 bytes long */
1298         memcpy(&capabilities, current_ptr, 2);
1299         dev_dbg(adapter->dev, "info: InterpretIE: capabilities=0x%X\n",
1300                capabilities);
1301         bss_entry->cap_info_bitmap = le16_to_cpu(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 = NL80211_IFTYPE_ADHOC;
1318         else
1319                 bss_entry->bss_mode = NL80211_IFTYPE_STATION;
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                                         NL80211_IFTYPE_UNSPECIFIED)) >= 0) {
2255                 dev_dbg(priv->adapter->dev,
2256                         "info: Scan: Delete SSID Entry: Found Idx = %d\n",
2257                        table_idx);
2258                 ret = 0;
2259                 mwifiex_scan_delete_table_entry(priv, table_idx);
2260         }
2261
2262         return ret;
2263 }
2264
2265 /*
2266  * This is an internal function used to start a scan based on an input
2267  * configuration.
2268  *
2269  * This uses the input user scan configuration information when provided in
2270  * order to send the appropriate scan commands to firmware to populate or
2271  * update the internal driver scan table.
2272  */
2273 int mwifiex_scan_networks(struct mwifiex_private *priv,
2274                           void *wait_buf, u16 action,
2275                           const struct mwifiex_user_scan_cfg *user_scan_in,
2276                           struct mwifiex_scan_resp *scan_resp)
2277 {
2278         int ret = 0;
2279         struct mwifiex_adapter *adapter = priv->adapter;
2280         struct cmd_ctrl_node *cmd_node = NULL;
2281         union mwifiex_scan_cmd_config_tlv *scan_cfg_out = NULL;
2282         struct mwifiex_ie_types_chan_list_param_set *chan_list_out;
2283         u32 buf_size;
2284         struct mwifiex_chan_scan_param_set *scan_chan_list;
2285         u8 keep_previous_scan;
2286         u8 filtered_scan;
2287         u8 scan_current_chan_only;
2288         u8 max_chan_per_scan;
2289         unsigned long flags;
2290
2291         if (action == HostCmd_ACT_GEN_GET) {
2292                 if (scan_resp) {
2293                         scan_resp->scan_table = (u8 *) adapter->scan_table;
2294                         scan_resp->num_in_scan_table =
2295                                 adapter->num_in_scan_table;
2296                 } else {
2297                         ret = -1;
2298                 }
2299                 return ret;
2300         }
2301
2302         if (adapter->scan_processing && action == HostCmd_ACT_GEN_SET) {
2303                 dev_dbg(adapter->dev, "cmd: Scan already in process...\n");
2304                 return ret;
2305         }
2306
2307         spin_lock_irqsave(&adapter->mwifiex_cmd_lock, flags);
2308         adapter->scan_processing = true;
2309         spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, flags);
2310
2311         if (priv->scan_block && action == HostCmd_ACT_GEN_SET) {
2312                 dev_dbg(adapter->dev,
2313                         "cmd: Scan is blocked during association...\n");
2314                 return ret;
2315         }
2316
2317         scan_cfg_out = kzalloc(sizeof(union mwifiex_scan_cmd_config_tlv),
2318                                         GFP_KERNEL);
2319         if (!scan_cfg_out) {
2320                 dev_err(adapter->dev, "failed to alloc scan_cfg_out\n");
2321                 return -1;
2322         }
2323
2324         buf_size = sizeof(struct mwifiex_chan_scan_param_set) *
2325                         MWIFIEX_USER_SCAN_CHAN_MAX;
2326         scan_chan_list = kzalloc(buf_size, GFP_KERNEL);
2327         if (!scan_chan_list) {
2328                 dev_err(adapter->dev, "failed to alloc scan_chan_list\n");
2329                 kfree(scan_cfg_out);
2330                 return -1;
2331         }
2332
2333         keep_previous_scan = false;
2334
2335         mwifiex_scan_setup_scan_config(priv, user_scan_in,
2336                                        &scan_cfg_out->config, &chan_list_out,
2337                                        scan_chan_list, &max_chan_per_scan,
2338                                        &filtered_scan, &scan_current_chan_only);
2339
2340         if (user_scan_in)
2341                 keep_previous_scan = user_scan_in->keep_previous_scan;
2342
2343
2344         if (!keep_previous_scan) {
2345                 memset(adapter->scan_table, 0x00,
2346                        sizeof(struct mwifiex_bssdescriptor) * IW_MAX_AP);
2347                 adapter->num_in_scan_table = 0;
2348                 adapter->bcn_buf_end = adapter->bcn_buf;
2349         }
2350
2351         ret = mwifiex_scan_channel_list(priv, wait_buf, max_chan_per_scan,
2352                                         filtered_scan, &scan_cfg_out->config,
2353                                         chan_list_out, scan_chan_list);
2354
2355         /* Get scan command from scan_pending_q and put to cmd_pending_q */
2356         if (!ret) {
2357                 spin_lock_irqsave(&adapter->scan_pending_q_lock, flags);
2358                 if (!list_empty(&adapter->scan_pending_q)) {
2359                         cmd_node = list_first_entry(&adapter->scan_pending_q,
2360                                                 struct cmd_ctrl_node, list);
2361                         list_del(&cmd_node->list);
2362                         spin_unlock_irqrestore(&adapter->scan_pending_q_lock,
2363                                                                         flags);
2364                         mwifiex_insert_cmd_to_pending_q(adapter, cmd_node,
2365                                                         true);
2366                 } else {
2367                         spin_unlock_irqrestore(&adapter->scan_pending_q_lock,
2368                                                flags);
2369                 }
2370                 ret = -EINPROGRESS;
2371         } else {
2372                 spin_lock_irqsave(&adapter->mwifiex_cmd_lock, flags);
2373                 adapter->scan_processing = true;
2374                 spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, flags);
2375         }
2376
2377         kfree(scan_cfg_out);
2378         kfree(scan_chan_list);
2379         return ret;
2380 }
2381
2382 /*
2383  * This function prepares a scan command to be sent to the firmware.
2384  *
2385  * This uses the scan command configuration sent to the command processing
2386  * module in command preparation stage to configure a scan command structure
2387  * to send to firmware.
2388  *
2389  * The fixed fields specifying the BSS type and BSSID filters as well as a
2390  * variable number/length of TLVs are sent in the command to firmware.
2391  *
2392  * Preparation also includes -
2393  *      - Setting command ID, and proper size
2394  *      - Ensuring correct endian-ness
2395  */
2396 int mwifiex_cmd_802_11_scan(struct mwifiex_private *priv,
2397                             struct host_cmd_ds_command *cmd, void *data_buf)
2398 {
2399         struct host_cmd_ds_802_11_scan *scan_cmd = &cmd->params.scan;
2400         struct mwifiex_scan_cmd_config *scan_cfg;
2401
2402         scan_cfg = (struct mwifiex_scan_cmd_config *) data_buf;
2403
2404         /* Set fixed field variables in scan command */
2405         scan_cmd->bss_mode = scan_cfg->bss_mode;
2406         memcpy(scan_cmd->bssid, scan_cfg->specific_bssid,
2407                sizeof(scan_cmd->bssid));
2408         memcpy(scan_cmd->tlv_buffer, scan_cfg->tlv_buf, scan_cfg->tlv_buf_len);
2409
2410         cmd->command = cpu_to_le16(HostCmd_CMD_802_11_SCAN);
2411
2412         /* Size is equal to the sizeof(fixed portions) + the TLV len + header */
2413         cmd->size = cpu_to_le16((u16) (sizeof(scan_cmd->bss_mode)
2414                                           + sizeof(scan_cmd->bssid)
2415                                           + scan_cfg->tlv_buf_len + S_DS_GEN));
2416
2417         return 0;
2418 }
2419
2420 /*
2421  * This function handles the command response of scan.
2422  *
2423  * The response buffer for the scan command has the following
2424  * memory layout:
2425  *
2426  *      .-------------------------------------------------------------.
2427  *      |  Header (4 * sizeof(t_u16)):  Standard command response hdr |
2428  *      .-------------------------------------------------------------.
2429  *      |  BufSize (t_u16) : sizeof the BSS Description data          |
2430  *      .-------------------------------------------------------------.
2431  *      |  NumOfSet (t_u8) : Number of BSS Descs returned             |
2432  *      .-------------------------------------------------------------.
2433  *      |  BSSDescription data (variable, size given in BufSize)      |
2434  *      .-------------------------------------------------------------.
2435  *      |  TLV data (variable, size calculated using Header->Size,    |
2436  *      |            BufSize and sizeof the fixed fields above)       |
2437  *      .-------------------------------------------------------------.
2438  */
2439 int mwifiex_ret_802_11_scan(struct mwifiex_private *priv,
2440                             struct host_cmd_ds_command *resp, void *wq_buf)
2441 {
2442         int ret = 0;
2443         struct mwifiex_adapter *adapter = priv->adapter;
2444         struct mwifiex_wait_queue *wait_queue = NULL;
2445         struct cmd_ctrl_node *cmd_node = NULL;
2446         struct host_cmd_ds_802_11_scan_rsp *scan_rsp = NULL;
2447         struct mwifiex_bssdescriptor *bss_new_entry = NULL;
2448         struct mwifiex_ie_types_data *tlv_data;
2449         struct mwifiex_ie_types_tsf_timestamp *tsf_tlv;
2450         u8 *bss_info;
2451         u32 scan_resp_size;
2452         u32 bytes_left;
2453         u32 num_in_table;
2454         u32 bss_idx;
2455         u32 idx;
2456         u32 tlv_buf_size;
2457         long long tsf_val;
2458         struct mwifiex_chan_freq_power *cfp;
2459         struct mwifiex_ie_types_chan_band_list_param_set *chan_band_tlv;
2460         struct chan_band_param_set *chan_band;
2461         u8 band;
2462         u8 is_bgscan_resp;
2463         unsigned long flags;
2464
2465         is_bgscan_resp = (le16_to_cpu(resp->command)
2466                 == HostCmd_CMD_802_11_BG_SCAN_QUERY);
2467         if (is_bgscan_resp)
2468                 scan_rsp = &resp->params.bg_scan_query_resp.scan_resp;
2469         else
2470                 scan_rsp = &resp->params.scan_resp;
2471
2472
2473         if (scan_rsp->number_of_sets > IW_MAX_AP) {
2474                 dev_err(adapter->dev, "SCAN_RESP: too many AP returned (%d)\n",
2475                        scan_rsp->number_of_sets);
2476                 ret = -1;
2477                 goto done;
2478         }
2479
2480         bytes_left = le16_to_cpu(scan_rsp->bss_descript_size);
2481         dev_dbg(adapter->dev, "info: SCAN_RESP: bss_descript_size %d\n",
2482                                                 bytes_left);
2483
2484         scan_resp_size = le16_to_cpu(resp->size);
2485
2486         dev_dbg(adapter->dev,
2487                 "info: SCAN_RESP: returned %d APs before parsing\n",
2488                scan_rsp->number_of_sets);
2489
2490         num_in_table = adapter->num_in_scan_table;
2491         bss_info = scan_rsp->bss_desc_and_tlv_buffer;
2492
2493         /*
2494          * The size of the TLV buffer is equal to the entire command response
2495          *   size (scan_resp_size) minus the fixed fields (sizeof()'s), the
2496          *   BSS Descriptions (bss_descript_size as bytesLef) and the command
2497          *   response header (S_DS_GEN)
2498          */
2499         tlv_buf_size = scan_resp_size - (bytes_left
2500                                          + sizeof(scan_rsp->bss_descript_size)
2501                                          + sizeof(scan_rsp->number_of_sets)
2502                                          + S_DS_GEN);
2503
2504         tlv_data = (struct mwifiex_ie_types_data *) (scan_rsp->
2505                                                  bss_desc_and_tlv_buffer +
2506                                                  bytes_left);
2507
2508         /* Search the TLV buffer space in the scan response for any valid
2509            TLVs */
2510         mwifiex_ret_802_11_scan_get_tlv_ptrs(adapter, tlv_data, tlv_buf_size,
2511                                              TLV_TYPE_TSFTIMESTAMP,
2512                                              (struct mwifiex_ie_types_data **)
2513                                              &tsf_tlv);
2514
2515         /* Search the TLV buffer space in the scan response for any valid
2516            TLVs */
2517         mwifiex_ret_802_11_scan_get_tlv_ptrs(adapter, tlv_data, tlv_buf_size,
2518                                              TLV_TYPE_CHANNELBANDLIST,
2519                                              (struct mwifiex_ie_types_data **)
2520                                              &chan_band_tlv);
2521
2522         /*
2523          *  Process each scan response returned (scan_rsp->number_of_sets).
2524          *  Save the information in the bss_new_entry and then insert into the
2525          *  driver scan table either as an update to an existing entry
2526          *  or as an addition at the end of the table
2527          */
2528         bss_new_entry = kzalloc(sizeof(struct mwifiex_bssdescriptor),
2529                                 GFP_KERNEL);
2530         if (!bss_new_entry) {
2531                 dev_err(adapter->dev, " failed to alloc bss_new_entry\n");
2532                 return -1;
2533         }
2534
2535         for (idx = 0; idx < scan_rsp->number_of_sets && bytes_left; idx++) {
2536                 /* Zero out the bss_new_entry we are about to store info in */
2537                 memset(bss_new_entry, 0x00,
2538                        sizeof(struct mwifiex_bssdescriptor));
2539
2540                 if (mwifiex_interpret_bss_desc_with_ie(adapter, bss_new_entry,
2541                                                         &bss_info,
2542                                                         &bytes_left)) {
2543                         /* Error parsing/interpreting scan response, skipped */
2544                         dev_err(adapter->dev, "SCAN_RESP: "
2545                                "mwifiex_interpret_bss_desc_with_ie "
2546                                "returned ERROR\n");
2547                         continue;
2548                 }
2549
2550                 /* Process the data fields and IEs returned for this BSS */
2551                 dev_dbg(adapter->dev, "info: SCAN_RESP: BSSID = %pM\n",
2552                        bss_new_entry->mac_address);
2553
2554                 /* Search the scan table for the same bssid */
2555                 for (bss_idx = 0; bss_idx < num_in_table; bss_idx++) {
2556                         if (memcmp(bss_new_entry->mac_address,
2557                                 adapter->scan_table[bss_idx].mac_address,
2558                                 sizeof(bss_new_entry->mac_address))) {
2559                                 continue;
2560                         }
2561                         /*
2562                          * If the SSID matches as well, it is a
2563                          * duplicate of this entry.  Keep the bss_idx
2564                          * set to this entry so we replace the old
2565                          * contents in the table
2566                          */
2567                         if ((bss_new_entry->ssid.ssid_len
2568                                 == adapter->scan_table[bss_idx]. ssid.ssid_len)
2569                                         && (!memcmp(bss_new_entry->ssid.ssid,
2570                                         adapter->scan_table[bss_idx].ssid.ssid,
2571                                         bss_new_entry->ssid.ssid_len))) {
2572                                 dev_dbg(adapter->dev, "info: SCAN_RESP:"
2573                                         " duplicate of index: %d\n", bss_idx);
2574                                 break;
2575                         }
2576                 }
2577                 /*
2578                  * If the bss_idx is equal to the number of entries in
2579                  * the table, the new entry was not a duplicate; append
2580                  * it to the scan table
2581                  */
2582                 if (bss_idx == num_in_table) {
2583                         /* Range check the bss_idx, keep it limited to
2584                            the last entry */
2585                         if (bss_idx == IW_MAX_AP)
2586                                 bss_idx--;
2587                         else
2588                                 num_in_table++;
2589                 }
2590
2591                 /*
2592                  * Save the beacon/probe response returned for later application
2593                  * retrieval.  Duplicate beacon/probe responses are updated if
2594                  * possible
2595                  */
2596                 mwifiex_ret_802_11_scan_store_beacon(priv, bss_idx,
2597                                                 num_in_table, bss_new_entry);
2598                 /*
2599                  * If the TSF TLV was appended to the scan results, save this
2600                  * entry's TSF value in the networkTSF field.The networkTSF is
2601                  * the firmware's TSF value at the time the beacon or probe
2602                  * response was received.
2603                  */
2604                 if (tsf_tlv) {
2605                         memcpy(&tsf_val, &tsf_tlv->tsf_data[idx * TSF_DATA_SIZE]
2606                                         , sizeof(tsf_val));
2607                         memcpy(&bss_new_entry->network_tsf, &tsf_val,
2608                                         sizeof(bss_new_entry->network_tsf));
2609                 }
2610                 band = BAND_G;
2611                 if (chan_band_tlv) {
2612                         chan_band = &chan_band_tlv->chan_band_param[idx];
2613                         band = mwifiex_radio_type_to_band(chan_band->radio_type
2614                                         & (BIT(0) | BIT(1)));
2615                 }
2616
2617                 /* Save the band designation for this entry for use in join */
2618                 bss_new_entry->bss_band = band;
2619                 cfp = mwifiex_get_cfp_by_band_and_channel_from_cfg80211(priv,
2620                                         (u8) bss_new_entry->bss_band,
2621                                         (u16)bss_new_entry->channel);
2622
2623                 if (cfp)
2624                         bss_new_entry->freq = cfp->freq;
2625                 else
2626                         bss_new_entry->freq = 0;
2627
2628                 /* Copy the locally created bss_new_entry to the scan table */
2629                 memcpy(&adapter->scan_table[bss_idx], bss_new_entry,
2630                        sizeof(adapter->scan_table[bss_idx]));
2631
2632         }
2633
2634         dev_dbg(adapter->dev,
2635                 "info: SCAN_RESP: Scanned %2d APs, %d valid, %d total\n",
2636                scan_rsp->number_of_sets,
2637                num_in_table - adapter->num_in_scan_table, num_in_table);
2638
2639         /* Update the total number of BSSIDs in the scan table */
2640         adapter->num_in_scan_table = num_in_table;
2641
2642         spin_lock_irqsave(&adapter->scan_pending_q_lock, flags);
2643         if (list_empty(&adapter->scan_pending_q)) {
2644                 spin_unlock_irqrestore(&adapter->scan_pending_q_lock, flags);
2645                 spin_lock_irqsave(&adapter->mwifiex_cmd_lock, flags);
2646                 adapter->scan_processing = false;
2647                 spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, flags);
2648                 /*
2649                  * Process the resulting scan table:
2650                  *   - Remove any bad ssids
2651                  *   - Update our current BSS information from scan data
2652                  */
2653                 mwifiex_process_scan_results(priv);
2654
2655                 /* Need to indicate IOCTL complete */
2656                 wait_queue = (struct mwifiex_wait_queue *) wq_buf;
2657                 if (wait_queue) {
2658                         wait_queue->status = MWIFIEX_ERROR_NO_ERROR;
2659
2660                         /* Indicate ioctl complete */
2661                         mwifiex_ioctl_complete(adapter,
2662                                (struct mwifiex_wait_queue *) wait_queue, 0);
2663                 }
2664                 if (priv->report_scan_result)
2665                         priv->report_scan_result = false;
2666                 if (priv->scan_pending_on_block) {
2667                         priv->scan_pending_on_block = false;
2668                         up(&priv->async_sem);
2669                 }
2670
2671         } else {
2672                 /* Get scan command from scan_pending_q and put to
2673                    cmd_pending_q */
2674                 cmd_node = list_first_entry(&adapter->scan_pending_q,
2675                                             struct cmd_ctrl_node, list);
2676                 list_del(&cmd_node->list);
2677                 spin_unlock_irqrestore(&adapter->scan_pending_q_lock, flags);
2678
2679                 mwifiex_insert_cmd_to_pending_q(adapter, cmd_node, true);
2680         }
2681
2682 done:
2683         kfree((u8 *) bss_new_entry);
2684         return ret;
2685 }
2686
2687 /*
2688  * This function prepares command for background scan query.
2689  *
2690  * Preparation includes -
2691  *      - Setting command ID and proper size
2692  *      - Setting background scan flush parameter
2693  *      - Ensuring correct endian-ness
2694  */
2695 int mwifiex_cmd_802_11_bg_scan_query(struct mwifiex_private *priv,
2696                                      struct host_cmd_ds_command *cmd,
2697                                      void *data_buf)
2698 {
2699         struct host_cmd_ds_802_11_bg_scan_query *bg_query =
2700                 &cmd->params.bg_scan_query;
2701
2702         cmd->command = cpu_to_le16(HostCmd_CMD_802_11_BG_SCAN_QUERY);
2703         cmd->size = cpu_to_le16(sizeof(struct host_cmd_ds_802_11_bg_scan_query)
2704                                 + S_DS_GEN);
2705
2706         bg_query->flush = 1;
2707
2708         return 0;
2709 }
2710
2711 /*
2712  * This function finds a SSID in the scan table.
2713  *
2714  * A BSSID may optionally be provided to qualify the SSID.
2715  * For non-Auto mode, further check is made to make sure the
2716  * BSS found in the scan table is compatible with the current
2717  * settings of the driver.
2718  */
2719 s32
2720 mwifiex_find_ssid_in_list(struct mwifiex_private *priv,
2721                           struct mwifiex_802_11_ssid *ssid, u8 *bssid,
2722                           u32 mode)
2723 {
2724         struct mwifiex_adapter *adapter = priv->adapter;
2725         s32 net = -1, j;
2726         u8 best_rssi = 0;
2727         u32 i;
2728
2729         dev_dbg(adapter->dev, "info: num of entries in table = %d\n",
2730                adapter->num_in_scan_table);
2731
2732         /*
2733          * Loop through the table until the maximum is reached or until a match
2734          *   is found based on the bssid field comparison
2735          */
2736         for (i = 0;
2737              i < adapter->num_in_scan_table && (!bssid || (bssid && net < 0));
2738              i++) {
2739                 if (!mwifiex_ssid_cmp(&adapter->scan_table[i].ssid, ssid) &&
2740                     (!bssid
2741                      || !memcmp(adapter->scan_table[i].mac_address, bssid,
2742                                 ETH_ALEN))
2743                     &&
2744                     (mwifiex_get_cfp_by_band_and_channel_from_cfg80211
2745                      (priv, (u8) adapter->scan_table[i].bss_band,
2746                       (u16) adapter->scan_table[i].channel))) {
2747                         switch (mode) {
2748                         case NL80211_IFTYPE_STATION:
2749                         case NL80211_IFTYPE_ADHOC:
2750                                 j = mwifiex_is_network_compatible(priv, i,
2751                                                                   mode);
2752
2753                                 if (j >= 0) {
2754                                         if (SCAN_RSSI
2755                                             (adapter->scan_table[i].rssi) >
2756                                             best_rssi) {
2757                                                 best_rssi = SCAN_RSSI(adapter->
2758                                                                   scan_table
2759                                                                   [i].rssi);
2760                                                 net = i;
2761                                         }
2762                                 } else {
2763                                         if (net == -1)
2764                                                 net = j;
2765                                 }
2766                                 break;
2767                         case NL80211_IFTYPE_UNSPECIFIED:
2768                         default:
2769                                 /*
2770                                  * Do not check compatibility if the mode
2771                                  * requested is Auto/Unknown.  Allows generic
2772                                  * find to work without verifying against the
2773                                  * Adapter security settings
2774                                  */
2775                                 if (SCAN_RSSI(adapter->scan_table[i].rssi) >
2776                                     best_rssi) {
2777                                         best_rssi = SCAN_RSSI(adapter->
2778                                                           scan_table[i].rssi);
2779                                         net = i;
2780                                 }
2781                                 break;
2782                         }
2783                 }
2784         }
2785
2786         return net;
2787 }
2788
2789 /*
2790  * This function finds a specific compatible BSSID in the scan list.
2791  *
2792  * This function loops through the scan table looking for a compatible
2793  * match. If a BSSID matches, but the BSS is found to be not compatible
2794  * the function ignores it and continues to search through the rest of
2795  * the entries in case there is an AP with multiple SSIDs assigned to
2796  * the same BSSID.
2797  */
2798 s32
2799 mwifiex_find_bssid_in_list(struct mwifiex_private *priv, u8 *bssid,
2800                            u32 mode)
2801 {
2802         struct mwifiex_adapter *adapter = priv->adapter;
2803         s32 net = -1;
2804         u32 i;
2805
2806         if (!bssid)
2807                 return -1;
2808
2809         dev_dbg(adapter->dev, "info: FindBSSID: Num of BSSIDs = %d\n",
2810                adapter->num_in_scan_table);
2811
2812         /*
2813          * Look through the scan table for a compatible match. The ret return
2814          *   variable will be equal to the index in the scan table (greater
2815          *   than zero) if the network is compatible.  The loop will continue
2816          *   past a matched bssid that is not compatible in case there is an
2817          *   AP with multiple SSIDs assigned to the same BSSID
2818          */
2819         for (i = 0; net < 0 && i < adapter->num_in_scan_table; i++) {
2820                 if (!memcmp
2821                     (adapter->scan_table[i].mac_address, bssid, ETH_ALEN)
2822                         && mwifiex_get_cfp_by_band_and_channel_from_cfg80211
2823                                                                 (priv,
2824                                                             (u8) adapter->
2825                                                             scan_table[i].
2826                                                             bss_band,
2827                                                             (u16) adapter->
2828                                                             scan_table[i].
2829                                                             channel)) {
2830                         switch (mode) {
2831                         case NL80211_IFTYPE_STATION:
2832                         case NL80211_IFTYPE_ADHOC:
2833                                 net = mwifiex_is_network_compatible(priv, i,
2834                                                                     mode);
2835                                 break;
2836                         default:
2837                                 net = i;
2838                                 break;
2839                         }
2840                 }
2841         }
2842
2843         return net;
2844 }
2845
2846 /*
2847  * This function inserts scan command node to the scan pending queue.
2848  */
2849 void
2850 mwifiex_queue_scan_cmd(struct mwifiex_private *priv,
2851                        struct cmd_ctrl_node *cmd_node)
2852 {
2853         struct mwifiex_adapter *adapter = priv->adapter;
2854         unsigned long flags;
2855
2856         spin_lock_irqsave(&adapter->scan_pending_q_lock, flags);
2857         list_add_tail(&cmd_node->list, &adapter->scan_pending_q);
2858         spin_unlock_irqrestore(&adapter->scan_pending_q_lock, flags);
2859 }
2860
2861 /*
2862  * This function finds an AP with specific ssid in the scan list.
2863  */
2864 int mwifiex_find_best_network(struct mwifiex_private *priv,
2865                               struct mwifiex_ssid_bssid *req_ssid_bssid)
2866 {
2867         struct mwifiex_adapter *adapter = priv->adapter;
2868         struct mwifiex_bssdescriptor *req_bss;
2869         s32 i;
2870
2871         memset(req_ssid_bssid, 0, sizeof(struct mwifiex_ssid_bssid));
2872
2873         i = mwifiex_find_best_network_in_list(priv);
2874
2875         if (i >= 0) {
2876                 req_bss = &adapter->scan_table[i];
2877                 memcpy(&req_ssid_bssid->ssid, &req_bss->ssid,
2878                        sizeof(struct mwifiex_802_11_ssid));
2879                 memcpy((u8 *) &req_ssid_bssid->bssid,
2880                        (u8 *) &req_bss->mac_address, ETH_ALEN);
2881
2882                 /* Make sure we are in the right mode */
2883                 if (priv->bss_mode == NL80211_IFTYPE_UNSPECIFIED)
2884                         priv->bss_mode = req_bss->bss_mode;
2885         }
2886
2887         if (!req_ssid_bssid->ssid.ssid_len)
2888                 return -1;
2889
2890         dev_dbg(adapter->dev, "info: Best network found = [%s], "
2891                "[%pM]\n", req_ssid_bssid->ssid.ssid,
2892                req_ssid_bssid->bssid);
2893
2894         return 0;
2895 }
2896
2897 /*
2898  * This function sends a scan command for all available channels to the
2899  * firmware, filtered on a specific SSID.
2900  */
2901 static int mwifiex_scan_specific_ssid(struct mwifiex_private *priv,
2902                                       void *wait_buf, u16 action,
2903                                       struct mwifiex_802_11_ssid *req_ssid,
2904                                       struct mwifiex_scan_resp *scan_resp)
2905 {
2906         struct mwifiex_adapter *adapter = priv->adapter;
2907         int ret = 0;
2908         struct mwifiex_user_scan_cfg *scan_cfg;
2909
2910         if (!req_ssid)
2911                 return -1;
2912
2913         if (action == HostCmd_ACT_GEN_GET) {
2914                 if (scan_resp) {
2915                         scan_resp->scan_table =
2916                                 (u8 *) &priv->curr_bss_params.bss_descriptor;
2917                         scan_resp->num_in_scan_table =
2918                                 adapter->num_in_scan_table;
2919                 } else {
2920                         ret = -1;
2921                 }
2922                 return ret;
2923         }
2924
2925         if (adapter->scan_processing && action == HostCmd_ACT_GEN_SET) {
2926                 dev_dbg(adapter->dev, "cmd: Scan already in process...\n");
2927                 return ret;
2928         }
2929
2930         if (priv->scan_block && action == HostCmd_ACT_GEN_SET) {
2931                 dev_dbg(adapter->dev,
2932                         "cmd: Scan is blocked during association...\n");
2933                 return ret;
2934         }
2935
2936         mwifiex_scan_delete_ssid_table_entry(priv, req_ssid);
2937
2938         scan_cfg = kzalloc(sizeof(struct mwifiex_user_scan_cfg), GFP_KERNEL);
2939         if (!scan_cfg) {
2940                 dev_err(adapter->dev, "failed to alloc scan_cfg\n");
2941                 return -1;
2942         }
2943
2944         memcpy(scan_cfg->ssid_list[0].ssid, req_ssid->ssid,
2945                req_ssid->ssid_len);
2946         scan_cfg->keep_previous_scan = true;
2947
2948         ret = mwifiex_scan_networks(priv, wait_buf, action, scan_cfg, NULL);
2949
2950         kfree(scan_cfg);
2951         return ret;
2952 }
2953
2954 /*
2955  * Sends IOCTL request to start a scan.
2956  *
2957  * This function allocates the IOCTL request buffer, fills it
2958  * with requisite parameters and calls the IOCTL handler.
2959  *
2960  * Scan command can be issued for both normal scan and specific SSID
2961  * scan, depending upon whether an SSID is provided or not.
2962  */
2963 int mwifiex_request_scan(struct mwifiex_private *priv, u8 wait_option,
2964                          struct mwifiex_802_11_ssid *req_ssid)
2965 {
2966         int ret = 0;
2967         struct mwifiex_wait_queue *wait = NULL;
2968         int status = 0;
2969
2970         if (down_interruptible(&priv->async_sem)) {
2971                 dev_err(priv->adapter->dev, "%s: acquire semaphore\n",
2972                                                 __func__);
2973                 return -1;
2974         }
2975         priv->scan_pending_on_block = true;
2976
2977         /* Allocate wait request buffer */
2978         wait = mwifiex_alloc_fill_wait_queue(priv, wait_option);
2979         if (!wait) {
2980                 ret = -1;
2981                 goto done;
2982         }
2983
2984         if (req_ssid && req_ssid->ssid_len != 0)
2985                 /* Specific SSID scan */
2986                 status = mwifiex_scan_specific_ssid(priv, wait,
2987                                                     HostCmd_ACT_GEN_SET,
2988                                                     req_ssid, NULL);
2989         else
2990                 /* Normal scan */
2991                 status = mwifiex_scan_networks(priv, wait, HostCmd_ACT_GEN_SET,
2992                                                NULL, NULL);
2993         status = mwifiex_request_ioctl(priv, wait, status, wait_option);
2994         if (status == -1)
2995                 ret = -1;
2996 done:
2997         if ((wait) && (status != -EINPROGRESS))
2998                 kfree(wait);
2999         if (ret == -1) {
3000                 priv->scan_pending_on_block = false;
3001                 up(&priv->async_sem);
3002         }
3003         return ret;
3004 }
3005
3006 /*
3007  * This function appends the vendor specific IE TLV to a buffer.
3008  */
3009 int
3010 mwifiex_cmd_append_vsie_tlv(struct mwifiex_private *priv,
3011                             u16 vsie_mask, u8 **buffer)
3012 {
3013         int id, ret_len = 0;
3014         struct mwifiex_ie_types_vendor_param_set *vs_param_set;
3015
3016         if (!buffer)
3017                 return 0;
3018         if (!(*buffer))
3019                 return 0;
3020
3021         /*
3022          * Traverse through the saved vendor specific IE array and append
3023          * the selected(scan/assoc/adhoc) IE as TLV to the command
3024          */
3025         for (id = 0; id < MWIFIEX_MAX_VSIE_NUM; id++) {
3026                 if (priv->vs_ie[id].mask & vsie_mask) {
3027                         vs_param_set =
3028                                 (struct mwifiex_ie_types_vendor_param_set *)
3029                                 *buffer;
3030                         vs_param_set->header.type =
3031                                 cpu_to_le16(TLV_TYPE_PASSTHROUGH);
3032                         vs_param_set->header.len =
3033                                 cpu_to_le16((((u16) priv->vs_ie[id].ie[1])
3034                                 & 0x00FF) + 2);
3035                         memcpy(vs_param_set->ie, priv->vs_ie[id].ie,
3036                                le16_to_cpu(vs_param_set->header.len));
3037                         *buffer += le16_to_cpu(vs_param_set->header.len) +
3038                                    sizeof(struct mwifiex_ie_types_header);
3039                         ret_len += le16_to_cpu(vs_param_set->header.len) +
3040                                    sizeof(struct mwifiex_ie_types_header);
3041                 }
3042         }
3043         return ret_len;
3044 }
3045
3046 /*
3047  * This function saves a beacon buffer of the current BSS descriptor.
3048  *
3049  * The current beacon buffer is saved so that it can be restored in the
3050  * following cases that makes the beacon buffer not to contain the current
3051  * ssid's beacon buffer.
3052  *      - The current ssid was not found somehow in the last scan.
3053  *      - The current ssid was the last entry of the scan table and overloaded.
3054  */
3055 void
3056 mwifiex_save_curr_bcn(struct mwifiex_private *priv)
3057 {
3058         struct mwifiex_bssdescriptor *curr_bss =
3059                 &priv->curr_bss_params.bss_descriptor;
3060
3061         /* save the beacon buffer if it is not saved or updated */
3062         if ((priv->curr_bcn_buf == NULL) ||
3063             (priv->curr_bcn_size != curr_bss->beacon_buf_size) ||
3064             (memcmp(priv->curr_bcn_buf, curr_bss->beacon_buf,
3065                     curr_bss->beacon_buf_size))) {
3066
3067                 kfree(priv->curr_bcn_buf);
3068                 priv->curr_bcn_buf = NULL;
3069
3070                 priv->curr_bcn_size = curr_bss->beacon_buf_size;
3071                 if (!priv->curr_bcn_size)
3072                         return;
3073
3074                 priv->curr_bcn_buf = kzalloc(curr_bss->beacon_buf_size,
3075                                                 GFP_KERNEL);
3076                 if (!priv->curr_bcn_buf) {
3077                         dev_err(priv->adapter->dev,
3078                                         "failed to alloc curr_bcn_buf\n");
3079                 } else {
3080                         memcpy(priv->curr_bcn_buf, curr_bss->beacon_buf,
3081                                curr_bss->beacon_buf_size);
3082                         dev_dbg(priv->adapter->dev,
3083                                 "info: current beacon saved %d\n",
3084                                priv->curr_bcn_size);
3085                 }
3086         }
3087 }
3088
3089 /*
3090  * This function frees the current BSS descriptor beacon buffer.
3091  */
3092 void
3093 mwifiex_free_curr_bcn(struct mwifiex_private *priv)
3094 {
3095         kfree(priv->curr_bcn_buf);
3096         priv->curr_bcn_buf = NULL;
3097 }