2 * Marvell Wireless LAN device driver: scan ioctl and command handling
4 * Copyright (C) 2011-2014, 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_DEF_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
;
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
;
149 u8 ret
= MWIFIEX_OUI_NOT_PRESENT
;
151 if (((bss_desc
->bcn_wpa_ie
) &&
152 ((*(bss_desc
->bcn_wpa_ie
)).vend_hdr
.element_id
==
153 WLAN_EID_VENDOR_SPECIFIC
))) {
154 iebody
= (struct ie_body
*) bss_desc
->bcn_wpa_ie
->data
;
155 oui
= &mwifiex_wpa_oui
[cipher
][0];
156 ret
= mwifiex_search_oui_in_ie(iebody
, oui
);
164 * This function compares two SSIDs and checks if they match.
167 mwifiex_ssid_cmp(struct cfg80211_ssid
*ssid1
, struct cfg80211_ssid
*ssid2
)
169 if (!ssid1
|| !ssid2
|| (ssid1
->ssid_len
!= ssid2
->ssid_len
))
171 return memcmp(ssid1
->ssid
, ssid2
->ssid
, ssid1
->ssid_len
);
175 * This function checks if wapi is enabled in driver and scanned network is
176 * compatible with it.
179 mwifiex_is_bss_wapi(struct mwifiex_private
*priv
,
180 struct mwifiex_bssdescriptor
*bss_desc
)
182 if (priv
->sec_info
.wapi_enabled
&&
183 (bss_desc
->bcn_wapi_ie
&&
184 ((*(bss_desc
->bcn_wapi_ie
)).ieee_hdr
.element_id
==
185 WLAN_EID_BSS_AC_ACCESS_DELAY
))) {
192 * This function checks if driver is configured with no security mode and
193 * scanned network is compatible with it.
196 mwifiex_is_bss_no_sec(struct mwifiex_private
*priv
,
197 struct mwifiex_bssdescriptor
*bss_desc
)
199 if (!priv
->sec_info
.wep_enabled
&& !priv
->sec_info
.wpa_enabled
&&
200 !priv
->sec_info
.wpa2_enabled
&& ((!bss_desc
->bcn_wpa_ie
) ||
201 ((*(bss_desc
->bcn_wpa_ie
)).vend_hdr
.element_id
!=
202 WLAN_EID_VENDOR_SPECIFIC
)) &&
203 ((!bss_desc
->bcn_rsn_ie
) ||
204 ((*(bss_desc
->bcn_rsn_ie
)).ieee_hdr
.element_id
!=
206 !priv
->sec_info
.encryption_mode
&& !bss_desc
->privacy
) {
213 * This function checks if static WEP is enabled in driver and scanned network
214 * is compatible with it.
217 mwifiex_is_bss_static_wep(struct mwifiex_private
*priv
,
218 struct mwifiex_bssdescriptor
*bss_desc
)
220 if (priv
->sec_info
.wep_enabled
&& !priv
->sec_info
.wpa_enabled
&&
221 !priv
->sec_info
.wpa2_enabled
&& bss_desc
->privacy
) {
228 * This function checks if wpa is enabled in driver and scanned network is
229 * compatible with it.
232 mwifiex_is_bss_wpa(struct mwifiex_private
*priv
,
233 struct mwifiex_bssdescriptor
*bss_desc
)
235 if (!priv
->sec_info
.wep_enabled
&& priv
->sec_info
.wpa_enabled
&&
236 !priv
->sec_info
.wpa2_enabled
&& ((bss_desc
->bcn_wpa_ie
) &&
237 ((*(bss_desc
->bcn_wpa_ie
)).
238 vend_hdr
.element_id
== WLAN_EID_VENDOR_SPECIFIC
))
240 * Privacy bit may NOT be set in some APs like
241 * LinkSys WRT54G && bss_desc->privacy
244 mwifiex_dbg(priv
->adapter
, INFO
,
246 "wpa_ie=%#x wpa2_ie=%#x WEP=%s WPA=%s WPA2=%s\t"
247 "EncMode=%#x privacy=%#x\n", __func__
,
248 (bss_desc
->bcn_wpa_ie
) ?
249 (*bss_desc
->bcn_wpa_ie
).
250 vend_hdr
.element_id
: 0,
251 (bss_desc
->bcn_rsn_ie
) ?
252 (*bss_desc
->bcn_rsn_ie
).
253 ieee_hdr
.element_id
: 0,
254 (priv
->sec_info
.wep_enabled
) ? "e" : "d",
255 (priv
->sec_info
.wpa_enabled
) ? "e" : "d",
256 (priv
->sec_info
.wpa2_enabled
) ? "e" : "d",
257 priv
->sec_info
.encryption_mode
,
265 * This function checks if wpa2 is enabled in driver and scanned network is
266 * compatible with it.
269 mwifiex_is_bss_wpa2(struct mwifiex_private
*priv
,
270 struct mwifiex_bssdescriptor
*bss_desc
)
272 if (!priv
->sec_info
.wep_enabled
&&
273 !priv
->sec_info
.wpa_enabled
&&
274 priv
->sec_info
.wpa2_enabled
&&
275 ((bss_desc
->bcn_rsn_ie
) &&
276 ((*(bss_desc
->bcn_rsn_ie
)).ieee_hdr
.element_id
== WLAN_EID_RSN
))) {
278 * Privacy bit may NOT be set in some APs like
279 * LinkSys WRT54G && bss_desc->privacy
281 mwifiex_dbg(priv
->adapter
, INFO
,
283 "wpa_ie=%#x wpa2_ie=%#x WEP=%s WPA=%s WPA2=%s\t"
284 "EncMode=%#x privacy=%#x\n", __func__
,
285 (bss_desc
->bcn_wpa_ie
) ?
286 (*bss_desc
->bcn_wpa_ie
).
287 vend_hdr
.element_id
: 0,
288 (bss_desc
->bcn_rsn_ie
) ?
289 (*bss_desc
->bcn_rsn_ie
).
290 ieee_hdr
.element_id
: 0,
291 (priv
->sec_info
.wep_enabled
) ? "e" : "d",
292 (priv
->sec_info
.wpa_enabled
) ? "e" : "d",
293 (priv
->sec_info
.wpa2_enabled
) ? "e" : "d",
294 priv
->sec_info
.encryption_mode
,
302 * This function checks if adhoc AES is enabled in driver and scanned network is
303 * compatible with it.
306 mwifiex_is_bss_adhoc_aes(struct mwifiex_private
*priv
,
307 struct mwifiex_bssdescriptor
*bss_desc
)
309 if (!priv
->sec_info
.wep_enabled
&& !priv
->sec_info
.wpa_enabled
&&
310 !priv
->sec_info
.wpa2_enabled
&&
311 ((!bss_desc
->bcn_wpa_ie
) ||
312 ((*(bss_desc
->bcn_wpa_ie
)).
313 vend_hdr
.element_id
!= WLAN_EID_VENDOR_SPECIFIC
)) &&
314 ((!bss_desc
->bcn_rsn_ie
) ||
315 ((*(bss_desc
->bcn_rsn_ie
)).ieee_hdr
.element_id
!= WLAN_EID_RSN
)) &&
316 !priv
->sec_info
.encryption_mode
&& bss_desc
->privacy
) {
323 * This function checks if dynamic WEP is enabled in driver and scanned network
324 * is compatible with it.
327 mwifiex_is_bss_dynamic_wep(struct mwifiex_private
*priv
,
328 struct mwifiex_bssdescriptor
*bss_desc
)
330 if (!priv
->sec_info
.wep_enabled
&& !priv
->sec_info
.wpa_enabled
&&
331 !priv
->sec_info
.wpa2_enabled
&&
332 ((!bss_desc
->bcn_wpa_ie
) ||
333 ((*(bss_desc
->bcn_wpa_ie
)).
334 vend_hdr
.element_id
!= WLAN_EID_VENDOR_SPECIFIC
)) &&
335 ((!bss_desc
->bcn_rsn_ie
) ||
336 ((*(bss_desc
->bcn_rsn_ie
)).ieee_hdr
.element_id
!= WLAN_EID_RSN
)) &&
337 priv
->sec_info
.encryption_mode
&& bss_desc
->privacy
) {
338 mwifiex_dbg(priv
->adapter
, INFO
,
339 "info: %s: dynamic\t"
340 "WEP: wpa_ie=%#x wpa2_ie=%#x\t"
341 "EncMode=%#x privacy=%#x\n",
343 (bss_desc
->bcn_wpa_ie
) ?
344 (*bss_desc
->bcn_wpa_ie
).
345 vend_hdr
.element_id
: 0,
346 (bss_desc
->bcn_rsn_ie
) ?
347 (*bss_desc
->bcn_rsn_ie
).
348 ieee_hdr
.element_id
: 0,
349 priv
->sec_info
.encryption_mode
,
357 * This function checks if a scanned network is compatible with the driver
360 * WEP WPA WPA2 ad-hoc encrypt Network
361 * enabled enabled enabled AES mode Privacy WPA WPA2 Compatible
362 * 0 0 0 0 NONE 0 0 0 yes No security
363 * 0 1 0 0 x 1x 1 x yes WPA (disable
365 * 0 0 1 0 x 1x x 1 yes WPA2 (disable
367 * 0 0 0 1 NONE 1 0 0 yes Ad-hoc AES
368 * 1 0 0 0 NONE 1 0 0 yes Static WEP
370 * 0 0 0 0 !=NONE 1 0 0 yes Dynamic WEP
372 * Compatibility is not matched while roaming, except for mode.
375 mwifiex_is_network_compatible(struct mwifiex_private
*priv
,
376 struct mwifiex_bssdescriptor
*bss_desc
, u32 mode
)
378 struct mwifiex_adapter
*adapter
= priv
->adapter
;
380 bss_desc
->disable_11n
= false;
382 /* Don't check for compatibility if roaming */
383 if (priv
->media_connected
&&
384 (priv
->bss_mode
== NL80211_IFTYPE_STATION
) &&
385 (bss_desc
->bss_mode
== NL80211_IFTYPE_STATION
))
388 if (priv
->wps
.session_enable
) {
389 mwifiex_dbg(adapter
, IOCTL
,
390 "info: return success directly in WPS period\n");
394 if (bss_desc
->chan_sw_ie_present
) {
395 mwifiex_dbg(adapter
, INFO
,
396 "Don't connect to AP with WLAN_EID_CHANNEL_SWITCH\n");
400 if (mwifiex_is_bss_wapi(priv
, bss_desc
)) {
401 mwifiex_dbg(adapter
, INFO
,
402 "info: return success for WAPI AP\n");
406 if (bss_desc
->bss_mode
== mode
) {
407 if (mwifiex_is_bss_no_sec(priv
, bss_desc
)) {
410 } else if (mwifiex_is_bss_static_wep(priv
, bss_desc
)) {
411 /* Static WEP enabled */
412 mwifiex_dbg(adapter
, INFO
,
413 "info: Disable 11n in WEP mode.\n");
414 bss_desc
->disable_11n
= true;
416 } else if (mwifiex_is_bss_wpa(priv
, bss_desc
)) {
418 if (((priv
->adapter
->config_bands
& BAND_GN
||
419 priv
->adapter
->config_bands
& BAND_AN
) &&
420 bss_desc
->bcn_ht_cap
) &&
421 !mwifiex_is_wpa_oui_present(bss_desc
,
422 CIPHER_SUITE_CCMP
)) {
424 if (mwifiex_is_wpa_oui_present
425 (bss_desc
, CIPHER_SUITE_TKIP
)) {
426 mwifiex_dbg(adapter
, INFO
,
427 "info: Disable 11n if AES\t"
428 "is not supported by AP\n");
429 bss_desc
->disable_11n
= true;
435 } else if (mwifiex_is_bss_wpa2(priv
, bss_desc
)) {
437 if (((priv
->adapter
->config_bands
& BAND_GN
||
438 priv
->adapter
->config_bands
& BAND_AN
) &&
439 bss_desc
->bcn_ht_cap
) &&
440 !mwifiex_is_rsn_oui_present(bss_desc
,
441 CIPHER_SUITE_CCMP
)) {
443 if (mwifiex_is_rsn_oui_present
444 (bss_desc
, CIPHER_SUITE_TKIP
)) {
445 mwifiex_dbg(adapter
, INFO
,
446 "info: Disable 11n if AES\t"
447 "is not supported by AP\n");
448 bss_desc
->disable_11n
= true;
454 } else if (mwifiex_is_bss_adhoc_aes(priv
, bss_desc
)) {
455 /* Ad-hoc AES enabled */
457 } else if (mwifiex_is_bss_dynamic_wep(priv
, bss_desc
)) {
458 /* Dynamic WEP enabled */
462 /* Security doesn't match */
463 mwifiex_dbg(adapter
, ERROR
,
464 "info: %s: failed: wpa_ie=%#x wpa2_ie=%#x WEP=%s\t"
465 "WPA=%s WPA2=%s EncMode=%#x privacy=%#x\n",
467 (bss_desc
->bcn_wpa_ie
) ?
468 (*bss_desc
->bcn_wpa_ie
).vend_hdr
.element_id
: 0,
469 (bss_desc
->bcn_rsn_ie
) ?
470 (*bss_desc
->bcn_rsn_ie
).ieee_hdr
.element_id
: 0,
471 (priv
->sec_info
.wep_enabled
) ? "e" : "d",
472 (priv
->sec_info
.wpa_enabled
) ? "e" : "d",
473 (priv
->sec_info
.wpa2_enabled
) ? "e" : "d",
474 priv
->sec_info
.encryption_mode
, bss_desc
->privacy
);
478 /* Mode doesn't match */
483 * This function creates a channel list for the driver to scan, based
484 * on region/band information.
486 * This routine is used for any scan that is not provided with a
487 * specific channel list to scan.
490 mwifiex_scan_create_channel_list(struct mwifiex_private
*priv
,
491 const struct mwifiex_user_scan_cfg
493 struct mwifiex_chan_scan_param_set
497 enum ieee80211_band band
;
498 struct ieee80211_supported_band
*sband
;
499 struct ieee80211_channel
*ch
;
500 struct mwifiex_adapter
*adapter
= priv
->adapter
;
503 for (band
= 0; (band
< IEEE80211_NUM_BANDS
) ; band
++) {
505 if (!priv
->wdev
.wiphy
->bands
[band
])
508 sband
= priv
->wdev
.wiphy
->bands
[band
];
510 for (i
= 0; (i
< sband
->n_channels
) ; i
++) {
511 ch
= &sband
->channels
[i
];
512 if (ch
->flags
& IEEE80211_CHAN_DISABLED
)
514 scan_chan_list
[chan_idx
].radio_type
= band
;
517 user_scan_in
->chan_list
[0].scan_time
)
518 scan_chan_list
[chan_idx
].max_scan_time
=
519 cpu_to_le16((u16
) user_scan_in
->
520 chan_list
[0].scan_time
);
521 else if (ch
->flags
& IEEE80211_CHAN_NO_IR
)
522 scan_chan_list
[chan_idx
].max_scan_time
=
523 cpu_to_le16(adapter
->passive_scan_time
);
525 scan_chan_list
[chan_idx
].max_scan_time
=
526 cpu_to_le16(adapter
->active_scan_time
);
528 if (ch
->flags
& IEEE80211_CHAN_NO_IR
)
529 scan_chan_list
[chan_idx
].chan_scan_mode_bitmap
530 |= MWIFIEX_PASSIVE_SCAN
;
532 scan_chan_list
[chan_idx
].chan_scan_mode_bitmap
533 &= ~MWIFIEX_PASSIVE_SCAN
;
534 scan_chan_list
[chan_idx
].chan_number
=
537 scan_chan_list
[chan_idx
].max_scan_time
=
538 cpu_to_le16(adapter
->specific_scan_time
);
539 scan_chan_list
[chan_idx
].chan_scan_mode_bitmap
540 |= MWIFIEX_DISABLE_CHAN_FILT
;
549 /* This function appends rate TLV to scan config command. */
551 mwifiex_append_rate_tlv(struct mwifiex_private
*priv
,
552 struct mwifiex_scan_cmd_config
*scan_cfg_out
,
555 struct mwifiex_ie_types_rates_param_set
*rates_tlv
;
556 u8 rates
[MWIFIEX_SUPPORTED_RATES
], *tlv_pos
;
559 memset(rates
, 0, sizeof(rates
));
561 tlv_pos
= (u8
*)scan_cfg_out
->tlv_buf
+ scan_cfg_out
->tlv_buf_len
;
563 if (priv
->scan_request
)
564 rates_size
= mwifiex_get_rates_from_cfg80211(priv
, rates
,
567 rates_size
= mwifiex_get_supported_rates(priv
, rates
);
569 mwifiex_dbg(priv
->adapter
, CMD
,
570 "info: SCAN_CMD: Rates size = %d\n",
572 rates_tlv
= (struct mwifiex_ie_types_rates_param_set
*)tlv_pos
;
573 rates_tlv
->header
.type
= cpu_to_le16(WLAN_EID_SUPP_RATES
);
574 rates_tlv
->header
.len
= cpu_to_le16((u16
) rates_size
);
575 memcpy(rates_tlv
->rates
, rates
, rates_size
);
576 scan_cfg_out
->tlv_buf_len
+= sizeof(rates_tlv
->header
) + rates_size
;
582 * This function constructs and sends multiple scan config commands to
585 * Previous routines in the code flow have created a scan command configuration
586 * with any requested TLVs. This function splits the channel TLV into maximum
587 * channels supported per scan lists and sends the portion of the channel TLV,
588 * along with the other TLVs, to the firmware.
591 mwifiex_scan_channel_list(struct mwifiex_private
*priv
,
592 u32 max_chan_per_scan
, u8 filtered_scan
,
593 struct mwifiex_scan_cmd_config
*scan_cfg_out
,
594 struct mwifiex_ie_types_chan_list_param_set
596 struct mwifiex_chan_scan_param_set
*scan_chan_list
)
598 struct mwifiex_adapter
*adapter
= priv
->adapter
;
600 struct mwifiex_chan_scan_param_set
*tmp_chan_list
;
601 struct mwifiex_chan_scan_param_set
*start_chan
;
602 struct cmd_ctrl_node
*cmd_node
, *tmp_node
;
604 u32 tlv_idx
, rates_size
, cmd_no
;
609 if (!scan_cfg_out
|| !chan_tlv_out
|| !scan_chan_list
) {
610 mwifiex_dbg(priv
->adapter
, ERROR
,
611 "info: Scan: Null detect: %p, %p, %p\n",
612 scan_cfg_out
, chan_tlv_out
, scan_chan_list
);
616 /* Check csa channel expiry before preparing scan list */
617 mwifiex_11h_get_csa_closed_channel(priv
);
619 chan_tlv_out
->header
.type
= cpu_to_le16(TLV_TYPE_CHANLIST
);
621 /* Set the temp channel struct pointer to the start of the desired
623 tmp_chan_list
= scan_chan_list
;
625 /* Loop through the desired channel list, sending a new firmware scan
626 commands for each max_chan_per_scan channels (or for 1,6,11
627 individually if configured accordingly) */
628 while (tmp_chan_list
->chan_number
) {
633 chan_tlv_out
->header
.len
= 0;
634 start_chan
= tmp_chan_list
;
638 * Construct the Channel TLV for the scan command. Continue to
639 * insert channel TLVs until:
640 * - the tlv_idx hits the maximum configured per scan command
641 * - the next channel to insert is 0 (end of desired channel
643 * - done_early is set (controlling individual scanning of
646 while (tlv_idx
< max_chan_per_scan
&&
647 tmp_chan_list
->chan_number
&& !done_early
) {
649 if (tmp_chan_list
->chan_number
== priv
->csa_chan
) {
654 radio_type
= tmp_chan_list
->radio_type
;
655 mwifiex_dbg(priv
->adapter
, INFO
,
656 "info: Scan: Chan(%3d), Radio(%d),\t"
657 "Mode(%d, %d), Dur(%d)\n",
658 tmp_chan_list
->chan_number
,
659 tmp_chan_list
->radio_type
,
660 tmp_chan_list
->chan_scan_mode_bitmap
661 & MWIFIEX_PASSIVE_SCAN
,
662 (tmp_chan_list
->chan_scan_mode_bitmap
663 & MWIFIEX_DISABLE_CHAN_FILT
) >> 1,
664 le16_to_cpu(tmp_chan_list
->max_scan_time
));
666 /* Copy the current channel TLV to the command being
668 memcpy(chan_tlv_out
->chan_scan_param
+ tlv_idx
,
670 sizeof(chan_tlv_out
->chan_scan_param
));
672 /* Increment the TLV header length by the size
674 le16_add_cpu(&chan_tlv_out
->header
.len
,
675 sizeof(chan_tlv_out
->chan_scan_param
));
678 * The tlv buffer length is set to the number of bytes
679 * of the between the channel tlv pointer and the start
680 * of the tlv buffer. This compensates for any TLVs
681 * that were appended before the channel list.
683 scan_cfg_out
->tlv_buf_len
= (u32
) ((u8
*) chan_tlv_out
-
684 scan_cfg_out
->tlv_buf
);
686 /* Add the size of the channel tlv header and the data
688 scan_cfg_out
->tlv_buf_len
+=
689 (sizeof(chan_tlv_out
->header
)
690 + le16_to_cpu(chan_tlv_out
->header
.len
));
692 /* Increment the index to the channel tlv we are
696 /* Count the total scan time per command */
698 le16_to_cpu(tmp_chan_list
->max_scan_time
);
702 /* Stop the loop if the *current* channel is in the
703 1,6,11 set and we are not filtering on a BSSID
705 if (!filtered_scan
&&
706 (tmp_chan_list
->chan_number
== 1 ||
707 tmp_chan_list
->chan_number
== 6 ||
708 tmp_chan_list
->chan_number
== 11))
711 /* Increment the tmp pointer to the next channel to
715 /* Stop the loop if the *next* channel is in the 1,6,11
716 set. This will cause it to be the only channel
717 scanned on the next interation */
718 if (!filtered_scan
&&
719 (tmp_chan_list
->chan_number
== 1 ||
720 tmp_chan_list
->chan_number
== 6 ||
721 tmp_chan_list
->chan_number
== 11))
725 /* The total scan time should be less than scan command timeout
727 if (total_scan_time
> MWIFIEX_MAX_TOTAL_SCAN_TIME
) {
728 mwifiex_dbg(priv
->adapter
, ERROR
,
729 "total scan time %dms\t"
730 "is over limit (%dms), scan skipped\n",
732 MWIFIEX_MAX_TOTAL_SCAN_TIME
);
737 rates_size
= mwifiex_append_rate_tlv(priv
, scan_cfg_out
,
740 priv
->adapter
->scan_channels
= start_chan
;
742 /* Send the scan command to the firmware with the specified
744 if (priv
->adapter
->ext_scan
)
745 cmd_no
= HostCmd_CMD_802_11_SCAN_EXT
;
747 cmd_no
= HostCmd_CMD_802_11_SCAN
;
749 ret
= mwifiex_send_cmd(priv
, cmd_no
, HostCmd_ACT_GEN_SET
,
750 0, scan_cfg_out
, false);
752 /* rate IE is updated per scan command but same starting
753 * pointer is used each time so that rate IE from earlier
754 * scan_cfg_out->buf is overwritten with new one.
756 scan_cfg_out
->tlv_buf_len
-=
757 sizeof(struct mwifiex_ie_types_header
) + rates_size
;
760 spin_lock_irqsave(&adapter
->scan_pending_q_lock
, flags
);
761 list_for_each_entry_safe(cmd_node
, tmp_node
,
762 &adapter
->scan_pending_q
,
764 list_del(&cmd_node
->list
);
765 cmd_node
->wait_q_enabled
= false;
766 mwifiex_insert_cmd_to_free_q(adapter
, cmd_node
);
768 spin_unlock_irqrestore(&adapter
->scan_pending_q_lock
,
781 * This function constructs a scan command configuration structure to use
784 * Application layer or other functions can invoke network scanning
785 * with a scan configuration supplied in a user scan configuration structure.
786 * This structure is used as the basis of one or many scan command configuration
787 * commands that are sent to the command processing module and eventually to the
790 * This function creates a scan command configuration structure based on the
791 * following user supplied parameters (if present):
794 * - Number of Probes to be sent
797 * If the SSID or BSSID filter is not present, the filter is disabled/cleared.
798 * If the number of probes is not set, adapter default setting is used.
801 mwifiex_config_scan(struct mwifiex_private
*priv
,
802 const struct mwifiex_user_scan_cfg
*user_scan_in
,
803 struct mwifiex_scan_cmd_config
*scan_cfg_out
,
804 struct mwifiex_ie_types_chan_list_param_set
**chan_list_out
,
805 struct mwifiex_chan_scan_param_set
*scan_chan_list
,
806 u8
*max_chan_per_scan
, u8
*filtered_scan
,
807 u8
*scan_current_only
)
809 struct mwifiex_adapter
*adapter
= priv
->adapter
;
810 struct mwifiex_ie_types_num_probes
*num_probes_tlv
;
811 struct mwifiex_ie_types_scan_chan_gap
*chan_gap_tlv
;
812 struct mwifiex_ie_types_wildcard_ssid_params
*wildcard_ssid_tlv
;
813 struct mwifiex_ie_types_bssid_list
*bssid_tlv
;
825 struct mwifiex_ie_types_htcap
*ht_cap
;
827 /* The tlv_buf_len is calculated for each scan command. The TLVs added
828 in this routine will be preserved since the routine that sends the
829 command will append channelTLVs at *chan_list_out. The difference
830 between the *chan_list_out and the tlv_buf start will be used to
831 calculate the size of anything we add in this routine. */
832 scan_cfg_out
->tlv_buf_len
= 0;
834 /* Running tlv pointer. Assigned to chan_list_out at end of function
835 so later routines know where channels can be added to the command
837 tlv_pos
= scan_cfg_out
->tlv_buf
;
839 /* Initialize the scan as un-filtered; the flag is later set to TRUE
840 below if a SSID or BSSID filter is sent in the command */
841 *filtered_scan
= false;
843 /* Initialize the scan as not being only on the current channel. If
844 the channel list is customized, only contains one channel, and is
845 the active channel, this is set true and data flow is not halted. */
846 *scan_current_only
= false;
850 /* Default the ssid_filter flag to TRUE, set false under
851 certain wildcard conditions and qualified by the existence
852 of an SSID list before marking the scan as filtered */
855 /* Set the BSS type scan filter, use Adapter setting if
857 scan_cfg_out
->bss_mode
=
858 (user_scan_in
->bss_mode
? (u8
) user_scan_in
->
859 bss_mode
: (u8
) adapter
->scan_mode
);
861 /* Set the number of probes to send, use Adapter setting
864 (user_scan_in
->num_probes
? user_scan_in
->
865 num_probes
: adapter
->scan_probes
);
868 * Set the BSSID filter to the incoming configuration,
869 * if non-zero. If not set, it will remain disabled
872 memcpy(scan_cfg_out
->specific_bssid
,
873 user_scan_in
->specific_bssid
,
874 sizeof(scan_cfg_out
->specific_bssid
));
876 if (adapter
->ext_scan
&&
877 !is_zero_ether_addr(scan_cfg_out
->specific_bssid
)) {
879 (struct mwifiex_ie_types_bssid_list
*)tlv_pos
;
880 bssid_tlv
->header
.type
= cpu_to_le16(TLV_TYPE_BSSID
);
881 bssid_tlv
->header
.len
= cpu_to_le16(ETH_ALEN
);
882 memcpy(bssid_tlv
->bssid
, user_scan_in
->specific_bssid
,
884 tlv_pos
+= sizeof(struct mwifiex_ie_types_bssid_list
);
887 for (i
= 0; i
< user_scan_in
->num_ssids
; i
++) {
888 ssid_len
= user_scan_in
->ssid_list
[i
].ssid_len
;
891 (struct mwifiex_ie_types_wildcard_ssid_params
*)
893 wildcard_ssid_tlv
->header
.type
=
894 cpu_to_le16(TLV_TYPE_WILDCARDSSID
);
895 wildcard_ssid_tlv
->header
.len
= cpu_to_le16(
896 (u16
) (ssid_len
+ sizeof(wildcard_ssid_tlv
->
900 * max_ssid_length = 0 tells firmware to perform
901 * specific scan for the SSID filled, whereas
902 * max_ssid_length = IEEE80211_MAX_SSID_LEN is for
906 wildcard_ssid_tlv
->max_ssid_length
= 0;
908 wildcard_ssid_tlv
->max_ssid_length
=
909 IEEE80211_MAX_SSID_LEN
;
911 memcpy(wildcard_ssid_tlv
->ssid
,
912 user_scan_in
->ssid_list
[i
].ssid
, ssid_len
);
914 tlv_pos
+= (sizeof(wildcard_ssid_tlv
->header
)
915 + le16_to_cpu(wildcard_ssid_tlv
->header
.len
));
917 mwifiex_dbg(adapter
, INFO
,
918 "info: scan: ssid[%d]: %s, %d\n",
919 i
, wildcard_ssid_tlv
->ssid
,
920 wildcard_ssid_tlv
->max_ssid_length
);
922 /* Empty wildcard ssid with a maxlen will match many or
923 potentially all SSIDs (maxlen == 32), therefore do
924 not treat the scan as
926 if (!ssid_len
&& wildcard_ssid_tlv
->max_ssid_length
)
931 * The default number of channels sent in the command is low to
932 * ensure the response buffer from the firmware does not
933 * truncate scan results. That is not an issue with an SSID
934 * or BSSID filter applied to the scan results in the firmware.
936 if ((i
&& ssid_filter
) ||
937 !is_zero_ether_addr(scan_cfg_out
->specific_bssid
))
938 *filtered_scan
= true;
940 if (user_scan_in
->scan_chan_gap
) {
941 mwifiex_dbg(adapter
, INFO
,
942 "info: scan: channel gap = %d\n",
943 user_scan_in
->scan_chan_gap
);
945 MWIFIEX_MAX_CHANNELS_PER_SPECIFIC_SCAN
;
947 chan_gap_tlv
= (void *)tlv_pos
;
948 chan_gap_tlv
->header
.type
=
949 cpu_to_le16(TLV_TYPE_SCAN_CHANNEL_GAP
);
950 chan_gap_tlv
->header
.len
=
951 cpu_to_le16(sizeof(chan_gap_tlv
->chan_gap
));
952 chan_gap_tlv
->chan_gap
=
953 cpu_to_le16((user_scan_in
->scan_chan_gap
));
955 sizeof(struct mwifiex_ie_types_scan_chan_gap
);
958 scan_cfg_out
->bss_mode
= (u8
) adapter
->scan_mode
;
959 num_probes
= adapter
->scan_probes
;
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.
967 *max_chan_per_scan
= MWIFIEX_MAX_CHANNELS_PER_SPECIFIC_SCAN
;
969 *max_chan_per_scan
= MWIFIEX_DEF_CHANNELS_PER_SCAN_CMD
;
971 /* If the input config or adapter has the number of Probes set,
975 mwifiex_dbg(adapter
, INFO
,
976 "info: scan: num_probes = %d\n",
979 num_probes_tlv
= (struct mwifiex_ie_types_num_probes
*) tlv_pos
;
980 num_probes_tlv
->header
.type
= cpu_to_le16(TLV_TYPE_NUMPROBES
);
981 num_probes_tlv
->header
.len
=
982 cpu_to_le16(sizeof(num_probes_tlv
->num_probes
));
983 num_probes_tlv
->num_probes
= cpu_to_le16((u16
) num_probes
);
985 tlv_pos
+= sizeof(num_probes_tlv
->header
) +
986 le16_to_cpu(num_probes_tlv
->header
.len
);
990 if (ISSUPP_11NENABLED(priv
->adapter
->fw_cap_info
) &&
991 (priv
->adapter
->config_bands
& BAND_GN
||
992 priv
->adapter
->config_bands
& BAND_AN
)) {
993 ht_cap
= (struct mwifiex_ie_types_htcap
*) tlv_pos
;
994 memset(ht_cap
, 0, sizeof(struct mwifiex_ie_types_htcap
));
995 ht_cap
->header
.type
= cpu_to_le16(WLAN_EID_HT_CAPABILITY
);
997 cpu_to_le16(sizeof(struct ieee80211_ht_cap
));
999 mwifiex_band_to_radio_type(priv
->adapter
->config_bands
);
1000 mwifiex_fill_cap_info(priv
, radio_type
, &ht_cap
->ht_cap
);
1001 tlv_pos
+= sizeof(struct mwifiex_ie_types_htcap
);
1004 /* Append vendor specific IE TLV */
1005 mwifiex_cmd_append_vsie_tlv(priv
, MWIFIEX_VSIE_MASK_SCAN
, &tlv_pos
);
1008 * Set the output for the channel TLV to the address in the tlv buffer
1009 * past any TLVs that were added in this function (SSID, num_probes).
1010 * Channel TLVs will be added past this for each scan command,
1011 * preserving the TLVs that were previously added.
1014 (struct mwifiex_ie_types_chan_list_param_set
*) tlv_pos
;
1016 if (user_scan_in
&& user_scan_in
->chan_list
[0].chan_number
) {
1018 mwifiex_dbg(adapter
, INFO
,
1019 "info: Scan: Using supplied channel list\n");
1022 chan_idx
< MWIFIEX_USER_SCAN_CHAN_MAX
&&
1023 user_scan_in
->chan_list
[chan_idx
].chan_number
;
1026 channel
= user_scan_in
->chan_list
[chan_idx
].chan_number
;
1027 (scan_chan_list
+ chan_idx
)->chan_number
= channel
;
1030 user_scan_in
->chan_list
[chan_idx
].radio_type
;
1031 (scan_chan_list
+ chan_idx
)->radio_type
= radio_type
;
1033 scan_type
= user_scan_in
->chan_list
[chan_idx
].scan_type
;
1035 if (scan_type
== MWIFIEX_SCAN_TYPE_PASSIVE
)
1037 chan_idx
)->chan_scan_mode_bitmap
1038 |= MWIFIEX_PASSIVE_SCAN
;
1041 chan_idx
)->chan_scan_mode_bitmap
1042 &= ~MWIFIEX_PASSIVE_SCAN
;
1046 chan_idx
)->chan_scan_mode_bitmap
1047 |= MWIFIEX_DISABLE_CHAN_FILT
;
1049 if (user_scan_in
->chan_list
[chan_idx
].scan_time
) {
1050 scan_dur
= (u16
) user_scan_in
->
1051 chan_list
[chan_idx
].scan_time
;
1053 if (scan_type
== MWIFIEX_SCAN_TYPE_PASSIVE
)
1054 scan_dur
= adapter
->passive_scan_time
;
1055 else if (*filtered_scan
)
1056 scan_dur
= adapter
->specific_scan_time
;
1058 scan_dur
= adapter
->active_scan_time
;
1061 (scan_chan_list
+ chan_idx
)->min_scan_time
=
1062 cpu_to_le16(scan_dur
);
1063 (scan_chan_list
+ chan_idx
)->max_scan_time
=
1064 cpu_to_le16(scan_dur
);
1067 /* Check if we are only scanning the current channel */
1068 if ((chan_idx
== 1) &&
1069 (user_scan_in
->chan_list
[0].chan_number
==
1070 priv
->curr_bss_params
.bss_descriptor
.channel
)) {
1071 *scan_current_only
= true;
1072 mwifiex_dbg(adapter
, INFO
,
1073 "info: Scan: Scanning current channel only\n");
1075 chan_num
= chan_idx
;
1077 mwifiex_dbg(adapter
, INFO
,
1078 "info: Scan: Creating full region channel list\n");
1079 chan_num
= mwifiex_scan_create_channel_list(priv
, user_scan_in
,
1087 * This function inspects the scan response buffer for pointers to
1090 * TLVs can be included at the end of the scan response BSS information.
1092 * Data in the buffer is parsed pointers to TLVs that can potentially
1093 * be passed back in the response.
1096 mwifiex_ret_802_11_scan_get_tlv_ptrs(struct mwifiex_adapter
*adapter
,
1097 struct mwifiex_ie_types_data
*tlv
,
1098 u32 tlv_buf_size
, u32 req_tlv_type
,
1099 struct mwifiex_ie_types_data
**tlv_data
)
1101 struct mwifiex_ie_types_data
*current_tlv
;
1107 tlv_buf_left
= tlv_buf_size
;
1110 mwifiex_dbg(adapter
, INFO
,
1111 "info: SCAN_RESP: tlv_buf_size = %d\n",
1114 while (tlv_buf_left
>= sizeof(struct mwifiex_ie_types_header
)) {
1116 tlv_type
= le16_to_cpu(current_tlv
->header
.type
);
1117 tlv_len
= le16_to_cpu(current_tlv
->header
.len
);
1119 if (sizeof(tlv
->header
) + tlv_len
> tlv_buf_left
) {
1120 mwifiex_dbg(adapter
, ERROR
,
1121 "SCAN_RESP: TLV buffer corrupt\n");
1125 if (req_tlv_type
== tlv_type
) {
1127 case TLV_TYPE_TSFTIMESTAMP
:
1128 mwifiex_dbg(adapter
, INFO
,
1129 "info: SCAN_RESP: TSF\t"
1130 "timestamp TLV, len = %d\n",
1132 *tlv_data
= current_tlv
;
1134 case TLV_TYPE_CHANNELBANDLIST
:
1135 mwifiex_dbg(adapter
, INFO
,
1136 "info: SCAN_RESP: channel\t"
1137 "band list TLV, len = %d\n",
1139 *tlv_data
= current_tlv
;
1142 mwifiex_dbg(adapter
, ERROR
,
1143 "SCAN_RESP: unhandled TLV = %d\n",
1145 /* Give up, this seems corrupted */
1154 tlv_buf_left
-= (sizeof(tlv
->header
) + tlv_len
);
1156 (struct mwifiex_ie_types_data
*) (current_tlv
->data
+
1163 * This function parses provided beacon buffer and updates
1164 * respective fields in bss descriptor structure.
1166 int mwifiex_update_bss_desc_with_ie(struct mwifiex_adapter
*adapter
,
1167 struct mwifiex_bssdescriptor
*bss_entry
)
1171 struct ieee_types_fh_param_set
*fh_param_set
;
1172 struct ieee_types_ds_param_set
*ds_param_set
;
1173 struct ieee_types_cf_param_set
*cf_param_set
;
1174 struct ieee_types_ibss_param_set
*ibss_param_set
;
1181 u8 found_data_rate_ie
;
1183 struct ieee_types_vendor_specific
*vendor_ie
;
1184 const u8 wpa_oui
[4] = { 0x00, 0x50, 0xf2, 0x01 };
1185 const u8 wmm_oui
[4] = { 0x00, 0x50, 0xf2, 0x02 };
1187 found_data_rate_ie
= false;
1189 current_ptr
= bss_entry
->beacon_buf
;
1190 bytes_left
= bss_entry
->beacon_buf_size
;
1192 /* Process variable IE */
1193 while (bytes_left
>= 2) {
1194 element_id
= *current_ptr
;
1195 element_len
= *(current_ptr
+ 1);
1196 total_ie_len
= element_len
+ sizeof(struct ieee_types_header
);
1198 if (bytes_left
< total_ie_len
) {
1199 mwifiex_dbg(adapter
, ERROR
,
1200 "err: InterpretIE: in processing\t"
1201 "IE, bytes left < IE length\n");
1204 switch (element_id
) {
1206 bss_entry
->ssid
.ssid_len
= element_len
;
1207 memcpy(bss_entry
->ssid
.ssid
, (current_ptr
+ 2),
1209 mwifiex_dbg(adapter
, INFO
,
1210 "info: InterpretIE: ssid: %-32s\n",
1211 bss_entry
->ssid
.ssid
);
1214 case WLAN_EID_SUPP_RATES
:
1215 memcpy(bss_entry
->data_rates
, current_ptr
+ 2,
1217 memcpy(bss_entry
->supported_rates
, current_ptr
+ 2,
1219 rate_size
= element_len
;
1220 found_data_rate_ie
= true;
1223 case WLAN_EID_FH_PARAMS
:
1225 (struct ieee_types_fh_param_set
*) current_ptr
;
1226 memcpy(&bss_entry
->phy_param_set
.fh_param_set
,
1228 sizeof(struct ieee_types_fh_param_set
));
1231 case WLAN_EID_DS_PARAMS
:
1233 (struct ieee_types_ds_param_set
*) current_ptr
;
1235 bss_entry
->channel
= ds_param_set
->current_chan
;
1237 memcpy(&bss_entry
->phy_param_set
.ds_param_set
,
1239 sizeof(struct ieee_types_ds_param_set
));
1242 case WLAN_EID_CF_PARAMS
:
1244 (struct ieee_types_cf_param_set
*) current_ptr
;
1245 memcpy(&bss_entry
->ss_param_set
.cf_param_set
,
1247 sizeof(struct ieee_types_cf_param_set
));
1250 case WLAN_EID_IBSS_PARAMS
:
1252 (struct ieee_types_ibss_param_set
*)
1254 memcpy(&bss_entry
->ss_param_set
.ibss_param_set
,
1256 sizeof(struct ieee_types_ibss_param_set
));
1259 case WLAN_EID_ERP_INFO
:
1260 bss_entry
->erp_flags
= *(current_ptr
+ 2);
1263 case WLAN_EID_PWR_CONSTRAINT
:
1264 bss_entry
->local_constraint
= *(current_ptr
+ 2);
1265 bss_entry
->sensed_11h
= true;
1268 case WLAN_EID_CHANNEL_SWITCH
:
1269 bss_entry
->chan_sw_ie_present
= true;
1270 case WLAN_EID_PWR_CAPABILITY
:
1271 case WLAN_EID_TPC_REPORT
:
1272 case WLAN_EID_QUIET
:
1273 bss_entry
->sensed_11h
= true;
1276 case WLAN_EID_EXT_SUPP_RATES
:
1278 * Only process extended supported rate
1279 * if data rate is already found.
1280 * Data rate IE should come before
1281 * extended supported rate IE
1283 if (found_data_rate_ie
) {
1284 if ((element_len
+ rate_size
) >
1285 MWIFIEX_SUPPORTED_RATES
)
1287 (MWIFIEX_SUPPORTED_RATES
-
1290 bytes_to_copy
= element_len
;
1292 rate
= (u8
*) bss_entry
->data_rates
;
1294 memcpy(rate
, current_ptr
+ 2, bytes_to_copy
);
1296 rate
= (u8
*) bss_entry
->supported_rates
;
1298 memcpy(rate
, current_ptr
+ 2, bytes_to_copy
);
1302 case WLAN_EID_VENDOR_SPECIFIC
:
1303 vendor_ie
= (struct ieee_types_vendor_specific
*)
1307 (vendor_ie
->vend_hdr
.oui
, wpa_oui
,
1309 bss_entry
->bcn_wpa_ie
=
1310 (struct ieee_types_vendor_specific
*)
1312 bss_entry
->wpa_offset
= (u16
)
1313 (current_ptr
- bss_entry
->beacon_buf
);
1314 } else if (!memcmp(vendor_ie
->vend_hdr
.oui
, wmm_oui
,
1317 sizeof(struct ieee_types_wmm_parameter
) ||
1319 sizeof(struct ieee_types_wmm_info
))
1321 * Only accept and copy the WMM IE if
1322 * it matches the size expected for the
1323 * WMM Info IE or the WMM Parameter IE.
1325 memcpy((u8
*) &bss_entry
->wmm_ie
,
1326 current_ptr
, total_ie_len
);
1330 bss_entry
->bcn_rsn_ie
=
1331 (struct ieee_types_generic
*) current_ptr
;
1332 bss_entry
->rsn_offset
= (u16
) (current_ptr
-
1333 bss_entry
->beacon_buf
);
1335 case WLAN_EID_BSS_AC_ACCESS_DELAY
:
1336 bss_entry
->bcn_wapi_ie
=
1337 (struct ieee_types_generic
*) current_ptr
;
1338 bss_entry
->wapi_offset
= (u16
) (current_ptr
-
1339 bss_entry
->beacon_buf
);
1341 case WLAN_EID_HT_CAPABILITY
:
1342 bss_entry
->bcn_ht_cap
= (struct ieee80211_ht_cap
*)
1344 sizeof(struct ieee_types_header
));
1345 bss_entry
->ht_cap_offset
= (u16
) (current_ptr
+
1346 sizeof(struct ieee_types_header
) -
1347 bss_entry
->beacon_buf
);
1349 case WLAN_EID_HT_OPERATION
:
1350 bss_entry
->bcn_ht_oper
=
1351 (struct ieee80211_ht_operation
*)(current_ptr
+
1352 sizeof(struct ieee_types_header
));
1353 bss_entry
->ht_info_offset
= (u16
) (current_ptr
+
1354 sizeof(struct ieee_types_header
) -
1355 bss_entry
->beacon_buf
);
1357 case WLAN_EID_VHT_CAPABILITY
:
1358 bss_entry
->disable_11ac
= false;
1359 bss_entry
->bcn_vht_cap
=
1360 (void *)(current_ptr
+
1361 sizeof(struct ieee_types_header
));
1362 bss_entry
->vht_cap_offset
=
1363 (u16
)((u8
*)bss_entry
->bcn_vht_cap
-
1364 bss_entry
->beacon_buf
);
1366 case WLAN_EID_VHT_OPERATION
:
1367 bss_entry
->bcn_vht_oper
=
1368 (void *)(current_ptr
+
1369 sizeof(struct ieee_types_header
));
1370 bss_entry
->vht_info_offset
=
1371 (u16
)((u8
*)bss_entry
->bcn_vht_oper
-
1372 bss_entry
->beacon_buf
);
1374 case WLAN_EID_BSS_COEX_2040
:
1375 bss_entry
->bcn_bss_co_2040
= current_ptr
;
1376 bss_entry
->bss_co_2040_offset
=
1377 (u16
) (current_ptr
- bss_entry
->beacon_buf
);
1379 case WLAN_EID_EXT_CAPABILITY
:
1380 bss_entry
->bcn_ext_cap
= current_ptr
;
1381 bss_entry
->ext_cap_offset
=
1382 (u16
) (current_ptr
- bss_entry
->beacon_buf
);
1384 case WLAN_EID_OPMODE_NOTIF
:
1385 bss_entry
->oper_mode
= (void *)current_ptr
;
1386 bss_entry
->oper_mode_offset
=
1387 (u16
)((u8
*)bss_entry
->oper_mode
-
1388 bss_entry
->beacon_buf
);
1394 current_ptr
+= element_len
+ 2;
1396 /* Need to account for IE ID and IE Len */
1397 bytes_left
-= (element_len
+ 2);
1399 } /* while (bytes_left > 2) */
1404 * This function converts radio type scan parameter to a band configuration
1405 * to be used in join command.
1408 mwifiex_radio_type_to_band(u8 radio_type
)
1410 switch (radio_type
) {
1411 case HostCmd_SCAN_RADIO_TYPE_A
:
1413 case HostCmd_SCAN_RADIO_TYPE_BG
:
1420 * This is an internal function used to start a scan based on an input
1423 * This uses the input user scan configuration information when provided in
1424 * order to send the appropriate scan commands to firmware to populate or
1425 * update the internal driver scan table.
1427 int mwifiex_scan_networks(struct mwifiex_private
*priv
,
1428 const struct mwifiex_user_scan_cfg
*user_scan_in
)
1431 struct mwifiex_adapter
*adapter
= priv
->adapter
;
1432 struct cmd_ctrl_node
*cmd_node
;
1433 union mwifiex_scan_cmd_config_tlv
*scan_cfg_out
;
1434 struct mwifiex_ie_types_chan_list_param_set
*chan_list_out
;
1435 struct mwifiex_chan_scan_param_set
*scan_chan_list
;
1437 u8 scan_current_chan_only
;
1438 u8 max_chan_per_scan
;
1439 unsigned long flags
;
1441 if (adapter
->scan_processing
) {
1442 mwifiex_dbg(adapter
, WARN
,
1443 "cmd: Scan already in process...\n");
1447 if (priv
->scan_block
) {
1448 mwifiex_dbg(adapter
, WARN
,
1449 "cmd: Scan is blocked during association...\n");
1453 if (adapter
->surprise_removed
|| adapter
->is_cmd_timedout
) {
1454 mwifiex_dbg(adapter
, ERROR
,
1455 "Ignore scan. Card removed or firmware in bad state\n");
1459 spin_lock_irqsave(&adapter
->mwifiex_cmd_lock
, flags
);
1460 adapter
->scan_processing
= true;
1461 spin_unlock_irqrestore(&adapter
->mwifiex_cmd_lock
, flags
);
1463 scan_cfg_out
= kzalloc(sizeof(union mwifiex_scan_cmd_config_tlv
),
1465 if (!scan_cfg_out
) {
1470 scan_chan_list
= kcalloc(MWIFIEX_USER_SCAN_CHAN_MAX
,
1471 sizeof(struct mwifiex_chan_scan_param_set
),
1473 if (!scan_chan_list
) {
1474 kfree(scan_cfg_out
);
1479 mwifiex_config_scan(priv
, user_scan_in
, &scan_cfg_out
->config
,
1480 &chan_list_out
, scan_chan_list
, &max_chan_per_scan
,
1481 &filtered_scan
, &scan_current_chan_only
);
1483 ret
= mwifiex_scan_channel_list(priv
, max_chan_per_scan
, filtered_scan
,
1484 &scan_cfg_out
->config
, chan_list_out
,
1487 /* Get scan command from scan_pending_q and put to cmd_pending_q */
1489 spin_lock_irqsave(&adapter
->scan_pending_q_lock
, flags
);
1490 if (!list_empty(&adapter
->scan_pending_q
)) {
1491 cmd_node
= list_first_entry(&adapter
->scan_pending_q
,
1492 struct cmd_ctrl_node
, list
);
1493 list_del(&cmd_node
->list
);
1494 spin_unlock_irqrestore(&adapter
->scan_pending_q_lock
,
1496 mwifiex_insert_cmd_to_pending_q(adapter
, cmd_node
,
1498 queue_work(adapter
->workqueue
, &adapter
->main_work
);
1500 /* Perform internal scan synchronously */
1501 if (!priv
->scan_request
) {
1502 mwifiex_dbg(adapter
, INFO
,
1503 "wait internal scan\n");
1504 mwifiex_wait_queue_complete(adapter
, cmd_node
);
1507 spin_unlock_irqrestore(&adapter
->scan_pending_q_lock
,
1512 kfree(scan_cfg_out
);
1513 kfree(scan_chan_list
);
1516 spin_lock_irqsave(&adapter
->mwifiex_cmd_lock
, flags
);
1517 adapter
->scan_processing
= false;
1518 spin_unlock_irqrestore(&adapter
->mwifiex_cmd_lock
, flags
);
1524 * This function prepares a scan command to be sent to the firmware.
1526 * This uses the scan command configuration sent to the command processing
1527 * module in command preparation stage to configure a scan command structure
1528 * to send to firmware.
1530 * The fixed fields specifying the BSS type and BSSID filters as well as a
1531 * variable number/length of TLVs are sent in the command to firmware.
1533 * Preparation also includes -
1534 * - Setting command ID, and proper size
1535 * - Ensuring correct endian-ness
1537 int mwifiex_cmd_802_11_scan(struct host_cmd_ds_command
*cmd
,
1538 struct mwifiex_scan_cmd_config
*scan_cfg
)
1540 struct host_cmd_ds_802_11_scan
*scan_cmd
= &cmd
->params
.scan
;
1542 /* Set fixed field variables in scan command */
1543 scan_cmd
->bss_mode
= scan_cfg
->bss_mode
;
1544 memcpy(scan_cmd
->bssid
, scan_cfg
->specific_bssid
,
1545 sizeof(scan_cmd
->bssid
));
1546 memcpy(scan_cmd
->tlv_buffer
, scan_cfg
->tlv_buf
, scan_cfg
->tlv_buf_len
);
1548 cmd
->command
= cpu_to_le16(HostCmd_CMD_802_11_SCAN
);
1550 /* Size is equal to the sizeof(fixed portions) + the TLV len + header */
1551 cmd
->size
= cpu_to_le16((u16
) (sizeof(scan_cmd
->bss_mode
)
1552 + sizeof(scan_cmd
->bssid
)
1553 + scan_cfg
->tlv_buf_len
+ S_DS_GEN
));
1559 * This function checks compatibility of requested network with current
1562 int mwifiex_check_network_compatibility(struct mwifiex_private
*priv
,
1563 struct mwifiex_bssdescriptor
*bss_desc
)
1570 if ((mwifiex_get_cfp(priv
, (u8
) bss_desc
->bss_band
,
1571 (u16
) bss_desc
->channel
, 0))) {
1572 switch (priv
->bss_mode
) {
1573 case NL80211_IFTYPE_STATION
:
1574 case NL80211_IFTYPE_ADHOC
:
1575 ret
= mwifiex_is_network_compatible(priv
, bss_desc
,
1578 mwifiex_dbg(priv
->adapter
, ERROR
,
1579 "Incompatible network settings\n");
1589 static int mwifiex_update_curr_bss_params(struct mwifiex_private
*priv
,
1590 struct cfg80211_bss
*bss
)
1592 struct mwifiex_bssdescriptor
*bss_desc
;
1594 unsigned long flags
;
1596 /* Allocate and fill new bss descriptor */
1597 bss_desc
= kzalloc(sizeof(struct mwifiex_bssdescriptor
), GFP_KERNEL
);
1601 ret
= mwifiex_fill_new_bss_desc(priv
, bss
, bss_desc
);
1605 ret
= mwifiex_check_network_compatibility(priv
, bss_desc
);
1609 spin_lock_irqsave(&priv
->curr_bcn_buf_lock
, flags
);
1610 /* Make a copy of current BSSID descriptor */
1611 memcpy(&priv
->curr_bss_params
.bss_descriptor
, bss_desc
,
1612 sizeof(priv
->curr_bss_params
.bss_descriptor
));
1614 /* The contents of beacon_ie will be copied to its own buffer
1615 * in mwifiex_save_curr_bcn()
1617 mwifiex_save_curr_bcn(priv
);
1618 spin_unlock_irqrestore(&priv
->curr_bcn_buf_lock
, flags
);
1621 /* beacon_ie buffer was allocated in function
1622 * mwifiex_fill_new_bss_desc(). Free it now.
1624 kfree(bss_desc
->beacon_buf
);
1630 mwifiex_parse_single_response_buf(struct mwifiex_private
*priv
, u8
**bss_info
,
1631 u32
*bytes_left
, u64 fw_tsf
, u8
*radio_type
,
1632 bool ext_scan
, s32 rssi_val
)
1634 struct mwifiex_adapter
*adapter
= priv
->adapter
;
1635 struct mwifiex_chan_freq_power
*cfp
;
1636 struct cfg80211_bss
*bss
;
1642 u16 beacon_size
= 0;
1646 u16 cap_info_bitmap
;
1649 struct mwifiex_fixed_bcn_param
*bcn_param
;
1650 struct mwifiex_bss_priv
*bss_priv
;
1652 if (*bytes_left
>= sizeof(beacon_size
)) {
1653 /* Extract & convert beacon size from command buffer */
1654 beacon_size
= le16_to_cpu(*(__le16
*)(*bss_info
));
1655 *bytes_left
-= sizeof(beacon_size
);
1656 *bss_info
+= sizeof(beacon_size
);
1659 if (!beacon_size
|| beacon_size
> *bytes_left
) {
1660 *bss_info
+= *bytes_left
;
1665 /* Initialize the current working beacon pointer for this BSS
1668 current_ptr
= *bss_info
;
1670 /* Advance the return beacon pointer past the current beacon */
1671 *bss_info
+= beacon_size
;
1672 *bytes_left
-= beacon_size
;
1674 curr_bcn_bytes
= beacon_size
;
1676 /* First 5 fields are bssid, RSSI(for legacy scan only),
1677 * time stamp, beacon interval, and capability information
1679 if (curr_bcn_bytes
< ETH_ALEN
+ sizeof(u8
) +
1680 sizeof(struct mwifiex_fixed_bcn_param
)) {
1681 mwifiex_dbg(adapter
, ERROR
,
1682 "InterpretIE: not enough bytes left\n");
1686 memcpy(bssid
, current_ptr
, ETH_ALEN
);
1687 current_ptr
+= ETH_ALEN
;
1688 curr_bcn_bytes
-= ETH_ALEN
;
1691 rssi
= (s32
) *current_ptr
;
1692 rssi
= (-rssi
) * 100; /* Convert dBm to mBm */
1693 current_ptr
+= sizeof(u8
);
1694 curr_bcn_bytes
-= sizeof(u8
);
1695 mwifiex_dbg(adapter
, INFO
,
1696 "info: InterpretIE: RSSI=%d\n", rssi
);
1701 bcn_param
= (struct mwifiex_fixed_bcn_param
*)current_ptr
;
1702 current_ptr
+= sizeof(*bcn_param
);
1703 curr_bcn_bytes
-= sizeof(*bcn_param
);
1705 timestamp
= le64_to_cpu(bcn_param
->timestamp
);
1706 beacon_period
= le16_to_cpu(bcn_param
->beacon_period
);
1708 cap_info_bitmap
= le16_to_cpu(bcn_param
->cap_info_bitmap
);
1709 mwifiex_dbg(adapter
, INFO
,
1710 "info: InterpretIE: capabilities=0x%X\n",
1713 /* Rest of the current buffer are IE's */
1714 ie_buf
= current_ptr
;
1715 ie_len
= curr_bcn_bytes
;
1716 mwifiex_dbg(adapter
, INFO
,
1717 "info: InterpretIE: IELength for this AP = %d\n",
1720 while (curr_bcn_bytes
>= sizeof(struct ieee_types_header
)) {
1721 u8 element_id
, element_len
;
1723 element_id
= *current_ptr
;
1724 element_len
= *(current_ptr
+ 1);
1725 if (curr_bcn_bytes
< element_len
+
1726 sizeof(struct ieee_types_header
)) {
1727 mwifiex_dbg(adapter
, ERROR
,
1728 "%s: bytes left < IE length\n", __func__
);
1731 if (element_id
== WLAN_EID_DS_PARAMS
) {
1732 channel
= *(current_ptr
+
1733 sizeof(struct ieee_types_header
));
1737 current_ptr
+= element_len
+ sizeof(struct ieee_types_header
);
1738 curr_bcn_bytes
-= element_len
+
1739 sizeof(struct ieee_types_header
);
1743 struct ieee80211_channel
*chan
;
1746 /* Skip entry if on csa closed channel */
1747 if (channel
== priv
->csa_chan
) {
1748 mwifiex_dbg(adapter
, WARN
,
1749 "Dropping entry on csa closed channel\n");
1755 band
= mwifiex_radio_type_to_band(*radio_type
&
1758 cfp
= mwifiex_get_cfp(priv
, band
, channel
, 0);
1760 freq
= cfp
? cfp
->freq
: 0;
1762 chan
= ieee80211_get_channel(priv
->wdev
.wiphy
, freq
);
1764 if (chan
&& !(chan
->flags
& IEEE80211_CHAN_DISABLED
)) {
1765 bss
= cfg80211_inform_bss(priv
->wdev
.wiphy
,
1766 chan
, CFG80211_BSS_FTYPE_UNKNOWN
,
1768 cap_info_bitmap
, beacon_period
,
1769 ie_buf
, ie_len
, rssi
, GFP_KERNEL
);
1770 bss_priv
= (struct mwifiex_bss_priv
*)bss
->priv
;
1771 bss_priv
->band
= band
;
1772 bss_priv
->fw_tsf
= fw_tsf
;
1773 if (priv
->media_connected
&&
1774 !memcmp(bssid
, priv
->curr_bss_params
.bss_descriptor
1775 .mac_address
, ETH_ALEN
))
1776 mwifiex_update_curr_bss_params(priv
, bss
);
1777 cfg80211_put_bss(priv
->wdev
.wiphy
, bss
);
1780 mwifiex_dbg(adapter
, WARN
, "missing BSS channel IE\n");
1786 static void mwifiex_complete_scan(struct mwifiex_private
*priv
)
1788 struct mwifiex_adapter
*adapter
= priv
->adapter
;
1790 adapter
->survey_idx
= 0;
1791 if (adapter
->curr_cmd
->wait_q_enabled
) {
1792 adapter
->cmd_wait_q
.status
= 0;
1793 if (!priv
->scan_request
) {
1794 mwifiex_dbg(adapter
, INFO
,
1795 "complete internal scan\n");
1796 mwifiex_complete_cmd(adapter
, adapter
->curr_cmd
);
1801 static void mwifiex_check_next_scan_command(struct mwifiex_private
*priv
)
1803 struct mwifiex_adapter
*adapter
= priv
->adapter
;
1804 struct cmd_ctrl_node
*cmd_node
, *tmp_node
;
1805 unsigned long flags
;
1807 spin_lock_irqsave(&adapter
->scan_pending_q_lock
, flags
);
1808 if (list_empty(&adapter
->scan_pending_q
)) {
1809 spin_unlock_irqrestore(&adapter
->scan_pending_q_lock
, flags
);
1810 spin_lock_irqsave(&adapter
->mwifiex_cmd_lock
, flags
);
1811 adapter
->scan_processing
= false;
1812 spin_unlock_irqrestore(&adapter
->mwifiex_cmd_lock
, flags
);
1814 if (!adapter
->ext_scan
)
1815 mwifiex_complete_scan(priv
);
1817 if (priv
->scan_request
) {
1818 mwifiex_dbg(adapter
, INFO
,
1819 "info: notifying scan done\n");
1820 cfg80211_scan_done(priv
->scan_request
, 0);
1821 priv
->scan_request
= NULL
;
1823 priv
->scan_aborting
= false;
1824 mwifiex_dbg(adapter
, INFO
,
1825 "info: scan already aborted\n");
1827 } else if ((priv
->scan_aborting
&& !priv
->scan_request
) ||
1829 list_for_each_entry_safe(cmd_node
, tmp_node
,
1830 &adapter
->scan_pending_q
, list
) {
1831 list_del(&cmd_node
->list
);
1832 mwifiex_insert_cmd_to_free_q(adapter
, cmd_node
);
1834 spin_unlock_irqrestore(&adapter
->scan_pending_q_lock
, flags
);
1836 spin_lock_irqsave(&adapter
->mwifiex_cmd_lock
, flags
);
1837 adapter
->scan_processing
= false;
1838 spin_unlock_irqrestore(&adapter
->mwifiex_cmd_lock
, flags
);
1840 if (priv
->scan_request
) {
1841 mwifiex_dbg(adapter
, INFO
,
1842 "info: aborting scan\n");
1843 cfg80211_scan_done(priv
->scan_request
, 1);
1844 priv
->scan_request
= NULL
;
1846 priv
->scan_aborting
= false;
1847 mwifiex_dbg(adapter
, INFO
,
1848 "info: scan already aborted\n");
1851 /* Get scan command from scan_pending_q and put to
1854 cmd_node
= list_first_entry(&adapter
->scan_pending_q
,
1855 struct cmd_ctrl_node
, list
);
1856 list_del(&cmd_node
->list
);
1857 spin_unlock_irqrestore(&adapter
->scan_pending_q_lock
, flags
);
1858 mwifiex_insert_cmd_to_pending_q(adapter
, cmd_node
, true);
1865 * This function handles the command response of scan.
1867 * The response buffer for the scan command has the following
1870 * .-------------------------------------------------------------.
1871 * | Header (4 * sizeof(t_u16)): Standard command response hdr |
1872 * .-------------------------------------------------------------.
1873 * | BufSize (t_u16) : sizeof the BSS Description data |
1874 * .-------------------------------------------------------------.
1875 * | NumOfSet (t_u8) : Number of BSS Descs returned |
1876 * .-------------------------------------------------------------.
1877 * | BSSDescription data (variable, size given in BufSize) |
1878 * .-------------------------------------------------------------.
1879 * | TLV data (variable, size calculated using Header->Size, |
1880 * | BufSize and sizeof the fixed fields above) |
1881 * .-------------------------------------------------------------.
1883 int mwifiex_ret_802_11_scan(struct mwifiex_private
*priv
,
1884 struct host_cmd_ds_command
*resp
)
1887 struct mwifiex_adapter
*adapter
= priv
->adapter
;
1888 struct host_cmd_ds_802_11_scan_rsp
*scan_rsp
;
1889 struct mwifiex_ie_types_data
*tlv_data
;
1890 struct mwifiex_ie_types_tsf_timestamp
*tsf_tlv
;
1896 struct mwifiex_ie_types_chan_band_list_param_set
*chan_band_tlv
;
1897 struct chan_band_param_set
*chan_band
;
1902 is_bgscan_resp
= (le16_to_cpu(resp
->command
)
1903 == HostCmd_CMD_802_11_BG_SCAN_QUERY
);
1905 scan_rsp
= &resp
->params
.bg_scan_query_resp
.scan_resp
;
1907 scan_rsp
= &resp
->params
.scan_resp
;
1910 if (scan_rsp
->number_of_sets
> MWIFIEX_MAX_AP
) {
1911 mwifiex_dbg(adapter
, ERROR
,
1912 "SCAN_RESP: too many AP returned (%d)\n",
1913 scan_rsp
->number_of_sets
);
1915 goto check_next_scan
;
1918 /* Check csa channel expiry before parsing scan response */
1919 mwifiex_11h_get_csa_closed_channel(priv
);
1921 bytes_left
= le16_to_cpu(scan_rsp
->bss_descript_size
);
1922 mwifiex_dbg(adapter
, INFO
,
1923 "info: SCAN_RESP: bss_descript_size %d\n",
1926 scan_resp_size
= le16_to_cpu(resp
->size
);
1928 mwifiex_dbg(adapter
, INFO
,
1929 "info: SCAN_RESP: returned %d APs before parsing\n",
1930 scan_rsp
->number_of_sets
);
1932 bss_info
= scan_rsp
->bss_desc_and_tlv_buffer
;
1935 * The size of the TLV buffer is equal to the entire command response
1936 * size (scan_resp_size) minus the fixed fields (sizeof()'s), the
1937 * BSS Descriptions (bss_descript_size as bytesLef) and the command
1938 * response header (S_DS_GEN)
1940 tlv_buf_size
= scan_resp_size
- (bytes_left
1941 + sizeof(scan_rsp
->bss_descript_size
)
1942 + sizeof(scan_rsp
->number_of_sets
)
1945 tlv_data
= (struct mwifiex_ie_types_data
*) (scan_rsp
->
1946 bss_desc_and_tlv_buffer
+
1949 /* Search the TLV buffer space in the scan response for any valid
1951 mwifiex_ret_802_11_scan_get_tlv_ptrs(adapter
, tlv_data
, tlv_buf_size
,
1952 TLV_TYPE_TSFTIMESTAMP
,
1953 (struct mwifiex_ie_types_data
**)
1956 /* Search the TLV buffer space in the scan response for any valid
1958 mwifiex_ret_802_11_scan_get_tlv_ptrs(adapter
, tlv_data
, tlv_buf_size
,
1959 TLV_TYPE_CHANNELBANDLIST
,
1960 (struct mwifiex_ie_types_data
**)
1963 for (idx
= 0; idx
< scan_rsp
->number_of_sets
&& bytes_left
; idx
++) {
1965 * If the TSF TLV was appended to the scan results, save this
1966 * entry's TSF value in the fw_tsf field. It is the firmware's
1967 * TSF value at the time the beacon or probe response was
1971 memcpy(&fw_tsf
, &tsf_tlv
->tsf_data
[idx
* TSF_DATA_SIZE
],
1974 if (chan_band_tlv
) {
1975 chan_band
= &chan_band_tlv
->chan_band_param
[idx
];
1976 radio_type
= &chan_band
->radio_type
;
1981 ret
= mwifiex_parse_single_response_buf(priv
, &bss_info
,
1983 le64_to_cpu(fw_tsf
),
1984 radio_type
, false, 0);
1986 goto check_next_scan
;
1990 mwifiex_check_next_scan_command(priv
);
1995 * This function prepares an extended scan command to be sent to the firmware
1997 * This uses the scan command configuration sent to the command processing
1998 * module in command preparation stage to configure a extended scan command
1999 * structure to send to firmware.
2001 int mwifiex_cmd_802_11_scan_ext(struct mwifiex_private
*priv
,
2002 struct host_cmd_ds_command
*cmd
,
2005 struct host_cmd_ds_802_11_scan_ext
*ext_scan
= &cmd
->params
.ext_scan
;
2006 struct mwifiex_scan_cmd_config
*scan_cfg
= data_buf
;
2008 memcpy(ext_scan
->tlv_buffer
, scan_cfg
->tlv_buf
, scan_cfg
->tlv_buf_len
);
2010 cmd
->command
= cpu_to_le16(HostCmd_CMD_802_11_SCAN_EXT
);
2012 /* Size is equal to the sizeof(fixed portions) + the TLV len + header */
2013 cmd
->size
= cpu_to_le16((u16
)(sizeof(ext_scan
->reserved
)
2014 + scan_cfg
->tlv_buf_len
+ S_DS_GEN
));
2020 mwifiex_update_chan_statistics(struct mwifiex_private
*priv
,
2021 struct mwifiex_ietypes_chanstats
*tlv_stat
)
2023 struct mwifiex_adapter
*adapter
= priv
->adapter
;
2025 struct mwifiex_fw_chan_stats
*fw_chan_stats
;
2026 struct mwifiex_chan_stats chan_stats
;
2028 fw_chan_stats
= (void *)((u8
*)tlv_stat
+
2029 sizeof(struct mwifiex_ie_types_header
));
2030 num_chan
= le16_to_cpu(tlv_stat
->header
.len
) /
2031 sizeof(struct mwifiex_chan_stats
);
2033 for (i
= 0 ; i
< num_chan
; i
++) {
2034 chan_stats
.chan_num
= fw_chan_stats
->chan_num
;
2035 chan_stats
.bandcfg
= fw_chan_stats
->bandcfg
;
2036 chan_stats
.flags
= fw_chan_stats
->flags
;
2037 chan_stats
.noise
= fw_chan_stats
->noise
;
2038 chan_stats
.total_bss
= le16_to_cpu(fw_chan_stats
->total_bss
);
2039 chan_stats
.cca_scan_dur
=
2040 le16_to_cpu(fw_chan_stats
->cca_scan_dur
);
2041 chan_stats
.cca_busy_dur
=
2042 le16_to_cpu(fw_chan_stats
->cca_busy_dur
);
2043 mwifiex_dbg(adapter
, INFO
,
2044 "chan=%d, noise=%d, total_network=%d scan_duration=%d, busy_duration=%d\n",
2045 chan_stats
.chan_num
,
2047 chan_stats
.total_bss
,
2048 chan_stats
.cca_scan_dur
,
2049 chan_stats
.cca_busy_dur
);
2050 memcpy(&adapter
->chan_stats
[adapter
->survey_idx
++], &chan_stats
,
2051 sizeof(struct mwifiex_chan_stats
));
2056 /* This function handles the command response of extended scan */
2057 int mwifiex_ret_802_11_scan_ext(struct mwifiex_private
*priv
,
2058 struct host_cmd_ds_command
*resp
)
2060 struct mwifiex_adapter
*adapter
= priv
->adapter
;
2061 struct host_cmd_ds_802_11_scan_ext
*ext_scan_resp
;
2062 struct mwifiex_ie_types_header
*tlv
;
2063 struct mwifiex_ietypes_chanstats
*tlv_stat
;
2064 u16 buf_left
, type
, len
;
2066 struct host_cmd_ds_command
*cmd_ptr
;
2067 struct cmd_ctrl_node
*cmd_node
;
2068 unsigned long cmd_flags
, scan_flags
;
2069 bool complete_scan
= false;
2071 mwifiex_dbg(adapter
, INFO
, "info: EXT scan returns successfully\n");
2073 ext_scan_resp
= &resp
->params
.ext_scan
;
2075 tlv
= (void *)ext_scan_resp
->tlv_buffer
;
2076 buf_left
= le16_to_cpu(resp
->size
) - (sizeof(*ext_scan_resp
) + S_DS_GEN
2079 while (buf_left
>= sizeof(struct mwifiex_ie_types_header
)) {
2080 type
= le16_to_cpu(tlv
->type
);
2081 len
= le16_to_cpu(tlv
->len
);
2083 if (buf_left
< (sizeof(struct mwifiex_ie_types_header
) + len
)) {
2084 mwifiex_dbg(adapter
, ERROR
,
2085 "error processing scan response TLVs");
2090 case TLV_TYPE_CHANNEL_STATS
:
2091 tlv_stat
= (void *)tlv
;
2092 mwifiex_update_chan_statistics(priv
, tlv_stat
);
2098 buf_left
-= len
+ sizeof(struct mwifiex_ie_types_header
);
2099 tlv
= (void *)((u8
*)tlv
+ len
+
2100 sizeof(struct mwifiex_ie_types_header
));
2103 spin_lock_irqsave(&adapter
->cmd_pending_q_lock
, cmd_flags
);
2104 spin_lock_irqsave(&adapter
->scan_pending_q_lock
, scan_flags
);
2105 if (list_empty(&adapter
->scan_pending_q
)) {
2106 complete_scan
= true;
2107 list_for_each_entry(cmd_node
, &adapter
->cmd_pending_q
, list
) {
2108 cmd_ptr
= (void *)cmd_node
->cmd_skb
->data
;
2109 if (le16_to_cpu(cmd_ptr
->command
) ==
2110 HostCmd_CMD_802_11_SCAN_EXT
) {
2111 mwifiex_dbg(adapter
, INFO
,
2112 "Scan pending in command pending list");
2113 complete_scan
= false;
2118 spin_unlock_irqrestore(&adapter
->scan_pending_q_lock
, scan_flags
);
2119 spin_unlock_irqrestore(&adapter
->cmd_pending_q_lock
, cmd_flags
);
2122 mwifiex_complete_scan(priv
);
2127 /* This function This function handles the event extended scan report. It
2128 * parses extended scan results and informs to cfg80211 stack.
2130 int mwifiex_handle_event_ext_scan_report(struct mwifiex_private
*priv
,
2134 struct mwifiex_adapter
*adapter
= priv
->adapter
;
2136 u32 bytes_left
, bytes_left_for_tlv
, idx
;
2138 struct mwifiex_ie_types_data
*tlv
;
2139 struct mwifiex_ie_types_bss_scan_rsp
*scan_rsp_tlv
;
2140 struct mwifiex_ie_types_bss_scan_info
*scan_info_tlv
;
2144 struct mwifiex_event_scan_result
*event_scan
= buf
;
2145 u8 num_of_set
= event_scan
->num_of_set
;
2146 u8
*scan_resp
= buf
+ sizeof(struct mwifiex_event_scan_result
);
2147 u16 scan_resp_size
= le16_to_cpu(event_scan
->buf_size
);
2149 if (num_of_set
> MWIFIEX_MAX_AP
) {
2150 mwifiex_dbg(adapter
, ERROR
,
2151 "EXT_SCAN: Invalid number of AP returned (%d)!!\n",
2154 goto check_next_scan
;
2157 bytes_left
= scan_resp_size
;
2158 mwifiex_dbg(adapter
, INFO
,
2159 "EXT_SCAN: size %d, returned %d APs...",
2160 scan_resp_size
, num_of_set
);
2161 mwifiex_dbg_dump(adapter
, CMD_D
, "EXT_SCAN buffer:", buf
,
2163 sizeof(struct mwifiex_event_scan_result
));
2165 tlv
= (struct mwifiex_ie_types_data
*)scan_resp
;
2167 for (idx
= 0; idx
< num_of_set
&& bytes_left
; idx
++) {
2168 type
= le16_to_cpu(tlv
->header
.type
);
2169 len
= le16_to_cpu(tlv
->header
.len
);
2170 if (bytes_left
< sizeof(struct mwifiex_ie_types_header
) + len
) {
2171 mwifiex_dbg(adapter
, ERROR
,
2172 "EXT_SCAN: Error bytes left < TLV length\n");
2175 scan_rsp_tlv
= NULL
;
2176 scan_info_tlv
= NULL
;
2177 bytes_left_for_tlv
= bytes_left
;
2179 /* BSS response TLV with beacon or probe response buffer
2180 * at the initial position of each descriptor
2182 if (type
!= TLV_TYPE_BSS_SCAN_RSP
)
2185 bss_info
= (u8
*)tlv
;
2186 scan_rsp_tlv
= (struct mwifiex_ie_types_bss_scan_rsp
*)tlv
;
2187 tlv
= (struct mwifiex_ie_types_data
*)(tlv
->data
+ len
);
2188 bytes_left_for_tlv
-=
2189 (len
+ sizeof(struct mwifiex_ie_types_header
));
2191 while (bytes_left_for_tlv
>=
2192 sizeof(struct mwifiex_ie_types_header
) &&
2193 le16_to_cpu(tlv
->header
.type
) != TLV_TYPE_BSS_SCAN_RSP
) {
2194 type
= le16_to_cpu(tlv
->header
.type
);
2195 len
= le16_to_cpu(tlv
->header
.len
);
2196 if (bytes_left_for_tlv
<
2197 sizeof(struct mwifiex_ie_types_header
) + len
) {
2198 mwifiex_dbg(adapter
, ERROR
,
2199 "EXT_SCAN: Error in processing TLV,\t"
2200 "bytes left < TLV length\n");
2201 scan_rsp_tlv
= NULL
;
2202 bytes_left_for_tlv
= 0;
2206 case TLV_TYPE_BSS_SCAN_INFO
:
2208 (struct mwifiex_ie_types_bss_scan_info
*)tlv
;
2210 sizeof(struct mwifiex_ie_types_bss_scan_info
) -
2211 sizeof(struct mwifiex_ie_types_header
)) {
2212 bytes_left_for_tlv
= 0;
2219 tlv
= (struct mwifiex_ie_types_data
*)(tlv
->data
+ len
);
2221 (len
+ sizeof(struct mwifiex_ie_types_header
));
2222 bytes_left_for_tlv
-=
2223 (len
+ sizeof(struct mwifiex_ie_types_header
));
2229 /* Advance pointer to the beacon buffer length and
2230 * update the bytes count so that the function
2231 * wlan_interpret_bss_desc_with_ie() can handle the
2232 * scan buffer withut any change
2234 bss_info
+= sizeof(u16
);
2235 bytes_left
-= sizeof(u16
);
2237 if (scan_info_tlv
) {
2238 rssi
= (s32
)(s16
)(le16_to_cpu(scan_info_tlv
->rssi
));
2239 rssi
*= 100; /* Convert dBm to mBm */
2240 mwifiex_dbg(adapter
, INFO
,
2241 "info: InterpretIE: RSSI=%d\n", rssi
);
2242 fw_tsf
= le64_to_cpu(scan_info_tlv
->tsf
);
2243 radio_type
= &scan_info_tlv
->radio_type
;
2247 ret
= mwifiex_parse_single_response_buf(priv
, &bss_info
,
2248 &bytes_left
, fw_tsf
,
2249 radio_type
, true, rssi
);
2251 goto check_next_scan
;
2255 if (!event_scan
->more_event
)
2256 mwifiex_check_next_scan_command(priv
);
2262 * This function prepares command for background scan query.
2264 * Preparation includes -
2265 * - Setting command ID and proper size
2266 * - Setting background scan flush parameter
2267 * - Ensuring correct endian-ness
2269 int mwifiex_cmd_802_11_bg_scan_query(struct host_cmd_ds_command
*cmd
)
2271 struct host_cmd_ds_802_11_bg_scan_query
*bg_query
=
2272 &cmd
->params
.bg_scan_query
;
2274 cmd
->command
= cpu_to_le16(HostCmd_CMD_802_11_BG_SCAN_QUERY
);
2275 cmd
->size
= cpu_to_le16(sizeof(struct host_cmd_ds_802_11_bg_scan_query
)
2278 bg_query
->flush
= 1;
2284 * This function inserts scan command node to the scan pending queue.
2287 mwifiex_queue_scan_cmd(struct mwifiex_private
*priv
,
2288 struct cmd_ctrl_node
*cmd_node
)
2290 struct mwifiex_adapter
*adapter
= priv
->adapter
;
2291 unsigned long flags
;
2293 cmd_node
->wait_q_enabled
= true;
2294 cmd_node
->condition
= &adapter
->scan_wait_q_woken
;
2295 spin_lock_irqsave(&adapter
->scan_pending_q_lock
, flags
);
2296 list_add_tail(&cmd_node
->list
, &adapter
->scan_pending_q
);
2297 spin_unlock_irqrestore(&adapter
->scan_pending_q_lock
, flags
);
2301 * This function sends a scan command for all available channels to the
2302 * firmware, filtered on a specific SSID.
2304 static int mwifiex_scan_specific_ssid(struct mwifiex_private
*priv
,
2305 struct cfg80211_ssid
*req_ssid
)
2307 struct mwifiex_adapter
*adapter
= priv
->adapter
;
2309 struct mwifiex_user_scan_cfg
*scan_cfg
;
2311 if (adapter
->scan_processing
) {
2312 mwifiex_dbg(adapter
, WARN
,
2313 "cmd: Scan already in process...\n");
2317 if (priv
->scan_block
) {
2318 mwifiex_dbg(adapter
, WARN
,
2319 "cmd: Scan is blocked during association...\n");
2323 scan_cfg
= kzalloc(sizeof(struct mwifiex_user_scan_cfg
), GFP_KERNEL
);
2327 scan_cfg
->ssid_list
= req_ssid
;
2328 scan_cfg
->num_ssids
= 1;
2330 ret
= mwifiex_scan_networks(priv
, scan_cfg
);
2337 * Sends IOCTL request to start a scan.
2339 * This function allocates the IOCTL request buffer, fills it
2340 * with requisite parameters and calls the IOCTL handler.
2342 * Scan command can be issued for both normal scan and specific SSID
2343 * scan, depending upon whether an SSID is provided or not.
2345 int mwifiex_request_scan(struct mwifiex_private
*priv
,
2346 struct cfg80211_ssid
*req_ssid
)
2350 if (down_interruptible(&priv
->async_sem
)) {
2351 mwifiex_dbg(priv
->adapter
, ERROR
,
2352 "%s: acquire semaphore fail\n",
2357 priv
->adapter
->scan_wait_q_woken
= false;
2359 if (req_ssid
&& req_ssid
->ssid_len
!= 0)
2360 /* Specific SSID scan */
2361 ret
= mwifiex_scan_specific_ssid(priv
, req_ssid
);
2364 ret
= mwifiex_scan_networks(priv
, NULL
);
2366 up(&priv
->async_sem
);
2372 * This function appends the vendor specific IE TLV to a buffer.
2375 mwifiex_cmd_append_vsie_tlv(struct mwifiex_private
*priv
,
2376 u16 vsie_mask
, u8
**buffer
)
2378 int id
, ret_len
= 0;
2379 struct mwifiex_ie_types_vendor_param_set
*vs_param_set
;
2387 * Traverse through the saved vendor specific IE array and append
2388 * the selected(scan/assoc/adhoc) IE as TLV to the command
2390 for (id
= 0; id
< MWIFIEX_MAX_VSIE_NUM
; id
++) {
2391 if (priv
->vs_ie
[id
].mask
& vsie_mask
) {
2393 (struct mwifiex_ie_types_vendor_param_set
*)
2395 vs_param_set
->header
.type
=
2396 cpu_to_le16(TLV_TYPE_PASSTHROUGH
);
2397 vs_param_set
->header
.len
=
2398 cpu_to_le16((((u16
) priv
->vs_ie
[id
].ie
[1])
2400 memcpy(vs_param_set
->ie
, priv
->vs_ie
[id
].ie
,
2401 le16_to_cpu(vs_param_set
->header
.len
));
2402 *buffer
+= le16_to_cpu(vs_param_set
->header
.len
) +
2403 sizeof(struct mwifiex_ie_types_header
);
2404 ret_len
+= le16_to_cpu(vs_param_set
->header
.len
) +
2405 sizeof(struct mwifiex_ie_types_header
);
2412 * This function saves a beacon buffer of the current BSS descriptor.
2414 * The current beacon buffer is saved so that it can be restored in the
2415 * following cases that makes the beacon buffer not to contain the current
2416 * ssid's beacon buffer.
2417 * - The current ssid was not found somehow in the last scan.
2418 * - The current ssid was the last entry of the scan table and overloaded.
2421 mwifiex_save_curr_bcn(struct mwifiex_private
*priv
)
2423 struct mwifiex_bssdescriptor
*curr_bss
=
2424 &priv
->curr_bss_params
.bss_descriptor
;
2426 if (!curr_bss
->beacon_buf_size
)
2429 /* allocate beacon buffer at 1st time; or if it's size has changed */
2430 if (!priv
->curr_bcn_buf
||
2431 priv
->curr_bcn_size
!= curr_bss
->beacon_buf_size
) {
2432 priv
->curr_bcn_size
= curr_bss
->beacon_buf_size
;
2434 kfree(priv
->curr_bcn_buf
);
2435 priv
->curr_bcn_buf
= kmalloc(curr_bss
->beacon_buf_size
,
2437 if (!priv
->curr_bcn_buf
)
2441 memcpy(priv
->curr_bcn_buf
, curr_bss
->beacon_buf
,
2442 curr_bss
->beacon_buf_size
);
2443 mwifiex_dbg(priv
->adapter
, INFO
,
2444 "info: current beacon saved %d\n",
2445 priv
->curr_bcn_size
);
2447 curr_bss
->beacon_buf
= priv
->curr_bcn_buf
;
2449 /* adjust the pointers in the current BSS descriptor */
2450 if (curr_bss
->bcn_wpa_ie
)
2451 curr_bss
->bcn_wpa_ie
=
2452 (struct ieee_types_vendor_specific
*)
2453 (curr_bss
->beacon_buf
+
2454 curr_bss
->wpa_offset
);
2456 if (curr_bss
->bcn_rsn_ie
)
2457 curr_bss
->bcn_rsn_ie
= (struct ieee_types_generic
*)
2458 (curr_bss
->beacon_buf
+
2459 curr_bss
->rsn_offset
);
2461 if (curr_bss
->bcn_ht_cap
)
2462 curr_bss
->bcn_ht_cap
= (struct ieee80211_ht_cap
*)
2463 (curr_bss
->beacon_buf
+
2464 curr_bss
->ht_cap_offset
);
2466 if (curr_bss
->bcn_ht_oper
)
2467 curr_bss
->bcn_ht_oper
= (struct ieee80211_ht_operation
*)
2468 (curr_bss
->beacon_buf
+
2469 curr_bss
->ht_info_offset
);
2471 if (curr_bss
->bcn_vht_cap
)
2472 curr_bss
->bcn_vht_cap
= (void *)(curr_bss
->beacon_buf
+
2473 curr_bss
->vht_cap_offset
);
2475 if (curr_bss
->bcn_vht_oper
)
2476 curr_bss
->bcn_vht_oper
= (void *)(curr_bss
->beacon_buf
+
2477 curr_bss
->vht_info_offset
);
2479 if (curr_bss
->bcn_bss_co_2040
)
2480 curr_bss
->bcn_bss_co_2040
=
2481 (curr_bss
->beacon_buf
+ curr_bss
->bss_co_2040_offset
);
2483 if (curr_bss
->bcn_ext_cap
)
2484 curr_bss
->bcn_ext_cap
= curr_bss
->beacon_buf
+
2485 curr_bss
->ext_cap_offset
;
2487 if (curr_bss
->oper_mode
)
2488 curr_bss
->oper_mode
= (void *)(curr_bss
->beacon_buf
+
2489 curr_bss
->oper_mode_offset
);
2493 * This function frees the current BSS descriptor beacon buffer.
2496 mwifiex_free_curr_bcn(struct mwifiex_private
*priv
)
2498 kfree(priv
->curr_bcn_buf
);
2499 priv
->curr_bcn_buf
= NULL
;