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