2 * Marvell Wireless LAN device driver: scan ioctl and command handling
4 * Copyright (C) 2011, Marvell International Ltd.
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.
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.
28 /* The maximum number of channels the firmware can scan per command */
29 #define MWIFIEX_MAX_CHANNELS_PER_SPECIFIC_SCAN 14
31 #define MWIFIEX_CHANNELS_PER_SCAN_CMD 4
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)))
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)
42 /* Memory needed to store a max number/size WildCard SSID TLV for a firmware
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))
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) \
55 + WILDCARD_SSID_TLV_MAX_SIZE)
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];
70 static u8 mwifiex_wpa_oui[CIPHER_SUITE_MAX][4] = {
71 { 0x00, 0x50, 0xf2, 0x02 }, /* TKIP */
72 { 0x00, 0x50, 0xf2, 0x04 }, /* AES */
74 static u8 mwifiex_rsn_oui[CIPHER_SUITE_MAX][4] = {
75 { 0x00, 0x0f, 0xac, 0x02 }, /* TKIP */
76 { 0x00, 0x0f, 0xac, 0x04 }, /* AES */
80 * This function parses a given IE for a given OUI.
82 * This is used to parse a WPA/RSN IE to find if it has
86 mwifiex_search_oui_in_ie(struct ie_body *iebody, u8 *oui)
90 count = iebody->ptk_cnt[0];
92 /* There could be multiple OUIs for PTK hence
94 2) Check all the OUIs for AES.
95 3) If one of them is AES then pass success. */
97 if (!memcmp(iebody->ptk_body, oui, sizeof(iebody->ptk_body)))
98 return MWIFIEX_OUI_PRESENT;
102 iebody = (struct ie_body *) ((u8 *) iebody +
103 sizeof(iebody->ptk_body));
106 pr_debug("info: %s: OUI is not found in PTK\n", __func__);
107 return MWIFIEX_OUI_NOT_PRESENT;
111 * This function checks if a given OUI is present in a RSN IE.
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
118 mwifiex_is_rsn_oui_present(struct mwifiex_bssdescriptor *bss_desc, u32 cipher)
121 struct ie_body *iebody = NULL;
122 u8 ret = MWIFIEX_OUI_NOT_PRESENT;
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) +
129 oui = &mwifiex_rsn_oui[cipher][0];
130 ret = mwifiex_search_oui_in_ie(iebody, oui);
138 * This function checks if a given OUI is present in a WPA IE.
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
145 mwifiex_is_wpa_oui_present(struct mwifiex_bssdescriptor *bss_desc, u32 cipher)
148 struct ie_body *iebody = NULL;
149 u8 ret = MWIFIEX_OUI_NOT_PRESENT;
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);
163 * This function compares two SSIDs and checks if they match.
166 mwifiex_ssid_cmp(struct mwifiex_802_11_ssid *ssid1,
167 struct mwifiex_802_11_ssid *ssid2)
169 if (!ssid1 || !ssid2 || (ssid1->ssid_len != ssid2->ssid_len))
171 return memcmp(ssid1->ssid, ssid2->ssid, ssid1->ssid_len);
175 * Sends IOCTL request to get the best BSS.
177 * This function allocates the IOCTL request buffer, fills it
178 * with requisite parameters and calls the IOCTL handler.
180 int mwifiex_find_best_bss(struct mwifiex_private *priv,
181 u8 wait_option, struct mwifiex_ssid_bssid *ssid_bssid)
183 struct mwifiex_wait_queue *wait = NULL;
184 struct mwifiex_ssid_bssid tmp_ssid_bssid;
191 /* Allocate wait request buffer */
192 wait = mwifiex_alloc_fill_wait_queue(priv, wait_option);
196 memcpy(&tmp_ssid_bssid, ssid_bssid,
197 sizeof(struct mwifiex_ssid_bssid));
198 ret = mwifiex_bss_ioctl_find_bss(priv, wait, &tmp_ssid_bssid);
201 memcpy(ssid_bssid, &tmp_ssid_bssid,
202 sizeof(struct mwifiex_ssid_bssid));
203 mac = (u8 *) &ssid_bssid->bssid;
204 dev_dbg(priv->adapter->dev, "cmd: found network: ssid=%s,"
205 " %pM\n", ssid_bssid->ssid.ssid, mac);
213 * Sends IOCTL request to start a scan with user configurations.
215 * This function allocates the IOCTL request buffer, fills it
216 * with requisite parameters and calls the IOCTL handler.
218 * Upon completion, it also generates a wireless event to notify
221 int mwifiex_set_user_scan_ioctl(struct mwifiex_private *priv,
222 struct mwifiex_user_scan_cfg *scan_req)
224 struct mwifiex_wait_queue *wait = NULL;
226 u8 wait_option = MWIFIEX_IOCTL_WAIT;
228 /* Allocate an IOCTL request buffer */
229 wait = mwifiex_alloc_fill_wait_queue(priv, wait_option);
233 status = mwifiex_scan_networks(priv, wait, HostCmd_ACT_GEN_SET,
236 status = mwifiex_request_ioctl(priv, wait, status, wait_option);
238 if (wait && (status != -EINPROGRESS))
244 * This function checks if wapi is enabled in driver and scanned network is
245 * compatible with it.
248 mwifiex_is_network_compatible_for_wapi(struct mwifiex_private *priv,
249 struct mwifiex_bssdescriptor *bss_desc)
251 if (priv->sec_info.wapi_enabled &&
252 (bss_desc->bcn_wapi_ie &&
253 ((*(bss_desc->bcn_wapi_ie)).ieee_hdr.element_id ==
254 WLAN_EID_BSS_AC_ACCESS_DELAY))) {
261 * This function checks if driver is configured with no security mode and
262 * scanned network is compatible with it.
265 mwifiex_is_network_compatible_for_no_sec(struct mwifiex_private *priv,
266 struct mwifiex_bssdescriptor *bss_desc)
268 if (priv->sec_info.wep_status == MWIFIEX_802_11_WEP_DISABLED
269 && !priv->sec_info.wpa_enabled && !priv->sec_info.wpa2_enabled
270 && ((!bss_desc->bcn_wpa_ie) ||
271 ((*(bss_desc->bcn_wpa_ie)).vend_hdr.element_id !=
273 && ((!bss_desc->bcn_rsn_ie) ||
274 ((*(bss_desc->bcn_rsn_ie)).ieee_hdr.element_id !=
276 && !priv->sec_info.encryption_mode
277 && !bss_desc->privacy) {
284 * This function checks if static WEP is enabled in driver and scanned network
285 * is compatible with it.
288 mwifiex_is_network_compatible_for_static_wep(struct mwifiex_private *priv,
289 struct mwifiex_bssdescriptor *bss_desc)
291 if (priv->sec_info.wep_status == MWIFIEX_802_11_WEP_ENABLED
292 && !priv->sec_info.wpa_enabled && !priv->sec_info.wpa2_enabled
293 && bss_desc->privacy) {
300 * This function checks if wpa is enabled in driver and scanned network is
301 * compatible with it.
304 mwifiex_is_network_compatible_for_wpa(struct mwifiex_private *priv,
305 struct mwifiex_bssdescriptor *bss_desc,
308 if (priv->sec_info.wep_status == MWIFIEX_802_11_WEP_DISABLED
309 && priv->sec_info.wpa_enabled && !priv->sec_info.wpa2_enabled
310 && ((bss_desc->bcn_wpa_ie) && ((*(bss_desc->bcn_wpa_ie)).vend_hdr.
311 element_id == WLAN_EID_WPA))
313 * Privacy bit may NOT be set in some APs like
314 * LinkSys WRT54G && bss_desc->privacy
317 dev_dbg(priv->adapter->dev, "info: %s: WPA: index=%d"
318 " wpa_ie=%#x wpa2_ie=%#x WEP=%s WPA=%s WPA2=%s "
319 "EncMode=%#x privacy=%#x\n", __func__, index,
320 (bss_desc->bcn_wpa_ie) ?
321 (*(bss_desc->bcn_wpa_ie)).
322 vend_hdr.element_id : 0,
323 (bss_desc->bcn_rsn_ie) ?
324 (*(bss_desc->bcn_rsn_ie)).
325 ieee_hdr.element_id : 0,
326 (priv->sec_info.wep_status ==
327 MWIFIEX_802_11_WEP_ENABLED) ? "e" : "d",
328 (priv->sec_info.wpa_enabled) ? "e" : "d",
329 (priv->sec_info.wpa2_enabled) ? "e" : "d",
330 priv->sec_info.encryption_mode,
338 * This function checks if wpa2 is enabled in driver and scanned network is
339 * compatible with it.
342 mwifiex_is_network_compatible_for_wpa2(struct mwifiex_private *priv,
343 struct mwifiex_bssdescriptor *bss_desc,
346 if (priv->sec_info.wep_status == MWIFIEX_802_11_WEP_DISABLED
347 && !priv->sec_info.wpa_enabled && priv->sec_info.wpa2_enabled
348 && ((bss_desc->bcn_rsn_ie) && ((*(bss_desc->bcn_rsn_ie)).ieee_hdr.
349 element_id == WLAN_EID_RSN))
351 * Privacy bit may NOT be set in some APs like
352 * LinkSys WRT54G && bss_desc->privacy
355 dev_dbg(priv->adapter->dev, "info: %s: WPA2: index=%d"
356 " wpa_ie=%#x wpa2_ie=%#x WEP=%s WPA=%s WPA2=%s "
357 "EncMode=%#x privacy=%#x\n", __func__, index,
358 (bss_desc->bcn_wpa_ie) ?
359 (*(bss_desc->bcn_wpa_ie)).
360 vend_hdr.element_id : 0,
361 (bss_desc->bcn_rsn_ie) ?
362 (*(bss_desc->bcn_rsn_ie)).
363 ieee_hdr.element_id : 0,
364 (priv->sec_info.wep_status ==
365 MWIFIEX_802_11_WEP_ENABLED) ? "e" : "d",
366 (priv->sec_info.wpa_enabled) ? "e" : "d",
367 (priv->sec_info.wpa2_enabled) ? "e" : "d",
368 priv->sec_info.encryption_mode,
376 * This function checks if adhoc AES is enabled in driver and scanned network is
377 * compatible with it.
380 mwifiex_is_network_compatible_for_adhoc_aes(struct mwifiex_private *priv,
381 struct mwifiex_bssdescriptor *bss_desc)
383 if (priv->sec_info.wep_status == MWIFIEX_802_11_WEP_DISABLED
384 && !priv->sec_info.wpa_enabled && !priv->sec_info.wpa2_enabled
385 && ((!bss_desc->bcn_wpa_ie) || ((*(bss_desc->bcn_wpa_ie)).vend_hdr.
386 element_id != WLAN_EID_WPA))
387 && ((!bss_desc->bcn_rsn_ie) || ((*(bss_desc->bcn_rsn_ie)).ieee_hdr.
388 element_id != WLAN_EID_RSN))
389 && !priv->sec_info.encryption_mode
390 && bss_desc->privacy) {
397 * This function checks if dynamic WEP is enabled in driver and scanned network
398 * is compatible with it.
401 mwifiex_is_network_compatible_for_dynamic_wep(struct mwifiex_private *priv,
402 struct mwifiex_bssdescriptor *bss_desc,
405 if (priv->sec_info.wep_status == MWIFIEX_802_11_WEP_DISABLED
406 && !priv->sec_info.wpa_enabled && !priv->sec_info.wpa2_enabled
407 && ((!bss_desc->bcn_wpa_ie) || ((*(bss_desc->bcn_wpa_ie)).vend_hdr.
408 element_id != WLAN_EID_WPA))
409 && ((!bss_desc->bcn_rsn_ie) || ((*(bss_desc->bcn_rsn_ie)).ieee_hdr.
410 element_id != WLAN_EID_RSN))
411 && priv->sec_info.encryption_mode
412 && bss_desc->privacy) {
413 dev_dbg(priv->adapter->dev, "info: %s: dynamic "
414 "WEP: index=%d wpa_ie=%#x wpa2_ie=%#x "
415 "EncMode=%#x privacy=%#x\n",
417 (bss_desc->bcn_wpa_ie) ?
418 (*(bss_desc->bcn_wpa_ie)).
419 vend_hdr.element_id : 0,
420 (bss_desc->bcn_rsn_ie) ?
421 (*(bss_desc->bcn_rsn_ie)).
422 ieee_hdr.element_id : 0,
423 priv->sec_info.encryption_mode,
431 * This function checks if a scanned network is compatible with the driver
434 * WEP WPA WPA2 ad-hoc encrypt Network
435 * enabled enabled enabled AES mode Privacy WPA WPA2 Compatible
436 * 0 0 0 0 NONE 0 0 0 yes No security
437 * 0 1 0 0 x 1x 1 x yes WPA (disable
439 * 0 0 1 0 x 1x x 1 yes WPA2 (disable
441 * 0 0 0 1 NONE 1 0 0 yes Ad-hoc AES
442 * 1 0 0 0 NONE 1 0 0 yes Static WEP
444 * 0 0 0 0 !=NONE 1 0 0 yes Dynamic WEP
446 * Compatibility is not matched while roaming, except for mode.
449 mwifiex_is_network_compatible(struct mwifiex_private *priv, u32 index, u32 mode)
451 struct mwifiex_adapter *adapter = priv->adapter;
452 struct mwifiex_bssdescriptor *bss_desc;
454 bss_desc = &adapter->scan_table[index];
455 bss_desc->disable_11n = false;
457 /* Don't check for compatibility if roaming */
458 if (priv->media_connected && (priv->bss_mode == NL80211_IFTYPE_STATION)
459 && (bss_desc->bss_mode == NL80211_IFTYPE_STATION))
462 if (priv->wps.session_enable) {
463 dev_dbg(adapter->dev,
464 "info: return success directly in WPS period\n");
468 if (mwifiex_is_network_compatible_for_wapi(priv, bss_desc)) {
469 dev_dbg(adapter->dev, "info: return success for WAPI AP\n");
473 if (bss_desc->bss_mode == mode) {
474 if (mwifiex_is_network_compatible_for_no_sec(priv, bss_desc)) {
477 } else if (mwifiex_is_network_compatible_for_static_wep(priv,
479 /* Static WEP enabled */
480 dev_dbg(adapter->dev, "info: Disable 11n in WEP mode.\n");
481 bss_desc->disable_11n = true;
483 } else if (mwifiex_is_network_compatible_for_wpa(priv, bss_desc,
486 if (((priv->adapter->config_bands & BAND_GN
487 || priv->adapter->config_bands & BAND_AN)
488 && bss_desc->bcn_ht_cap)
489 && !mwifiex_is_wpa_oui_present(bss_desc,
490 CIPHER_SUITE_CCMP)) {
492 if (mwifiex_is_wpa_oui_present(bss_desc,
493 CIPHER_SUITE_TKIP)) {
494 dev_dbg(adapter->dev,
495 "info: Disable 11n if AES "
496 "is not supported by AP\n");
497 bss_desc->disable_11n = true;
503 } else if (mwifiex_is_network_compatible_for_wpa2(priv,
506 if (((priv->adapter->config_bands & BAND_GN
507 || priv->adapter->config_bands & BAND_AN)
508 && bss_desc->bcn_ht_cap)
509 && !mwifiex_is_rsn_oui_present(bss_desc,
510 CIPHER_SUITE_CCMP)) {
512 if (mwifiex_is_rsn_oui_present(bss_desc,
513 CIPHER_SUITE_TKIP)) {
514 dev_dbg(adapter->dev,
515 "info: Disable 11n if AES "
516 "is not supported by AP\n");
517 bss_desc->disable_11n = true;
523 } else if (mwifiex_is_network_compatible_for_adhoc_aes(priv,
525 /* Ad-hoc AES enabled */
527 } else if (mwifiex_is_network_compatible_for_dynamic_wep(priv,
529 /* Dynamic WEP enabled */
533 /* Security doesn't match */
534 dev_dbg(adapter->dev, "info: %s: failed: index=%d "
535 "wpa_ie=%#x wpa2_ie=%#x WEP=%s WPA=%s WPA2=%s EncMode"
536 "=%#x privacy=%#x\n",
538 (bss_desc->bcn_wpa_ie) ?
539 (*(bss_desc->bcn_wpa_ie)).vend_hdr.
541 (bss_desc->bcn_rsn_ie) ?
542 (*(bss_desc->bcn_rsn_ie)).ieee_hdr.
544 (priv->sec_info.wep_status ==
545 MWIFIEX_802_11_WEP_ENABLED) ? "e" : "d",
546 (priv->sec_info.wpa_enabled) ? "e" : "d",
547 (priv->sec_info.wpa2_enabled) ? "e" : "d",
548 priv->sec_info.encryption_mode, bss_desc->privacy);
552 /* Mode doesn't match */
557 * This function finds the best SSID in the scan list.
559 * It searches the scan table for the best SSID that also matches the current
560 * adapter network preference (mode, security etc.).
563 mwifiex_find_best_network_in_list(struct mwifiex_private *priv)
565 struct mwifiex_adapter *adapter = priv->adapter;
566 u32 mode = priv->bss_mode;
571 dev_dbg(adapter->dev, "info: num of BSSIDs = %d\n",
572 adapter->num_in_scan_table);
574 for (i = 0; i < adapter->num_in_scan_table; i++) {
576 case NL80211_IFTYPE_STATION:
577 case NL80211_IFTYPE_ADHOC:
578 if (mwifiex_is_network_compatible(priv, i, mode) >= 0) {
579 if (SCAN_RSSI(adapter->scan_table[i].rssi) >
581 best_rssi = SCAN_RSSI(adapter->
587 case NL80211_IFTYPE_UNSPECIFIED:
589 if (SCAN_RSSI(adapter->scan_table[i].rssi) >
591 best_rssi = SCAN_RSSI(adapter->scan_table[i].
603 * This function creates a channel list for the driver to scan, based
604 * on region/band information.
606 * This routine is used for any scan that is not provided with a
607 * specific channel list to scan.
610 mwifiex_scan_create_channel_list(struct mwifiex_private *priv,
611 const struct mwifiex_user_scan_cfg
613 struct mwifiex_chan_scan_param_set
617 enum ieee80211_band band;
618 struct ieee80211_supported_band *sband;
619 struct ieee80211_channel *ch;
620 struct mwifiex_adapter *adapter = priv->adapter;
624 for (band = 0; (band < IEEE80211_NUM_BANDS) ; band++) {
626 if (!priv->wdev->wiphy->bands[band])
629 sband = priv->wdev->wiphy->bands[band];
631 for (i = 0; (i < sband->n_channels) ; i++, chan_idx++) {
632 ch = &sband->channels[i];
633 if (ch->flags & IEEE80211_CHAN_DISABLED)
635 scan_chan_list[chan_idx].radio_type = band;
636 scan_type = ch->flags & IEEE80211_CHAN_PASSIVE_SCAN;
638 user_scan_in->chan_list[0].scan_time)
639 scan_chan_list[chan_idx].max_scan_time =
640 cpu_to_le16((u16) user_scan_in->
641 chan_list[0].scan_time);
642 else if (scan_type == MWIFIEX_SCAN_TYPE_PASSIVE)
643 scan_chan_list[chan_idx].max_scan_time =
644 cpu_to_le16(adapter->passive_scan_time);
646 scan_chan_list[chan_idx].max_scan_time =
647 cpu_to_le16(adapter->active_scan_time);
648 if (scan_type == MWIFIEX_SCAN_TYPE_PASSIVE)
649 scan_chan_list[chan_idx].chan_scan_mode_bitmap
650 |= MWIFIEX_PASSIVE_SCAN;
652 scan_chan_list[chan_idx].chan_scan_mode_bitmap
653 &= ~MWIFIEX_PASSIVE_SCAN;
654 scan_chan_list[chan_idx].chan_number =
657 scan_chan_list[chan_idx].max_scan_time =
658 cpu_to_le16(adapter->specific_scan_time);
659 scan_chan_list[chan_idx].chan_scan_mode_bitmap
660 |= MWIFIEX_DISABLE_CHAN_FILT;
668 * This function constructs and sends multiple scan config commands to
671 * Previous routines in the code flow have created a scan command configuration
672 * with any requested TLVs. This function splits the channel TLV into maximum
673 * channels supported per scan lists and sends the portion of the channel TLV,
674 * along with the other TLVs, to the firmware.
677 mwifiex_scan_channel_list(struct mwifiex_private *priv, void *wait_buf,
678 u32 max_chan_per_scan, u8 filtered_scan,
679 struct mwifiex_scan_cmd_config *scan_cfg_out,
680 struct mwifiex_ie_types_chan_list_param_set
682 struct mwifiex_chan_scan_param_set *scan_chan_list)
685 struct mwifiex_chan_scan_param_set *tmp_chan_list;
686 struct mwifiex_chan_scan_param_set *start_chan;
692 if (!scan_cfg_out || !chan_tlv_out || !scan_chan_list) {
693 dev_dbg(priv->adapter->dev,
694 "info: Scan: Null detect: %p, %p, %p\n",
695 scan_cfg_out, chan_tlv_out, scan_chan_list);
699 chan_tlv_out->header.type = cpu_to_le16(TLV_TYPE_CHANLIST);
701 /* Set the temp channel struct pointer to the start of the desired
703 tmp_chan_list = scan_chan_list;
705 /* Loop through the desired channel list, sending a new firmware scan
706 commands for each max_chan_per_scan channels (or for 1,6,11
707 individually if configured accordingly) */
708 while (tmp_chan_list->chan_number) {
712 chan_tlv_out->header.len = 0;
713 start_chan = tmp_chan_list;
717 * Construct the Channel TLV for the scan command. Continue to
718 * insert channel TLVs until:
719 * - the tlv_idx hits the maximum configured per scan command
720 * - the next channel to insert is 0 (end of desired channel
722 * - done_early is set (controlling individual scanning of
725 while (tlv_idx < max_chan_per_scan
726 && tmp_chan_list->chan_number && !done_early) {
728 dev_dbg(priv->adapter->dev,
729 "info: Scan: Chan(%3d), Radio(%d),"
730 " Mode(%d, %d), Dur(%d)\n",
731 tmp_chan_list->chan_number,
732 tmp_chan_list->radio_type,
733 tmp_chan_list->chan_scan_mode_bitmap
734 & MWIFIEX_PASSIVE_SCAN,
735 (tmp_chan_list->chan_scan_mode_bitmap
736 & MWIFIEX_DISABLE_CHAN_FILT) >> 1,
737 le16_to_cpu(tmp_chan_list->max_scan_time));
739 /* Copy the current channel TLV to the command being
741 memcpy(chan_tlv_out->chan_scan_param + tlv_idx,
743 sizeof(chan_tlv_out->chan_scan_param));
745 /* Increment the TLV header length by the size
747 chan_tlv_out->header.len =
748 cpu_to_le16(le16_to_cpu(chan_tlv_out->header.len) +
749 (sizeof(chan_tlv_out->chan_scan_param)));
752 * The tlv buffer length is set to the number of bytes
753 * of the between the channel tlv pointer and the start
754 * of the tlv buffer. This compensates for any TLVs
755 * that were appended before the channel list.
757 scan_cfg_out->tlv_buf_len = (u32) ((u8 *) chan_tlv_out -
758 scan_cfg_out->tlv_buf);
760 /* Add the size of the channel tlv header and the data
762 scan_cfg_out->tlv_buf_len +=
763 (sizeof(chan_tlv_out->header)
764 + le16_to_cpu(chan_tlv_out->header.len));
766 /* Increment the index to the channel tlv we are
770 /* Count the total scan time per command */
772 le16_to_cpu(tmp_chan_list->max_scan_time);
776 /* Stop the loop if the *current* channel is in the
777 1,6,11 set and we are not filtering on a BSSID
779 if (!filtered_scan && (tmp_chan_list->chan_number == 1
780 || tmp_chan_list->chan_number == 6
781 || tmp_chan_list->chan_number == 11))
784 /* Increment the tmp pointer to the next channel to
788 /* Stop the loop if the *next* channel is in the 1,6,11
789 set. This will cause it to be the only channel
790 scanned on the next interation */
791 if (!filtered_scan && (tmp_chan_list->chan_number == 1
792 || tmp_chan_list->chan_number == 6
793 || tmp_chan_list->chan_number == 11))
797 /* The total scan time should be less than scan command timeout
799 if (total_scan_time > MWIFIEX_MAX_TOTAL_SCAN_TIME) {
800 dev_err(priv->adapter->dev, "total scan time %dms"
801 " is over limit (%dms), scan skipped\n",
802 total_scan_time, MWIFIEX_MAX_TOTAL_SCAN_TIME);
807 priv->adapter->scan_channels = start_chan;
809 /* Send the scan command to the firmware with the specified
811 ret = mwifiex_prepare_cmd(priv, HostCmd_CMD_802_11_SCAN,
813 0, wait_buf, scan_cfg_out);
825 * This function constructs a scan command configuration structure to use
828 * Application layer or other functions can invoke network scanning
829 * with a scan configuration supplied in a user scan configuration structure.
830 * This structure is used as the basis of one or many scan command configuration
831 * commands that are sent to the command processing module and eventually to the
834 * This function creates a scan command configuration structure based on the
835 * following user supplied parameters (if present):
838 * - Number of Probes to be sent
841 * If the SSID or BSSID filter is not present, the filter is disabled/cleared.
842 * If the number of probes is not set, adapter default setting is used.
845 mwifiex_scan_setup_scan_config(struct mwifiex_private *priv,
846 const struct mwifiex_user_scan_cfg *user_scan_in,
847 struct mwifiex_scan_cmd_config *scan_cfg_out,
848 struct mwifiex_ie_types_chan_list_param_set
850 struct mwifiex_chan_scan_param_set
852 u8 *max_chan_per_scan, u8 *filtered_scan,
853 u8 *scan_current_only)
855 struct mwifiex_adapter *adapter = priv->adapter;
856 struct mwifiex_ie_types_num_probes *num_probes_tlv;
857 struct mwifiex_ie_types_wildcard_ssid_params *wildcard_ssid_tlv;
858 struct mwifiex_ie_types_rates_param_set *rates_tlv;
859 const u8 zero_mac[ETH_ALEN] = { 0, 0, 0, 0, 0, 0 };
870 u8 rates[MWIFIEX_SUPPORTED_RATES];
872 struct mwifiex_ie_types_htcap *ht_cap;
874 /* The tlv_buf_len is calculated for each scan command. The TLVs added
875 in this routine will be preserved since the routine that sends the
876 command will append channelTLVs at *chan_list_out. The difference
877 between the *chan_list_out and the tlv_buf start will be used to
878 calculate the size of anything we add in this routine. */
879 scan_cfg_out->tlv_buf_len = 0;
881 /* Running tlv pointer. Assigned to chan_list_out at end of function
882 so later routines know where channels can be added to the command
884 tlv_pos = scan_cfg_out->tlv_buf;
886 /* Initialize the scan as un-filtered; the flag is later set to TRUE
887 below if a SSID or BSSID filter is sent in the command */
888 *filtered_scan = false;
890 /* Initialize the scan as not being only on the current channel. If
891 the channel list is customized, only contains one channel, and is
892 the active channel, this is set true and data flow is not halted. */
893 *scan_current_only = false;
897 /* Default the ssid_filter flag to TRUE, set false under
898 certain wildcard conditions and qualified by the existence
899 of an SSID list before marking the scan as filtered */
902 /* Set the BSS type scan filter, use Adapter setting if
904 scan_cfg_out->bss_mode =
905 (user_scan_in->bss_mode ? (u8) user_scan_in->
906 bss_mode : (u8) adapter->scan_mode);
908 /* Set the number of probes to send, use Adapter setting
911 (user_scan_in->num_probes ? user_scan_in->
912 num_probes : adapter->scan_probes);
915 * Set the BSSID filter to the incoming configuration,
916 * if non-zero. If not set, it will remain disabled
919 memcpy(scan_cfg_out->specific_bssid,
920 user_scan_in->specific_bssid,
921 sizeof(scan_cfg_out->specific_bssid));
924 ((ssid_idx < ARRAY_SIZE(user_scan_in->ssid_list))
925 && (*user_scan_in->ssid_list[ssid_idx].ssid
926 || user_scan_in->ssid_list[ssid_idx].max_len));
929 ssid_len = strlen(user_scan_in->ssid_list[ssid_idx].
933 (struct mwifiex_ie_types_wildcard_ssid_params *)
935 wildcard_ssid_tlv->header.type =
936 cpu_to_le16(TLV_TYPE_WILDCARDSSID);
937 wildcard_ssid_tlv->header.len = cpu_to_le16(
938 (u16) (ssid_len + sizeof(wildcard_ssid_tlv->
940 wildcard_ssid_tlv->max_ssid_length =
941 user_scan_in->ssid_list[ssid_idx].max_len;
943 memcpy(wildcard_ssid_tlv->ssid,
944 user_scan_in->ssid_list[ssid_idx].ssid,
947 tlv_pos += (sizeof(wildcard_ssid_tlv->header)
948 + le16_to_cpu(wildcard_ssid_tlv->header.len));
950 dev_dbg(adapter->dev, "info: scan: ssid_list[%d]: %s, %d\n",
951 ssid_idx, wildcard_ssid_tlv->ssid,
952 wildcard_ssid_tlv->max_ssid_length);
954 /* Empty wildcard ssid with a maxlen will match many or
955 potentially all SSIDs (maxlen == 32), therefore do
956 not treat the scan as
958 if (!ssid_len && wildcard_ssid_tlv->max_ssid_length)
964 * The default number of channels sent in the command is low to
965 * ensure the response buffer from the firmware does not
966 * truncate scan results. That is not an issue with an SSID
967 * or BSSID filter applied to the scan results in the firmware.
969 if ((ssid_idx && ssid_filter)
970 || memcmp(scan_cfg_out->specific_bssid, &zero_mac,
972 *filtered_scan = true;
974 scan_cfg_out->bss_mode = (u8) adapter->scan_mode;
975 num_probes = adapter->scan_probes;
979 * If a specific BSSID or SSID is used, the number of channels in the
980 * scan command will be increased to the absolute maximum.
983 *max_chan_per_scan = MWIFIEX_MAX_CHANNELS_PER_SPECIFIC_SCAN;
985 *max_chan_per_scan = MWIFIEX_CHANNELS_PER_SCAN_CMD;
987 /* If the input config or adapter has the number of Probes set,
991 dev_dbg(adapter->dev, "info: scan: num_probes = %d\n",
994 num_probes_tlv = (struct mwifiex_ie_types_num_probes *) tlv_pos;
995 num_probes_tlv->header.type = cpu_to_le16(TLV_TYPE_NUMPROBES);
996 num_probes_tlv->header.len =
997 cpu_to_le16(sizeof(num_probes_tlv->num_probes));
998 num_probes_tlv->num_probes = cpu_to_le16((u16) num_probes);
1000 tlv_pos += sizeof(num_probes_tlv->header) +
1001 le16_to_cpu(num_probes_tlv->header.len);
1005 /* Append rates tlv */
1006 memset(rates, 0, sizeof(rates));
1008 rates_size = mwifiex_get_supported_rates(priv, rates);
1010 rates_tlv = (struct mwifiex_ie_types_rates_param_set *) tlv_pos;
1011 rates_tlv->header.type = cpu_to_le16(WLAN_EID_SUPP_RATES);
1012 rates_tlv->header.len = cpu_to_le16((u16) rates_size);
1013 memcpy(rates_tlv->rates, rates, rates_size);
1014 tlv_pos += sizeof(rates_tlv->header) + rates_size;
1016 dev_dbg(adapter->dev, "info: SCAN_CMD: Rates size = %d\n", rates_size);
1018 if (ISSUPP_11NENABLED(priv->adapter->fw_cap_info)
1019 && (priv->adapter->config_bands & BAND_GN
1020 || priv->adapter->config_bands & BAND_AN)) {
1021 ht_cap = (struct mwifiex_ie_types_htcap *) tlv_pos;
1022 memset(ht_cap, 0, sizeof(struct mwifiex_ie_types_htcap));
1023 ht_cap->header.type = cpu_to_le16(WLAN_EID_HT_CAPABILITY);
1024 ht_cap->header.len =
1025 cpu_to_le16(sizeof(struct ieee80211_ht_cap));
1026 mwifiex_fill_cap_info(priv, ht_cap);
1027 tlv_pos += sizeof(struct mwifiex_ie_types_htcap);
1030 /* Append vendor specific IE TLV */
1031 mwifiex_cmd_append_vsie_tlv(priv, MWIFIEX_VSIE_MASK_SCAN, &tlv_pos);
1034 * Set the output for the channel TLV to the address in the tlv buffer
1035 * past any TLVs that were added in this function (SSID, num_probes).
1036 * Channel TLVs will be added past this for each scan command,
1037 * preserving the TLVs that were previously added.
1040 (struct mwifiex_ie_types_chan_list_param_set *) tlv_pos;
1042 if (user_scan_in && user_scan_in->chan_list[0].chan_number) {
1044 dev_dbg(adapter->dev, "info: Scan: Using supplied channel list\n");
1047 chan_idx < MWIFIEX_USER_SCAN_CHAN_MAX
1048 && user_scan_in->chan_list[chan_idx].chan_number;
1051 channel = user_scan_in->chan_list[chan_idx].chan_number;
1052 (scan_chan_list + chan_idx)->chan_number = channel;
1055 user_scan_in->chan_list[chan_idx].radio_type;
1056 (scan_chan_list + chan_idx)->radio_type = radio_type;
1058 scan_type = user_scan_in->chan_list[chan_idx].scan_type;
1060 if (scan_type == MWIFIEX_SCAN_TYPE_PASSIVE)
1062 chan_idx)->chan_scan_mode_bitmap
1063 |= MWIFIEX_PASSIVE_SCAN;
1066 chan_idx)->chan_scan_mode_bitmap
1067 &= ~MWIFIEX_PASSIVE_SCAN;
1069 if (user_scan_in->chan_list[chan_idx].scan_time) {
1070 scan_dur = (u16) user_scan_in->
1071 chan_list[chan_idx].scan_time;
1073 if (scan_type == MWIFIEX_SCAN_TYPE_PASSIVE)
1074 scan_dur = adapter->passive_scan_time;
1075 else if (*filtered_scan)
1076 scan_dur = adapter->specific_scan_time;
1078 scan_dur = adapter->active_scan_time;
1081 (scan_chan_list + chan_idx)->min_scan_time =
1082 cpu_to_le16(scan_dur);
1083 (scan_chan_list + chan_idx)->max_scan_time =
1084 cpu_to_le16(scan_dur);
1087 /* Check if we are only scanning the current channel */
1089 && (user_scan_in->chan_list[0].chan_number
1090 == priv->curr_bss_params.bss_descriptor.channel)) {
1091 *scan_current_only = true;
1092 dev_dbg(adapter->dev,
1093 "info: Scan: Scanning current channel only\n");
1097 dev_dbg(adapter->dev,
1098 "info: Scan: Creating full region channel list\n");
1099 mwifiex_scan_create_channel_list(priv, user_scan_in,
1106 * This function inspects the scan response buffer for pointers to
1109 * TLVs can be included at the end of the scan response BSS information.
1111 * Data in the buffer is parsed pointers to TLVs that can potentially
1112 * be passed back in the response.
1115 mwifiex_ret_802_11_scan_get_tlv_ptrs(struct mwifiex_adapter *adapter,
1116 struct mwifiex_ie_types_data *tlv,
1117 u32 tlv_buf_size, u32 req_tlv_type,
1118 struct mwifiex_ie_types_data **tlv_data)
1120 struct mwifiex_ie_types_data *current_tlv;
1126 tlv_buf_left = tlv_buf_size;
1129 dev_dbg(adapter->dev, "info: SCAN_RESP: tlv_buf_size = %d\n",
1132 while (tlv_buf_left >= sizeof(struct mwifiex_ie_types_header)) {
1134 tlv_type = le16_to_cpu(current_tlv->header.type);
1135 tlv_len = le16_to_cpu(current_tlv->header.len);
1137 if (sizeof(tlv->header) + tlv_len > tlv_buf_left) {
1138 dev_err(adapter->dev, "SCAN_RESP: TLV buffer corrupt\n");
1142 if (req_tlv_type == tlv_type) {
1144 case TLV_TYPE_TSFTIMESTAMP:
1145 dev_dbg(adapter->dev, "info: SCAN_RESP: TSF "
1146 "timestamp TLV, len = %d\n", tlv_len);
1147 *tlv_data = (struct mwifiex_ie_types_data *)
1150 case TLV_TYPE_CHANNELBANDLIST:
1151 dev_dbg(adapter->dev, "info: SCAN_RESP: channel"
1152 " band list TLV, len = %d\n", tlv_len);
1153 *tlv_data = (struct mwifiex_ie_types_data *)
1157 dev_err(adapter->dev,
1158 "SCAN_RESP: unhandled TLV = %d\n",
1160 /* Give up, this seems corrupted */
1169 tlv_buf_left -= (sizeof(tlv->header) + tlv_len);
1171 (struct mwifiex_ie_types_data *) (current_tlv->data +
1178 * This function interprets a BSS scan response returned from the firmware.
1180 * The various fixed fields and IEs are parsed and passed back for a BSS
1181 * probe response or beacon from scan command. Information is recorded as
1182 * needed in the scan table for that entry.
1184 * The following IE types are recognized and parsed -
1187 * - FH parameters set
1188 * - DS parameters set
1189 * - CF parameters set
1190 * - IBSS parameters set
1192 * - Extended supported rates
1193 * - Vendor specific (221)
1198 * - BSS Coexistence 20/40
1199 * - Extended capability
1200 * - Overlapping BSS scan parameters
1203 mwifiex_interpret_bss_desc_with_ie(struct mwifiex_adapter *adapter,
1204 struct mwifiex_bssdescriptor *bss_entry,
1205 u8 **beacon_info, u32 *bytes_left)
1209 struct ieee_types_fh_param_set *fh_param_set;
1210 struct ieee_types_ds_param_set *ds_param_set;
1211 struct ieee_types_cf_param_set *cf_param_set;
1212 struct ieee_types_ibss_param_set *ibss_param_set;
1213 __le16 beacon_interval;
1214 __le16 capabilities;
1222 u8 found_data_rate_ie;
1223 u32 bytes_left_for_current_beacon;
1224 struct ieee_types_vendor_specific *vendor_ie;
1225 const u8 wpa_oui[4] = { 0x00, 0x50, 0xf2, 0x01 };
1226 const u8 wmm_oui[4] = { 0x00, 0x50, 0xf2, 0x02 };
1228 found_data_rate_ie = false;
1232 if (*bytes_left >= sizeof(beacon_size)) {
1233 /* Extract & convert beacon size from the command buffer */
1234 memcpy(&beacon_size, *beacon_info, sizeof(beacon_size));
1235 *bytes_left -= sizeof(beacon_size);
1236 *beacon_info += sizeof(beacon_size);
1239 if (!beacon_size || beacon_size > *bytes_left) {
1240 *beacon_info += *bytes_left;
1245 /* Initialize the current working beacon pointer for this BSS
1247 current_ptr = *beacon_info;
1249 /* Advance the return beacon pointer past the current beacon */
1250 *beacon_info += beacon_size;
1251 *bytes_left -= beacon_size;
1253 bytes_left_for_current_beacon = beacon_size;
1255 memcpy(bss_entry->mac_address, current_ptr, ETH_ALEN);
1256 dev_dbg(adapter->dev, "info: InterpretIE: AP MAC Addr: %pM\n",
1257 bss_entry->mac_address);
1259 current_ptr += ETH_ALEN;
1260 bytes_left_for_current_beacon -= ETH_ALEN;
1262 if (bytes_left_for_current_beacon < 12) {
1263 dev_err(adapter->dev, "InterpretIE: not enough bytes left\n");
1268 * Next 4 fields are RSSI, time stamp, beacon interval,
1269 * and capability information
1272 /* RSSI is 1 byte long */
1273 bss_entry->rssi = (s32) (*current_ptr);
1274 dev_dbg(adapter->dev, "info: InterpretIE: RSSI=%02X\n", *current_ptr);
1276 bytes_left_for_current_beacon -= 1;
1279 * The RSSI is not part of the beacon/probe response. After we have
1280 * advanced current_ptr past the RSSI field, save the remaining
1281 * data for use at the application layer
1283 bss_entry->beacon_buf = current_ptr;
1284 bss_entry->beacon_buf_size = bytes_left_for_current_beacon;
1286 /* Time stamp is 8 bytes long */
1287 memcpy(bss_entry->time_stamp, current_ptr, 8);
1289 bytes_left_for_current_beacon -= 8;
1291 /* Beacon interval is 2 bytes long */
1292 memcpy(&beacon_interval, current_ptr, 2);
1293 bss_entry->beacon_period = le16_to_cpu(beacon_interval);
1295 bytes_left_for_current_beacon -= 2;
1297 /* Capability information is 2 bytes long */
1298 memcpy(&capabilities, current_ptr, 2);
1299 dev_dbg(adapter->dev, "info: InterpretIE: capabilities=0x%X\n",
1301 bss_entry->cap_info_bitmap = le16_to_cpu(capabilities);
1303 bytes_left_for_current_beacon -= 2;
1305 /* Rest of the current buffer are IE's */
1306 dev_dbg(adapter->dev, "info: InterpretIE: IELength for this AP = %d\n",
1307 bytes_left_for_current_beacon);
1309 if (bss_entry->cap_info_bitmap & WLAN_CAPABILITY_PRIVACY) {
1310 dev_dbg(adapter->dev, "info: InterpretIE: AP WEP enabled\n");
1311 bss_entry->privacy = MWIFIEX_802_11_PRIV_FILTER_8021X_WEP;
1313 bss_entry->privacy = MWIFIEX_802_11_PRIV_FILTER_ACCEPT_ALL;
1316 if (bss_entry->cap_info_bitmap & WLAN_CAPABILITY_IBSS)
1317 bss_entry->bss_mode = NL80211_IFTYPE_ADHOC;
1319 bss_entry->bss_mode = NL80211_IFTYPE_STATION;
1322 /* Process variable IE */
1323 while (bytes_left_for_current_beacon >= 2) {
1324 element_id = *current_ptr;
1325 element_len = *(current_ptr + 1);
1326 total_ie_len = element_len + sizeof(struct ieee_types_header);
1328 if (bytes_left_for_current_beacon < total_ie_len) {
1329 dev_err(adapter->dev, "err: InterpretIE: in processing"
1330 " IE, bytes left < IE length\n");
1331 bytes_left_for_current_beacon = 0;
1335 switch (element_id) {
1337 bss_entry->ssid.ssid_len = element_len;
1338 memcpy(bss_entry->ssid.ssid, (current_ptr + 2),
1340 dev_dbg(adapter->dev, "info: InterpretIE: ssid: %-32s\n",
1341 bss_entry->ssid.ssid);
1344 case WLAN_EID_SUPP_RATES:
1345 memcpy(bss_entry->data_rates, current_ptr + 2,
1347 memcpy(bss_entry->supported_rates, current_ptr + 2,
1349 rate_size = element_len;
1350 found_data_rate_ie = true;
1353 case WLAN_EID_FH_PARAMS:
1355 (struct ieee_types_fh_param_set *) current_ptr;
1356 memcpy(&bss_entry->phy_param_set.fh_param_set,
1358 sizeof(struct ieee_types_fh_param_set));
1361 case WLAN_EID_DS_PARAMS:
1363 (struct ieee_types_ds_param_set *) current_ptr;
1365 bss_entry->channel = ds_param_set->current_chan;
1367 memcpy(&bss_entry->phy_param_set.ds_param_set,
1369 sizeof(struct ieee_types_ds_param_set));
1372 case WLAN_EID_CF_PARAMS:
1374 (struct ieee_types_cf_param_set *) current_ptr;
1375 memcpy(&bss_entry->ss_param_set.cf_param_set,
1377 sizeof(struct ieee_types_cf_param_set));
1380 case WLAN_EID_IBSS_PARAMS:
1382 (struct ieee_types_ibss_param_set *)
1384 memcpy(&bss_entry->ss_param_set.ibss_param_set,
1386 sizeof(struct ieee_types_ibss_param_set));
1389 case WLAN_EID_ERP_INFO:
1390 bss_entry->erp_flags = *(current_ptr + 2);
1393 case WLAN_EID_EXT_SUPP_RATES:
1395 * Only process extended supported rate
1396 * if data rate is already found.
1397 * Data rate IE should come before
1398 * extended supported rate IE
1400 if (found_data_rate_ie) {
1401 if ((element_len + rate_size) >
1402 MWIFIEX_SUPPORTED_RATES)
1404 (MWIFIEX_SUPPORTED_RATES -
1407 bytes_to_copy = element_len;
1409 rate = (u8 *) bss_entry->data_rates;
1411 memcpy(rate, current_ptr + 2, bytes_to_copy);
1413 rate = (u8 *) bss_entry->supported_rates;
1415 memcpy(rate, current_ptr + 2, bytes_to_copy);
1419 case WLAN_EID_VENDOR_SPECIFIC:
1420 vendor_ie = (struct ieee_types_vendor_specific *)
1424 (vendor_ie->vend_hdr.oui, wpa_oui,
1426 bss_entry->bcn_wpa_ie =
1427 (struct ieee_types_vendor_specific *)
1429 bss_entry->wpa_offset = (u16) (current_ptr -
1430 bss_entry->beacon_buf);
1431 } else if (!memcmp(vendor_ie->vend_hdr.oui, wmm_oui,
1434 sizeof(struct ieee_types_wmm_parameter)
1436 sizeof(struct ieee_types_wmm_info))
1438 * Only accept and copy the WMM IE if
1439 * it matches the size expected for the
1440 * WMM Info IE or the WMM Parameter IE.
1442 memcpy((u8 *) &bss_entry->wmm_ie,
1443 current_ptr, total_ie_len);
1447 bss_entry->bcn_rsn_ie =
1448 (struct ieee_types_generic *) current_ptr;
1449 bss_entry->rsn_offset = (u16) (current_ptr -
1450 bss_entry->beacon_buf);
1452 case WLAN_EID_BSS_AC_ACCESS_DELAY:
1453 bss_entry->bcn_wapi_ie =
1454 (struct ieee_types_generic *) current_ptr;
1455 bss_entry->wapi_offset = (u16) (current_ptr -
1456 bss_entry->beacon_buf);
1458 case WLAN_EID_HT_CAPABILITY:
1459 bss_entry->bcn_ht_cap = (struct ieee80211_ht_cap *)
1461 sizeof(struct ieee_types_header));
1462 bss_entry->ht_cap_offset = (u16) (current_ptr +
1463 sizeof(struct ieee_types_header) -
1464 bss_entry->beacon_buf);
1466 case WLAN_EID_HT_INFORMATION:
1467 bss_entry->bcn_ht_info = (struct ieee80211_ht_info *)
1469 sizeof(struct ieee_types_header));
1470 bss_entry->ht_info_offset = (u16) (current_ptr +
1471 sizeof(struct ieee_types_header) -
1472 bss_entry->beacon_buf);
1474 case WLAN_EID_BSS_COEX_2040:
1475 bss_entry->bcn_bss_co_2040 = (u8 *) (current_ptr +
1476 sizeof(struct ieee_types_header));
1477 bss_entry->bss_co_2040_offset = (u16) (current_ptr +
1478 sizeof(struct ieee_types_header) -
1479 bss_entry->beacon_buf);
1481 case WLAN_EID_EXT_CAPABILITY:
1482 bss_entry->bcn_ext_cap = (u8 *) (current_ptr +
1483 sizeof(struct ieee_types_header));
1484 bss_entry->ext_cap_offset = (u16) (current_ptr +
1485 sizeof(struct ieee_types_header) -
1486 bss_entry->beacon_buf);
1488 case WLAN_EID_OVERLAP_BSS_SCAN_PARAM:
1489 bss_entry->bcn_obss_scan =
1490 (struct ieee_types_obss_scan_param *)
1492 bss_entry->overlap_bss_offset = (u16) (current_ptr -
1493 bss_entry->beacon_buf);
1499 current_ptr += element_len + 2;
1501 /* Need to account for IE ID and IE Len */
1502 bytes_left_for_current_beacon -= (element_len + 2);
1504 } /* while (bytes_left_for_current_beacon > 2) */
1509 * This function adjusts the pointers used in beacon buffers to reflect
1512 * The memory allocated for beacon buffers is of fixed sizes where all the
1513 * saved beacons must be stored. New beacons are added in the free portion
1514 * of this memory, space permitting; while duplicate beacon buffers are
1515 * placed at the same start location. However, since duplicate beacon
1516 * buffers may not match the size of the old one, all the following buffers
1517 * in the memory must be shifted to either make space, or to fill up freed
1520 * This function is used to update the beacon buffer pointers that are past
1521 * an existing beacon buffer that is updated with a new one of different
1522 * size. The pointers are shifted by a fixed amount, either forward or
1525 * the following pointers in every affected beacon buffers are changed, if
1530 * - HT capability IE pointer
1531 * - HT information IE pointer
1532 * - BSS coexistence 20/40 IE pointer
1533 * - Extended capability IE pointer
1534 * - Overlapping BSS scan parameter IE pointer
1537 mwifiex_adjust_beacon_buffer_ptrs(struct mwifiex_private *priv, u8 advance,
1538 u8 *bcn_store, u32 rem_bcn_size,
1541 struct mwifiex_adapter *adapter = priv->adapter;
1543 for (adj_idx = 0; adj_idx < num_of_ent; adj_idx++) {
1544 if (adapter->scan_table[adj_idx].beacon_buf > bcn_store) {
1547 adapter->scan_table[adj_idx].beacon_buf +=
1550 adapter->scan_table[adj_idx].beacon_buf -=
1553 if (adapter->scan_table[adj_idx].bcn_wpa_ie)
1554 adapter->scan_table[adj_idx].bcn_wpa_ie =
1555 (struct ieee_types_vendor_specific *)
1556 (adapter->scan_table[adj_idx].beacon_buf +
1557 adapter->scan_table[adj_idx].wpa_offset);
1558 if (adapter->scan_table[adj_idx].bcn_rsn_ie)
1559 adapter->scan_table[adj_idx].bcn_rsn_ie =
1560 (struct ieee_types_generic *)
1561 (adapter->scan_table[adj_idx].beacon_buf +
1562 adapter->scan_table[adj_idx].rsn_offset);
1563 if (adapter->scan_table[adj_idx].bcn_wapi_ie)
1564 adapter->scan_table[adj_idx].bcn_wapi_ie =
1565 (struct ieee_types_generic *)
1566 (adapter->scan_table[adj_idx].beacon_buf +
1567 adapter->scan_table[adj_idx].wapi_offset);
1568 if (adapter->scan_table[adj_idx].bcn_ht_cap)
1569 adapter->scan_table[adj_idx].bcn_ht_cap =
1570 (struct ieee80211_ht_cap *)
1571 (adapter->scan_table[adj_idx].beacon_buf +
1572 adapter->scan_table[adj_idx].ht_cap_offset);
1574 if (adapter->scan_table[adj_idx].bcn_ht_info)
1575 adapter->scan_table[adj_idx].bcn_ht_info =
1576 (struct ieee80211_ht_info *)
1577 (adapter->scan_table[adj_idx].beacon_buf +
1578 adapter->scan_table[adj_idx].ht_info_offset);
1579 if (adapter->scan_table[adj_idx].bcn_bss_co_2040)
1580 adapter->scan_table[adj_idx].bcn_bss_co_2040 =
1582 (adapter->scan_table[adj_idx].beacon_buf +
1583 adapter->scan_table[adj_idx].bss_co_2040_offset);
1584 if (adapter->scan_table[adj_idx].bcn_ext_cap)
1585 adapter->scan_table[adj_idx].bcn_ext_cap =
1587 (adapter->scan_table[adj_idx].beacon_buf +
1588 adapter->scan_table[adj_idx].ext_cap_offset);
1589 if (adapter->scan_table[adj_idx].bcn_obss_scan)
1590 adapter->scan_table[adj_idx].bcn_obss_scan =
1591 (struct ieee_types_obss_scan_param *)
1592 (adapter->scan_table[adj_idx].beacon_buf +
1593 adapter->scan_table[adj_idx].overlap_bss_offset);
1599 * This function updates the pointers used in beacon buffer for given bss
1600 * descriptor to reflect shifts
1602 * Following pointers are updated
1606 * - HT capability IE pointer
1607 * - HT information IE pointer
1608 * - BSS coexistence 20/40 IE pointer
1609 * - Extended capability IE pointer
1610 * - Overlapping BSS scan parameter IE pointer
1613 mwifiex_update_beacon_buffer_ptrs(struct mwifiex_bssdescriptor *beacon)
1615 if (beacon->bcn_wpa_ie)
1616 beacon->bcn_wpa_ie = (struct ieee_types_vendor_specific *)
1617 (beacon->beacon_buf + beacon->wpa_offset);
1618 if (beacon->bcn_rsn_ie)
1619 beacon->bcn_rsn_ie = (struct ieee_types_generic *)
1620 (beacon->beacon_buf + beacon->rsn_offset);
1621 if (beacon->bcn_wapi_ie)
1622 beacon->bcn_wapi_ie = (struct ieee_types_generic *)
1623 (beacon->beacon_buf + beacon->wapi_offset);
1624 if (beacon->bcn_ht_cap)
1625 beacon->bcn_ht_cap = (struct ieee80211_ht_cap *)
1626 (beacon->beacon_buf + beacon->ht_cap_offset);
1627 if (beacon->bcn_ht_info)
1628 beacon->bcn_ht_info = (struct ieee80211_ht_info *)
1629 (beacon->beacon_buf + beacon->ht_info_offset);
1630 if (beacon->bcn_bss_co_2040)
1631 beacon->bcn_bss_co_2040 = (u8 *) (beacon->beacon_buf +
1632 beacon->bss_co_2040_offset);
1633 if (beacon->bcn_ext_cap)
1634 beacon->bcn_ext_cap = (u8 *) (beacon->beacon_buf +
1635 beacon->ext_cap_offset);
1636 if (beacon->bcn_obss_scan)
1637 beacon->bcn_obss_scan = (struct ieee_types_obss_scan_param *)
1638 (beacon->beacon_buf + beacon->overlap_bss_offset);
1642 * This function stores a beacon or probe response for a BSS returned
1645 * This stores a new scan response or an update for a previous scan response.
1646 * New entries need to verify that they do not exceed the total amount of
1647 * memory allocated for the table.
1649 * Replacement entries need to take into consideration the amount of space
1650 * currently allocated for the beacon/probe response and adjust the entry
1653 * A small amount of extra pad (SCAN_BEACON_ENTRY_PAD) is generally reserved
1654 * for an entry in case it is a beacon since a probe response for the
1655 * network will by larger per the standard. This helps to reduce the
1656 * amount of memory copying to fit a new probe response into an entry
1657 * already occupied by a network's previously stored beacon.
1660 mwifiex_ret_802_11_scan_store_beacon(struct mwifiex_private *priv,
1661 u32 beacon_idx, u32 num_of_ent,
1662 struct mwifiex_bssdescriptor *new_beacon)
1664 struct mwifiex_adapter *adapter = priv->adapter;
1670 if (adapter->scan_table[beacon_idx].beacon_buf) {
1672 new_bcn_size = new_beacon->beacon_buf_size;
1673 old_bcn_size = adapter->scan_table[beacon_idx].beacon_buf_size;
1674 bcn_space = adapter->scan_table[beacon_idx].beacon_buf_size_max;
1675 bcn_store = adapter->scan_table[beacon_idx].beacon_buf;
1677 /* Set the max to be the same as current entry unless changed
1679 new_beacon->beacon_buf_size_max = bcn_space;
1680 if (new_bcn_size == old_bcn_size) {
1682 * Beacon is the same size as the previous entry.
1683 * Replace the previous contents with the scan result
1685 memcpy(bcn_store, new_beacon->beacon_buf,
1686 new_beacon->beacon_buf_size);
1688 } else if (new_bcn_size <= bcn_space) {
1690 * New beacon size will fit in the amount of space
1691 * we have previously allocated for it
1694 /* Copy the new beacon buffer entry over the old one */
1695 memcpy(bcn_store, new_beacon->beacon_buf, new_bcn_size);
1698 * If the old beacon size was less than the maximum
1699 * we had alloted for the entry, and the new entry
1700 * is even smaller, reset the max size to the old
1701 * beacon entry and compress the storage space
1702 * (leaving a new pad space of (old_bcn_size -
1705 if (old_bcn_size < bcn_space
1706 && new_bcn_size <= old_bcn_size) {
1708 * Old Beacon size is smaller than the alloted
1709 * storage size. Shrink the alloted storage
1712 dev_dbg(adapter->dev, "info: AppControl:"
1713 " smaller duplicate beacon "
1714 "(%d), old = %d, new = %d, space = %d,"
1716 beacon_idx, old_bcn_size, new_bcn_size,
1718 (int)(sizeof(adapter->bcn_buf) -
1719 (adapter->bcn_buf_end -
1720 adapter->bcn_buf)));
1723 * memmove (since the memory overlaps) the
1724 * data after the beacon we just stored to the
1725 * end of the current beacon. This cleans up
1726 * any unused space the old larger beacon was
1727 * using in the buffer
1729 memmove(bcn_store + old_bcn_size,
1730 bcn_store + bcn_space,
1731 adapter->bcn_buf_end - (bcn_store +
1735 * Decrement the end pointer by the difference
1736 * between the old larger size and the new
1737 * smaller size since we are using less space
1738 * due to the new beacon being smaller
1740 adapter->bcn_buf_end -=
1741 (bcn_space - old_bcn_size);
1743 /* Set the maximum storage size to the old
1745 new_beacon->beacon_buf_size_max = old_bcn_size;
1747 /* Adjust beacon buffer pointers that are past
1749 mwifiex_adjust_beacon_buffer_ptrs(priv, 0,
1750 bcn_store, (bcn_space - old_bcn_size),
1753 } else if (adapter->bcn_buf_end + (new_bcn_size - bcn_space)
1754 < (adapter->bcn_buf + sizeof(adapter->bcn_buf))) {
1756 * Beacon is larger than space previously allocated
1757 * (bcn_space) and there is enough space left in the
1758 * beaconBuffer to store the additional data
1760 dev_dbg(adapter->dev, "info: AppControl:"
1761 " larger duplicate beacon (%d), "
1762 "old = %d, new = %d, space = %d, left = %d\n",
1763 beacon_idx, old_bcn_size, new_bcn_size,
1765 (int)(sizeof(adapter->bcn_buf) -
1766 (adapter->bcn_buf_end -
1767 adapter->bcn_buf)));
1770 * memmove (since the memory overlaps) the data
1771 * after the beacon we just stored to the end of
1772 * the current beacon. This moves the data for
1773 * the beacons after this further in memory to
1774 * make space for the new larger beacon we are
1777 memmove(bcn_store + new_bcn_size,
1778 bcn_store + bcn_space,
1779 adapter->bcn_buf_end - (bcn_store + bcn_space));
1781 /* Copy the new beacon buffer entry over the old one */
1782 memcpy(bcn_store, new_beacon->beacon_buf, new_bcn_size);
1784 /* Move the beacon end pointer by the amount of new
1785 beacon data we are adding */
1786 adapter->bcn_buf_end += (new_bcn_size - bcn_space);
1789 * This entry is bigger than the alloted max space
1790 * previously reserved. Increase the max space to
1791 * be equal to the new beacon size
1793 new_beacon->beacon_buf_size_max = new_bcn_size;
1795 /* Adjust beacon buffer pointers that are past the
1797 mwifiex_adjust_beacon_buffer_ptrs(priv, 1, bcn_store,
1798 (new_bcn_size - bcn_space),
1802 * Beacon is larger than the previously allocated space,
1803 * but there is not enough free space to store the
1806 dev_err(adapter->dev, "AppControl: larger duplicate "
1807 " beacon (%d), old = %d new = %d, space = %d,"
1808 " left = %d\n", beacon_idx, old_bcn_size,
1809 new_bcn_size, bcn_space,
1810 (int)(sizeof(adapter->bcn_buf) -
1811 (adapter->bcn_buf_end - adapter->bcn_buf)));
1813 /* Storage failure, keep old beacon intact */
1814 new_beacon->beacon_buf_size = old_bcn_size;
1815 if (new_beacon->bcn_wpa_ie)
1816 new_beacon->wpa_offset =
1817 adapter->scan_table[beacon_idx].
1819 if (new_beacon->bcn_rsn_ie)
1820 new_beacon->rsn_offset =
1821 adapter->scan_table[beacon_idx].
1823 if (new_beacon->bcn_wapi_ie)
1824 new_beacon->wapi_offset =
1825 adapter->scan_table[beacon_idx].
1827 if (new_beacon->bcn_ht_cap)
1828 new_beacon->ht_cap_offset =
1829 adapter->scan_table[beacon_idx].
1831 if (new_beacon->bcn_ht_info)
1832 new_beacon->ht_info_offset =
1833 adapter->scan_table[beacon_idx].
1835 if (new_beacon->bcn_bss_co_2040)
1836 new_beacon->bss_co_2040_offset =
1837 adapter->scan_table[beacon_idx].
1839 if (new_beacon->bcn_ext_cap)
1840 new_beacon->ext_cap_offset =
1841 adapter->scan_table[beacon_idx].
1843 if (new_beacon->bcn_obss_scan)
1844 new_beacon->overlap_bss_offset =
1845 adapter->scan_table[beacon_idx].
1848 /* Point the new entry to its permanent storage space */
1849 new_beacon->beacon_buf = bcn_store;
1850 mwifiex_update_beacon_buffer_ptrs(new_beacon);
1853 * No existing beacon data exists for this entry, check to see
1854 * if we can fit it in the remaining space
1856 if (adapter->bcn_buf_end + new_beacon->beacon_buf_size +
1857 SCAN_BEACON_ENTRY_PAD < (adapter->bcn_buf +
1858 sizeof(adapter->bcn_buf))) {
1861 * Copy the beacon buffer data from the local entry to
1862 * the adapter dev struct buffer space used to store
1863 * the raw beacon data for each entry in the scan table
1865 memcpy(adapter->bcn_buf_end, new_beacon->beacon_buf,
1866 new_beacon->beacon_buf_size);
1868 /* Update the beacon ptr to point to the table save
1870 new_beacon->beacon_buf = adapter->bcn_buf_end;
1871 new_beacon->beacon_buf_size_max =
1872 (new_beacon->beacon_buf_size +
1873 SCAN_BEACON_ENTRY_PAD);
1875 mwifiex_update_beacon_buffer_ptrs(new_beacon);
1877 /* Increment the end pointer by the size reserved */
1878 adapter->bcn_buf_end += new_beacon->beacon_buf_size_max;
1880 dev_dbg(adapter->dev, "info: AppControl: beacon[%02d]"
1881 " sz=%03d, used = %04d, left = %04d\n",
1883 new_beacon->beacon_buf_size,
1884 (int)(adapter->bcn_buf_end - adapter->bcn_buf),
1885 (int)(sizeof(adapter->bcn_buf) -
1886 (adapter->bcn_buf_end -
1887 adapter->bcn_buf)));
1889 /* No space for new beacon */
1890 dev_dbg(adapter->dev, "info: AppControl: no space for"
1891 " beacon (%d): %pM sz=%03d, left=%03d\n",
1892 beacon_idx, new_beacon->mac_address,
1893 new_beacon->beacon_buf_size,
1894 (int)(sizeof(adapter->bcn_buf) -
1895 (adapter->bcn_buf_end -
1896 adapter->bcn_buf)));
1898 /* Storage failure; clear storage records for this
1900 new_beacon->beacon_buf = NULL;
1901 new_beacon->beacon_buf_size = 0;
1902 new_beacon->beacon_buf_size_max = 0;
1903 new_beacon->bcn_wpa_ie = NULL;
1904 new_beacon->wpa_offset = 0;
1905 new_beacon->bcn_rsn_ie = NULL;
1906 new_beacon->rsn_offset = 0;
1907 new_beacon->bcn_wapi_ie = NULL;
1908 new_beacon->wapi_offset = 0;
1909 new_beacon->bcn_ht_cap = NULL;
1910 new_beacon->ht_cap_offset = 0;
1911 new_beacon->bcn_ht_info = NULL;
1912 new_beacon->ht_info_offset = 0;
1913 new_beacon->bcn_bss_co_2040 = NULL;
1914 new_beacon->bss_co_2040_offset = 0;
1915 new_beacon->bcn_ext_cap = NULL;
1916 new_beacon->ext_cap_offset = 0;
1917 new_beacon->bcn_obss_scan = NULL;
1918 new_beacon->overlap_bss_offset = 0;
1924 * This function restores a beacon buffer of the current BSS descriptor.
1926 static void mwifiex_restore_curr_bcn(struct mwifiex_private *priv)
1928 struct mwifiex_adapter *adapter = priv->adapter;
1929 struct mwifiex_bssdescriptor *curr_bss =
1930 &priv->curr_bss_params.bss_descriptor;
1931 unsigned long flags;
1933 if (priv->curr_bcn_buf &&
1934 ((adapter->bcn_buf_end + priv->curr_bcn_size) <
1935 (adapter->bcn_buf + sizeof(adapter->bcn_buf)))) {
1936 spin_lock_irqsave(&priv->curr_bcn_buf_lock, flags);
1938 /* restore the current beacon buffer */
1939 memcpy(adapter->bcn_buf_end, priv->curr_bcn_buf,
1940 priv->curr_bcn_size);
1941 curr_bss->beacon_buf = adapter->bcn_buf_end;
1942 curr_bss->beacon_buf_size = priv->curr_bcn_size;
1943 adapter->bcn_buf_end += priv->curr_bcn_size;
1945 /* adjust the pointers in the current BSS descriptor */
1946 if (curr_bss->bcn_wpa_ie)
1947 curr_bss->bcn_wpa_ie =
1948 (struct ieee_types_vendor_specific *)
1949 (curr_bss->beacon_buf +
1950 curr_bss->wpa_offset);
1952 if (curr_bss->bcn_rsn_ie)
1953 curr_bss->bcn_rsn_ie = (struct ieee_types_generic *)
1954 (curr_bss->beacon_buf +
1955 curr_bss->rsn_offset);
1957 if (curr_bss->bcn_ht_cap)
1958 curr_bss->bcn_ht_cap = (struct ieee80211_ht_cap *)
1959 (curr_bss->beacon_buf +
1960 curr_bss->ht_cap_offset);
1962 if (curr_bss->bcn_ht_info)
1963 curr_bss->bcn_ht_info = (struct ieee80211_ht_info *)
1964 (curr_bss->beacon_buf +
1965 curr_bss->ht_info_offset);
1967 if (curr_bss->bcn_bss_co_2040)
1968 curr_bss->bcn_bss_co_2040 =
1969 (u8 *) (curr_bss->beacon_buf +
1970 curr_bss->bss_co_2040_offset);
1972 if (curr_bss->bcn_ext_cap)
1973 curr_bss->bcn_ext_cap = (u8 *) (curr_bss->beacon_buf +
1974 curr_bss->ext_cap_offset);
1976 if (curr_bss->bcn_obss_scan)
1977 curr_bss->bcn_obss_scan =
1978 (struct ieee_types_obss_scan_param *)
1979 (curr_bss->beacon_buf +
1980 curr_bss->overlap_bss_offset);
1982 spin_unlock_irqrestore(&priv->curr_bcn_buf_lock, flags);
1984 dev_dbg(adapter->dev, "info: current beacon restored %d\n",
1985 priv->curr_bcn_size);
1987 dev_warn(adapter->dev,
1988 "curr_bcn_buf not saved or bcn_buf has no space\n");
1993 * This function post processes the scan table after a new scan command has
1996 * It inspects each entry of the scan table and tries to find an entry that
1997 * matches with our current associated/joined network from the scan. If
1998 * one is found, the stored copy of the BSS descriptor of our current network
2001 * It also debug dumps the current scan table contents after processing is over.
2004 mwifiex_process_scan_results(struct mwifiex_private *priv)
2006 struct mwifiex_adapter *adapter = priv->adapter;
2009 unsigned long flags;
2011 if (priv->media_connected) {
2013 j = mwifiex_find_ssid_in_list(priv, &priv->curr_bss_params.
2014 bss_descriptor.ssid,
2015 priv->curr_bss_params.
2016 bss_descriptor.mac_address,
2020 spin_lock_irqsave(&priv->curr_bcn_buf_lock, flags);
2021 priv->curr_bss_params.bss_descriptor.bcn_wpa_ie = NULL;
2022 priv->curr_bss_params.bss_descriptor.wpa_offset = 0;
2023 priv->curr_bss_params.bss_descriptor.bcn_rsn_ie = NULL;
2024 priv->curr_bss_params.bss_descriptor.rsn_offset = 0;
2025 priv->curr_bss_params.bss_descriptor.bcn_wapi_ie = NULL;
2026 priv->curr_bss_params.bss_descriptor.wapi_offset = 0;
2027 priv->curr_bss_params.bss_descriptor.bcn_ht_cap = NULL;
2028 priv->curr_bss_params.bss_descriptor.ht_cap_offset =
2030 priv->curr_bss_params.bss_descriptor.bcn_ht_info = NULL;
2031 priv->curr_bss_params.bss_descriptor.ht_info_offset =
2033 priv->curr_bss_params.bss_descriptor.bcn_bss_co_2040 =
2035 priv->curr_bss_params.bss_descriptor.
2036 bss_co_2040_offset = 0;
2037 priv->curr_bss_params.bss_descriptor.bcn_ext_cap = NULL;
2038 priv->curr_bss_params.bss_descriptor.ext_cap_offset = 0;
2039 priv->curr_bss_params.bss_descriptor.
2040 bcn_obss_scan = NULL;
2041 priv->curr_bss_params.bss_descriptor.
2042 overlap_bss_offset = 0;
2043 priv->curr_bss_params.bss_descriptor.beacon_buf = NULL;
2044 priv->curr_bss_params.bss_descriptor.beacon_buf_size =
2046 priv->curr_bss_params.bss_descriptor.
2047 beacon_buf_size_max = 0;
2049 dev_dbg(adapter->dev, "info: Found current ssid/bssid"
2050 " in list @ index #%d\n", j);
2051 /* Make a copy of current BSSID descriptor */
2052 memcpy(&priv->curr_bss_params.bss_descriptor,
2053 &adapter->scan_table[j],
2054 sizeof(priv->curr_bss_params.bss_descriptor));
2056 mwifiex_save_curr_bcn(priv);
2057 spin_unlock_irqrestore(&priv->curr_bcn_buf_lock, flags);
2060 mwifiex_restore_curr_bcn(priv);
2064 for (i = 0; i < adapter->num_in_scan_table; i++)
2065 dev_dbg(adapter->dev, "info: scan:(%02d) %pM "
2066 "RSSI[%03d], SSID[%s]\n",
2067 i, adapter->scan_table[i].mac_address,
2068 (s32) adapter->scan_table[i].rssi,
2069 adapter->scan_table[i].ssid.ssid);
2073 * This function converts radio type scan parameter to a band configuration
2074 * to be used in join command.
2077 mwifiex_radio_type_to_band(u8 radio_type)
2081 switch (radio_type) {
2082 case HostCmd_SCAN_RADIO_TYPE_A:
2085 case HostCmd_SCAN_RADIO_TYPE_BG:
2095 * This function deletes a specific indexed entry from the scan table.
2097 * This also compacts the remaining entries and adjusts any buffering
2098 * of beacon/probe response data if needed.
2101 mwifiex_scan_delete_table_entry(struct mwifiex_private *priv, s32 table_idx)
2103 struct mwifiex_adapter *adapter = priv->adapter;
2109 * Shift the saved beacon buffer data for the scan table back over the
2110 * entry being removed. Update the end of buffer pointer. Save the
2111 * deleted buffer allocation size for pointer adjustments for entries
2112 * compacted after the deleted index.
2114 beacon_buf_adj = adapter->scan_table[table_idx].beacon_buf_size_max;
2116 dev_dbg(adapter->dev, "info: Scan: Delete Entry %d, beacon buffer "
2117 "removal = %d bytes\n", table_idx, beacon_buf_adj);
2119 /* Check if the table entry had storage allocated for its beacon */
2120 if (beacon_buf_adj) {
2121 beacon_buf = adapter->scan_table[table_idx].beacon_buf;
2124 * Remove the entry's buffer space, decrement the table end
2125 * pointer by the amount we are removing
2127 adapter->bcn_buf_end -= beacon_buf_adj;
2129 dev_dbg(adapter->dev, "info: scan: delete entry %d,"
2130 " compact data: %p <- %p (sz = %d)\n",
2131 table_idx, beacon_buf,
2132 beacon_buf + beacon_buf_adj,
2133 (int)(adapter->bcn_buf_end - beacon_buf));
2136 * Compact data storage. Copy all data after the deleted
2137 * entry's end address (beacon_buf + beacon_buf_adj) back
2138 * to the original start address (beacon_buf).
2140 * Scan table entries affected by the move will have their
2141 * entry pointer adjusted below.
2143 * Use memmove since the dest/src memory regions overlap.
2145 memmove(beacon_buf, beacon_buf + beacon_buf_adj,
2146 adapter->bcn_buf_end - beacon_buf);
2149 dev_dbg(adapter->dev,
2150 "info: Scan: Delete Entry %d, num_in_scan_table = %d\n",
2151 table_idx, adapter->num_in_scan_table);
2153 /* Shift all of the entries after the table_idx back by one, compacting
2154 the table and removing the requested entry */
2155 for (del_idx = table_idx; (del_idx + 1) < adapter->num_in_scan_table;
2157 /* Copy the next entry over this one */
2158 memcpy(adapter->scan_table + del_idx,
2159 adapter->scan_table + del_idx + 1,
2160 sizeof(struct mwifiex_bssdescriptor));
2163 * Adjust this entry's pointer to its beacon buffer based on
2164 * the removed/compacted entry from the deleted index. Don't
2165 * decrement if the buffer pointer is NULL (no data stored for
2168 if (adapter->scan_table[del_idx].beacon_buf) {
2169 adapter->scan_table[del_idx].beacon_buf -=
2171 if (adapter->scan_table[del_idx].bcn_wpa_ie)
2172 adapter->scan_table[del_idx].bcn_wpa_ie =
2173 (struct ieee_types_vendor_specific *)
2174 (adapter->scan_table[del_idx].
2176 adapter->scan_table[del_idx].
2178 if (adapter->scan_table[del_idx].bcn_rsn_ie)
2179 adapter->scan_table[del_idx].bcn_rsn_ie =
2180 (struct ieee_types_generic *)
2181 (adapter->scan_table[del_idx].
2183 adapter->scan_table[del_idx].
2185 if (adapter->scan_table[del_idx].bcn_wapi_ie)
2186 adapter->scan_table[del_idx].bcn_wapi_ie =
2187 (struct ieee_types_generic *)
2188 (adapter->scan_table[del_idx].beacon_buf
2189 + adapter->scan_table[del_idx].
2191 if (adapter->scan_table[del_idx].bcn_ht_cap)
2192 adapter->scan_table[del_idx].bcn_ht_cap =
2193 (struct ieee80211_ht_cap *)
2194 (adapter->scan_table[del_idx].beacon_buf
2195 + adapter->scan_table[del_idx].
2198 if (adapter->scan_table[del_idx].bcn_ht_info)
2199 adapter->scan_table[del_idx].bcn_ht_info =
2200 (struct ieee80211_ht_info *)
2201 (adapter->scan_table[del_idx].beacon_buf
2202 + adapter->scan_table[del_idx].
2204 if (adapter->scan_table[del_idx].bcn_bss_co_2040)
2205 adapter->scan_table[del_idx].bcn_bss_co_2040 =
2207 (adapter->scan_table[del_idx].beacon_buf
2208 + adapter->scan_table[del_idx].
2209 bss_co_2040_offset);
2210 if (adapter->scan_table[del_idx].bcn_ext_cap)
2211 adapter->scan_table[del_idx].bcn_ext_cap =
2213 (adapter->scan_table[del_idx].beacon_buf
2214 + adapter->scan_table[del_idx].
2216 if (adapter->scan_table[del_idx].bcn_obss_scan)
2217 adapter->scan_table[del_idx].
2219 (struct ieee_types_obss_scan_param *)
2220 (adapter->scan_table[del_idx].beacon_buf
2221 + adapter->scan_table[del_idx].
2222 overlap_bss_offset);
2226 /* The last entry is invalid now that it has been deleted or moved
2228 memset(adapter->scan_table + adapter->num_in_scan_table - 1,
2229 0x00, sizeof(struct mwifiex_bssdescriptor));
2231 adapter->num_in_scan_table--;
2235 * This function deletes all occurrences of a given SSID from the scan table.
2237 * This iterates through the scan table and deletes all entries that match
2238 * the given SSID. It also compacts the remaining scan table entries.
2241 mwifiex_scan_delete_ssid_table_entry(struct mwifiex_private *priv,
2242 struct mwifiex_802_11_ssid *del_ssid)
2247 dev_dbg(priv->adapter->dev, "info: scan: delete ssid entry: %-32s\n",
2250 /* If the requested SSID is found in the table, delete it. Then keep
2251 searching the table for multiple entires for the SSID until no
2253 while ((table_idx = mwifiex_find_ssid_in_list(priv, del_ssid, NULL,
2254 NL80211_IFTYPE_UNSPECIFIED)) >= 0) {
2255 dev_dbg(priv->adapter->dev,
2256 "info: Scan: Delete SSID Entry: Found Idx = %d\n",
2259 mwifiex_scan_delete_table_entry(priv, table_idx);
2266 * This is an internal function used to start a scan based on an input
2269 * This uses the input user scan configuration information when provided in
2270 * order to send the appropriate scan commands to firmware to populate or
2271 * update the internal driver scan table.
2273 int mwifiex_scan_networks(struct mwifiex_private *priv,
2274 void *wait_buf, u16 action,
2275 const struct mwifiex_user_scan_cfg *user_scan_in,
2276 struct mwifiex_scan_resp *scan_resp)
2279 struct mwifiex_adapter *adapter = priv->adapter;
2280 struct cmd_ctrl_node *cmd_node = NULL;
2281 union mwifiex_scan_cmd_config_tlv *scan_cfg_out = NULL;
2282 struct mwifiex_ie_types_chan_list_param_set *chan_list_out;
2284 struct mwifiex_chan_scan_param_set *scan_chan_list;
2285 u8 keep_previous_scan;
2287 u8 scan_current_chan_only;
2288 u8 max_chan_per_scan;
2289 unsigned long flags;
2291 if (action == HostCmd_ACT_GEN_GET) {
2293 scan_resp->scan_table = (u8 *) adapter->scan_table;
2294 scan_resp->num_in_scan_table =
2295 adapter->num_in_scan_table;
2302 if (adapter->scan_processing && action == HostCmd_ACT_GEN_SET) {
2303 dev_dbg(adapter->dev, "cmd: Scan already in process...\n");
2307 spin_lock_irqsave(&adapter->mwifiex_cmd_lock, flags);
2308 adapter->scan_processing = true;
2309 spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, flags);
2311 if (priv->scan_block && action == HostCmd_ACT_GEN_SET) {
2312 dev_dbg(adapter->dev,
2313 "cmd: Scan is blocked during association...\n");
2317 scan_cfg_out = kzalloc(sizeof(union mwifiex_scan_cmd_config_tlv),
2319 if (!scan_cfg_out) {
2320 dev_err(adapter->dev, "failed to alloc scan_cfg_out\n");
2324 buf_size = sizeof(struct mwifiex_chan_scan_param_set) *
2325 MWIFIEX_USER_SCAN_CHAN_MAX;
2326 scan_chan_list = kzalloc(buf_size, GFP_KERNEL);
2327 if (!scan_chan_list) {
2328 dev_err(adapter->dev, "failed to alloc scan_chan_list\n");
2329 kfree(scan_cfg_out);
2333 keep_previous_scan = false;
2335 mwifiex_scan_setup_scan_config(priv, user_scan_in,
2336 &scan_cfg_out->config, &chan_list_out,
2337 scan_chan_list, &max_chan_per_scan,
2338 &filtered_scan, &scan_current_chan_only);
2341 keep_previous_scan = user_scan_in->keep_previous_scan;
2344 if (!keep_previous_scan) {
2345 memset(adapter->scan_table, 0x00,
2346 sizeof(struct mwifiex_bssdescriptor) * IW_MAX_AP);
2347 adapter->num_in_scan_table = 0;
2348 adapter->bcn_buf_end = adapter->bcn_buf;
2351 ret = mwifiex_scan_channel_list(priv, wait_buf, max_chan_per_scan,
2352 filtered_scan, &scan_cfg_out->config,
2353 chan_list_out, scan_chan_list);
2355 /* Get scan command from scan_pending_q and put to cmd_pending_q */
2357 spin_lock_irqsave(&adapter->scan_pending_q_lock, flags);
2358 if (!list_empty(&adapter->scan_pending_q)) {
2359 cmd_node = list_first_entry(&adapter->scan_pending_q,
2360 struct cmd_ctrl_node, list);
2361 list_del(&cmd_node->list);
2362 spin_unlock_irqrestore(&adapter->scan_pending_q_lock,
2364 mwifiex_insert_cmd_to_pending_q(adapter, cmd_node,
2367 spin_unlock_irqrestore(&adapter->scan_pending_q_lock,
2372 spin_lock_irqsave(&adapter->mwifiex_cmd_lock, flags);
2373 adapter->scan_processing = true;
2374 spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, flags);
2377 kfree(scan_cfg_out);
2378 kfree(scan_chan_list);
2383 * This function prepares a scan command to be sent to the firmware.
2385 * This uses the scan command configuration sent to the command processing
2386 * module in command preparation stage to configure a scan command structure
2387 * to send to firmware.
2389 * The fixed fields specifying the BSS type and BSSID filters as well as a
2390 * variable number/length of TLVs are sent in the command to firmware.
2392 * Preparation also includes -
2393 * - Setting command ID, and proper size
2394 * - Ensuring correct endian-ness
2396 int mwifiex_cmd_802_11_scan(struct mwifiex_private *priv,
2397 struct host_cmd_ds_command *cmd, void *data_buf)
2399 struct host_cmd_ds_802_11_scan *scan_cmd = &cmd->params.scan;
2400 struct mwifiex_scan_cmd_config *scan_cfg;
2402 scan_cfg = (struct mwifiex_scan_cmd_config *) data_buf;
2404 /* Set fixed field variables in scan command */
2405 scan_cmd->bss_mode = scan_cfg->bss_mode;
2406 memcpy(scan_cmd->bssid, scan_cfg->specific_bssid,
2407 sizeof(scan_cmd->bssid));
2408 memcpy(scan_cmd->tlv_buffer, scan_cfg->tlv_buf, scan_cfg->tlv_buf_len);
2410 cmd->command = cpu_to_le16(HostCmd_CMD_802_11_SCAN);
2412 /* Size is equal to the sizeof(fixed portions) + the TLV len + header */
2413 cmd->size = cpu_to_le16((u16) (sizeof(scan_cmd->bss_mode)
2414 + sizeof(scan_cmd->bssid)
2415 + scan_cfg->tlv_buf_len + S_DS_GEN));
2421 * This function handles the command response of scan.
2423 * The response buffer for the scan command has the following
2426 * .-------------------------------------------------------------.
2427 * | Header (4 * sizeof(t_u16)): Standard command response hdr |
2428 * .-------------------------------------------------------------.
2429 * | BufSize (t_u16) : sizeof the BSS Description data |
2430 * .-------------------------------------------------------------.
2431 * | NumOfSet (t_u8) : Number of BSS Descs returned |
2432 * .-------------------------------------------------------------.
2433 * | BSSDescription data (variable, size given in BufSize) |
2434 * .-------------------------------------------------------------.
2435 * | TLV data (variable, size calculated using Header->Size, |
2436 * | BufSize and sizeof the fixed fields above) |
2437 * .-------------------------------------------------------------.
2439 int mwifiex_ret_802_11_scan(struct mwifiex_private *priv,
2440 struct host_cmd_ds_command *resp, void *wq_buf)
2443 struct mwifiex_adapter *adapter = priv->adapter;
2444 struct mwifiex_wait_queue *wait_queue = NULL;
2445 struct cmd_ctrl_node *cmd_node = NULL;
2446 struct host_cmd_ds_802_11_scan_rsp *scan_rsp = NULL;
2447 struct mwifiex_bssdescriptor *bss_new_entry = NULL;
2448 struct mwifiex_ie_types_data *tlv_data;
2449 struct mwifiex_ie_types_tsf_timestamp *tsf_tlv;
2458 struct mwifiex_chan_freq_power *cfp;
2459 struct mwifiex_ie_types_chan_band_list_param_set *chan_band_tlv;
2460 struct chan_band_param_set *chan_band;
2463 unsigned long flags;
2465 is_bgscan_resp = (le16_to_cpu(resp->command)
2466 == HostCmd_CMD_802_11_BG_SCAN_QUERY);
2468 scan_rsp = &resp->params.bg_scan_query_resp.scan_resp;
2470 scan_rsp = &resp->params.scan_resp;
2473 if (scan_rsp->number_of_sets > IW_MAX_AP) {
2474 dev_err(adapter->dev, "SCAN_RESP: too many AP returned (%d)\n",
2475 scan_rsp->number_of_sets);
2480 bytes_left = le16_to_cpu(scan_rsp->bss_descript_size);
2481 dev_dbg(adapter->dev, "info: SCAN_RESP: bss_descript_size %d\n",
2484 scan_resp_size = le16_to_cpu(resp->size);
2486 dev_dbg(adapter->dev,
2487 "info: SCAN_RESP: returned %d APs before parsing\n",
2488 scan_rsp->number_of_sets);
2490 num_in_table = adapter->num_in_scan_table;
2491 bss_info = scan_rsp->bss_desc_and_tlv_buffer;
2494 * The size of the TLV buffer is equal to the entire command response
2495 * size (scan_resp_size) minus the fixed fields (sizeof()'s), the
2496 * BSS Descriptions (bss_descript_size as bytesLef) and the command
2497 * response header (S_DS_GEN)
2499 tlv_buf_size = scan_resp_size - (bytes_left
2500 + sizeof(scan_rsp->bss_descript_size)
2501 + sizeof(scan_rsp->number_of_sets)
2504 tlv_data = (struct mwifiex_ie_types_data *) (scan_rsp->
2505 bss_desc_and_tlv_buffer +
2508 /* Search the TLV buffer space in the scan response for any valid
2510 mwifiex_ret_802_11_scan_get_tlv_ptrs(adapter, tlv_data, tlv_buf_size,
2511 TLV_TYPE_TSFTIMESTAMP,
2512 (struct mwifiex_ie_types_data **)
2515 /* Search the TLV buffer space in the scan response for any valid
2517 mwifiex_ret_802_11_scan_get_tlv_ptrs(adapter, tlv_data, tlv_buf_size,
2518 TLV_TYPE_CHANNELBANDLIST,
2519 (struct mwifiex_ie_types_data **)
2523 * Process each scan response returned (scan_rsp->number_of_sets).
2524 * Save the information in the bss_new_entry and then insert into the
2525 * driver scan table either as an update to an existing entry
2526 * or as an addition at the end of the table
2528 bss_new_entry = kzalloc(sizeof(struct mwifiex_bssdescriptor),
2530 if (!bss_new_entry) {
2531 dev_err(adapter->dev, " failed to alloc bss_new_entry\n");
2535 for (idx = 0; idx < scan_rsp->number_of_sets && bytes_left; idx++) {
2536 /* Zero out the bss_new_entry we are about to store info in */
2537 memset(bss_new_entry, 0x00,
2538 sizeof(struct mwifiex_bssdescriptor));
2540 if (mwifiex_interpret_bss_desc_with_ie(adapter, bss_new_entry,
2543 /* Error parsing/interpreting scan response, skipped */
2544 dev_err(adapter->dev, "SCAN_RESP: "
2545 "mwifiex_interpret_bss_desc_with_ie "
2546 "returned ERROR\n");
2550 /* Process the data fields and IEs returned for this BSS */
2551 dev_dbg(adapter->dev, "info: SCAN_RESP: BSSID = %pM\n",
2552 bss_new_entry->mac_address);
2554 /* Search the scan table for the same bssid */
2555 for (bss_idx = 0; bss_idx < num_in_table; bss_idx++) {
2556 if (memcmp(bss_new_entry->mac_address,
2557 adapter->scan_table[bss_idx].mac_address,
2558 sizeof(bss_new_entry->mac_address))) {
2562 * If the SSID matches as well, it is a
2563 * duplicate of this entry. Keep the bss_idx
2564 * set to this entry so we replace the old
2565 * contents in the table
2567 if ((bss_new_entry->ssid.ssid_len
2568 == adapter->scan_table[bss_idx]. ssid.ssid_len)
2569 && (!memcmp(bss_new_entry->ssid.ssid,
2570 adapter->scan_table[bss_idx].ssid.ssid,
2571 bss_new_entry->ssid.ssid_len))) {
2572 dev_dbg(adapter->dev, "info: SCAN_RESP:"
2573 " duplicate of index: %d\n", bss_idx);
2578 * If the bss_idx is equal to the number of entries in
2579 * the table, the new entry was not a duplicate; append
2580 * it to the scan table
2582 if (bss_idx == num_in_table) {
2583 /* Range check the bss_idx, keep it limited to
2585 if (bss_idx == IW_MAX_AP)
2592 * Save the beacon/probe response returned for later application
2593 * retrieval. Duplicate beacon/probe responses are updated if
2596 mwifiex_ret_802_11_scan_store_beacon(priv, bss_idx,
2597 num_in_table, bss_new_entry);
2599 * If the TSF TLV was appended to the scan results, save this
2600 * entry's TSF value in the networkTSF field.The networkTSF is
2601 * the firmware's TSF value at the time the beacon or probe
2602 * response was received.
2605 memcpy(&tsf_val, &tsf_tlv->tsf_data[idx * TSF_DATA_SIZE]
2607 memcpy(&bss_new_entry->network_tsf, &tsf_val,
2608 sizeof(bss_new_entry->network_tsf));
2611 if (chan_band_tlv) {
2612 chan_band = &chan_band_tlv->chan_band_param[idx];
2613 band = mwifiex_radio_type_to_band(chan_band->radio_type
2614 & (BIT(0) | BIT(1)));
2617 /* Save the band designation for this entry for use in join */
2618 bss_new_entry->bss_band = band;
2619 cfp = mwifiex_get_cfp_by_band_and_channel_from_cfg80211(priv,
2620 (u8) bss_new_entry->bss_band,
2621 (u16)bss_new_entry->channel);
2624 bss_new_entry->freq = cfp->freq;
2626 bss_new_entry->freq = 0;
2628 /* Copy the locally created bss_new_entry to the scan table */
2629 memcpy(&adapter->scan_table[bss_idx], bss_new_entry,
2630 sizeof(adapter->scan_table[bss_idx]));
2634 dev_dbg(adapter->dev,
2635 "info: SCAN_RESP: Scanned %2d APs, %d valid, %d total\n",
2636 scan_rsp->number_of_sets,
2637 num_in_table - adapter->num_in_scan_table, num_in_table);
2639 /* Update the total number of BSSIDs in the scan table */
2640 adapter->num_in_scan_table = num_in_table;
2642 spin_lock_irqsave(&adapter->scan_pending_q_lock, flags);
2643 if (list_empty(&adapter->scan_pending_q)) {
2644 spin_unlock_irqrestore(&adapter->scan_pending_q_lock, flags);
2645 spin_lock_irqsave(&adapter->mwifiex_cmd_lock, flags);
2646 adapter->scan_processing = false;
2647 spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, flags);
2649 * Process the resulting scan table:
2650 * - Remove any bad ssids
2651 * - Update our current BSS information from scan data
2653 mwifiex_process_scan_results(priv);
2655 /* Need to indicate IOCTL complete */
2656 wait_queue = (struct mwifiex_wait_queue *) wq_buf;
2658 wait_queue->status = MWIFIEX_ERROR_NO_ERROR;
2660 /* Indicate ioctl complete */
2661 mwifiex_ioctl_complete(adapter,
2662 (struct mwifiex_wait_queue *) wait_queue, 0);
2664 if (priv->report_scan_result)
2665 priv->report_scan_result = false;
2666 if (priv->scan_pending_on_block) {
2667 priv->scan_pending_on_block = false;
2668 up(&priv->async_sem);
2672 /* Get scan command from scan_pending_q and put to
2674 cmd_node = list_first_entry(&adapter->scan_pending_q,
2675 struct cmd_ctrl_node, list);
2676 list_del(&cmd_node->list);
2677 spin_unlock_irqrestore(&adapter->scan_pending_q_lock, flags);
2679 mwifiex_insert_cmd_to_pending_q(adapter, cmd_node, true);
2683 kfree((u8 *) bss_new_entry);
2688 * This function prepares command for background scan query.
2690 * Preparation includes -
2691 * - Setting command ID and proper size
2692 * - Setting background scan flush parameter
2693 * - Ensuring correct endian-ness
2695 int mwifiex_cmd_802_11_bg_scan_query(struct mwifiex_private *priv,
2696 struct host_cmd_ds_command *cmd,
2699 struct host_cmd_ds_802_11_bg_scan_query *bg_query =
2700 &cmd->params.bg_scan_query;
2702 cmd->command = cpu_to_le16(HostCmd_CMD_802_11_BG_SCAN_QUERY);
2703 cmd->size = cpu_to_le16(sizeof(struct host_cmd_ds_802_11_bg_scan_query)
2706 bg_query->flush = 1;
2712 * This function finds a SSID in the scan table.
2714 * A BSSID may optionally be provided to qualify the SSID.
2715 * For non-Auto mode, further check is made to make sure the
2716 * BSS found in the scan table is compatible with the current
2717 * settings of the driver.
2720 mwifiex_find_ssid_in_list(struct mwifiex_private *priv,
2721 struct mwifiex_802_11_ssid *ssid, u8 *bssid,
2724 struct mwifiex_adapter *adapter = priv->adapter;
2729 dev_dbg(adapter->dev, "info: num of entries in table = %d\n",
2730 adapter->num_in_scan_table);
2733 * Loop through the table until the maximum is reached or until a match
2734 * is found based on the bssid field comparison
2737 i < adapter->num_in_scan_table && (!bssid || (bssid && net < 0));
2739 if (!mwifiex_ssid_cmp(&adapter->scan_table[i].ssid, ssid) &&
2741 || !memcmp(adapter->scan_table[i].mac_address, bssid,
2744 (mwifiex_get_cfp_by_band_and_channel_from_cfg80211
2745 (priv, (u8) adapter->scan_table[i].bss_band,
2746 (u16) adapter->scan_table[i].channel))) {
2748 case NL80211_IFTYPE_STATION:
2749 case NL80211_IFTYPE_ADHOC:
2750 j = mwifiex_is_network_compatible(priv, i,
2755 (adapter->scan_table[i].rssi) >
2757 best_rssi = SCAN_RSSI(adapter->
2767 case NL80211_IFTYPE_UNSPECIFIED:
2770 * Do not check compatibility if the mode
2771 * requested is Auto/Unknown. Allows generic
2772 * find to work without verifying against the
2773 * Adapter security settings
2775 if (SCAN_RSSI(adapter->scan_table[i].rssi) >
2777 best_rssi = SCAN_RSSI(adapter->
2778 scan_table[i].rssi);
2790 * This function finds a specific compatible BSSID in the scan list.
2792 * This function loops through the scan table looking for a compatible
2793 * match. If a BSSID matches, but the BSS is found to be not compatible
2794 * the function ignores it and continues to search through the rest of
2795 * the entries in case there is an AP with multiple SSIDs assigned to
2799 mwifiex_find_bssid_in_list(struct mwifiex_private *priv, u8 *bssid,
2802 struct mwifiex_adapter *adapter = priv->adapter;
2809 dev_dbg(adapter->dev, "info: FindBSSID: Num of BSSIDs = %d\n",
2810 adapter->num_in_scan_table);
2813 * Look through the scan table for a compatible match. The ret return
2814 * variable will be equal to the index in the scan table (greater
2815 * than zero) if the network is compatible. The loop will continue
2816 * past a matched bssid that is not compatible in case there is an
2817 * AP with multiple SSIDs assigned to the same BSSID
2819 for (i = 0; net < 0 && i < adapter->num_in_scan_table; i++) {
2821 (adapter->scan_table[i].mac_address, bssid, ETH_ALEN)
2822 && mwifiex_get_cfp_by_band_and_channel_from_cfg80211
2831 case NL80211_IFTYPE_STATION:
2832 case NL80211_IFTYPE_ADHOC:
2833 net = mwifiex_is_network_compatible(priv, i,
2847 * This function inserts scan command node to the scan pending queue.
2850 mwifiex_queue_scan_cmd(struct mwifiex_private *priv,
2851 struct cmd_ctrl_node *cmd_node)
2853 struct mwifiex_adapter *adapter = priv->adapter;
2854 unsigned long flags;
2856 spin_lock_irqsave(&adapter->scan_pending_q_lock, flags);
2857 list_add_tail(&cmd_node->list, &adapter->scan_pending_q);
2858 spin_unlock_irqrestore(&adapter->scan_pending_q_lock, flags);
2862 * This function finds an AP with specific ssid in the scan list.
2864 int mwifiex_find_best_network(struct mwifiex_private *priv,
2865 struct mwifiex_ssid_bssid *req_ssid_bssid)
2867 struct mwifiex_adapter *adapter = priv->adapter;
2868 struct mwifiex_bssdescriptor *req_bss;
2871 memset(req_ssid_bssid, 0, sizeof(struct mwifiex_ssid_bssid));
2873 i = mwifiex_find_best_network_in_list(priv);
2876 req_bss = &adapter->scan_table[i];
2877 memcpy(&req_ssid_bssid->ssid, &req_bss->ssid,
2878 sizeof(struct mwifiex_802_11_ssid));
2879 memcpy((u8 *) &req_ssid_bssid->bssid,
2880 (u8 *) &req_bss->mac_address, ETH_ALEN);
2882 /* Make sure we are in the right mode */
2883 if (priv->bss_mode == NL80211_IFTYPE_UNSPECIFIED)
2884 priv->bss_mode = req_bss->bss_mode;
2887 if (!req_ssid_bssid->ssid.ssid_len)
2890 dev_dbg(adapter->dev, "info: Best network found = [%s], "
2891 "[%pM]\n", req_ssid_bssid->ssid.ssid,
2892 req_ssid_bssid->bssid);
2898 * This function sends a scan command for all available channels to the
2899 * firmware, filtered on a specific SSID.
2901 static int mwifiex_scan_specific_ssid(struct mwifiex_private *priv,
2902 void *wait_buf, u16 action,
2903 struct mwifiex_802_11_ssid *req_ssid,
2904 struct mwifiex_scan_resp *scan_resp)
2906 struct mwifiex_adapter *adapter = priv->adapter;
2908 struct mwifiex_user_scan_cfg *scan_cfg;
2913 if (action == HostCmd_ACT_GEN_GET) {
2915 scan_resp->scan_table =
2916 (u8 *) &priv->curr_bss_params.bss_descriptor;
2917 scan_resp->num_in_scan_table =
2918 adapter->num_in_scan_table;
2925 if (adapter->scan_processing && action == HostCmd_ACT_GEN_SET) {
2926 dev_dbg(adapter->dev, "cmd: Scan already in process...\n");
2930 if (priv->scan_block && action == HostCmd_ACT_GEN_SET) {
2931 dev_dbg(adapter->dev,
2932 "cmd: Scan is blocked during association...\n");
2936 mwifiex_scan_delete_ssid_table_entry(priv, req_ssid);
2938 scan_cfg = kzalloc(sizeof(struct mwifiex_user_scan_cfg), GFP_KERNEL);
2940 dev_err(adapter->dev, "failed to alloc scan_cfg\n");
2944 memcpy(scan_cfg->ssid_list[0].ssid, req_ssid->ssid,
2945 req_ssid->ssid_len);
2946 scan_cfg->keep_previous_scan = true;
2948 ret = mwifiex_scan_networks(priv, wait_buf, action, scan_cfg, NULL);
2955 * Sends IOCTL request to start a scan.
2957 * This function allocates the IOCTL request buffer, fills it
2958 * with requisite parameters and calls the IOCTL handler.
2960 * Scan command can be issued for both normal scan and specific SSID
2961 * scan, depending upon whether an SSID is provided or not.
2963 int mwifiex_request_scan(struct mwifiex_private *priv, u8 wait_option,
2964 struct mwifiex_802_11_ssid *req_ssid)
2967 struct mwifiex_wait_queue *wait = NULL;
2970 if (down_interruptible(&priv->async_sem)) {
2971 dev_err(priv->adapter->dev, "%s: acquire semaphore\n",
2975 priv->scan_pending_on_block = true;
2977 /* Allocate wait request buffer */
2978 wait = mwifiex_alloc_fill_wait_queue(priv, wait_option);
2984 if (req_ssid && req_ssid->ssid_len != 0)
2985 /* Specific SSID scan */
2986 status = mwifiex_scan_specific_ssid(priv, wait,
2987 HostCmd_ACT_GEN_SET,
2991 status = mwifiex_scan_networks(priv, wait, HostCmd_ACT_GEN_SET,
2993 status = mwifiex_request_ioctl(priv, wait, status, wait_option);
2997 if ((wait) && (status != -EINPROGRESS))
3000 priv->scan_pending_on_block = false;
3001 up(&priv->async_sem);
3007 * This function appends the vendor specific IE TLV to a buffer.
3010 mwifiex_cmd_append_vsie_tlv(struct mwifiex_private *priv,
3011 u16 vsie_mask, u8 **buffer)
3013 int id, ret_len = 0;
3014 struct mwifiex_ie_types_vendor_param_set *vs_param_set;
3022 * Traverse through the saved vendor specific IE array and append
3023 * the selected(scan/assoc/adhoc) IE as TLV to the command
3025 for (id = 0; id < MWIFIEX_MAX_VSIE_NUM; id++) {
3026 if (priv->vs_ie[id].mask & vsie_mask) {
3028 (struct mwifiex_ie_types_vendor_param_set *)
3030 vs_param_set->header.type =
3031 cpu_to_le16(TLV_TYPE_PASSTHROUGH);
3032 vs_param_set->header.len =
3033 cpu_to_le16((((u16) priv->vs_ie[id].ie[1])
3035 memcpy(vs_param_set->ie, priv->vs_ie[id].ie,
3036 le16_to_cpu(vs_param_set->header.len));
3037 *buffer += le16_to_cpu(vs_param_set->header.len) +
3038 sizeof(struct mwifiex_ie_types_header);
3039 ret_len += le16_to_cpu(vs_param_set->header.len) +
3040 sizeof(struct mwifiex_ie_types_header);
3047 * This function saves a beacon buffer of the current BSS descriptor.
3049 * The current beacon buffer is saved so that it can be restored in the
3050 * following cases that makes the beacon buffer not to contain the current
3051 * ssid's beacon buffer.
3052 * - The current ssid was not found somehow in the last scan.
3053 * - The current ssid was the last entry of the scan table and overloaded.
3056 mwifiex_save_curr_bcn(struct mwifiex_private *priv)
3058 struct mwifiex_bssdescriptor *curr_bss =
3059 &priv->curr_bss_params.bss_descriptor;
3061 /* save the beacon buffer if it is not saved or updated */
3062 if ((priv->curr_bcn_buf == NULL) ||
3063 (priv->curr_bcn_size != curr_bss->beacon_buf_size) ||
3064 (memcmp(priv->curr_bcn_buf, curr_bss->beacon_buf,
3065 curr_bss->beacon_buf_size))) {
3067 kfree(priv->curr_bcn_buf);
3068 priv->curr_bcn_buf = NULL;
3070 priv->curr_bcn_size = curr_bss->beacon_buf_size;
3071 if (!priv->curr_bcn_size)
3074 priv->curr_bcn_buf = kzalloc(curr_bss->beacon_buf_size,
3076 if (!priv->curr_bcn_buf) {
3077 dev_err(priv->adapter->dev,
3078 "failed to alloc curr_bcn_buf\n");
3080 memcpy(priv->curr_bcn_buf, curr_bss->beacon_buf,
3081 curr_bss->beacon_buf_size);
3082 dev_dbg(priv->adapter->dev,
3083 "info: current beacon saved %d\n",
3084 priv->curr_bcn_size);
3090 * This function frees the current BSS descriptor beacon buffer.
3093 mwifiex_free_curr_bcn(struct mwifiex_private *priv)
3095 kfree(priv->curr_bcn_buf);
3096 priv->curr_bcn_buf = NULL;