1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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
29#define MWIFIEX_MAX_CHANNELS_PER_SPECIFIC_SCAN 14
30
31#define MWIFIEX_DEF_CHANNELS_PER_SCAN_CMD 4
32
33
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
39#define RATE_TLV_MAX_SIZE (sizeof(struct mwifiex_ie_types_rates_param_set) \
40 + HOSTCMD_SUPPORTED_RATES)
41
42
43
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
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
58union mwifiex_scan_cmd_config_tlv {
59
60 struct mwifiex_scan_cmd_config config;
61
62 u8 config_alloc_buf[MAX_SCAN_CFG_ALLOC];
63};
64
65enum cipher_suite {
66 CIPHER_SUITE_TKIP,
67 CIPHER_SUITE_CCMP,
68 CIPHER_SUITE_MAX
69};
70static u8 mwifiex_wpa_oui[CIPHER_SUITE_MAX][4] = {
71 { 0x00, 0x50, 0xf2, 0x02 },
72 { 0x00, 0x50, 0xf2, 0x04 },
73};
74static u8 mwifiex_rsn_oui[CIPHER_SUITE_MAX][4] = {
75 { 0x00, 0x0f, 0xac, 0x02 },
76 { 0x00, 0x0f, 0xac, 0x04 },
77};
78
79
80
81
82
83
84
85static u8
86mwifiex_search_oui_in_ie(struct ie_body *iebody, u8 *oui)
87{
88 u8 count;
89
90 count = iebody->ptk_cnt[0];
91
92
93
94
95
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
112
113
114
115
116
117static u8
118mwifiex_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
139
140
141
142
143
144static u8
145mwifiex_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
165
166s32
167mwifiex_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
176
177
178static bool
179mwifiex_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
193
194
195static bool
196mwifiex_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
214
215
216static bool
217mwifiex_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
229
230
231static bool
232mwifiex_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
241
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
266
267
268static bool
269mwifiex_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
279
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
303
304
305static bool
306mwifiex_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
324
325
326static bool
327mwifiex_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
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374static s32
375mwifiex_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
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
409 return 0;
410 } else if (mwifiex_is_bss_static_wep(priv, bss_desc)) {
411
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
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
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
456 return 0;
457 } else if (mwifiex_is_bss_dynamic_wep(priv, bss_desc)) {
458
459 return 0;
460 }
461
462
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
479 return -1;
480}
481
482
483
484
485
486
487
488
489static int
490mwifiex_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 MWIFIEX_HIDDEN_SSID_REPORT);
532 else
533 scan_chan_list[chan_idx].chan_scan_mode_bitmap
534 &= ~MWIFIEX_PASSIVE_SCAN;
535 scan_chan_list[chan_idx].chan_number =
536 (u32) ch->hw_value;
537 if (filtered_scan) {
538 scan_chan_list[chan_idx].max_scan_time =
539 cpu_to_le16(adapter->specific_scan_time);
540 scan_chan_list[chan_idx].chan_scan_mode_bitmap
541 |= MWIFIEX_DISABLE_CHAN_FILT;
542 }
543 chan_idx++;
544 }
545
546 }
547 return chan_idx;
548}
549
550
551
552
553static int
554mwifiex_bgscan_create_channel_list(struct mwifiex_private *priv,
555 const struct mwifiex_bg_scan_cfg
556 *bgscan_cfg_in,
557 struct mwifiex_chan_scan_param_set
558 *scan_chan_list)
559{
560 enum ieee80211_band band;
561 struct ieee80211_supported_band *sband;
562 struct ieee80211_channel *ch;
563 struct mwifiex_adapter *adapter = priv->adapter;
564 int chan_idx = 0, i;
565
566 for (band = 0; (band < IEEE80211_NUM_BANDS); band++) {
567 if (!priv->wdev.wiphy->bands[band])
568 continue;
569
570 sband = priv->wdev.wiphy->bands[band];
571
572 for (i = 0; (i < sband->n_channels) ; i++) {
573 ch = &sband->channels[i];
574 if (ch->flags & IEEE80211_CHAN_DISABLED)
575 continue;
576 scan_chan_list[chan_idx].radio_type = band;
577
578 if (bgscan_cfg_in->chan_list[0].scan_time)
579 scan_chan_list[chan_idx].max_scan_time =
580 cpu_to_le16((u16)bgscan_cfg_in->
581 chan_list[0].scan_time);
582 else if (ch->flags & IEEE80211_CHAN_NO_IR)
583 scan_chan_list[chan_idx].max_scan_time =
584 cpu_to_le16(adapter->passive_scan_time);
585 else
586 scan_chan_list[chan_idx].max_scan_time =
587 cpu_to_le16(adapter->
588 specific_scan_time);
589
590 if (ch->flags & IEEE80211_CHAN_NO_IR)
591 scan_chan_list[chan_idx].chan_scan_mode_bitmap
592 |= MWIFIEX_PASSIVE_SCAN;
593 else
594 scan_chan_list[chan_idx].chan_scan_mode_bitmap
595 &= ~MWIFIEX_PASSIVE_SCAN;
596
597 scan_chan_list[chan_idx].chan_number =
598 (u32)ch->hw_value;
599 chan_idx++;
600 }
601 }
602 return chan_idx;
603}
604
605
606static int
607mwifiex_append_rate_tlv(struct mwifiex_private *priv,
608 struct mwifiex_scan_cmd_config *scan_cfg_out,
609 u8 radio)
610{
611 struct mwifiex_ie_types_rates_param_set *rates_tlv;
612 u8 rates[MWIFIEX_SUPPORTED_RATES], *tlv_pos;
613 u32 rates_size;
614
615 memset(rates, 0, sizeof(rates));
616
617 tlv_pos = (u8 *)scan_cfg_out->tlv_buf + scan_cfg_out->tlv_buf_len;
618
619 if (priv->scan_request)
620 rates_size = mwifiex_get_rates_from_cfg80211(priv, rates,
621 radio);
622 else
623 rates_size = mwifiex_get_supported_rates(priv, rates);
624
625 mwifiex_dbg(priv->adapter, CMD,
626 "info: SCAN_CMD: Rates size = %d\n",
627 rates_size);
628 rates_tlv = (struct mwifiex_ie_types_rates_param_set *)tlv_pos;
629 rates_tlv->header.type = cpu_to_le16(WLAN_EID_SUPP_RATES);
630 rates_tlv->header.len = cpu_to_le16((u16) rates_size);
631 memcpy(rates_tlv->rates, rates, rates_size);
632 scan_cfg_out->tlv_buf_len += sizeof(rates_tlv->header) + rates_size;
633
634 return rates_size;
635}
636
637
638
639
640
641
642
643
644
645
646static int
647mwifiex_scan_channel_list(struct mwifiex_private *priv,
648 u32 max_chan_per_scan, u8 filtered_scan,
649 struct mwifiex_scan_cmd_config *scan_cfg_out,
650 struct mwifiex_ie_types_chan_list_param_set
651 *chan_tlv_out,
652 struct mwifiex_chan_scan_param_set *scan_chan_list)
653{
654 struct mwifiex_adapter *adapter = priv->adapter;
655 int ret = 0;
656 struct mwifiex_chan_scan_param_set *tmp_chan_list;
657 struct mwifiex_chan_scan_param_set *start_chan;
658 struct cmd_ctrl_node *cmd_node, *tmp_node;
659 unsigned long flags;
660 u32 tlv_idx, rates_size, cmd_no;
661 u32 total_scan_time;
662 u32 done_early;
663 u8 radio_type;
664
665 if (!scan_cfg_out || !chan_tlv_out || !scan_chan_list) {
666 mwifiex_dbg(priv->adapter, ERROR,
667 "info: Scan: Null detect: %p, %p, %p\n",
668 scan_cfg_out, chan_tlv_out, scan_chan_list);
669 return -1;
670 }
671
672
673 mwifiex_11h_get_csa_closed_channel(priv);
674
675 chan_tlv_out->header.type = cpu_to_le16(TLV_TYPE_CHANLIST);
676
677
678
679 tmp_chan_list = scan_chan_list;
680
681
682
683
684 while (tmp_chan_list->chan_number) {
685
686 tlv_idx = 0;
687 total_scan_time = 0;
688 radio_type = 0;
689 chan_tlv_out->header.len = 0;
690 start_chan = tmp_chan_list;
691 done_early = false;
692
693
694
695
696
697
698
699
700
701
702 while (tlv_idx < max_chan_per_scan &&
703 tmp_chan_list->chan_number && !done_early) {
704
705 if (tmp_chan_list->chan_number == priv->csa_chan) {
706 tmp_chan_list++;
707 continue;
708 }
709
710 radio_type = tmp_chan_list->radio_type;
711 mwifiex_dbg(priv->adapter, INFO,
712 "info: Scan: Chan(%3d), Radio(%d),\t"
713 "Mode(%d, %d), Dur(%d)\n",
714 tmp_chan_list->chan_number,
715 tmp_chan_list->radio_type,
716 tmp_chan_list->chan_scan_mode_bitmap
717 & MWIFIEX_PASSIVE_SCAN,
718 (tmp_chan_list->chan_scan_mode_bitmap
719 & MWIFIEX_DISABLE_CHAN_FILT) >> 1,
720 le16_to_cpu(tmp_chan_list->max_scan_time));
721
722
723
724 memcpy(chan_tlv_out->chan_scan_param + tlv_idx,
725 tmp_chan_list,
726 sizeof(chan_tlv_out->chan_scan_param));
727
728
729
730 le16_add_cpu(&chan_tlv_out->header.len,
731 sizeof(chan_tlv_out->chan_scan_param));
732
733
734
735
736
737
738
739 scan_cfg_out->tlv_buf_len = (u32) ((u8 *) chan_tlv_out -
740 scan_cfg_out->tlv_buf);
741
742
743
744 scan_cfg_out->tlv_buf_len +=
745 (sizeof(chan_tlv_out->header)
746 + le16_to_cpu(chan_tlv_out->header.len));
747
748
749
750 tlv_idx++;
751
752
753 total_scan_time +=
754 le16_to_cpu(tmp_chan_list->max_scan_time);
755
756 done_early = false;
757
758
759
760
761 if (!filtered_scan &&
762 (tmp_chan_list->chan_number == 1 ||
763 tmp_chan_list->chan_number == 6 ||
764 tmp_chan_list->chan_number == 11))
765 done_early = true;
766
767
768
769 tmp_chan_list++;
770
771
772
773
774 if (!filtered_scan &&
775 (tmp_chan_list->chan_number == 1 ||
776 tmp_chan_list->chan_number == 6 ||
777 tmp_chan_list->chan_number == 11))
778 done_early = true;
779 }
780
781
782
783 if (total_scan_time > MWIFIEX_MAX_TOTAL_SCAN_TIME) {
784 mwifiex_dbg(priv->adapter, ERROR,
785 "total scan time %dms\t"
786 "is over limit (%dms), scan skipped\n",
787 total_scan_time,
788 MWIFIEX_MAX_TOTAL_SCAN_TIME);
789 ret = -1;
790 break;
791 }
792
793 rates_size = mwifiex_append_rate_tlv(priv, scan_cfg_out,
794 radio_type);
795
796 priv->adapter->scan_channels = start_chan;
797
798
799
800 if (priv->adapter->ext_scan)
801 cmd_no = HostCmd_CMD_802_11_SCAN_EXT;
802 else
803 cmd_no = HostCmd_CMD_802_11_SCAN;
804
805 ret = mwifiex_send_cmd(priv, cmd_no, HostCmd_ACT_GEN_SET,
806 0, scan_cfg_out, false);
807
808
809
810
811
812 scan_cfg_out->tlv_buf_len -=
813 sizeof(struct mwifiex_ie_types_header) + rates_size;
814
815 if (ret) {
816 spin_lock_irqsave(&adapter->scan_pending_q_lock, flags);
817 list_for_each_entry_safe(cmd_node, tmp_node,
818 &adapter->scan_pending_q,
819 list) {
820 list_del(&cmd_node->list);
821 cmd_node->wait_q_enabled = false;
822 mwifiex_insert_cmd_to_free_q(adapter, cmd_node);
823 }
824 spin_unlock_irqrestore(&adapter->scan_pending_q_lock,
825 flags);
826 break;
827 }
828 }
829
830 if (ret)
831 return -1;
832
833 return 0;
834}
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856static void
857mwifiex_config_scan(struct mwifiex_private *priv,
858 const struct mwifiex_user_scan_cfg *user_scan_in,
859 struct mwifiex_scan_cmd_config *scan_cfg_out,
860 struct mwifiex_ie_types_chan_list_param_set **chan_list_out,
861 struct mwifiex_chan_scan_param_set *scan_chan_list,
862 u8 *max_chan_per_scan, u8 *filtered_scan,
863 u8 *scan_current_only)
864{
865 struct mwifiex_adapter *adapter = priv->adapter;
866 struct mwifiex_ie_types_num_probes *num_probes_tlv;
867 struct mwifiex_ie_types_scan_chan_gap *chan_gap_tlv;
868 struct mwifiex_ie_types_wildcard_ssid_params *wildcard_ssid_tlv;
869 struct mwifiex_ie_types_bssid_list *bssid_tlv;
870 u8 *tlv_pos;
871 u32 num_probes;
872 u32 ssid_len;
873 u32 chan_idx;
874 u32 chan_num;
875 u32 scan_type;
876 u16 scan_dur;
877 u8 channel;
878 u8 radio_type;
879 int i;
880 u8 ssid_filter;
881 struct mwifiex_ie_types_htcap *ht_cap;
882 struct mwifiex_ie_types_bss_mode *bss_mode;
883
884
885
886
887
888
889 scan_cfg_out->tlv_buf_len = 0;
890
891
892
893
894 tlv_pos = scan_cfg_out->tlv_buf;
895
896
897
898 *filtered_scan = false;
899
900
901
902
903 *scan_current_only = false;
904
905 if (user_scan_in) {
906
907
908
909
910 ssid_filter = true;
911
912
913
914 scan_cfg_out->bss_mode =
915 (user_scan_in->bss_mode ? (u8) user_scan_in->
916 bss_mode : (u8) adapter->scan_mode);
917
918
919
920 num_probes =
921 (user_scan_in->num_probes ? user_scan_in->
922 num_probes : adapter->scan_probes);
923
924
925
926
927
928
929 memcpy(scan_cfg_out->specific_bssid,
930 user_scan_in->specific_bssid,
931 sizeof(scan_cfg_out->specific_bssid));
932
933 if (adapter->ext_scan &&
934 !is_zero_ether_addr(scan_cfg_out->specific_bssid)) {
935 bssid_tlv =
936 (struct mwifiex_ie_types_bssid_list *)tlv_pos;
937 bssid_tlv->header.type = cpu_to_le16(TLV_TYPE_BSSID);
938 bssid_tlv->header.len = cpu_to_le16(ETH_ALEN);
939 memcpy(bssid_tlv->bssid, user_scan_in->specific_bssid,
940 ETH_ALEN);
941 tlv_pos += sizeof(struct mwifiex_ie_types_bssid_list);
942 }
943
944 for (i = 0; i < user_scan_in->num_ssids; i++) {
945 ssid_len = user_scan_in->ssid_list[i].ssid_len;
946
947 wildcard_ssid_tlv =
948 (struct mwifiex_ie_types_wildcard_ssid_params *)
949 tlv_pos;
950 wildcard_ssid_tlv->header.type =
951 cpu_to_le16(TLV_TYPE_WILDCARDSSID);
952 wildcard_ssid_tlv->header.len = cpu_to_le16(
953 (u16) (ssid_len + sizeof(wildcard_ssid_tlv->
954 max_ssid_length)));
955
956
957
958
959
960
961
962 if (ssid_len)
963 wildcard_ssid_tlv->max_ssid_length = 0;
964 else
965 wildcard_ssid_tlv->max_ssid_length =
966 IEEE80211_MAX_SSID_LEN;
967
968 if (!memcmp(user_scan_in->ssid_list[i].ssid,
969 "DIRECT-", 7))
970 wildcard_ssid_tlv->max_ssid_length = 0xfe;
971
972 memcpy(wildcard_ssid_tlv->ssid,
973 user_scan_in->ssid_list[i].ssid, ssid_len);
974
975 tlv_pos += (sizeof(wildcard_ssid_tlv->header)
976 + le16_to_cpu(wildcard_ssid_tlv->header.len));
977
978 mwifiex_dbg(adapter, INFO,
979 "info: scan: ssid[%d]: %s, %d\n",
980 i, wildcard_ssid_tlv->ssid,
981 wildcard_ssid_tlv->max_ssid_length);
982
983
984
985
986
987 if (!ssid_len && wildcard_ssid_tlv->max_ssid_length)
988 ssid_filter = false;
989 }
990
991
992
993
994
995
996
997 if ((i && ssid_filter) ||
998 !is_zero_ether_addr(scan_cfg_out->specific_bssid))
999 *filtered_scan = true;
1000
1001 if (user_scan_in->scan_chan_gap) {
1002 mwifiex_dbg(adapter, INFO,
1003 "info: scan: channel gap = %d\n",
1004 user_scan_in->scan_chan_gap);
1005 *max_chan_per_scan =
1006 MWIFIEX_MAX_CHANNELS_PER_SPECIFIC_SCAN;
1007
1008 chan_gap_tlv = (void *)tlv_pos;
1009 chan_gap_tlv->header.type =
1010 cpu_to_le16(TLV_TYPE_SCAN_CHANNEL_GAP);
1011 chan_gap_tlv->header.len =
1012 cpu_to_le16(sizeof(chan_gap_tlv->chan_gap));
1013 chan_gap_tlv->chan_gap =
1014 cpu_to_le16((user_scan_in->scan_chan_gap));
1015 tlv_pos +=
1016 sizeof(struct mwifiex_ie_types_scan_chan_gap);
1017 }
1018 } else {
1019 scan_cfg_out->bss_mode = (u8) adapter->scan_mode;
1020 num_probes = adapter->scan_probes;
1021 }
1022
1023
1024
1025
1026
1027 if (*filtered_scan)
1028 *max_chan_per_scan = MWIFIEX_MAX_CHANNELS_PER_SPECIFIC_SCAN;
1029 else
1030 *max_chan_per_scan = MWIFIEX_DEF_CHANNELS_PER_SCAN_CMD;
1031
1032 if (adapter->ext_scan) {
1033 bss_mode = (struct mwifiex_ie_types_bss_mode *)tlv_pos;
1034 bss_mode->header.type = cpu_to_le16(TLV_TYPE_BSS_MODE);
1035 bss_mode->header.len = cpu_to_le16(sizeof(bss_mode->bss_mode));
1036 bss_mode->bss_mode = scan_cfg_out->bss_mode;
1037 tlv_pos += sizeof(bss_mode->header) +
1038 le16_to_cpu(bss_mode->header.len);
1039 }
1040
1041
1042
1043 if (num_probes) {
1044
1045 mwifiex_dbg(adapter, INFO,
1046 "info: scan: num_probes = %d\n",
1047 num_probes);
1048
1049 num_probes_tlv = (struct mwifiex_ie_types_num_probes *) tlv_pos;
1050 num_probes_tlv->header.type = cpu_to_le16(TLV_TYPE_NUMPROBES);
1051 num_probes_tlv->header.len =
1052 cpu_to_le16(sizeof(num_probes_tlv->num_probes));
1053 num_probes_tlv->num_probes = cpu_to_le16((u16) num_probes);
1054
1055 tlv_pos += sizeof(num_probes_tlv->header) +
1056 le16_to_cpu(num_probes_tlv->header.len);
1057
1058 }
1059
1060 if (ISSUPP_11NENABLED(priv->adapter->fw_cap_info) &&
1061 (priv->adapter->config_bands & BAND_GN ||
1062 priv->adapter->config_bands & BAND_AN)) {
1063 ht_cap = (struct mwifiex_ie_types_htcap *) tlv_pos;
1064 memset(ht_cap, 0, sizeof(struct mwifiex_ie_types_htcap));
1065 ht_cap->header.type = cpu_to_le16(WLAN_EID_HT_CAPABILITY);
1066 ht_cap->header.len =
1067 cpu_to_le16(sizeof(struct ieee80211_ht_cap));
1068 radio_type =
1069 mwifiex_band_to_radio_type(priv->adapter->config_bands);
1070 mwifiex_fill_cap_info(priv, radio_type, &ht_cap->ht_cap);
1071 tlv_pos += sizeof(struct mwifiex_ie_types_htcap);
1072 }
1073
1074
1075 mwifiex_cmd_append_vsie_tlv(priv, MWIFIEX_VSIE_MASK_SCAN, &tlv_pos);
1076
1077
1078
1079
1080
1081
1082
1083 *chan_list_out =
1084 (struct mwifiex_ie_types_chan_list_param_set *) tlv_pos;
1085
1086 if (user_scan_in && user_scan_in->chan_list[0].chan_number) {
1087
1088 mwifiex_dbg(adapter, INFO,
1089 "info: Scan: Using supplied channel list\n");
1090
1091 for (chan_idx = 0;
1092 chan_idx < MWIFIEX_USER_SCAN_CHAN_MAX &&
1093 user_scan_in->chan_list[chan_idx].chan_number;
1094 chan_idx++) {
1095
1096 channel = user_scan_in->chan_list[chan_idx].chan_number;
1097 (scan_chan_list + chan_idx)->chan_number = channel;
1098
1099 radio_type =
1100 user_scan_in->chan_list[chan_idx].radio_type;
1101 (scan_chan_list + chan_idx)->radio_type = radio_type;
1102
1103 scan_type = user_scan_in->chan_list[chan_idx].scan_type;
1104
1105 if (scan_type == MWIFIEX_SCAN_TYPE_PASSIVE)
1106 (scan_chan_list +
1107 chan_idx)->chan_scan_mode_bitmap
1108 |= (MWIFIEX_PASSIVE_SCAN |
1109 MWIFIEX_HIDDEN_SSID_REPORT);
1110 else
1111 (scan_chan_list +
1112 chan_idx)->chan_scan_mode_bitmap
1113 &= ~MWIFIEX_PASSIVE_SCAN;
1114
1115 if (*filtered_scan)
1116 (scan_chan_list +
1117 chan_idx)->chan_scan_mode_bitmap
1118 |= MWIFIEX_DISABLE_CHAN_FILT;
1119
1120 if (user_scan_in->chan_list[chan_idx].scan_time) {
1121 scan_dur = (u16) user_scan_in->
1122 chan_list[chan_idx].scan_time;
1123 } else {
1124 if (scan_type == MWIFIEX_SCAN_TYPE_PASSIVE)
1125 scan_dur = adapter->passive_scan_time;
1126 else if (*filtered_scan)
1127 scan_dur = adapter->specific_scan_time;
1128 else
1129 scan_dur = adapter->active_scan_time;
1130 }
1131
1132 (scan_chan_list + chan_idx)->min_scan_time =
1133 cpu_to_le16(scan_dur);
1134 (scan_chan_list + chan_idx)->max_scan_time =
1135 cpu_to_le16(scan_dur);
1136 }
1137
1138
1139 if ((chan_idx == 1) &&
1140 (user_scan_in->chan_list[0].chan_number ==
1141 priv->curr_bss_params.bss_descriptor.channel)) {
1142 *scan_current_only = true;
1143 mwifiex_dbg(adapter, INFO,
1144 "info: Scan: Scanning current channel only\n");
1145 }
1146 chan_num = chan_idx;
1147 } else {
1148 mwifiex_dbg(adapter, INFO,
1149 "info: Scan: Creating full region channel list\n");
1150 chan_num = mwifiex_scan_create_channel_list(priv, user_scan_in,
1151 scan_chan_list,
1152 *filtered_scan);
1153 }
1154
1155}
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166static void
1167mwifiex_ret_802_11_scan_get_tlv_ptrs(struct mwifiex_adapter *adapter,
1168 struct mwifiex_ie_types_data *tlv,
1169 u32 tlv_buf_size, u32 req_tlv_type,
1170 struct mwifiex_ie_types_data **tlv_data)
1171{
1172 struct mwifiex_ie_types_data *current_tlv;
1173 u32 tlv_buf_left;
1174 u32 tlv_type;
1175 u32 tlv_len;
1176
1177 current_tlv = tlv;
1178 tlv_buf_left = tlv_buf_size;
1179 *tlv_data = NULL;
1180
1181 mwifiex_dbg(adapter, INFO,
1182 "info: SCAN_RESP: tlv_buf_size = %d\n",
1183 tlv_buf_size);
1184
1185 while (tlv_buf_left >= sizeof(struct mwifiex_ie_types_header)) {
1186
1187 tlv_type = le16_to_cpu(current_tlv->header.type);
1188 tlv_len = le16_to_cpu(current_tlv->header.len);
1189
1190 if (sizeof(tlv->header) + tlv_len > tlv_buf_left) {
1191 mwifiex_dbg(adapter, ERROR,
1192 "SCAN_RESP: TLV buffer corrupt\n");
1193 break;
1194 }
1195
1196 if (req_tlv_type == tlv_type) {
1197 switch (tlv_type) {
1198 case TLV_TYPE_TSFTIMESTAMP:
1199 mwifiex_dbg(adapter, INFO,
1200 "info: SCAN_RESP: TSF\t"
1201 "timestamp TLV, len = %d\n",
1202 tlv_len);
1203 *tlv_data = current_tlv;
1204 break;
1205 case TLV_TYPE_CHANNELBANDLIST:
1206 mwifiex_dbg(adapter, INFO,
1207 "info: SCAN_RESP: channel\t"
1208 "band list TLV, len = %d\n",
1209 tlv_len);
1210 *tlv_data = current_tlv;
1211 break;
1212 default:
1213 mwifiex_dbg(adapter, ERROR,
1214 "SCAN_RESP: unhandled TLV = %d\n",
1215 tlv_type);
1216
1217 return;
1218 }
1219 }
1220
1221 if (*tlv_data)
1222 break;
1223
1224
1225 tlv_buf_left -= (sizeof(tlv->header) + tlv_len);
1226 current_tlv =
1227 (struct mwifiex_ie_types_data *) (current_tlv->data +
1228 tlv_len);
1229
1230 }
1231}
1232
1233
1234
1235
1236
1237int mwifiex_update_bss_desc_with_ie(struct mwifiex_adapter *adapter,
1238 struct mwifiex_bssdescriptor *bss_entry)
1239{
1240 int ret = 0;
1241 u8 element_id;
1242 struct ieee_types_fh_param_set *fh_param_set;
1243 struct ieee_types_ds_param_set *ds_param_set;
1244 struct ieee_types_cf_param_set *cf_param_set;
1245 struct ieee_types_ibss_param_set *ibss_param_set;
1246 u8 *current_ptr;
1247 u8 *rate;
1248 u8 element_len;
1249 u16 total_ie_len;
1250 u8 bytes_to_copy;
1251 u8 rate_size;
1252 u8 found_data_rate_ie;
1253 u32 bytes_left;
1254 struct ieee_types_vendor_specific *vendor_ie;
1255 const u8 wpa_oui[4] = { 0x00, 0x50, 0xf2, 0x01 };
1256 const u8 wmm_oui[4] = { 0x00, 0x50, 0xf2, 0x02 };
1257
1258 found_data_rate_ie = false;
1259 rate_size = 0;
1260 current_ptr = bss_entry->beacon_buf;
1261 bytes_left = bss_entry->beacon_buf_size;
1262
1263
1264 while (bytes_left >= 2) {
1265 element_id = *current_ptr;
1266 element_len = *(current_ptr + 1);
1267 total_ie_len = element_len + sizeof(struct ieee_types_header);
1268
1269 if (bytes_left < total_ie_len) {
1270 mwifiex_dbg(adapter, ERROR,
1271 "err: InterpretIE: in processing\t"
1272 "IE, bytes left < IE length\n");
1273 return -1;
1274 }
1275 switch (element_id) {
1276 case WLAN_EID_SSID:
1277 bss_entry->ssid.ssid_len = element_len;
1278 memcpy(bss_entry->ssid.ssid, (current_ptr + 2),
1279 element_len);
1280 mwifiex_dbg(adapter, INFO,
1281 "info: InterpretIE: ssid: %-32s\n",
1282 bss_entry->ssid.ssid);
1283 break;
1284
1285 case WLAN_EID_SUPP_RATES:
1286 memcpy(bss_entry->data_rates, current_ptr + 2,
1287 element_len);
1288 memcpy(bss_entry->supported_rates, current_ptr + 2,
1289 element_len);
1290 rate_size = element_len;
1291 found_data_rate_ie = true;
1292 break;
1293
1294 case WLAN_EID_FH_PARAMS:
1295 fh_param_set =
1296 (struct ieee_types_fh_param_set *) current_ptr;
1297 memcpy(&bss_entry->phy_param_set.fh_param_set,
1298 fh_param_set,
1299 sizeof(struct ieee_types_fh_param_set));
1300 break;
1301
1302 case WLAN_EID_DS_PARAMS:
1303 ds_param_set =
1304 (struct ieee_types_ds_param_set *) current_ptr;
1305
1306 bss_entry->channel = ds_param_set->current_chan;
1307
1308 memcpy(&bss_entry->phy_param_set.ds_param_set,
1309 ds_param_set,
1310 sizeof(struct ieee_types_ds_param_set));
1311 break;
1312
1313 case WLAN_EID_CF_PARAMS:
1314 cf_param_set =
1315 (struct ieee_types_cf_param_set *) current_ptr;
1316 memcpy(&bss_entry->ss_param_set.cf_param_set,
1317 cf_param_set,
1318 sizeof(struct ieee_types_cf_param_set));
1319 break;
1320
1321 case WLAN_EID_IBSS_PARAMS:
1322 ibss_param_set =
1323 (struct ieee_types_ibss_param_set *)
1324 current_ptr;
1325 memcpy(&bss_entry->ss_param_set.ibss_param_set,
1326 ibss_param_set,
1327 sizeof(struct ieee_types_ibss_param_set));
1328 break;
1329
1330 case WLAN_EID_ERP_INFO:
1331 bss_entry->erp_flags = *(current_ptr + 2);
1332 break;
1333
1334 case WLAN_EID_PWR_CONSTRAINT:
1335 bss_entry->local_constraint = *(current_ptr + 2);
1336 bss_entry->sensed_11h = true;
1337 break;
1338
1339 case WLAN_EID_CHANNEL_SWITCH:
1340 bss_entry->chan_sw_ie_present = true;
1341 case WLAN_EID_PWR_CAPABILITY:
1342 case WLAN_EID_TPC_REPORT:
1343 case WLAN_EID_QUIET:
1344 bss_entry->sensed_11h = true;
1345 break;
1346
1347 case WLAN_EID_EXT_SUPP_RATES:
1348
1349
1350
1351
1352
1353
1354 if (found_data_rate_ie) {
1355 if ((element_len + rate_size) >
1356 MWIFIEX_SUPPORTED_RATES)
1357 bytes_to_copy =
1358 (MWIFIEX_SUPPORTED_RATES -
1359 rate_size);
1360 else
1361 bytes_to_copy = element_len;
1362
1363 rate = (u8 *) bss_entry->data_rates;
1364 rate += rate_size;
1365 memcpy(rate, current_ptr + 2, bytes_to_copy);
1366
1367 rate = (u8 *) bss_entry->supported_rates;
1368 rate += rate_size;
1369 memcpy(rate, current_ptr + 2, bytes_to_copy);
1370 }
1371 break;
1372
1373 case WLAN_EID_VENDOR_SPECIFIC:
1374 vendor_ie = (struct ieee_types_vendor_specific *)
1375 current_ptr;
1376
1377 if (!memcmp
1378 (vendor_ie->vend_hdr.oui, wpa_oui,
1379 sizeof(wpa_oui))) {
1380 bss_entry->bcn_wpa_ie =
1381 (struct ieee_types_vendor_specific *)
1382 current_ptr;
1383 bss_entry->wpa_offset = (u16)
1384 (current_ptr - bss_entry->beacon_buf);
1385 } else if (!memcmp(vendor_ie->vend_hdr.oui, wmm_oui,
1386 sizeof(wmm_oui))) {
1387 if (total_ie_len ==
1388 sizeof(struct ieee_types_wmm_parameter) ||
1389 total_ie_len ==
1390 sizeof(struct ieee_types_wmm_info))
1391
1392
1393
1394
1395
1396 memcpy((u8 *) &bss_entry->wmm_ie,
1397 current_ptr, total_ie_len);
1398 }
1399 break;
1400 case WLAN_EID_RSN:
1401 bss_entry->bcn_rsn_ie =
1402 (struct ieee_types_generic *) current_ptr;
1403 bss_entry->rsn_offset = (u16) (current_ptr -
1404 bss_entry->beacon_buf);
1405 break;
1406 case WLAN_EID_BSS_AC_ACCESS_DELAY:
1407 bss_entry->bcn_wapi_ie =
1408 (struct ieee_types_generic *) current_ptr;
1409 bss_entry->wapi_offset = (u16) (current_ptr -
1410 bss_entry->beacon_buf);
1411 break;
1412 case WLAN_EID_HT_CAPABILITY:
1413 bss_entry->bcn_ht_cap = (struct ieee80211_ht_cap *)
1414 (current_ptr +
1415 sizeof(struct ieee_types_header));
1416 bss_entry->ht_cap_offset = (u16) (current_ptr +
1417 sizeof(struct ieee_types_header) -
1418 bss_entry->beacon_buf);
1419 break;
1420 case WLAN_EID_HT_OPERATION:
1421 bss_entry->bcn_ht_oper =
1422 (struct ieee80211_ht_operation *)(current_ptr +
1423 sizeof(struct ieee_types_header));
1424 bss_entry->ht_info_offset = (u16) (current_ptr +
1425 sizeof(struct ieee_types_header) -
1426 bss_entry->beacon_buf);
1427 break;
1428 case WLAN_EID_VHT_CAPABILITY:
1429 bss_entry->disable_11ac = false;
1430 bss_entry->bcn_vht_cap =
1431 (void *)(current_ptr +
1432 sizeof(struct ieee_types_header));
1433 bss_entry->vht_cap_offset =
1434 (u16)((u8 *)bss_entry->bcn_vht_cap -
1435 bss_entry->beacon_buf);
1436 break;
1437 case WLAN_EID_VHT_OPERATION:
1438 bss_entry->bcn_vht_oper =
1439 (void *)(current_ptr +
1440 sizeof(struct ieee_types_header));
1441 bss_entry->vht_info_offset =
1442 (u16)((u8 *)bss_entry->bcn_vht_oper -
1443 bss_entry->beacon_buf);
1444 break;
1445 case WLAN_EID_BSS_COEX_2040:
1446 bss_entry->bcn_bss_co_2040 = current_ptr;
1447 bss_entry->bss_co_2040_offset =
1448 (u16) (current_ptr - bss_entry->beacon_buf);
1449 break;
1450 case WLAN_EID_EXT_CAPABILITY:
1451 bss_entry->bcn_ext_cap = current_ptr;
1452 bss_entry->ext_cap_offset =
1453 (u16) (current_ptr - bss_entry->beacon_buf);
1454 break;
1455 case WLAN_EID_OPMODE_NOTIF:
1456 bss_entry->oper_mode = (void *)current_ptr;
1457 bss_entry->oper_mode_offset =
1458 (u16)((u8 *)bss_entry->oper_mode -
1459 bss_entry->beacon_buf);
1460 break;
1461 default:
1462 break;
1463 }
1464
1465 current_ptr += element_len + 2;
1466
1467
1468 bytes_left -= (element_len + 2);
1469
1470 }
1471 return ret;
1472}
1473
1474
1475
1476
1477
1478static u8
1479mwifiex_radio_type_to_band(u8 radio_type)
1480{
1481 switch (radio_type) {
1482 case HostCmd_SCAN_RADIO_TYPE_A:
1483 return BAND_A;
1484 case HostCmd_SCAN_RADIO_TYPE_BG:
1485 default:
1486 return BAND_G;
1487 }
1488}
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498int mwifiex_scan_networks(struct mwifiex_private *priv,
1499 const struct mwifiex_user_scan_cfg *user_scan_in)
1500{
1501 int ret;
1502 struct mwifiex_adapter *adapter = priv->adapter;
1503 struct cmd_ctrl_node *cmd_node;
1504 union mwifiex_scan_cmd_config_tlv *scan_cfg_out;
1505 struct mwifiex_ie_types_chan_list_param_set *chan_list_out;
1506 struct mwifiex_chan_scan_param_set *scan_chan_list;
1507 u8 filtered_scan;
1508 u8 scan_current_chan_only;
1509 u8 max_chan_per_scan;
1510 unsigned long flags;
1511
1512 if (adapter->scan_processing) {
1513 mwifiex_dbg(adapter, WARN,
1514 "cmd: Scan already in process...\n");
1515 return -EBUSY;
1516 }
1517
1518 if (priv->scan_block) {
1519 mwifiex_dbg(adapter, WARN,
1520 "cmd: Scan is blocked during association...\n");
1521 return -EBUSY;
1522 }
1523
1524 if (adapter->surprise_removed || adapter->is_cmd_timedout) {
1525 mwifiex_dbg(adapter, ERROR,
1526 "Ignore scan. Card removed or firmware in bad state\n");
1527 return -EFAULT;
1528 }
1529
1530 spin_lock_irqsave(&adapter->mwifiex_cmd_lock, flags);
1531 adapter->scan_processing = true;
1532 spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, flags);
1533
1534 scan_cfg_out = kzalloc(sizeof(union mwifiex_scan_cmd_config_tlv),
1535 GFP_KERNEL);
1536 if (!scan_cfg_out) {
1537 ret = -ENOMEM;
1538 goto done;
1539 }
1540
1541 scan_chan_list = kcalloc(MWIFIEX_USER_SCAN_CHAN_MAX,
1542 sizeof(struct mwifiex_chan_scan_param_set),
1543 GFP_KERNEL);
1544 if (!scan_chan_list) {
1545 kfree(scan_cfg_out);
1546 ret = -ENOMEM;
1547 goto done;
1548 }
1549
1550 mwifiex_config_scan(priv, user_scan_in, &scan_cfg_out->config,
1551 &chan_list_out, scan_chan_list, &max_chan_per_scan,
1552 &filtered_scan, &scan_current_chan_only);
1553
1554 ret = mwifiex_scan_channel_list(priv, max_chan_per_scan, filtered_scan,
1555 &scan_cfg_out->config, chan_list_out,
1556 scan_chan_list);
1557
1558
1559 if (!ret) {
1560 spin_lock_irqsave(&adapter->scan_pending_q_lock, flags);
1561 if (!list_empty(&adapter->scan_pending_q)) {
1562 cmd_node = list_first_entry(&adapter->scan_pending_q,
1563 struct cmd_ctrl_node, list);
1564 list_del(&cmd_node->list);
1565 spin_unlock_irqrestore(&adapter->scan_pending_q_lock,
1566 flags);
1567 mwifiex_insert_cmd_to_pending_q(adapter, cmd_node,
1568 true);
1569 queue_work(adapter->workqueue, &adapter->main_work);
1570
1571
1572 if (!priv->scan_request) {
1573 mwifiex_dbg(adapter, INFO,
1574 "wait internal scan\n");
1575 mwifiex_wait_queue_complete(adapter, cmd_node);
1576 }
1577 } else {
1578 spin_unlock_irqrestore(&adapter->scan_pending_q_lock,
1579 flags);
1580 }
1581 }
1582
1583 kfree(scan_cfg_out);
1584 kfree(scan_chan_list);
1585done:
1586 if (ret) {
1587 spin_lock_irqsave(&adapter->mwifiex_cmd_lock, flags);
1588 adapter->scan_processing = false;
1589 spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, flags);
1590 }
1591 return ret;
1592}
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608int mwifiex_cmd_802_11_scan(struct host_cmd_ds_command *cmd,
1609 struct mwifiex_scan_cmd_config *scan_cfg)
1610{
1611 struct host_cmd_ds_802_11_scan *scan_cmd = &cmd->params.scan;
1612
1613
1614 scan_cmd->bss_mode = scan_cfg->bss_mode;
1615 memcpy(scan_cmd->bssid, scan_cfg->specific_bssid,
1616 sizeof(scan_cmd->bssid));
1617 memcpy(scan_cmd->tlv_buffer, scan_cfg->tlv_buf, scan_cfg->tlv_buf_len);
1618
1619 cmd->command = cpu_to_le16(HostCmd_CMD_802_11_SCAN);
1620
1621
1622 cmd->size = cpu_to_le16((u16) (sizeof(scan_cmd->bss_mode)
1623 + sizeof(scan_cmd->bssid)
1624 + scan_cfg->tlv_buf_len + S_DS_GEN));
1625
1626 return 0;
1627}
1628
1629
1630
1631
1632
1633int mwifiex_check_network_compatibility(struct mwifiex_private *priv,
1634 struct mwifiex_bssdescriptor *bss_desc)
1635{
1636 int ret = -1;
1637
1638 if (!bss_desc)
1639 return -1;
1640
1641 if ((mwifiex_get_cfp(priv, (u8) bss_desc->bss_band,
1642 (u16) bss_desc->channel, 0))) {
1643 switch (priv->bss_mode) {
1644 case NL80211_IFTYPE_STATION:
1645 case NL80211_IFTYPE_ADHOC:
1646 ret = mwifiex_is_network_compatible(priv, bss_desc,
1647 priv->bss_mode);
1648 if (ret)
1649 mwifiex_dbg(priv->adapter, ERROR,
1650 "Incompatible network settings\n");
1651 break;
1652 default:
1653 ret = 0;
1654 }
1655 }
1656
1657 return ret;
1658}
1659
1660
1661static bool mwifiex_is_hidden_ssid(struct cfg80211_ssid *ssid)
1662{
1663 int idx;
1664
1665 for (idx = 0; idx < ssid->ssid_len; idx++) {
1666 if (ssid->ssid[idx])
1667 return false;
1668 }
1669
1670 return true;
1671}
1672
1673
1674
1675
1676static int mwifiex_save_hidden_ssid_channels(struct mwifiex_private *priv,
1677 struct cfg80211_bss *bss)
1678{
1679 struct mwifiex_bssdescriptor *bss_desc;
1680 int ret;
1681 int chid;
1682
1683
1684 bss_desc = kzalloc(sizeof(*bss_desc), GFP_KERNEL);
1685 if (!bss_desc)
1686 return -ENOMEM;
1687
1688 ret = mwifiex_fill_new_bss_desc(priv, bss, bss_desc);
1689 if (ret)
1690 goto done;
1691
1692 if (mwifiex_is_hidden_ssid(&bss_desc->ssid)) {
1693 mwifiex_dbg(priv->adapter, INFO, "found hidden SSID\n");
1694 for (chid = 0 ; chid < MWIFIEX_USER_SCAN_CHAN_MAX; chid++) {
1695 if (priv->hidden_chan[chid].chan_number ==
1696 bss->channel->hw_value)
1697 break;
1698
1699 if (!priv->hidden_chan[chid].chan_number) {
1700 priv->hidden_chan[chid].chan_number =
1701 bss->channel->hw_value;
1702 priv->hidden_chan[chid].radio_type =
1703 bss->channel->band;
1704 priv->hidden_chan[chid].scan_type =
1705 MWIFIEX_SCAN_TYPE_ACTIVE;
1706 break;
1707 }
1708 }
1709 }
1710
1711done:
1712 kfree(bss_desc);
1713 return 0;
1714}
1715
1716static int mwifiex_update_curr_bss_params(struct mwifiex_private *priv,
1717 struct cfg80211_bss *bss)
1718{
1719 struct mwifiex_bssdescriptor *bss_desc;
1720 int ret;
1721 unsigned long flags;
1722
1723
1724 bss_desc = kzalloc(sizeof(struct mwifiex_bssdescriptor), GFP_KERNEL);
1725 if (!bss_desc)
1726 return -ENOMEM;
1727
1728 ret = mwifiex_fill_new_bss_desc(priv, bss, bss_desc);
1729 if (ret)
1730 goto done;
1731
1732 ret = mwifiex_check_network_compatibility(priv, bss_desc);
1733 if (ret)
1734 goto done;
1735
1736 spin_lock_irqsave(&priv->curr_bcn_buf_lock, flags);
1737
1738 memcpy(&priv->curr_bss_params.bss_descriptor, bss_desc,
1739 sizeof(priv->curr_bss_params.bss_descriptor));
1740
1741
1742
1743
1744 mwifiex_save_curr_bcn(priv);
1745 spin_unlock_irqrestore(&priv->curr_bcn_buf_lock, flags);
1746
1747done:
1748
1749
1750
1751 kfree(bss_desc->beacon_buf);
1752 kfree(bss_desc);
1753 return 0;
1754}
1755
1756static int
1757mwifiex_parse_single_response_buf(struct mwifiex_private *priv, u8 **bss_info,
1758 u32 *bytes_left, u64 fw_tsf, u8 *radio_type,
1759 bool ext_scan, s32 rssi_val)
1760{
1761 struct mwifiex_adapter *adapter = priv->adapter;
1762 struct mwifiex_chan_freq_power *cfp;
1763 struct cfg80211_bss *bss;
1764 u8 bssid[ETH_ALEN];
1765 s32 rssi;
1766 const u8 *ie_buf;
1767 size_t ie_len;
1768 u16 channel = 0;
1769 u16 beacon_size = 0;
1770 u32 curr_bcn_bytes;
1771 u32 freq;
1772 u16 beacon_period;
1773 u16 cap_info_bitmap;
1774 u8 *current_ptr;
1775 u64 timestamp;
1776 struct mwifiex_fixed_bcn_param *bcn_param;
1777 struct mwifiex_bss_priv *bss_priv;
1778
1779 if (*bytes_left >= sizeof(beacon_size)) {
1780
1781 beacon_size = le16_to_cpu(*(__le16 *)(*bss_info));
1782 *bytes_left -= sizeof(beacon_size);
1783 *bss_info += sizeof(beacon_size);
1784 }
1785
1786 if (!beacon_size || beacon_size > *bytes_left) {
1787 *bss_info += *bytes_left;
1788 *bytes_left = 0;
1789 return -EFAULT;
1790 }
1791
1792
1793
1794
1795 current_ptr = *bss_info;
1796
1797
1798 *bss_info += beacon_size;
1799 *bytes_left -= beacon_size;
1800
1801 curr_bcn_bytes = beacon_size;
1802
1803
1804
1805
1806 if (curr_bcn_bytes < ETH_ALEN + sizeof(u8) +
1807 sizeof(struct mwifiex_fixed_bcn_param)) {
1808 mwifiex_dbg(adapter, ERROR,
1809 "InterpretIE: not enough bytes left\n");
1810 return -EFAULT;
1811 }
1812
1813 memcpy(bssid, current_ptr, ETH_ALEN);
1814 current_ptr += ETH_ALEN;
1815 curr_bcn_bytes -= ETH_ALEN;
1816
1817 if (!ext_scan) {
1818 rssi = (s32) *current_ptr;
1819 rssi = (-rssi) * 100;
1820 current_ptr += sizeof(u8);
1821 curr_bcn_bytes -= sizeof(u8);
1822 mwifiex_dbg(adapter, INFO,
1823 "info: InterpretIE: RSSI=%d\n", rssi);
1824 } else {
1825 rssi = rssi_val;
1826 }
1827
1828 bcn_param = (struct mwifiex_fixed_bcn_param *)current_ptr;
1829 current_ptr += sizeof(*bcn_param);
1830 curr_bcn_bytes -= sizeof(*bcn_param);
1831
1832 timestamp = le64_to_cpu(bcn_param->timestamp);
1833 beacon_period = le16_to_cpu(bcn_param->beacon_period);
1834
1835 cap_info_bitmap = le16_to_cpu(bcn_param->cap_info_bitmap);
1836 mwifiex_dbg(adapter, INFO,
1837 "info: InterpretIE: capabilities=0x%X\n",
1838 cap_info_bitmap);
1839
1840
1841 ie_buf = current_ptr;
1842 ie_len = curr_bcn_bytes;
1843 mwifiex_dbg(adapter, INFO,
1844 "info: InterpretIE: IELength for this AP = %d\n",
1845 curr_bcn_bytes);
1846
1847 while (curr_bcn_bytes >= sizeof(struct ieee_types_header)) {
1848 u8 element_id, element_len;
1849
1850 element_id = *current_ptr;
1851 element_len = *(current_ptr + 1);
1852 if (curr_bcn_bytes < element_len +
1853 sizeof(struct ieee_types_header)) {
1854 mwifiex_dbg(adapter, ERROR,
1855 "%s: bytes left < IE length\n", __func__);
1856 return -EFAULT;
1857 }
1858 if (element_id == WLAN_EID_DS_PARAMS) {
1859 channel = *(current_ptr +
1860 sizeof(struct ieee_types_header));
1861 break;
1862 }
1863
1864 current_ptr += element_len + sizeof(struct ieee_types_header);
1865 curr_bcn_bytes -= element_len +
1866 sizeof(struct ieee_types_header);
1867 }
1868
1869 if (channel) {
1870 struct ieee80211_channel *chan;
1871 u8 band;
1872
1873
1874 if (channel == priv->csa_chan) {
1875 mwifiex_dbg(adapter, WARN,
1876 "Dropping entry on csa closed channel\n");
1877 return 0;
1878 }
1879
1880 band = BAND_G;
1881 if (radio_type)
1882 band = mwifiex_radio_type_to_band(*radio_type &
1883 (BIT(0) | BIT(1)));
1884
1885 cfp = mwifiex_get_cfp(priv, band, channel, 0);
1886
1887 freq = cfp ? cfp->freq : 0;
1888
1889 chan = ieee80211_get_channel(priv->wdev.wiphy, freq);
1890
1891 if (chan && !(chan->flags & IEEE80211_CHAN_DISABLED)) {
1892 bss = cfg80211_inform_bss(priv->wdev.wiphy,
1893 chan, CFG80211_BSS_FTYPE_UNKNOWN,
1894 bssid, timestamp,
1895 cap_info_bitmap, beacon_period,
1896 ie_buf, ie_len, rssi, GFP_KERNEL);
1897 if (bss) {
1898 bss_priv = (struct mwifiex_bss_priv *)bss->priv;
1899 bss_priv->band = band;
1900 bss_priv->fw_tsf = fw_tsf;
1901 if (priv->media_connected &&
1902 !memcmp(bssid, priv->curr_bss_params.
1903 bss_descriptor.mac_address,
1904 ETH_ALEN))
1905 mwifiex_update_curr_bss_params(priv,
1906 bss);
1907 cfg80211_put_bss(priv->wdev.wiphy, bss);
1908 }
1909
1910 if ((chan->flags & IEEE80211_CHAN_RADAR) ||
1911 (chan->flags & IEEE80211_CHAN_NO_IR)) {
1912 mwifiex_dbg(adapter, INFO,
1913 "radar or passive channel %d\n",
1914 channel);
1915 mwifiex_save_hidden_ssid_channels(priv, bss);
1916 }
1917 }
1918 } else {
1919 mwifiex_dbg(adapter, WARN, "missing BSS channel IE\n");
1920 }
1921
1922 return 0;
1923}
1924
1925static void mwifiex_complete_scan(struct mwifiex_private *priv)
1926{
1927 struct mwifiex_adapter *adapter = priv->adapter;
1928
1929 adapter->survey_idx = 0;
1930 if (adapter->curr_cmd->wait_q_enabled) {
1931 adapter->cmd_wait_q.status = 0;
1932 if (!priv->scan_request) {
1933 mwifiex_dbg(adapter, INFO,
1934 "complete internal scan\n");
1935 mwifiex_complete_cmd(adapter, adapter->curr_cmd);
1936 }
1937 }
1938}
1939
1940
1941
1942
1943static int
1944mwifiex_active_scan_req_for_passive_chan(struct mwifiex_private *priv)
1945{
1946 int ret;
1947 struct mwifiex_adapter *adapter = priv->adapter;
1948 u8 id = 0;
1949 struct mwifiex_user_scan_cfg *user_scan_cfg;
1950
1951 if (adapter->active_scan_triggered || !priv->scan_request) {
1952 adapter->active_scan_triggered = false;
1953 return 0;
1954 }
1955
1956 if (!priv->hidden_chan[0].chan_number) {
1957 mwifiex_dbg(adapter, INFO, "No BSS with hidden SSID found on DFS channels\n");
1958 return 0;
1959 }
1960 user_scan_cfg = kzalloc(sizeof(*user_scan_cfg), GFP_KERNEL);
1961
1962 if (!user_scan_cfg)
1963 return -ENOMEM;
1964
1965 memset(user_scan_cfg, 0, sizeof(*user_scan_cfg));
1966
1967 for (id = 0; id < MWIFIEX_USER_SCAN_CHAN_MAX; id++) {
1968 if (!priv->hidden_chan[id].chan_number)
1969 break;
1970 memcpy(&user_scan_cfg->chan_list[id],
1971 &priv->hidden_chan[id],
1972 sizeof(struct mwifiex_user_scan_chan));
1973 }
1974
1975 adapter->active_scan_triggered = true;
1976 user_scan_cfg->num_ssids = priv->scan_request->n_ssids;
1977 user_scan_cfg->ssid_list = priv->scan_request->ssids;
1978
1979 ret = mwifiex_scan_networks(priv, user_scan_cfg);
1980 kfree(user_scan_cfg);
1981
1982 memset(&priv->hidden_chan, 0, sizeof(priv->hidden_chan));
1983
1984 if (ret) {
1985 dev_err(priv->adapter->dev, "scan failed: %d\n", ret);
1986 return ret;
1987 }
1988
1989 return 0;
1990}
1991static void mwifiex_check_next_scan_command(struct mwifiex_private *priv)
1992{
1993 struct mwifiex_adapter *adapter = priv->adapter;
1994 struct cmd_ctrl_node *cmd_node, *tmp_node;
1995 unsigned long flags;
1996
1997 spin_lock_irqsave(&adapter->scan_pending_q_lock, flags);
1998 if (list_empty(&adapter->scan_pending_q)) {
1999 spin_unlock_irqrestore(&adapter->scan_pending_q_lock, flags);
2000 spin_lock_irqsave(&adapter->mwifiex_cmd_lock, flags);
2001 adapter->scan_processing = false;
2002 spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, flags);
2003
2004 mwifiex_active_scan_req_for_passive_chan(priv);
2005
2006 if (!adapter->ext_scan)
2007 mwifiex_complete_scan(priv);
2008
2009 if (priv->scan_request) {
2010 mwifiex_dbg(adapter, INFO,
2011 "info: notifying scan done\n");
2012 cfg80211_scan_done(priv->scan_request, 0);
2013 priv->scan_request = NULL;
2014 } else {
2015 priv->scan_aborting = false;
2016 mwifiex_dbg(adapter, INFO,
2017 "info: scan already aborted\n");
2018 }
2019 } else if ((priv->scan_aborting && !priv->scan_request) ||
2020 priv->scan_block) {
2021 list_for_each_entry_safe(cmd_node, tmp_node,
2022 &adapter->scan_pending_q, list) {
2023 list_del(&cmd_node->list);
2024 mwifiex_insert_cmd_to_free_q(adapter, cmd_node);
2025 }
2026 spin_unlock_irqrestore(&adapter->scan_pending_q_lock, flags);
2027
2028 spin_lock_irqsave(&adapter->mwifiex_cmd_lock, flags);
2029 adapter->scan_processing = false;
2030 spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, flags);
2031
2032 if (!adapter->active_scan_triggered) {
2033 if (priv->scan_request) {
2034 mwifiex_dbg(adapter, INFO,
2035 "info: aborting scan\n");
2036 cfg80211_scan_done(priv->scan_request, 1);
2037 priv->scan_request = NULL;
2038 } else {
2039 priv->scan_aborting = false;
2040 mwifiex_dbg(adapter, INFO,
2041 "info: scan already aborted\n");
2042 }
2043 }
2044 } else {
2045
2046
2047
2048 cmd_node = list_first_entry(&adapter->scan_pending_q,
2049 struct cmd_ctrl_node, list);
2050 list_del(&cmd_node->list);
2051 spin_unlock_irqrestore(&adapter->scan_pending_q_lock, flags);
2052 mwifiex_insert_cmd_to_pending_q(adapter, cmd_node, true);
2053 }
2054
2055 return;
2056}
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077int mwifiex_ret_802_11_scan(struct mwifiex_private *priv,
2078 struct host_cmd_ds_command *resp)
2079{
2080 int ret = 0;
2081 struct mwifiex_adapter *adapter = priv->adapter;
2082 struct host_cmd_ds_802_11_scan_rsp *scan_rsp;
2083 struct mwifiex_ie_types_data *tlv_data;
2084 struct mwifiex_ie_types_tsf_timestamp *tsf_tlv;
2085 u8 *bss_info;
2086 u32 scan_resp_size;
2087 u32 bytes_left;
2088 u32 idx;
2089 u32 tlv_buf_size;
2090 struct mwifiex_ie_types_chan_band_list_param_set *chan_band_tlv;
2091 struct chan_band_param_set *chan_band;
2092 u8 is_bgscan_resp;
2093 __le64 fw_tsf = 0;
2094 u8 *radio_type;
2095 struct cfg80211_wowlan_nd_match *pmatch;
2096 struct cfg80211_sched_scan_request *nd_config = NULL;
2097
2098 is_bgscan_resp = (le16_to_cpu(resp->command)
2099 == HostCmd_CMD_802_11_BG_SCAN_QUERY);
2100 if (is_bgscan_resp)
2101 scan_rsp = &resp->params.bg_scan_query_resp.scan_resp;
2102 else
2103 scan_rsp = &resp->params.scan_resp;
2104
2105
2106 if (scan_rsp->number_of_sets > MWIFIEX_MAX_AP) {
2107 mwifiex_dbg(adapter, ERROR,
2108 "SCAN_RESP: too many AP returned (%d)\n",
2109 scan_rsp->number_of_sets);
2110 ret = -1;
2111 goto check_next_scan;
2112 }
2113
2114
2115 mwifiex_11h_get_csa_closed_channel(priv);
2116
2117 bytes_left = le16_to_cpu(scan_rsp->bss_descript_size);
2118 mwifiex_dbg(adapter, INFO,
2119 "info: SCAN_RESP: bss_descript_size %d\n",
2120 bytes_left);
2121
2122 scan_resp_size = le16_to_cpu(resp->size);
2123
2124 mwifiex_dbg(adapter, INFO,
2125 "info: SCAN_RESP: returned %d APs before parsing\n",
2126 scan_rsp->number_of_sets);
2127
2128 bss_info = scan_rsp->bss_desc_and_tlv_buffer;
2129
2130
2131
2132
2133
2134
2135
2136 tlv_buf_size = scan_resp_size - (bytes_left
2137 + sizeof(scan_rsp->bss_descript_size)
2138 + sizeof(scan_rsp->number_of_sets)
2139 + S_DS_GEN);
2140
2141 tlv_data = (struct mwifiex_ie_types_data *) (scan_rsp->
2142 bss_desc_and_tlv_buffer +
2143 bytes_left);
2144
2145
2146
2147 mwifiex_ret_802_11_scan_get_tlv_ptrs(adapter, tlv_data, tlv_buf_size,
2148 TLV_TYPE_TSFTIMESTAMP,
2149 (struct mwifiex_ie_types_data **)
2150 &tsf_tlv);
2151
2152
2153
2154 mwifiex_ret_802_11_scan_get_tlv_ptrs(adapter, tlv_data, tlv_buf_size,
2155 TLV_TYPE_CHANNELBANDLIST,
2156 (struct mwifiex_ie_types_data **)
2157 &chan_band_tlv);
2158
2159#ifdef CONFIG_PM
2160 if (priv->wdev.wiphy->wowlan_config)
2161 nd_config = priv->wdev.wiphy->wowlan_config->nd_config;
2162#endif
2163
2164 if (nd_config) {
2165 adapter->nd_info =
2166 kzalloc(sizeof(struct cfg80211_wowlan_nd_match) +
2167 sizeof(struct cfg80211_wowlan_nd_match *) *
2168 scan_rsp->number_of_sets, GFP_ATOMIC);
2169
2170 if (adapter->nd_info)
2171 adapter->nd_info->n_matches = scan_rsp->number_of_sets;
2172 }
2173
2174 for (idx = 0; idx < scan_rsp->number_of_sets && bytes_left; idx++) {
2175
2176
2177
2178
2179
2180
2181 if (tsf_tlv)
2182 memcpy(&fw_tsf, &tsf_tlv->tsf_data[idx * TSF_DATA_SIZE],
2183 sizeof(fw_tsf));
2184
2185 if (chan_band_tlv) {
2186 chan_band = &chan_band_tlv->chan_band_param[idx];
2187 radio_type = &chan_band->radio_type;
2188 } else {
2189 radio_type = NULL;
2190 }
2191
2192 if (chan_band_tlv && adapter->nd_info) {
2193 adapter->nd_info->matches[idx] =
2194 kzalloc(sizeof(*pmatch) +
2195 sizeof(u32), GFP_ATOMIC);
2196
2197 pmatch = adapter->nd_info->matches[idx];
2198
2199 if (pmatch) {
2200 memset(pmatch, 0, sizeof(*pmatch));
2201 if (chan_band_tlv) {
2202 pmatch->n_channels = 1;
2203 pmatch->channels[0] =
2204 chan_band->chan_number;
2205 }
2206 }
2207 }
2208
2209 ret = mwifiex_parse_single_response_buf(priv, &bss_info,
2210 &bytes_left,
2211 le64_to_cpu(fw_tsf),
2212 radio_type, false, 0);
2213 if (ret)
2214 goto check_next_scan;
2215 }
2216
2217check_next_scan:
2218 mwifiex_check_next_scan_command(priv);
2219 return ret;
2220}
2221
2222
2223
2224
2225
2226
2227
2228
2229int mwifiex_cmd_802_11_scan_ext(struct mwifiex_private *priv,
2230 struct host_cmd_ds_command *cmd,
2231 void *data_buf)
2232{
2233 struct host_cmd_ds_802_11_scan_ext *ext_scan = &cmd->params.ext_scan;
2234 struct mwifiex_scan_cmd_config *scan_cfg = data_buf;
2235
2236 memcpy(ext_scan->tlv_buffer, scan_cfg->tlv_buf, scan_cfg->tlv_buf_len);
2237
2238 cmd->command = cpu_to_le16(HostCmd_CMD_802_11_SCAN_EXT);
2239
2240
2241 cmd->size = cpu_to_le16((u16)(sizeof(ext_scan->reserved)
2242 + scan_cfg->tlv_buf_len + S_DS_GEN));
2243
2244 return 0;
2245}
2246
2247
2248
2249
2250int mwifiex_cmd_802_11_bg_scan_config(struct mwifiex_private *priv,
2251 struct host_cmd_ds_command *cmd,
2252 void *data_buf)
2253{
2254 struct host_cmd_ds_802_11_bg_scan_config *bgscan_config =
2255 &cmd->params.bg_scan_config;
2256 struct mwifiex_bg_scan_cfg *bgscan_cfg_in = data_buf;
2257 u8 *tlv_pos = bgscan_config->tlv;
2258 u8 num_probes;
2259 u32 ssid_len, chan_idx, scan_type, scan_dur, chan_num;
2260 int i;
2261 struct mwifiex_ie_types_num_probes *num_probes_tlv;
2262 struct mwifiex_ie_types_repeat_count *repeat_count_tlv;
2263 struct mwifiex_ie_types_min_rssi_threshold *rssi_threshold_tlv;
2264 struct mwifiex_ie_types_bgscan_start_later *start_later_tlv;
2265 struct mwifiex_ie_types_wildcard_ssid_params *wildcard_ssid_tlv;
2266 struct mwifiex_ie_types_chan_list_param_set *chan_list_tlv;
2267 struct mwifiex_chan_scan_param_set *temp_chan;
2268
2269 cmd->command = cpu_to_le16(HostCmd_CMD_802_11_BG_SCAN_CONFIG);
2270 cmd->size = cpu_to_le16(sizeof(*bgscan_config) + S_DS_GEN);
2271
2272 bgscan_config->action = cpu_to_le16(bgscan_cfg_in->action);
2273 bgscan_config->enable = bgscan_cfg_in->enable;
2274 bgscan_config->bss_type = bgscan_cfg_in->bss_type;
2275 bgscan_config->scan_interval =
2276 cpu_to_le32(bgscan_cfg_in->scan_interval);
2277 bgscan_config->report_condition =
2278 cpu_to_le32(bgscan_cfg_in->report_condition);
2279
2280
2281 if (!bgscan_config->enable)
2282 return 0;
2283
2284 bgscan_config->chan_per_scan = bgscan_cfg_in->chan_per_scan;
2285
2286 num_probes = (bgscan_cfg_in->num_probes ? bgscan_cfg_in->
2287 num_probes : priv->adapter->scan_probes);
2288
2289 if (num_probes) {
2290 num_probes_tlv = (struct mwifiex_ie_types_num_probes *)tlv_pos;
2291 num_probes_tlv->header.type = cpu_to_le16(TLV_TYPE_NUMPROBES);
2292 num_probes_tlv->header.len =
2293 cpu_to_le16(sizeof(num_probes_tlv->num_probes));
2294 num_probes_tlv->num_probes = cpu_to_le16((u16)num_probes);
2295
2296 tlv_pos += sizeof(num_probes_tlv->header) +
2297 le16_to_cpu(num_probes_tlv->header.len);
2298 }
2299
2300 if (bgscan_cfg_in->repeat_count) {
2301 repeat_count_tlv =
2302 (struct mwifiex_ie_types_repeat_count *)tlv_pos;
2303 repeat_count_tlv->header.type =
2304 cpu_to_le16(TLV_TYPE_REPEAT_COUNT);
2305 repeat_count_tlv->header.len =
2306 cpu_to_le16(sizeof(repeat_count_tlv->repeat_count));
2307 repeat_count_tlv->repeat_count =
2308 cpu_to_le16(bgscan_cfg_in->repeat_count);
2309
2310 tlv_pos += sizeof(repeat_count_tlv->header) +
2311 le16_to_cpu(repeat_count_tlv->header.len);
2312 }
2313
2314 if (bgscan_cfg_in->rssi_threshold) {
2315 rssi_threshold_tlv =
2316 (struct mwifiex_ie_types_min_rssi_threshold *)tlv_pos;
2317 rssi_threshold_tlv->header.type =
2318 cpu_to_le16(TLV_TYPE_RSSI_LOW);
2319 rssi_threshold_tlv->header.len =
2320 cpu_to_le16(sizeof(rssi_threshold_tlv->rssi_threshold));
2321 rssi_threshold_tlv->rssi_threshold =
2322 cpu_to_le16(bgscan_cfg_in->rssi_threshold);
2323
2324 tlv_pos += sizeof(rssi_threshold_tlv->header) +
2325 le16_to_cpu(rssi_threshold_tlv->header.len);
2326 }
2327
2328 for (i = 0; i < bgscan_cfg_in->num_ssids; i++) {
2329 ssid_len = bgscan_cfg_in->ssid_list[i].ssid.ssid_len;
2330
2331 wildcard_ssid_tlv =
2332 (struct mwifiex_ie_types_wildcard_ssid_params *)tlv_pos;
2333 wildcard_ssid_tlv->header.type =
2334 cpu_to_le16(TLV_TYPE_WILDCARDSSID);
2335 wildcard_ssid_tlv->header.len = cpu_to_le16(
2336 (u16)(ssid_len + sizeof(wildcard_ssid_tlv->
2337 max_ssid_length)));
2338
2339
2340
2341
2342
2343
2344 if (ssid_len)
2345 wildcard_ssid_tlv->max_ssid_length = 0;
2346 else
2347 wildcard_ssid_tlv->max_ssid_length =
2348 IEEE80211_MAX_SSID_LEN;
2349
2350 memcpy(wildcard_ssid_tlv->ssid,
2351 bgscan_cfg_in->ssid_list[i].ssid.ssid, ssid_len);
2352
2353 tlv_pos += (sizeof(wildcard_ssid_tlv->header)
2354 + le16_to_cpu(wildcard_ssid_tlv->header.len));
2355 }
2356
2357 chan_list_tlv = (struct mwifiex_ie_types_chan_list_param_set *)tlv_pos;
2358
2359 if (bgscan_cfg_in->chan_list[0].chan_number) {
2360 dev_dbg(priv->adapter->dev, "info: bgscan: Using supplied channel list\n");
2361
2362 chan_list_tlv->header.type = cpu_to_le16(TLV_TYPE_CHANLIST);
2363
2364 for (chan_idx = 0;
2365 chan_idx < MWIFIEX_BG_SCAN_CHAN_MAX &&
2366 bgscan_cfg_in->chan_list[chan_idx].chan_number;
2367 chan_idx++) {
2368 temp_chan = chan_list_tlv->chan_scan_param + chan_idx;
2369
2370
2371 le16_add_cpu(&chan_list_tlv->header.len,
2372 sizeof(chan_list_tlv->chan_scan_param));
2373
2374 temp_chan->chan_number =
2375 bgscan_cfg_in->chan_list[chan_idx].chan_number;
2376 temp_chan->radio_type =
2377 bgscan_cfg_in->chan_list[chan_idx].radio_type;
2378
2379 scan_type =
2380 bgscan_cfg_in->chan_list[chan_idx].scan_type;
2381
2382 if (scan_type == MWIFIEX_SCAN_TYPE_PASSIVE)
2383 temp_chan->chan_scan_mode_bitmap
2384 |= MWIFIEX_PASSIVE_SCAN;
2385 else
2386 temp_chan->chan_scan_mode_bitmap
2387 &= ~MWIFIEX_PASSIVE_SCAN;
2388
2389 if (bgscan_cfg_in->chan_list[chan_idx].scan_time) {
2390 scan_dur = (u16)bgscan_cfg_in->
2391 chan_list[chan_idx].scan_time;
2392 } else {
2393 scan_dur = (scan_type ==
2394 MWIFIEX_SCAN_TYPE_PASSIVE) ?
2395 priv->adapter->passive_scan_time :
2396 priv->adapter->specific_scan_time;
2397 }
2398
2399 temp_chan->min_scan_time = cpu_to_le16(scan_dur);
2400 temp_chan->max_scan_time = cpu_to_le16(scan_dur);
2401 }
2402 } else {
2403 dev_dbg(priv->adapter->dev,
2404 "info: bgscan: Creating full region channel list\n");
2405 chan_num =
2406 mwifiex_bgscan_create_channel_list(priv, bgscan_cfg_in,
2407 chan_list_tlv->
2408 chan_scan_param);
2409 le16_add_cpu(&chan_list_tlv->header.len,
2410 chan_num *
2411 sizeof(chan_list_tlv->chan_scan_param[0]));
2412 }
2413
2414 tlv_pos += (sizeof(chan_list_tlv->header)
2415 + le16_to_cpu(chan_list_tlv->header.len));
2416
2417 if (bgscan_cfg_in->start_later) {
2418 start_later_tlv =
2419 (struct mwifiex_ie_types_bgscan_start_later *)tlv_pos;
2420 start_later_tlv->header.type =
2421 cpu_to_le16(TLV_TYPE_BGSCAN_START_LATER);
2422 start_later_tlv->header.len =
2423 cpu_to_le16(sizeof(start_later_tlv->start_later));
2424 start_later_tlv->start_later =
2425 cpu_to_le16(bgscan_cfg_in->start_later);
2426
2427 tlv_pos += sizeof(start_later_tlv->header) +
2428 le16_to_cpu(start_later_tlv->header.len);
2429 }
2430
2431
2432 mwifiex_cmd_append_vsie_tlv(priv, MWIFIEX_VSIE_MASK_BGSCAN, &tlv_pos);
2433
2434 le16_add_cpu(&cmd->size, tlv_pos - bgscan_config->tlv);
2435
2436 return 0;
2437}
2438
2439int mwifiex_stop_bg_scan(struct mwifiex_private *priv)
2440{
2441 struct mwifiex_bg_scan_cfg *bgscan_cfg;
2442
2443 if (!priv->sched_scanning) {
2444 dev_dbg(priv->adapter->dev, "bgscan already stopped!\n");
2445 return 0;
2446 }
2447
2448 bgscan_cfg = kzalloc(sizeof(*bgscan_cfg), GFP_KERNEL);
2449 if (!bgscan_cfg)
2450 return -ENOMEM;
2451
2452 bgscan_cfg->bss_type = MWIFIEX_BSS_MODE_INFRA;
2453 bgscan_cfg->action = MWIFIEX_BGSCAN_ACT_SET;
2454 bgscan_cfg->enable = false;
2455
2456 if (mwifiex_send_cmd(priv, HostCmd_CMD_802_11_BG_SCAN_CONFIG,
2457 HostCmd_ACT_GEN_SET, 0, bgscan_cfg, true)) {
2458 kfree(bgscan_cfg);
2459 return -EFAULT;
2460 }
2461
2462 kfree(bgscan_cfg);
2463 priv->sched_scanning = false;
2464
2465 return 0;
2466}
2467
2468static void
2469mwifiex_update_chan_statistics(struct mwifiex_private *priv,
2470 struct mwifiex_ietypes_chanstats *tlv_stat)
2471{
2472 struct mwifiex_adapter *adapter = priv->adapter;
2473 u8 i, num_chan;
2474 struct mwifiex_fw_chan_stats *fw_chan_stats;
2475 struct mwifiex_chan_stats chan_stats;
2476
2477 fw_chan_stats = (void *)((u8 *)tlv_stat +
2478 sizeof(struct mwifiex_ie_types_header));
2479 num_chan = le16_to_cpu(tlv_stat->header.len) /
2480 sizeof(struct mwifiex_chan_stats);
2481
2482 for (i = 0 ; i < num_chan; i++) {
2483 chan_stats.chan_num = fw_chan_stats->chan_num;
2484 chan_stats.bandcfg = fw_chan_stats->bandcfg;
2485 chan_stats.flags = fw_chan_stats->flags;
2486 chan_stats.noise = fw_chan_stats->noise;
2487 chan_stats.total_bss = le16_to_cpu(fw_chan_stats->total_bss);
2488 chan_stats.cca_scan_dur =
2489 le16_to_cpu(fw_chan_stats->cca_scan_dur);
2490 chan_stats.cca_busy_dur =
2491 le16_to_cpu(fw_chan_stats->cca_busy_dur);
2492 mwifiex_dbg(adapter, INFO,
2493 "chan=%d, noise=%d, total_network=%d scan_duration=%d, busy_duration=%d\n",
2494 chan_stats.chan_num,
2495 chan_stats.noise,
2496 chan_stats.total_bss,
2497 chan_stats.cca_scan_dur,
2498 chan_stats.cca_busy_dur);
2499 memcpy(&adapter->chan_stats[adapter->survey_idx++], &chan_stats,
2500 sizeof(struct mwifiex_chan_stats));
2501 fw_chan_stats++;
2502 }
2503}
2504
2505
2506int mwifiex_ret_802_11_scan_ext(struct mwifiex_private *priv,
2507 struct host_cmd_ds_command *resp)
2508{
2509 struct mwifiex_adapter *adapter = priv->adapter;
2510 struct host_cmd_ds_802_11_scan_ext *ext_scan_resp;
2511 struct mwifiex_ie_types_header *tlv;
2512 struct mwifiex_ietypes_chanstats *tlv_stat;
2513 u16 buf_left, type, len;
2514
2515 struct host_cmd_ds_command *cmd_ptr;
2516 struct cmd_ctrl_node *cmd_node;
2517 unsigned long cmd_flags, scan_flags;
2518 bool complete_scan = false;
2519
2520 mwifiex_dbg(adapter, INFO, "info: EXT scan returns successfully\n");
2521
2522 ext_scan_resp = &resp->params.ext_scan;
2523
2524 tlv = (void *)ext_scan_resp->tlv_buffer;
2525 buf_left = le16_to_cpu(resp->size) - (sizeof(*ext_scan_resp) + S_DS_GEN
2526 - 1);
2527
2528 while (buf_left >= sizeof(struct mwifiex_ie_types_header)) {
2529 type = le16_to_cpu(tlv->type);
2530 len = le16_to_cpu(tlv->len);
2531
2532 if (buf_left < (sizeof(struct mwifiex_ie_types_header) + len)) {
2533 mwifiex_dbg(adapter, ERROR,
2534 "error processing scan response TLVs");
2535 break;
2536 }
2537
2538 switch (type) {
2539 case TLV_TYPE_CHANNEL_STATS:
2540 tlv_stat = (void *)tlv;
2541 mwifiex_update_chan_statistics(priv, tlv_stat);
2542 break;
2543 default:
2544 break;
2545 }
2546
2547 buf_left -= len + sizeof(struct mwifiex_ie_types_header);
2548 tlv = (void *)((u8 *)tlv + len +
2549 sizeof(struct mwifiex_ie_types_header));
2550 }
2551
2552 spin_lock_irqsave(&adapter->cmd_pending_q_lock, cmd_flags);
2553 spin_lock_irqsave(&adapter->scan_pending_q_lock, scan_flags);
2554 if (list_empty(&adapter->scan_pending_q)) {
2555 complete_scan = true;
2556 list_for_each_entry(cmd_node, &adapter->cmd_pending_q, list) {
2557 cmd_ptr = (void *)cmd_node->cmd_skb->data;
2558 if (le16_to_cpu(cmd_ptr->command) ==
2559 HostCmd_CMD_802_11_SCAN_EXT) {
2560 mwifiex_dbg(adapter, INFO,
2561 "Scan pending in command pending list");
2562 complete_scan = false;
2563 break;
2564 }
2565 }
2566 }
2567 spin_unlock_irqrestore(&adapter->scan_pending_q_lock, scan_flags);
2568 spin_unlock_irqrestore(&adapter->cmd_pending_q_lock, cmd_flags);
2569
2570 if (complete_scan)
2571 mwifiex_complete_scan(priv);
2572
2573 return 0;
2574}
2575
2576
2577
2578
2579int mwifiex_handle_event_ext_scan_report(struct mwifiex_private *priv,
2580 void *buf)
2581{
2582 int ret = 0;
2583 struct mwifiex_adapter *adapter = priv->adapter;
2584 u8 *bss_info;
2585 u32 bytes_left, bytes_left_for_tlv, idx;
2586 u16 type, len;
2587 struct mwifiex_ie_types_data *tlv;
2588 struct mwifiex_ie_types_bss_scan_rsp *scan_rsp_tlv;
2589 struct mwifiex_ie_types_bss_scan_info *scan_info_tlv;
2590 u8 *radio_type;
2591 u64 fw_tsf = 0;
2592 s32 rssi = 0;
2593 struct mwifiex_event_scan_result *event_scan = buf;
2594 u8 num_of_set = event_scan->num_of_set;
2595 u8 *scan_resp = buf + sizeof(struct mwifiex_event_scan_result);
2596 u16 scan_resp_size = le16_to_cpu(event_scan->buf_size);
2597
2598 if (num_of_set > MWIFIEX_MAX_AP) {
2599 mwifiex_dbg(adapter, ERROR,
2600 "EXT_SCAN: Invalid number of AP returned (%d)!!\n",
2601 num_of_set);
2602 ret = -1;
2603 goto check_next_scan;
2604 }
2605
2606 bytes_left = scan_resp_size;
2607 mwifiex_dbg(adapter, INFO,
2608 "EXT_SCAN: size %d, returned %d APs...",
2609 scan_resp_size, num_of_set);
2610 mwifiex_dbg_dump(adapter, CMD_D, "EXT_SCAN buffer:", buf,
2611 scan_resp_size +
2612 sizeof(struct mwifiex_event_scan_result));
2613
2614 tlv = (struct mwifiex_ie_types_data *)scan_resp;
2615
2616 for (idx = 0; idx < num_of_set && bytes_left; idx++) {
2617 type = le16_to_cpu(tlv->header.type);
2618 len = le16_to_cpu(tlv->header.len);
2619 if (bytes_left < sizeof(struct mwifiex_ie_types_header) + len) {
2620 mwifiex_dbg(adapter, ERROR,
2621 "EXT_SCAN: Error bytes left < TLV length\n");
2622 break;
2623 }
2624 scan_rsp_tlv = NULL;
2625 scan_info_tlv = NULL;
2626 bytes_left_for_tlv = bytes_left;
2627
2628
2629
2630
2631 if (type != TLV_TYPE_BSS_SCAN_RSP)
2632 break;
2633
2634 bss_info = (u8 *)tlv;
2635 scan_rsp_tlv = (struct mwifiex_ie_types_bss_scan_rsp *)tlv;
2636 tlv = (struct mwifiex_ie_types_data *)(tlv->data + len);
2637 bytes_left_for_tlv -=
2638 (len + sizeof(struct mwifiex_ie_types_header));
2639
2640 while (bytes_left_for_tlv >=
2641 sizeof(struct mwifiex_ie_types_header) &&
2642 le16_to_cpu(tlv->header.type) != TLV_TYPE_BSS_SCAN_RSP) {
2643 type = le16_to_cpu(tlv->header.type);
2644 len = le16_to_cpu(tlv->header.len);
2645 if (bytes_left_for_tlv <
2646 sizeof(struct mwifiex_ie_types_header) + len) {
2647 mwifiex_dbg(adapter, ERROR,
2648 "EXT_SCAN: Error in processing TLV,\t"
2649 "bytes left < TLV length\n");
2650 scan_rsp_tlv = NULL;
2651 bytes_left_for_tlv = 0;
2652 continue;
2653 }
2654 switch (type) {
2655 case TLV_TYPE_BSS_SCAN_INFO:
2656 scan_info_tlv =
2657 (struct mwifiex_ie_types_bss_scan_info *)tlv;
2658 if (len !=
2659 sizeof(struct mwifiex_ie_types_bss_scan_info) -
2660 sizeof(struct mwifiex_ie_types_header)) {
2661 bytes_left_for_tlv = 0;
2662 continue;
2663 }
2664 break;
2665 default:
2666 break;
2667 }
2668 tlv = (struct mwifiex_ie_types_data *)(tlv->data + len);
2669 bytes_left -=
2670 (len + sizeof(struct mwifiex_ie_types_header));
2671 bytes_left_for_tlv -=
2672 (len + sizeof(struct mwifiex_ie_types_header));
2673 }
2674
2675 if (!scan_rsp_tlv)
2676 break;
2677
2678
2679
2680
2681
2682
2683 bss_info += sizeof(u16);
2684 bytes_left -= sizeof(u16);
2685
2686 if (scan_info_tlv) {
2687 rssi = (s32)(s16)(le16_to_cpu(scan_info_tlv->rssi));
2688 rssi *= 100;
2689 mwifiex_dbg(adapter, INFO,
2690 "info: InterpretIE: RSSI=%d\n", rssi);
2691 fw_tsf = le64_to_cpu(scan_info_tlv->tsf);
2692 radio_type = &scan_info_tlv->radio_type;
2693 } else {
2694 radio_type = NULL;
2695 }
2696 ret = mwifiex_parse_single_response_buf(priv, &bss_info,
2697 &bytes_left, fw_tsf,
2698 radio_type, true, rssi);
2699 if (ret)
2700 goto check_next_scan;
2701 }
2702
2703check_next_scan:
2704 if (!event_scan->more_event)
2705 mwifiex_check_next_scan_command(priv);
2706
2707 return ret;
2708}
2709
2710
2711
2712
2713
2714
2715
2716
2717
2718int mwifiex_cmd_802_11_bg_scan_query(struct host_cmd_ds_command *cmd)
2719{
2720 struct host_cmd_ds_802_11_bg_scan_query *bg_query =
2721 &cmd->params.bg_scan_query;
2722
2723 cmd->command = cpu_to_le16(HostCmd_CMD_802_11_BG_SCAN_QUERY);
2724 cmd->size = cpu_to_le16(sizeof(struct host_cmd_ds_802_11_bg_scan_query)
2725 + S_DS_GEN);
2726
2727 bg_query->flush = 1;
2728
2729 return 0;
2730}
2731
2732
2733
2734
2735void
2736mwifiex_queue_scan_cmd(struct mwifiex_private *priv,
2737 struct cmd_ctrl_node *cmd_node)
2738{
2739 struct mwifiex_adapter *adapter = priv->adapter;
2740 unsigned long flags;
2741
2742 cmd_node->wait_q_enabled = true;
2743 cmd_node->condition = &adapter->scan_wait_q_woken;
2744 spin_lock_irqsave(&adapter->scan_pending_q_lock, flags);
2745 list_add_tail(&cmd_node->list, &adapter->scan_pending_q);
2746 spin_unlock_irqrestore(&adapter->scan_pending_q_lock, flags);
2747}
2748
2749
2750
2751
2752
2753static int mwifiex_scan_specific_ssid(struct mwifiex_private *priv,
2754 struct cfg80211_ssid *req_ssid)
2755{
2756 struct mwifiex_adapter *adapter = priv->adapter;
2757 int ret;
2758 struct mwifiex_user_scan_cfg *scan_cfg;
2759
2760 if (adapter->scan_processing) {
2761 mwifiex_dbg(adapter, WARN,
2762 "cmd: Scan already in process...\n");
2763 return -EBUSY;
2764 }
2765
2766 if (priv->scan_block) {
2767 mwifiex_dbg(adapter, WARN,
2768 "cmd: Scan is blocked during association...\n");
2769 return -EBUSY;
2770 }
2771
2772 scan_cfg = kzalloc(sizeof(struct mwifiex_user_scan_cfg), GFP_KERNEL);
2773 if (!scan_cfg)
2774 return -ENOMEM;
2775
2776 scan_cfg->ssid_list = req_ssid;
2777 scan_cfg->num_ssids = 1;
2778
2779 ret = mwifiex_scan_networks(priv, scan_cfg);
2780
2781 kfree(scan_cfg);
2782 return ret;
2783}
2784
2785
2786
2787
2788
2789
2790
2791
2792
2793
2794int mwifiex_request_scan(struct mwifiex_private *priv,
2795 struct cfg80211_ssid *req_ssid)
2796{
2797 int ret;
2798
2799 if (down_interruptible(&priv->async_sem)) {
2800 mwifiex_dbg(priv->adapter, ERROR,
2801 "%s: acquire semaphore fail\n",
2802 __func__);
2803 return -1;
2804 }
2805
2806 priv->adapter->scan_wait_q_woken = false;
2807
2808 if (req_ssid && req_ssid->ssid_len != 0)
2809
2810 ret = mwifiex_scan_specific_ssid(priv, req_ssid);
2811 else
2812
2813 ret = mwifiex_scan_networks(priv, NULL);
2814
2815 up(&priv->async_sem);
2816
2817 return ret;
2818}
2819
2820
2821
2822
2823int
2824mwifiex_cmd_append_vsie_tlv(struct mwifiex_private *priv,
2825 u16 vsie_mask, u8 **buffer)
2826{
2827 int id, ret_len = 0;
2828 struct mwifiex_ie_types_vendor_param_set *vs_param_set;
2829
2830 if (!buffer)
2831 return 0;
2832 if (!(*buffer))
2833 return 0;
2834
2835
2836
2837
2838
2839 for (id = 0; id < MWIFIEX_MAX_VSIE_NUM; id++) {
2840 if (priv->vs_ie[id].mask & vsie_mask) {
2841 vs_param_set =
2842 (struct mwifiex_ie_types_vendor_param_set *)
2843 *buffer;
2844 vs_param_set->header.type =
2845 cpu_to_le16(TLV_TYPE_PASSTHROUGH);
2846 vs_param_set->header.len =
2847 cpu_to_le16((((u16) priv->vs_ie[id].ie[1])
2848 & 0x00FF) + 2);
2849 memcpy(vs_param_set->ie, priv->vs_ie[id].ie,
2850 le16_to_cpu(vs_param_set->header.len));
2851 *buffer += le16_to_cpu(vs_param_set->header.len) +
2852 sizeof(struct mwifiex_ie_types_header);
2853 ret_len += le16_to_cpu(vs_param_set->header.len) +
2854 sizeof(struct mwifiex_ie_types_header);
2855 }
2856 }
2857 return ret_len;
2858}
2859
2860
2861
2862
2863
2864
2865
2866
2867
2868
2869void
2870mwifiex_save_curr_bcn(struct mwifiex_private *priv)
2871{
2872 struct mwifiex_bssdescriptor *curr_bss =
2873 &priv->curr_bss_params.bss_descriptor;
2874
2875 if (!curr_bss->beacon_buf_size)
2876 return;
2877
2878
2879 if (!priv->curr_bcn_buf ||
2880 priv->curr_bcn_size != curr_bss->beacon_buf_size) {
2881 priv->curr_bcn_size = curr_bss->beacon_buf_size;
2882
2883 kfree(priv->curr_bcn_buf);
2884 priv->curr_bcn_buf = kmalloc(curr_bss->beacon_buf_size,
2885 GFP_ATOMIC);
2886 if (!priv->curr_bcn_buf)
2887 return;
2888 }
2889
2890 memcpy(priv->curr_bcn_buf, curr_bss->beacon_buf,
2891 curr_bss->beacon_buf_size);
2892 mwifiex_dbg(priv->adapter, INFO,
2893 "info: current beacon saved %d\n",
2894 priv->curr_bcn_size);
2895
2896 curr_bss->beacon_buf = priv->curr_bcn_buf;
2897
2898
2899 if (curr_bss->bcn_wpa_ie)
2900 curr_bss->bcn_wpa_ie =
2901 (struct ieee_types_vendor_specific *)
2902 (curr_bss->beacon_buf +
2903 curr_bss->wpa_offset);
2904
2905 if (curr_bss->bcn_rsn_ie)
2906 curr_bss->bcn_rsn_ie = (struct ieee_types_generic *)
2907 (curr_bss->beacon_buf +
2908 curr_bss->rsn_offset);
2909
2910 if (curr_bss->bcn_ht_cap)
2911 curr_bss->bcn_ht_cap = (struct ieee80211_ht_cap *)
2912 (curr_bss->beacon_buf +
2913 curr_bss->ht_cap_offset);
2914
2915 if (curr_bss->bcn_ht_oper)
2916 curr_bss->bcn_ht_oper = (struct ieee80211_ht_operation *)
2917 (curr_bss->beacon_buf +
2918 curr_bss->ht_info_offset);
2919
2920 if (curr_bss->bcn_vht_cap)
2921 curr_bss->bcn_vht_cap = (void *)(curr_bss->beacon_buf +
2922 curr_bss->vht_cap_offset);
2923
2924 if (curr_bss->bcn_vht_oper)
2925 curr_bss->bcn_vht_oper = (void *)(curr_bss->beacon_buf +
2926 curr_bss->vht_info_offset);
2927
2928 if (curr_bss->bcn_bss_co_2040)
2929 curr_bss->bcn_bss_co_2040 =
2930 (curr_bss->beacon_buf + curr_bss->bss_co_2040_offset);
2931
2932 if (curr_bss->bcn_ext_cap)
2933 curr_bss->bcn_ext_cap = curr_bss->beacon_buf +
2934 curr_bss->ext_cap_offset;
2935
2936 if (curr_bss->oper_mode)
2937 curr_bss->oper_mode = (void *)(curr_bss->beacon_buf +
2938 curr_bss->oper_mode_offset);
2939}
2940
2941
2942
2943
2944void
2945mwifiex_free_curr_bcn(struct mwifiex_private *priv)
2946{
2947 kfree(priv->curr_bcn_buf);
2948 priv->curr_bcn_buf = NULL;
2949}
2950