Merge branch 'upstream' of git://git.linux-mips.org/pub/scm/ralf/upstream-linus
[deliverable/linux.git] / drivers / net / wireless / mwifiex / scan.c
1 /*
2 * Marvell Wireless LAN device driver: scan ioctl and command handling
3 *
4 * Copyright (C) 2011-2014, Marvell International Ltd.
5 *
6 * This software file (the "File") is distributed by Marvell International
7 * Ltd. under the terms of the GNU General Public License Version 2, June 1991
8 * (the "License"). You may use, redistribute and/or modify this File in
9 * accordance with the terms and conditions of the License, a copy of which
10 * is available by writing to the Free Software Foundation, Inc.,
11 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
12 * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
13 *
14 * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
16 * ARE EXPRESSLY DISCLAIMED. The License provides additional details about
17 * this warranty disclaimer.
18 */
19
20 #include "decl.h"
21 #include "ioctl.h"
22 #include "util.h"
23 #include "fw.h"
24 #include "main.h"
25 #include "11n.h"
26 #include "cfg80211.h"
27
28 /* The maximum number of channels the firmware can scan per command */
29 #define MWIFIEX_MAX_CHANNELS_PER_SPECIFIC_SCAN 14
30
31 #define MWIFIEX_DEF_CHANNELS_PER_SCAN_CMD 4
32
33 /* Memory needed to store a max sized Channel List TLV for a firmware scan */
34 #define CHAN_TLV_MAX_SIZE (sizeof(struct mwifiex_ie_types_header) \
35 + (MWIFIEX_MAX_CHANNELS_PER_SPECIFIC_SCAN \
36 *sizeof(struct mwifiex_chan_scan_param_set)))
37
38 /* Memory needed to store supported rate */
39 #define RATE_TLV_MAX_SIZE (sizeof(struct mwifiex_ie_types_rates_param_set) \
40 + HOSTCMD_SUPPORTED_RATES)
41
42 /* Memory needed to store a max number/size WildCard SSID TLV for a firmware
43 scan */
44 #define WILDCARD_SSID_TLV_MAX_SIZE \
45 (MWIFIEX_MAX_SSID_LIST_LENGTH * \
46 (sizeof(struct mwifiex_ie_types_wildcard_ssid_params) \
47 + IEEE80211_MAX_SSID_LEN))
48
49 /* Maximum memory needed for a mwifiex_scan_cmd_config with all TLVs at max */
50 #define MAX_SCAN_CFG_ALLOC (sizeof(struct mwifiex_scan_cmd_config) \
51 + sizeof(struct mwifiex_ie_types_num_probes) \
52 + sizeof(struct mwifiex_ie_types_htcap) \
53 + CHAN_TLV_MAX_SIZE \
54 + RATE_TLV_MAX_SIZE \
55 + WILDCARD_SSID_TLV_MAX_SIZE)
56
57
58 union mwifiex_scan_cmd_config_tlv {
59 /* Scan configuration (variable length) */
60 struct mwifiex_scan_cmd_config config;
61 /* Max allocated block */
62 u8 config_alloc_buf[MAX_SCAN_CFG_ALLOC];
63 };
64
65 enum cipher_suite {
66 CIPHER_SUITE_TKIP,
67 CIPHER_SUITE_CCMP,
68 CIPHER_SUITE_MAX
69 };
70 static u8 mwifiex_wpa_oui[CIPHER_SUITE_MAX][4] = {
71 { 0x00, 0x50, 0xf2, 0x02 }, /* TKIP */
72 { 0x00, 0x50, 0xf2, 0x04 }, /* AES */
73 };
74 static u8 mwifiex_rsn_oui[CIPHER_SUITE_MAX][4] = {
75 { 0x00, 0x0f, 0xac, 0x02 }, /* TKIP */
76 { 0x00, 0x0f, 0xac, 0x04 }, /* AES */
77 };
78
79 /*
80 * This function parses a given IE for a given OUI.
81 *
82 * This is used to parse a WPA/RSN IE to find if it has
83 * a given oui in PTK.
84 */
85 static u8
86 mwifiex_search_oui_in_ie(struct ie_body *iebody, u8 *oui)
87 {
88 u8 count;
89
90 count = iebody->ptk_cnt[0];
91
92 /* There could be multiple OUIs for PTK hence
93 1) Take the length.
94 2) Check all the OUIs for AES.
95 3) If one of them is AES then pass success. */
96 while (count) {
97 if (!memcmp(iebody->ptk_body, oui, sizeof(iebody->ptk_body)))
98 return MWIFIEX_OUI_PRESENT;
99
100 --count;
101 if (count)
102 iebody = (struct ie_body *) ((u8 *) iebody +
103 sizeof(iebody->ptk_body));
104 }
105
106 pr_debug("info: %s: OUI is not found in PTK\n", __func__);
107 return MWIFIEX_OUI_NOT_PRESENT;
108 }
109
110 /*
111 * This function checks if a given OUI is present in a RSN IE.
112 *
113 * The function first checks if a RSN IE is present or not in the
114 * BSS descriptor. It tries to locate the OUI only if such an IE is
115 * present.
116 */
117 static u8
118 mwifiex_is_rsn_oui_present(struct mwifiex_bssdescriptor *bss_desc, u32 cipher)
119 {
120 u8 *oui;
121 struct ie_body *iebody;
122 u8 ret = MWIFIEX_OUI_NOT_PRESENT;
123
124 if (((bss_desc->bcn_rsn_ie) && ((*(bss_desc->bcn_rsn_ie)).
125 ieee_hdr.element_id == WLAN_EID_RSN))) {
126 iebody = (struct ie_body *)
127 (((u8 *) bss_desc->bcn_rsn_ie->data) +
128 RSN_GTK_OUI_OFFSET);
129 oui = &mwifiex_rsn_oui[cipher][0];
130 ret = mwifiex_search_oui_in_ie(iebody, oui);
131 if (ret)
132 return ret;
133 }
134 return ret;
135 }
136
137 /*
138 * This function checks if a given OUI is present in a WPA IE.
139 *
140 * The function first checks if a WPA IE is present or not in the
141 * BSS descriptor. It tries to locate the OUI only if such an IE is
142 * present.
143 */
144 static u8
145 mwifiex_is_wpa_oui_present(struct mwifiex_bssdescriptor *bss_desc, u32 cipher)
146 {
147 u8 *oui;
148 struct ie_body *iebody;
149 u8 ret = MWIFIEX_OUI_NOT_PRESENT;
150
151 if (((bss_desc->bcn_wpa_ie) &&
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);
157 if (ret)
158 return ret;
159 }
160 return ret;
161 }
162
163 /*
164 * This function compares two SSIDs and checks if they match.
165 */
166 s32
167 mwifiex_ssid_cmp(struct cfg80211_ssid *ssid1, struct cfg80211_ssid *ssid2)
168 {
169 if (!ssid1 || !ssid2 || (ssid1->ssid_len != ssid2->ssid_len))
170 return -1;
171 return memcmp(ssid1->ssid, ssid2->ssid, ssid1->ssid_len);
172 }
173
174 /*
175 * This function checks if wapi is enabled in driver and scanned network is
176 * compatible with it.
177 */
178 static bool
179 mwifiex_is_bss_wapi(struct mwifiex_private *priv,
180 struct mwifiex_bssdescriptor *bss_desc)
181 {
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))) {
186 return true;
187 }
188 return false;
189 }
190
191 /*
192 * This function checks if driver is configured with no security mode and
193 * scanned network is compatible with it.
194 */
195 static bool
196 mwifiex_is_bss_no_sec(struct mwifiex_private *priv,
197 struct mwifiex_bssdescriptor *bss_desc)
198 {
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 !=
205 WLAN_EID_RSN)) &&
206 !priv->sec_info.encryption_mode && !bss_desc->privacy) {
207 return true;
208 }
209 return false;
210 }
211
212 /*
213 * This function checks if static WEP is enabled in driver and scanned network
214 * is compatible with it.
215 */
216 static bool
217 mwifiex_is_bss_static_wep(struct mwifiex_private *priv,
218 struct mwifiex_bssdescriptor *bss_desc)
219 {
220 if (priv->sec_info.wep_enabled && !priv->sec_info.wpa_enabled &&
221 !priv->sec_info.wpa2_enabled && bss_desc->privacy) {
222 return true;
223 }
224 return false;
225 }
226
227 /*
228 * This function checks if wpa is enabled in driver and scanned network is
229 * compatible with it.
230 */
231 static bool
232 mwifiex_is_bss_wpa(struct mwifiex_private *priv,
233 struct mwifiex_bssdescriptor *bss_desc)
234 {
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))
239 /*
240 * Privacy bit may NOT be set in some APs like
241 * LinkSys WRT54G && bss_desc->privacy
242 */
243 ) {
244 mwifiex_dbg(priv->adapter, INFO,
245 "info: %s: WPA:\t"
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,
258 bss_desc->privacy);
259 return true;
260 }
261 return false;
262 }
263
264 /*
265 * This function checks if wpa2 is enabled in driver and scanned network is
266 * compatible with it.
267 */
268 static bool
269 mwifiex_is_bss_wpa2(struct mwifiex_private *priv,
270 struct mwifiex_bssdescriptor *bss_desc)
271 {
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))) {
277 /*
278 * Privacy bit may NOT be set in some APs like
279 * LinkSys WRT54G && bss_desc->privacy
280 */
281 mwifiex_dbg(priv->adapter, INFO,
282 "info: %s: WPA2:\t"
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,
295 bss_desc->privacy);
296 return true;
297 }
298 return false;
299 }
300
301 /*
302 * This function checks if adhoc AES is enabled in driver and scanned network is
303 * compatible with it.
304 */
305 static bool
306 mwifiex_is_bss_adhoc_aes(struct mwifiex_private *priv,
307 struct mwifiex_bssdescriptor *bss_desc)
308 {
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) {
317 return true;
318 }
319 return false;
320 }
321
322 /*
323 * This function checks if dynamic WEP is enabled in driver and scanned network
324 * is compatible with it.
325 */
326 static bool
327 mwifiex_is_bss_dynamic_wep(struct mwifiex_private *priv,
328 struct mwifiex_bssdescriptor *bss_desc)
329 {
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",
342 __func__,
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,
350 bss_desc->privacy);
351 return true;
352 }
353 return false;
354 }
355
356 /*
357 * This function checks if a scanned network is compatible with the driver
358 * settings.
359 *
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
364 * HT if no AES)
365 * 0 0 1 0 x 1x x 1 yes WPA2 (disable
366 * HT if no AES)
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
369 * (disable HT)
370 * 0 0 0 0 !=NONE 1 0 0 yes Dynamic WEP
371 *
372 * Compatibility is not matched while roaming, except for mode.
373 */
374 static s32
375 mwifiex_is_network_compatible(struct mwifiex_private *priv,
376 struct mwifiex_bssdescriptor *bss_desc, u32 mode)
377 {
378 struct mwifiex_adapter *adapter = priv->adapter;
379
380 bss_desc->disable_11n = false;
381
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))
386 return 0;
387
388 if (priv->wps.session_enable) {
389 mwifiex_dbg(adapter, IOCTL,
390 "info: return success directly in WPS period\n");
391 return 0;
392 }
393
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");
397 return -1;
398 }
399
400 if (mwifiex_is_bss_wapi(priv, bss_desc)) {
401 mwifiex_dbg(adapter, INFO,
402 "info: return success for WAPI AP\n");
403 return 0;
404 }
405
406 if (bss_desc->bss_mode == mode) {
407 if (mwifiex_is_bss_no_sec(priv, bss_desc)) {
408 /* No security */
409 return 0;
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;
415 return 0;
416 } else if (mwifiex_is_bss_wpa(priv, bss_desc)) {
417 /* WPA enabled */
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)) {
423
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;
430 } else {
431 return -1;
432 }
433 }
434 return 0;
435 } else if (mwifiex_is_bss_wpa2(priv, bss_desc)) {
436 /* WPA2 enabled */
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)) {
442
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;
449 } else {
450 return -1;
451 }
452 }
453 return 0;
454 } else if (mwifiex_is_bss_adhoc_aes(priv, bss_desc)) {
455 /* Ad-hoc AES enabled */
456 return 0;
457 } else if (mwifiex_is_bss_dynamic_wep(priv, bss_desc)) {
458 /* Dynamic WEP enabled */
459 return 0;
460 }
461
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",
466 __func__,
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);
475 return -1;
476 }
477
478 /* Mode doesn't match */
479 return -1;
480 }
481
482 /*
483 * This function creates a channel list for the driver to scan, based
484 * on region/band information.
485 *
486 * This routine is used for any scan that is not provided with a
487 * specific channel list to scan.
488 */
489 static int
490 mwifiex_scan_create_channel_list(struct mwifiex_private *priv,
491 const struct mwifiex_user_scan_cfg
492 *user_scan_in,
493 struct mwifiex_chan_scan_param_set
494 *scan_chan_list,
495 u8 filtered_scan)
496 {
497 enum ieee80211_band band;
498 struct ieee80211_supported_band *sband;
499 struct ieee80211_channel *ch;
500 struct mwifiex_adapter *adapter = priv->adapter;
501 int chan_idx = 0, i;
502
503 for (band = 0; (band < IEEE80211_NUM_BANDS) ; band++) {
504
505 if (!priv->wdev.wiphy->bands[band])
506 continue;
507
508 sband = priv->wdev.wiphy->bands[band];
509
510 for (i = 0; (i < sband->n_channels) ; i++) {
511 ch = &sband->channels[i];
512 if (ch->flags & IEEE80211_CHAN_DISABLED)
513 continue;
514 scan_chan_list[chan_idx].radio_type = band;
515
516 if (user_scan_in &&
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);
524 else
525 scan_chan_list[chan_idx].max_scan_time =
526 cpu_to_le16(adapter->active_scan_time);
527
528 if (ch->flags & IEEE80211_CHAN_NO_IR)
529 scan_chan_list[chan_idx].chan_scan_mode_bitmap
530 |= MWIFIEX_PASSIVE_SCAN;
531 else
532 scan_chan_list[chan_idx].chan_scan_mode_bitmap
533 &= ~MWIFIEX_PASSIVE_SCAN;
534 scan_chan_list[chan_idx].chan_number =
535 (u32) ch->hw_value;
536 if (filtered_scan) {
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;
541 }
542 chan_idx++;
543 }
544
545 }
546 return chan_idx;
547 }
548
549 /* This function appends rate TLV to scan config command. */
550 static int
551 mwifiex_append_rate_tlv(struct mwifiex_private *priv,
552 struct mwifiex_scan_cmd_config *scan_cfg_out,
553 u8 radio)
554 {
555 struct mwifiex_ie_types_rates_param_set *rates_tlv;
556 u8 rates[MWIFIEX_SUPPORTED_RATES], *tlv_pos;
557 u32 rates_size;
558
559 memset(rates, 0, sizeof(rates));
560
561 tlv_pos = (u8 *)scan_cfg_out->tlv_buf + scan_cfg_out->tlv_buf_len;
562
563 if (priv->scan_request)
564 rates_size = mwifiex_get_rates_from_cfg80211(priv, rates,
565 radio);
566 else
567 rates_size = mwifiex_get_supported_rates(priv, rates);
568
569 mwifiex_dbg(priv->adapter, CMD,
570 "info: SCAN_CMD: Rates size = %d\n",
571 rates_size);
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;
577
578 return rates_size;
579 }
580
581 /*
582 * This function constructs and sends multiple scan config commands to
583 * the firmware.
584 *
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.
589 */
590 static int
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
595 *chan_tlv_out,
596 struct mwifiex_chan_scan_param_set *scan_chan_list)
597 {
598 struct mwifiex_adapter *adapter = priv->adapter;
599 int ret = 0;
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;
603 unsigned long flags;
604 u32 tlv_idx, rates_size, cmd_no;
605 u32 total_scan_time;
606 u32 done_early;
607 u8 radio_type;
608
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);
613 return -1;
614 }
615
616 /* Check csa channel expiry before preparing scan list */
617 mwifiex_11h_get_csa_closed_channel(priv);
618
619 chan_tlv_out->header.type = cpu_to_le16(TLV_TYPE_CHANLIST);
620
621 /* Set the temp channel struct pointer to the start of the desired
622 list */
623 tmp_chan_list = scan_chan_list;
624
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) {
629
630 tlv_idx = 0;
631 total_scan_time = 0;
632 radio_type = 0;
633 chan_tlv_out->header.len = 0;
634 start_chan = tmp_chan_list;
635 done_early = false;
636
637 /*
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
642 * list)
643 * - done_early is set (controlling individual scanning of
644 * 1,6,11)
645 */
646 while (tlv_idx < max_chan_per_scan &&
647 tmp_chan_list->chan_number && !done_early) {
648
649 if (tmp_chan_list->chan_number == priv->csa_chan) {
650 tmp_chan_list++;
651 continue;
652 }
653
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));
665
666 /* Copy the current channel TLV to the command being
667 prepared */
668 memcpy(chan_tlv_out->chan_scan_param + tlv_idx,
669 tmp_chan_list,
670 sizeof(chan_tlv_out->chan_scan_param));
671
672 /* Increment the TLV header length by the size
673 appended */
674 le16_add_cpu(&chan_tlv_out->header.len,
675 sizeof(chan_tlv_out->chan_scan_param));
676
677 /*
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.
682 */
683 scan_cfg_out->tlv_buf_len = (u32) ((u8 *) chan_tlv_out -
684 scan_cfg_out->tlv_buf);
685
686 /* Add the size of the channel tlv header and the data
687 length */
688 scan_cfg_out->tlv_buf_len +=
689 (sizeof(chan_tlv_out->header)
690 + le16_to_cpu(chan_tlv_out->header.len));
691
692 /* Increment the index to the channel tlv we are
693 constructing */
694 tlv_idx++;
695
696 /* Count the total scan time per command */
697 total_scan_time +=
698 le16_to_cpu(tmp_chan_list->max_scan_time);
699
700 done_early = false;
701
702 /* Stop the loop if the *current* channel is in the
703 1,6,11 set and we are not filtering on a BSSID
704 or SSID. */
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))
709 done_early = true;
710
711 /* Increment the tmp pointer to the next channel to
712 be scanned */
713 tmp_chan_list++;
714
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))
722 done_early = true;
723 }
724
725 /* The total scan time should be less than scan command timeout
726 value */
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",
731 total_scan_time,
732 MWIFIEX_MAX_TOTAL_SCAN_TIME);
733 ret = -1;
734 break;
735 }
736
737 rates_size = mwifiex_append_rate_tlv(priv, scan_cfg_out,
738 radio_type);
739
740 priv->adapter->scan_channels = start_chan;
741
742 /* Send the scan command to the firmware with the specified
743 cfg */
744 if (priv->adapter->ext_scan)
745 cmd_no = HostCmd_CMD_802_11_SCAN_EXT;
746 else
747 cmd_no = HostCmd_CMD_802_11_SCAN;
748
749 ret = mwifiex_send_cmd(priv, cmd_no, HostCmd_ACT_GEN_SET,
750 0, scan_cfg_out, false);
751
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.
755 */
756 scan_cfg_out->tlv_buf_len -=
757 sizeof(struct mwifiex_ie_types_header) + rates_size;
758
759 if (ret) {
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,
763 list) {
764 list_del(&cmd_node->list);
765 cmd_node->wait_q_enabled = false;
766 mwifiex_insert_cmd_to_free_q(adapter, cmd_node);
767 }
768 spin_unlock_irqrestore(&adapter->scan_pending_q_lock,
769 flags);
770 break;
771 }
772 }
773
774 if (ret)
775 return -1;
776
777 return 0;
778 }
779
780 /*
781 * This function constructs a scan command configuration structure to use
782 * in scan commands.
783 *
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
788 * firmware.
789 *
790 * This function creates a scan command configuration structure based on the
791 * following user supplied parameters (if present):
792 * - SSID filter
793 * - BSSID filter
794 * - Number of Probes to be sent
795 * - Channel list
796 *
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.
799 */
800 static void
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)
808 {
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;
814 u8 *tlv_pos;
815 u32 num_probes;
816 u32 ssid_len;
817 u32 chan_idx;
818 u32 chan_num;
819 u32 scan_type;
820 u16 scan_dur;
821 u8 channel;
822 u8 radio_type;
823 int i;
824 u8 ssid_filter;
825 struct mwifiex_ie_types_htcap *ht_cap;
826
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;
833
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
836 buf */
837 tlv_pos = scan_cfg_out->tlv_buf;
838
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;
842
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;
847
848 if (user_scan_in) {
849
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 */
853 ssid_filter = true;
854
855 /* Set the BSS type scan filter, use Adapter setting if
856 unset */
857 scan_cfg_out->bss_mode =
858 (user_scan_in->bss_mode ? (u8) user_scan_in->
859 bss_mode : (u8) adapter->scan_mode);
860
861 /* Set the number of probes to send, use Adapter setting
862 if unset */
863 num_probes =
864 (user_scan_in->num_probes ? user_scan_in->
865 num_probes : adapter->scan_probes);
866
867 /*
868 * Set the BSSID filter to the incoming configuration,
869 * if non-zero. If not set, it will remain disabled
870 * (all zeros).
871 */
872 memcpy(scan_cfg_out->specific_bssid,
873 user_scan_in->specific_bssid,
874 sizeof(scan_cfg_out->specific_bssid));
875
876 if (adapter->ext_scan &&
877 !is_zero_ether_addr(scan_cfg_out->specific_bssid)) {
878 bssid_tlv =
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,
883 ETH_ALEN);
884 tlv_pos += sizeof(struct mwifiex_ie_types_bssid_list);
885 }
886
887 for (i = 0; i < user_scan_in->num_ssids; i++) {
888 ssid_len = user_scan_in->ssid_list[i].ssid_len;
889
890 wildcard_ssid_tlv =
891 (struct mwifiex_ie_types_wildcard_ssid_params *)
892 tlv_pos;
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->
897 max_ssid_length)));
898
899 /*
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
903 * wildcard scan.
904 */
905 if (ssid_len)
906 wildcard_ssid_tlv->max_ssid_length = 0;
907 else
908 wildcard_ssid_tlv->max_ssid_length =
909 IEEE80211_MAX_SSID_LEN;
910
911 memcpy(wildcard_ssid_tlv->ssid,
912 user_scan_in->ssid_list[i].ssid, ssid_len);
913
914 tlv_pos += (sizeof(wildcard_ssid_tlv->header)
915 + le16_to_cpu(wildcard_ssid_tlv->header.len));
916
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);
921
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
925 filtered. */
926 if (!ssid_len && wildcard_ssid_tlv->max_ssid_length)
927 ssid_filter = false;
928 }
929
930 /*
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.
935 */
936 if ((i && ssid_filter) ||
937 !is_zero_ether_addr(scan_cfg_out->specific_bssid))
938 *filtered_scan = true;
939
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);
944 *max_chan_per_scan =
945 MWIFIEX_MAX_CHANNELS_PER_SPECIFIC_SCAN;
946
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));
954 tlv_pos +=
955 sizeof(struct mwifiex_ie_types_scan_chan_gap);
956 }
957 } else {
958 scan_cfg_out->bss_mode = (u8) adapter->scan_mode;
959 num_probes = adapter->scan_probes;
960 }
961
962 /*
963 * If a specific BSSID or SSID is used, the number of channels in the
964 * scan command will be increased to the absolute maximum.
965 */
966 if (*filtered_scan)
967 *max_chan_per_scan = MWIFIEX_MAX_CHANNELS_PER_SPECIFIC_SCAN;
968 else
969 *max_chan_per_scan = MWIFIEX_DEF_CHANNELS_PER_SCAN_CMD;
970
971 /* If the input config or adapter has the number of Probes set,
972 add tlv */
973 if (num_probes) {
974
975 mwifiex_dbg(adapter, INFO,
976 "info: scan: num_probes = %d\n",
977 num_probes);
978
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);
984
985 tlv_pos += sizeof(num_probes_tlv->header) +
986 le16_to_cpu(num_probes_tlv->header.len);
987
988 }
989
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);
996 ht_cap->header.len =
997 cpu_to_le16(sizeof(struct ieee80211_ht_cap));
998 radio_type =
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);
1002 }
1003
1004 /* Append vendor specific IE TLV */
1005 mwifiex_cmd_append_vsie_tlv(priv, MWIFIEX_VSIE_MASK_SCAN, &tlv_pos);
1006
1007 /*
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.
1012 */
1013 *chan_list_out =
1014 (struct mwifiex_ie_types_chan_list_param_set *) tlv_pos;
1015
1016 if (user_scan_in && user_scan_in->chan_list[0].chan_number) {
1017
1018 mwifiex_dbg(adapter, INFO,
1019 "info: Scan: Using supplied channel list\n");
1020
1021 for (chan_idx = 0;
1022 chan_idx < MWIFIEX_USER_SCAN_CHAN_MAX &&
1023 user_scan_in->chan_list[chan_idx].chan_number;
1024 chan_idx++) {
1025
1026 channel = user_scan_in->chan_list[chan_idx].chan_number;
1027 (scan_chan_list + chan_idx)->chan_number = channel;
1028
1029 radio_type =
1030 user_scan_in->chan_list[chan_idx].radio_type;
1031 (scan_chan_list + chan_idx)->radio_type = radio_type;
1032
1033 scan_type = user_scan_in->chan_list[chan_idx].scan_type;
1034
1035 if (scan_type == MWIFIEX_SCAN_TYPE_PASSIVE)
1036 (scan_chan_list +
1037 chan_idx)->chan_scan_mode_bitmap
1038 |= MWIFIEX_PASSIVE_SCAN;
1039 else
1040 (scan_chan_list +
1041 chan_idx)->chan_scan_mode_bitmap
1042 &= ~MWIFIEX_PASSIVE_SCAN;
1043
1044 if (*filtered_scan)
1045 (scan_chan_list +
1046 chan_idx)->chan_scan_mode_bitmap
1047 |= MWIFIEX_DISABLE_CHAN_FILT;
1048
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;
1052 } else {
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;
1057 else
1058 scan_dur = adapter->active_scan_time;
1059 }
1060
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);
1065 }
1066
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");
1074 }
1075 chan_num = chan_idx;
1076 } else {
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,
1080 scan_chan_list,
1081 *filtered_scan);
1082 }
1083
1084 }
1085
1086 /*
1087 * This function inspects the scan response buffer for pointers to
1088 * expected TLVs.
1089 *
1090 * TLVs can be included at the end of the scan response BSS information.
1091 *
1092 * Data in the buffer is parsed pointers to TLVs that can potentially
1093 * be passed back in the response.
1094 */
1095 static void
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)
1100 {
1101 struct mwifiex_ie_types_data *current_tlv;
1102 u32 tlv_buf_left;
1103 u32 tlv_type;
1104 u32 tlv_len;
1105
1106 current_tlv = tlv;
1107 tlv_buf_left = tlv_buf_size;
1108 *tlv_data = NULL;
1109
1110 mwifiex_dbg(adapter, INFO,
1111 "info: SCAN_RESP: tlv_buf_size = %d\n",
1112 tlv_buf_size);
1113
1114 while (tlv_buf_left >= sizeof(struct mwifiex_ie_types_header)) {
1115
1116 tlv_type = le16_to_cpu(current_tlv->header.type);
1117 tlv_len = le16_to_cpu(current_tlv->header.len);
1118
1119 if (sizeof(tlv->header) + tlv_len > tlv_buf_left) {
1120 mwifiex_dbg(adapter, ERROR,
1121 "SCAN_RESP: TLV buffer corrupt\n");
1122 break;
1123 }
1124
1125 if (req_tlv_type == tlv_type) {
1126 switch (tlv_type) {
1127 case TLV_TYPE_TSFTIMESTAMP:
1128 mwifiex_dbg(adapter, INFO,
1129 "info: SCAN_RESP: TSF\t"
1130 "timestamp TLV, len = %d\n",
1131 tlv_len);
1132 *tlv_data = current_tlv;
1133 break;
1134 case TLV_TYPE_CHANNELBANDLIST:
1135 mwifiex_dbg(adapter, INFO,
1136 "info: SCAN_RESP: channel\t"
1137 "band list TLV, len = %d\n",
1138 tlv_len);
1139 *tlv_data = current_tlv;
1140 break;
1141 default:
1142 mwifiex_dbg(adapter, ERROR,
1143 "SCAN_RESP: unhandled TLV = %d\n",
1144 tlv_type);
1145 /* Give up, this seems corrupted */
1146 return;
1147 }
1148 }
1149
1150 if (*tlv_data)
1151 break;
1152
1153
1154 tlv_buf_left -= (sizeof(tlv->header) + tlv_len);
1155 current_tlv =
1156 (struct mwifiex_ie_types_data *) (current_tlv->data +
1157 tlv_len);
1158
1159 } /* while */
1160 }
1161
1162 /*
1163 * This function parses provided beacon buffer and updates
1164 * respective fields in bss descriptor structure.
1165 */
1166 int mwifiex_update_bss_desc_with_ie(struct mwifiex_adapter *adapter,
1167 struct mwifiex_bssdescriptor *bss_entry)
1168 {
1169 int ret = 0;
1170 u8 element_id;
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;
1175 u8 *current_ptr;
1176 u8 *rate;
1177 u8 element_len;
1178 u16 total_ie_len;
1179 u8 bytes_to_copy;
1180 u8 rate_size;
1181 u8 found_data_rate_ie;
1182 u32 bytes_left;
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 };
1186
1187 found_data_rate_ie = false;
1188 rate_size = 0;
1189 current_ptr = bss_entry->beacon_buf;
1190 bytes_left = bss_entry->beacon_buf_size;
1191
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);
1197
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");
1202 return -1;
1203 }
1204 switch (element_id) {
1205 case WLAN_EID_SSID:
1206 bss_entry->ssid.ssid_len = element_len;
1207 memcpy(bss_entry->ssid.ssid, (current_ptr + 2),
1208 element_len);
1209 mwifiex_dbg(adapter, INFO,
1210 "info: InterpretIE: ssid: %-32s\n",
1211 bss_entry->ssid.ssid);
1212 break;
1213
1214 case WLAN_EID_SUPP_RATES:
1215 memcpy(bss_entry->data_rates, current_ptr + 2,
1216 element_len);
1217 memcpy(bss_entry->supported_rates, current_ptr + 2,
1218 element_len);
1219 rate_size = element_len;
1220 found_data_rate_ie = true;
1221 break;
1222
1223 case WLAN_EID_FH_PARAMS:
1224 fh_param_set =
1225 (struct ieee_types_fh_param_set *) current_ptr;
1226 memcpy(&bss_entry->phy_param_set.fh_param_set,
1227 fh_param_set,
1228 sizeof(struct ieee_types_fh_param_set));
1229 break;
1230
1231 case WLAN_EID_DS_PARAMS:
1232 ds_param_set =
1233 (struct ieee_types_ds_param_set *) current_ptr;
1234
1235 bss_entry->channel = ds_param_set->current_chan;
1236
1237 memcpy(&bss_entry->phy_param_set.ds_param_set,
1238 ds_param_set,
1239 sizeof(struct ieee_types_ds_param_set));
1240 break;
1241
1242 case WLAN_EID_CF_PARAMS:
1243 cf_param_set =
1244 (struct ieee_types_cf_param_set *) current_ptr;
1245 memcpy(&bss_entry->ss_param_set.cf_param_set,
1246 cf_param_set,
1247 sizeof(struct ieee_types_cf_param_set));
1248 break;
1249
1250 case WLAN_EID_IBSS_PARAMS:
1251 ibss_param_set =
1252 (struct ieee_types_ibss_param_set *)
1253 current_ptr;
1254 memcpy(&bss_entry->ss_param_set.ibss_param_set,
1255 ibss_param_set,
1256 sizeof(struct ieee_types_ibss_param_set));
1257 break;
1258
1259 case WLAN_EID_ERP_INFO:
1260 bss_entry->erp_flags = *(current_ptr + 2);
1261 break;
1262
1263 case WLAN_EID_PWR_CONSTRAINT:
1264 bss_entry->local_constraint = *(current_ptr + 2);
1265 bss_entry->sensed_11h = true;
1266 break;
1267
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;
1274 break;
1275
1276 case WLAN_EID_EXT_SUPP_RATES:
1277 /*
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
1282 */
1283 if (found_data_rate_ie) {
1284 if ((element_len + rate_size) >
1285 MWIFIEX_SUPPORTED_RATES)
1286 bytes_to_copy =
1287 (MWIFIEX_SUPPORTED_RATES -
1288 rate_size);
1289 else
1290 bytes_to_copy = element_len;
1291
1292 rate = (u8 *) bss_entry->data_rates;
1293 rate += rate_size;
1294 memcpy(rate, current_ptr + 2, bytes_to_copy);
1295
1296 rate = (u8 *) bss_entry->supported_rates;
1297 rate += rate_size;
1298 memcpy(rate, current_ptr + 2, bytes_to_copy);
1299 }
1300 break;
1301
1302 case WLAN_EID_VENDOR_SPECIFIC:
1303 vendor_ie = (struct ieee_types_vendor_specific *)
1304 current_ptr;
1305
1306 if (!memcmp
1307 (vendor_ie->vend_hdr.oui, wpa_oui,
1308 sizeof(wpa_oui))) {
1309 bss_entry->bcn_wpa_ie =
1310 (struct ieee_types_vendor_specific *)
1311 current_ptr;
1312 bss_entry->wpa_offset = (u16)
1313 (current_ptr - bss_entry->beacon_buf);
1314 } else if (!memcmp(vendor_ie->vend_hdr.oui, wmm_oui,
1315 sizeof(wmm_oui))) {
1316 if (total_ie_len ==
1317 sizeof(struct ieee_types_wmm_parameter) ||
1318 total_ie_len ==
1319 sizeof(struct ieee_types_wmm_info))
1320 /*
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.
1324 */
1325 memcpy((u8 *) &bss_entry->wmm_ie,
1326 current_ptr, total_ie_len);
1327 }
1328 break;
1329 case WLAN_EID_RSN:
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);
1334 break;
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);
1340 break;
1341 case WLAN_EID_HT_CAPABILITY:
1342 bss_entry->bcn_ht_cap = (struct ieee80211_ht_cap *)
1343 (current_ptr +
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);
1348 break;
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);
1356 break;
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);
1365 break;
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);
1373 break;
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);
1378 break;
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);
1383 break;
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);
1389 break;
1390 default:
1391 break;
1392 }
1393
1394 current_ptr += element_len + 2;
1395
1396 /* Need to account for IE ID and IE Len */
1397 bytes_left -= (element_len + 2);
1398
1399 } /* while (bytes_left > 2) */
1400 return ret;
1401 }
1402
1403 /*
1404 * This function converts radio type scan parameter to a band configuration
1405 * to be used in join command.
1406 */
1407 static u8
1408 mwifiex_radio_type_to_band(u8 radio_type)
1409 {
1410 switch (radio_type) {
1411 case HostCmd_SCAN_RADIO_TYPE_A:
1412 return BAND_A;
1413 case HostCmd_SCAN_RADIO_TYPE_BG:
1414 default:
1415 return BAND_G;
1416 }
1417 }
1418
1419 /*
1420 * This is an internal function used to start a scan based on an input
1421 * configuration.
1422 *
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.
1426 */
1427 int mwifiex_scan_networks(struct mwifiex_private *priv,
1428 const struct mwifiex_user_scan_cfg *user_scan_in)
1429 {
1430 int ret;
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;
1436 u8 filtered_scan;
1437 u8 scan_current_chan_only;
1438 u8 max_chan_per_scan;
1439 unsigned long flags;
1440
1441 if (adapter->scan_processing) {
1442 mwifiex_dbg(adapter, WARN,
1443 "cmd: Scan already in process...\n");
1444 return -EBUSY;
1445 }
1446
1447 if (priv->scan_block) {
1448 mwifiex_dbg(adapter, WARN,
1449 "cmd: Scan is blocked during association...\n");
1450 return -EBUSY;
1451 }
1452
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");
1456 return -EFAULT;
1457 }
1458
1459 spin_lock_irqsave(&adapter->mwifiex_cmd_lock, flags);
1460 adapter->scan_processing = true;
1461 spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, flags);
1462
1463 scan_cfg_out = kzalloc(sizeof(union mwifiex_scan_cmd_config_tlv),
1464 GFP_KERNEL);
1465 if (!scan_cfg_out) {
1466 ret = -ENOMEM;
1467 goto done;
1468 }
1469
1470 scan_chan_list = kcalloc(MWIFIEX_USER_SCAN_CHAN_MAX,
1471 sizeof(struct mwifiex_chan_scan_param_set),
1472 GFP_KERNEL);
1473 if (!scan_chan_list) {
1474 kfree(scan_cfg_out);
1475 ret = -ENOMEM;
1476 goto done;
1477 }
1478
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);
1482
1483 ret = mwifiex_scan_channel_list(priv, max_chan_per_scan, filtered_scan,
1484 &scan_cfg_out->config, chan_list_out,
1485 scan_chan_list);
1486
1487 /* Get scan command from scan_pending_q and put to cmd_pending_q */
1488 if (!ret) {
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,
1495 flags);
1496 mwifiex_insert_cmd_to_pending_q(adapter, cmd_node,
1497 true);
1498 queue_work(adapter->workqueue, &adapter->main_work);
1499
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);
1505 }
1506 } else {
1507 spin_unlock_irqrestore(&adapter->scan_pending_q_lock,
1508 flags);
1509 }
1510 }
1511
1512 kfree(scan_cfg_out);
1513 kfree(scan_chan_list);
1514 done:
1515 if (ret) {
1516 spin_lock_irqsave(&adapter->mwifiex_cmd_lock, flags);
1517 adapter->scan_processing = false;
1518 spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, flags);
1519 }
1520 return ret;
1521 }
1522
1523 /*
1524 * This function prepares a scan command to be sent to the firmware.
1525 *
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.
1529 *
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.
1532 *
1533 * Preparation also includes -
1534 * - Setting command ID, and proper size
1535 * - Ensuring correct endian-ness
1536 */
1537 int mwifiex_cmd_802_11_scan(struct host_cmd_ds_command *cmd,
1538 struct mwifiex_scan_cmd_config *scan_cfg)
1539 {
1540 struct host_cmd_ds_802_11_scan *scan_cmd = &cmd->params.scan;
1541
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);
1547
1548 cmd->command = cpu_to_le16(HostCmd_CMD_802_11_SCAN);
1549
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));
1554
1555 return 0;
1556 }
1557
1558 /*
1559 * This function checks compatibility of requested network with current
1560 * driver settings.
1561 */
1562 int mwifiex_check_network_compatibility(struct mwifiex_private *priv,
1563 struct mwifiex_bssdescriptor *bss_desc)
1564 {
1565 int ret = -1;
1566
1567 if (!bss_desc)
1568 return -1;
1569
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,
1576 priv->bss_mode);
1577 if (ret)
1578 mwifiex_dbg(priv->adapter, ERROR,
1579 "Incompatible network settings\n");
1580 break;
1581 default:
1582 ret = 0;
1583 }
1584 }
1585
1586 return ret;
1587 }
1588
1589 static int mwifiex_update_curr_bss_params(struct mwifiex_private *priv,
1590 struct cfg80211_bss *bss)
1591 {
1592 struct mwifiex_bssdescriptor *bss_desc;
1593 int ret;
1594 unsigned long flags;
1595
1596 /* Allocate and fill new bss descriptor */
1597 bss_desc = kzalloc(sizeof(struct mwifiex_bssdescriptor), GFP_KERNEL);
1598 if (!bss_desc)
1599 return -ENOMEM;
1600
1601 ret = mwifiex_fill_new_bss_desc(priv, bss, bss_desc);
1602 if (ret)
1603 goto done;
1604
1605 ret = mwifiex_check_network_compatibility(priv, bss_desc);
1606 if (ret)
1607 goto done;
1608
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));
1613
1614 /* The contents of beacon_ie will be copied to its own buffer
1615 * in mwifiex_save_curr_bcn()
1616 */
1617 mwifiex_save_curr_bcn(priv);
1618 spin_unlock_irqrestore(&priv->curr_bcn_buf_lock, flags);
1619
1620 done:
1621 /* beacon_ie buffer was allocated in function
1622 * mwifiex_fill_new_bss_desc(). Free it now.
1623 */
1624 kfree(bss_desc->beacon_buf);
1625 kfree(bss_desc);
1626 return 0;
1627 }
1628
1629 static int
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)
1633 {
1634 struct mwifiex_adapter *adapter = priv->adapter;
1635 struct mwifiex_chan_freq_power *cfp;
1636 struct cfg80211_bss *bss;
1637 u8 bssid[ETH_ALEN];
1638 s32 rssi;
1639 const u8 *ie_buf;
1640 size_t ie_len;
1641 u16 channel = 0;
1642 u16 beacon_size = 0;
1643 u32 curr_bcn_bytes;
1644 u32 freq;
1645 u16 beacon_period;
1646 u16 cap_info_bitmap;
1647 u8 *current_ptr;
1648 u64 timestamp;
1649 struct mwifiex_fixed_bcn_param *bcn_param;
1650 struct mwifiex_bss_priv *bss_priv;
1651
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);
1657 }
1658
1659 if (!beacon_size || beacon_size > *bytes_left) {
1660 *bss_info += *bytes_left;
1661 *bytes_left = 0;
1662 return -EFAULT;
1663 }
1664
1665 /* Initialize the current working beacon pointer for this BSS
1666 * iteration
1667 */
1668 current_ptr = *bss_info;
1669
1670 /* Advance the return beacon pointer past the current beacon */
1671 *bss_info += beacon_size;
1672 *bytes_left -= beacon_size;
1673
1674 curr_bcn_bytes = beacon_size;
1675
1676 /* First 5 fields are bssid, RSSI(for legacy scan only),
1677 * time stamp, beacon interval, and capability information
1678 */
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");
1683 return -EFAULT;
1684 }
1685
1686 memcpy(bssid, current_ptr, ETH_ALEN);
1687 current_ptr += ETH_ALEN;
1688 curr_bcn_bytes -= ETH_ALEN;
1689
1690 if (!ext_scan) {
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);
1697 } else {
1698 rssi = rssi_val;
1699 }
1700
1701 bcn_param = (struct mwifiex_fixed_bcn_param *)current_ptr;
1702 current_ptr += sizeof(*bcn_param);
1703 curr_bcn_bytes -= sizeof(*bcn_param);
1704
1705 timestamp = le64_to_cpu(bcn_param->timestamp);
1706 beacon_period = le16_to_cpu(bcn_param->beacon_period);
1707
1708 cap_info_bitmap = le16_to_cpu(bcn_param->cap_info_bitmap);
1709 mwifiex_dbg(adapter, INFO,
1710 "info: InterpretIE: capabilities=0x%X\n",
1711 cap_info_bitmap);
1712
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",
1718 curr_bcn_bytes);
1719
1720 while (curr_bcn_bytes >= sizeof(struct ieee_types_header)) {
1721 u8 element_id, element_len;
1722
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__);
1729 return -EFAULT;
1730 }
1731 if (element_id == WLAN_EID_DS_PARAMS) {
1732 channel = *(current_ptr +
1733 sizeof(struct ieee_types_header));
1734 break;
1735 }
1736
1737 current_ptr += element_len + sizeof(struct ieee_types_header);
1738 curr_bcn_bytes -= element_len +
1739 sizeof(struct ieee_types_header);
1740 }
1741
1742 if (channel) {
1743 struct ieee80211_channel *chan;
1744 u8 band;
1745
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");
1750 return 0;
1751 }
1752
1753 band = BAND_G;
1754 if (radio_type)
1755 band = mwifiex_radio_type_to_band(*radio_type &
1756 (BIT(0) | BIT(1)));
1757
1758 cfp = mwifiex_get_cfp(priv, band, channel, 0);
1759
1760 freq = cfp ? cfp->freq : 0;
1761
1762 chan = ieee80211_get_channel(priv->wdev.wiphy, freq);
1763
1764 if (chan && !(chan->flags & IEEE80211_CHAN_DISABLED)) {
1765 bss = cfg80211_inform_bss(priv->wdev.wiphy,
1766 chan, CFG80211_BSS_FTYPE_UNKNOWN,
1767 bssid, timestamp,
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);
1778 }
1779 } else {
1780 mwifiex_dbg(adapter, WARN, "missing BSS channel IE\n");
1781 }
1782
1783 return 0;
1784 }
1785
1786 static void mwifiex_complete_scan(struct mwifiex_private *priv)
1787 {
1788 struct mwifiex_adapter *adapter = priv->adapter;
1789
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);
1797 }
1798 }
1799 }
1800
1801 static void mwifiex_check_next_scan_command(struct mwifiex_private *priv)
1802 {
1803 struct mwifiex_adapter *adapter = priv->adapter;
1804 struct cmd_ctrl_node *cmd_node, *tmp_node;
1805 unsigned long flags;
1806
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);
1813
1814 if (!adapter->ext_scan)
1815 mwifiex_complete_scan(priv);
1816
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;
1822 } else {
1823 priv->scan_aborting = false;
1824 mwifiex_dbg(adapter, INFO,
1825 "info: scan already aborted\n");
1826 }
1827 } else if ((priv->scan_aborting && !priv->scan_request) ||
1828 priv->scan_block) {
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);
1833 }
1834 spin_unlock_irqrestore(&adapter->scan_pending_q_lock, flags);
1835
1836 spin_lock_irqsave(&adapter->mwifiex_cmd_lock, flags);
1837 adapter->scan_processing = false;
1838 spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, flags);
1839
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;
1845 } else {
1846 priv->scan_aborting = false;
1847 mwifiex_dbg(adapter, INFO,
1848 "info: scan already aborted\n");
1849 }
1850 } else {
1851 /* Get scan command from scan_pending_q and put to
1852 * cmd_pending_q
1853 */
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);
1859 }
1860
1861 return;
1862 }
1863
1864 /*
1865 * This function handles the command response of scan.
1866 *
1867 * The response buffer for the scan command has the following
1868 * memory layout:
1869 *
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 * .-------------------------------------------------------------.
1882 */
1883 int mwifiex_ret_802_11_scan(struct mwifiex_private *priv,
1884 struct host_cmd_ds_command *resp)
1885 {
1886 int ret = 0;
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;
1891 u8 *bss_info;
1892 u32 scan_resp_size;
1893 u32 bytes_left;
1894 u32 idx;
1895 u32 tlv_buf_size;
1896 struct mwifiex_ie_types_chan_band_list_param_set *chan_band_tlv;
1897 struct chan_band_param_set *chan_band;
1898 u8 is_bgscan_resp;
1899 __le64 fw_tsf = 0;
1900 u8 *radio_type;
1901
1902 is_bgscan_resp = (le16_to_cpu(resp->command)
1903 == HostCmd_CMD_802_11_BG_SCAN_QUERY);
1904 if (is_bgscan_resp)
1905 scan_rsp = &resp->params.bg_scan_query_resp.scan_resp;
1906 else
1907 scan_rsp = &resp->params.scan_resp;
1908
1909
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);
1914 ret = -1;
1915 goto check_next_scan;
1916 }
1917
1918 /* Check csa channel expiry before parsing scan response */
1919 mwifiex_11h_get_csa_closed_channel(priv);
1920
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",
1924 bytes_left);
1925
1926 scan_resp_size = le16_to_cpu(resp->size);
1927
1928 mwifiex_dbg(adapter, INFO,
1929 "info: SCAN_RESP: returned %d APs before parsing\n",
1930 scan_rsp->number_of_sets);
1931
1932 bss_info = scan_rsp->bss_desc_and_tlv_buffer;
1933
1934 /*
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)
1939 */
1940 tlv_buf_size = scan_resp_size - (bytes_left
1941 + sizeof(scan_rsp->bss_descript_size)
1942 + sizeof(scan_rsp->number_of_sets)
1943 + S_DS_GEN);
1944
1945 tlv_data = (struct mwifiex_ie_types_data *) (scan_rsp->
1946 bss_desc_and_tlv_buffer +
1947 bytes_left);
1948
1949 /* Search the TLV buffer space in the scan response for any valid
1950 TLVs */
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 **)
1954 &tsf_tlv);
1955
1956 /* Search the TLV buffer space in the scan response for any valid
1957 TLVs */
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 **)
1961 &chan_band_tlv);
1962
1963 for (idx = 0; idx < scan_rsp->number_of_sets && bytes_left; idx++) {
1964 /*
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
1968 * received.
1969 */
1970 if (tsf_tlv)
1971 memcpy(&fw_tsf, &tsf_tlv->tsf_data[idx * TSF_DATA_SIZE],
1972 sizeof(fw_tsf));
1973
1974 if (chan_band_tlv) {
1975 chan_band = &chan_band_tlv->chan_band_param[idx];
1976 radio_type = &chan_band->radio_type;
1977 } else {
1978 radio_type = NULL;
1979 }
1980
1981 ret = mwifiex_parse_single_response_buf(priv, &bss_info,
1982 &bytes_left,
1983 le64_to_cpu(fw_tsf),
1984 radio_type, false, 0);
1985 if (ret)
1986 goto check_next_scan;
1987 }
1988
1989 check_next_scan:
1990 mwifiex_check_next_scan_command(priv);
1991 return ret;
1992 }
1993
1994 /*
1995 * This function prepares an extended scan command to be sent to the firmware
1996 *
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.
2000 */
2001 int mwifiex_cmd_802_11_scan_ext(struct mwifiex_private *priv,
2002 struct host_cmd_ds_command *cmd,
2003 void *data_buf)
2004 {
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;
2007
2008 memcpy(ext_scan->tlv_buffer, scan_cfg->tlv_buf, scan_cfg->tlv_buf_len);
2009
2010 cmd->command = cpu_to_le16(HostCmd_CMD_802_11_SCAN_EXT);
2011
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));
2015
2016 return 0;
2017 }
2018
2019 static void
2020 mwifiex_update_chan_statistics(struct mwifiex_private *priv,
2021 struct mwifiex_ietypes_chanstats *tlv_stat)
2022 {
2023 struct mwifiex_adapter *adapter = priv->adapter;
2024 u8 i, num_chan;
2025 struct mwifiex_fw_chan_stats *fw_chan_stats;
2026 struct mwifiex_chan_stats chan_stats;
2027
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);
2032
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,
2046 chan_stats.noise,
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));
2052 fw_chan_stats++;
2053 }
2054 }
2055
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)
2059 {
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;
2065
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;
2070
2071 mwifiex_dbg(adapter, INFO, "info: EXT scan returns successfully\n");
2072
2073 ext_scan_resp = &resp->params.ext_scan;
2074
2075 tlv = (void *)ext_scan_resp->tlv_buffer;
2076 buf_left = le16_to_cpu(resp->size) - (sizeof(*ext_scan_resp) + S_DS_GEN
2077 - 1);
2078
2079 while (buf_left >= sizeof(struct mwifiex_ie_types_header)) {
2080 type = le16_to_cpu(tlv->type);
2081 len = le16_to_cpu(tlv->len);
2082
2083 if (buf_left < (sizeof(struct mwifiex_ie_types_header) + len)) {
2084 mwifiex_dbg(adapter, ERROR,
2085 "error processing scan response TLVs");
2086 break;
2087 }
2088
2089 switch (type) {
2090 case TLV_TYPE_CHANNEL_STATS:
2091 tlv_stat = (void *)tlv;
2092 mwifiex_update_chan_statistics(priv, tlv_stat);
2093 break;
2094 default:
2095 break;
2096 }
2097
2098 buf_left -= len + sizeof(struct mwifiex_ie_types_header);
2099 tlv = (void *)((u8 *)tlv + len +
2100 sizeof(struct mwifiex_ie_types_header));
2101 }
2102
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;
2114 break;
2115 }
2116 }
2117 }
2118 spin_unlock_irqrestore(&adapter->scan_pending_q_lock, scan_flags);
2119 spin_unlock_irqrestore(&adapter->cmd_pending_q_lock, cmd_flags);
2120
2121 if (complete_scan)
2122 mwifiex_complete_scan(priv);
2123
2124 return 0;
2125 }
2126
2127 /* This function This function handles the event extended scan report. It
2128 * parses extended scan results and informs to cfg80211 stack.
2129 */
2130 int mwifiex_handle_event_ext_scan_report(struct mwifiex_private *priv,
2131 void *buf)
2132 {
2133 int ret = 0;
2134 struct mwifiex_adapter *adapter = priv->adapter;
2135 u8 *bss_info;
2136 u32 bytes_left, bytes_left_for_tlv, idx;
2137 u16 type, len;
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;
2141 u8 *radio_type;
2142 u64 fw_tsf = 0;
2143 s32 rssi = 0;
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);
2148
2149 if (num_of_set > MWIFIEX_MAX_AP) {
2150 mwifiex_dbg(adapter, ERROR,
2151 "EXT_SCAN: Invalid number of AP returned (%d)!!\n",
2152 num_of_set);
2153 ret = -1;
2154 goto check_next_scan;
2155 }
2156
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,
2162 scan_resp_size +
2163 sizeof(struct mwifiex_event_scan_result));
2164
2165 tlv = (struct mwifiex_ie_types_data *)scan_resp;
2166
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");
2173 break;
2174 }
2175 scan_rsp_tlv = NULL;
2176 scan_info_tlv = NULL;
2177 bytes_left_for_tlv = bytes_left;
2178
2179 /* BSS response TLV with beacon or probe response buffer
2180 * at the initial position of each descriptor
2181 */
2182 if (type != TLV_TYPE_BSS_SCAN_RSP)
2183 break;
2184
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));
2190
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;
2203 continue;
2204 }
2205 switch (type) {
2206 case TLV_TYPE_BSS_SCAN_INFO:
2207 scan_info_tlv =
2208 (struct mwifiex_ie_types_bss_scan_info *)tlv;
2209 if (len !=
2210 sizeof(struct mwifiex_ie_types_bss_scan_info) -
2211 sizeof(struct mwifiex_ie_types_header)) {
2212 bytes_left_for_tlv = 0;
2213 continue;
2214 }
2215 break;
2216 default:
2217 break;
2218 }
2219 tlv = (struct mwifiex_ie_types_data *)(tlv->data + len);
2220 bytes_left -=
2221 (len + sizeof(struct mwifiex_ie_types_header));
2222 bytes_left_for_tlv -=
2223 (len + sizeof(struct mwifiex_ie_types_header));
2224 }
2225
2226 if (!scan_rsp_tlv)
2227 break;
2228
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
2233 */
2234 bss_info += sizeof(u16);
2235 bytes_left -= sizeof(u16);
2236
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;
2244 } else {
2245 radio_type = NULL;
2246 }
2247 ret = mwifiex_parse_single_response_buf(priv, &bss_info,
2248 &bytes_left, fw_tsf,
2249 radio_type, true, rssi);
2250 if (ret)
2251 goto check_next_scan;
2252 }
2253
2254 check_next_scan:
2255 if (!event_scan->more_event)
2256 mwifiex_check_next_scan_command(priv);
2257
2258 return ret;
2259 }
2260
2261 /*
2262 * This function prepares command for background scan query.
2263 *
2264 * Preparation includes -
2265 * - Setting command ID and proper size
2266 * - Setting background scan flush parameter
2267 * - Ensuring correct endian-ness
2268 */
2269 int mwifiex_cmd_802_11_bg_scan_query(struct host_cmd_ds_command *cmd)
2270 {
2271 struct host_cmd_ds_802_11_bg_scan_query *bg_query =
2272 &cmd->params.bg_scan_query;
2273
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)
2276 + S_DS_GEN);
2277
2278 bg_query->flush = 1;
2279
2280 return 0;
2281 }
2282
2283 /*
2284 * This function inserts scan command node to the scan pending queue.
2285 */
2286 void
2287 mwifiex_queue_scan_cmd(struct mwifiex_private *priv,
2288 struct cmd_ctrl_node *cmd_node)
2289 {
2290 struct mwifiex_adapter *adapter = priv->adapter;
2291 unsigned long flags;
2292
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);
2298 }
2299
2300 /*
2301 * This function sends a scan command for all available channels to the
2302 * firmware, filtered on a specific SSID.
2303 */
2304 static int mwifiex_scan_specific_ssid(struct mwifiex_private *priv,
2305 struct cfg80211_ssid *req_ssid)
2306 {
2307 struct mwifiex_adapter *adapter = priv->adapter;
2308 int ret;
2309 struct mwifiex_user_scan_cfg *scan_cfg;
2310
2311 if (adapter->scan_processing) {
2312 mwifiex_dbg(adapter, WARN,
2313 "cmd: Scan already in process...\n");
2314 return -EBUSY;
2315 }
2316
2317 if (priv->scan_block) {
2318 mwifiex_dbg(adapter, WARN,
2319 "cmd: Scan is blocked during association...\n");
2320 return -EBUSY;
2321 }
2322
2323 scan_cfg = kzalloc(sizeof(struct mwifiex_user_scan_cfg), GFP_KERNEL);
2324 if (!scan_cfg)
2325 return -ENOMEM;
2326
2327 scan_cfg->ssid_list = req_ssid;
2328 scan_cfg->num_ssids = 1;
2329
2330 ret = mwifiex_scan_networks(priv, scan_cfg);
2331
2332 kfree(scan_cfg);
2333 return ret;
2334 }
2335
2336 /*
2337 * Sends IOCTL request to start a scan.
2338 *
2339 * This function allocates the IOCTL request buffer, fills it
2340 * with requisite parameters and calls the IOCTL handler.
2341 *
2342 * Scan command can be issued for both normal scan and specific SSID
2343 * scan, depending upon whether an SSID is provided or not.
2344 */
2345 int mwifiex_request_scan(struct mwifiex_private *priv,
2346 struct cfg80211_ssid *req_ssid)
2347 {
2348 int ret;
2349
2350 if (down_interruptible(&priv->async_sem)) {
2351 mwifiex_dbg(priv->adapter, ERROR,
2352 "%s: acquire semaphore fail\n",
2353 __func__);
2354 return -1;
2355 }
2356
2357 priv->adapter->scan_wait_q_woken = false;
2358
2359 if (req_ssid && req_ssid->ssid_len != 0)
2360 /* Specific SSID scan */
2361 ret = mwifiex_scan_specific_ssid(priv, req_ssid);
2362 else
2363 /* Normal scan */
2364 ret = mwifiex_scan_networks(priv, NULL);
2365
2366 up(&priv->async_sem);
2367
2368 return ret;
2369 }
2370
2371 /*
2372 * This function appends the vendor specific IE TLV to a buffer.
2373 */
2374 int
2375 mwifiex_cmd_append_vsie_tlv(struct mwifiex_private *priv,
2376 u16 vsie_mask, u8 **buffer)
2377 {
2378 int id, ret_len = 0;
2379 struct mwifiex_ie_types_vendor_param_set *vs_param_set;
2380
2381 if (!buffer)
2382 return 0;
2383 if (!(*buffer))
2384 return 0;
2385
2386 /*
2387 * Traverse through the saved vendor specific IE array and append
2388 * the selected(scan/assoc/adhoc) IE as TLV to the command
2389 */
2390 for (id = 0; id < MWIFIEX_MAX_VSIE_NUM; id++) {
2391 if (priv->vs_ie[id].mask & vsie_mask) {
2392 vs_param_set =
2393 (struct mwifiex_ie_types_vendor_param_set *)
2394 *buffer;
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])
2399 & 0x00FF) + 2);
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);
2406 }
2407 }
2408 return ret_len;
2409 }
2410
2411 /*
2412 * This function saves a beacon buffer of the current BSS descriptor.
2413 *
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.
2419 */
2420 void
2421 mwifiex_save_curr_bcn(struct mwifiex_private *priv)
2422 {
2423 struct mwifiex_bssdescriptor *curr_bss =
2424 &priv->curr_bss_params.bss_descriptor;
2425
2426 if (!curr_bss->beacon_buf_size)
2427 return;
2428
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;
2433
2434 kfree(priv->curr_bcn_buf);
2435 priv->curr_bcn_buf = kmalloc(curr_bss->beacon_buf_size,
2436 GFP_ATOMIC);
2437 if (!priv->curr_bcn_buf)
2438 return;
2439 }
2440
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);
2446
2447 curr_bss->beacon_buf = priv->curr_bcn_buf;
2448
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);
2455
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);
2460
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);
2465
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);
2470
2471 if (curr_bss->bcn_vht_cap)
2472 curr_bss->bcn_vht_cap = (void *)(curr_bss->beacon_buf +
2473 curr_bss->vht_cap_offset);
2474
2475 if (curr_bss->bcn_vht_oper)
2476 curr_bss->bcn_vht_oper = (void *)(curr_bss->beacon_buf +
2477 curr_bss->vht_info_offset);
2478
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);
2482
2483 if (curr_bss->bcn_ext_cap)
2484 curr_bss->bcn_ext_cap = curr_bss->beacon_buf +
2485 curr_bss->ext_cap_offset;
2486
2487 if (curr_bss->oper_mode)
2488 curr_bss->oper_mode = (void *)(curr_bss->beacon_buf +
2489 curr_bss->oper_mode_offset);
2490 }
2491
2492 /*
2493 * This function frees the current BSS descriptor beacon buffer.
2494 */
2495 void
2496 mwifiex_free_curr_bcn(struct mwifiex_private *priv)
2497 {
2498 kfree(priv->curr_bcn_buf);
2499 priv->curr_bcn_buf = NULL;
2500 }
This page took 0.151874 seconds and 5 git commands to generate.