1// SPDX-License-Identifier: GPL-2.0
2/******************************************************************************
3 *
4 * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
5 *
6 ******************************************************************************/
7#include <linux/etherdevice.h>
8#include <drv_types.h>
9#include <rtw_debug.h>
10#include <hal_btcoex.h>
11#include <linux/jiffies.h>
12
13int rtw_init_mlme_priv(struct adapter *padapter)
14{
15 int i;
16 u8 *pbuf;
17 struct wlan_network *pnetwork;
18 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
19 int res = _SUCCESS;
20
21 pmlmepriv->nic_hdl = (u8 *)padapter;
22
23 pmlmepriv->pscanned = NULL;
24 pmlmepriv->fw_state = WIFI_STATION_STATE; /* Must sync with rtw_wdev_alloc() */
25 /* wdev->iftype = NL80211_IFTYPE_STATION */
26 pmlmepriv->cur_network.network.infrastructure_mode = Ndis802_11AutoUnknown;
27 pmlmepriv->scan_mode = SCAN_ACTIVE;/* 1: active, 0: passive. Maybe someday we should rename this varable to "active_mode" (Jeff) */
28
29 spin_lock_init(&pmlmepriv->lock);
30 INIT_LIST_HEAD(list: &pmlmepriv->free_bss_pool.queue);
31 spin_lock_init(&pmlmepriv->free_bss_pool.lock);
32 INIT_LIST_HEAD(list: &pmlmepriv->scanned_queue.queue);
33 spin_lock_init(&pmlmepriv->scanned_queue.lock);
34
35 memset(&pmlmepriv->assoc_ssid, 0, sizeof(struct ndis_802_11_ssid));
36
37 pbuf = vzalloc(array_size(MAX_BSS_CNT, sizeof(struct wlan_network)));
38
39 if (!pbuf) {
40 res = _FAIL;
41 goto exit;
42 }
43 pmlmepriv->free_bss_buf = pbuf;
44
45 pnetwork = (struct wlan_network *)pbuf;
46
47 for (i = 0; i < MAX_BSS_CNT; i++) {
48 INIT_LIST_HEAD(list: &pnetwork->list);
49
50 list_add_tail(new: &pnetwork->list, head: &pmlmepriv->free_bss_pool.queue);
51
52 pnetwork++;
53 }
54
55 /* allocate DMA-able/Non-Page memory for cmd_buf and rsp_buf */
56
57 rtw_clear_scan_deny(adapter: padapter);
58
59 #define RTW_ROAM_SCAN_RESULT_EXP_MS 5000
60 #define RTW_ROAM_RSSI_DIFF_TH 10
61 #define RTW_ROAM_SCAN_INTERVAL_MS 10000
62
63 pmlmepriv->roam_flags = 0
64 | RTW_ROAM_ON_EXPIRED
65 | RTW_ROAM_ON_RESUME
66 ;
67
68 pmlmepriv->roam_scanr_exp_ms = RTW_ROAM_SCAN_RESULT_EXP_MS;
69 pmlmepriv->roam_rssi_diff_th = RTW_ROAM_RSSI_DIFF_TH;
70 pmlmepriv->roam_scan_int_ms = RTW_ROAM_SCAN_INTERVAL_MS;
71
72 rtw_init_mlme_timer(padapter);
73
74exit:
75
76 return res;
77}
78
79static void rtw_free_mlme_ie_data(u8 **ppie, u32 *plen)
80{
81 if (*ppie) {
82 kfree(objp: *ppie);
83 *plen = 0;
84 *ppie = NULL;
85 }
86}
87
88void rtw_free_mlme_priv_ie_data(struct mlme_priv *pmlmepriv)
89{
90 rtw_buf_free(buf: &pmlmepriv->assoc_req, buf_len: &pmlmepriv->assoc_req_len);
91 rtw_buf_free(buf: &pmlmepriv->assoc_rsp, buf_len: &pmlmepriv->assoc_rsp_len);
92 rtw_free_mlme_ie_data(ppie: &pmlmepriv->wps_beacon_ie, plen: &pmlmepriv->wps_beacon_ie_len);
93 rtw_free_mlme_ie_data(ppie: &pmlmepriv->wps_probe_req_ie, plen: &pmlmepriv->wps_probe_req_ie_len);
94 rtw_free_mlme_ie_data(ppie: &pmlmepriv->wps_probe_resp_ie, plen: &pmlmepriv->wps_probe_resp_ie_len);
95 rtw_free_mlme_ie_data(ppie: &pmlmepriv->wps_assoc_resp_ie, plen: &pmlmepriv->wps_assoc_resp_ie_len);
96
97 rtw_free_mlme_ie_data(ppie: &pmlmepriv->p2p_beacon_ie, plen: &pmlmepriv->p2p_beacon_ie_len);
98 rtw_free_mlme_ie_data(ppie: &pmlmepriv->p2p_probe_req_ie, plen: &pmlmepriv->p2p_probe_req_ie_len);
99 rtw_free_mlme_ie_data(ppie: &pmlmepriv->p2p_probe_resp_ie, plen: &pmlmepriv->p2p_probe_resp_ie_len);
100 rtw_free_mlme_ie_data(ppie: &pmlmepriv->p2p_go_probe_resp_ie, plen: &pmlmepriv->p2p_go_probe_resp_ie_len);
101 rtw_free_mlme_ie_data(ppie: &pmlmepriv->p2p_assoc_req_ie, plen: &pmlmepriv->p2p_assoc_req_ie_len);
102}
103
104void _rtw_free_mlme_priv(struct mlme_priv *pmlmepriv)
105{
106 if (pmlmepriv) {
107 rtw_free_mlme_priv_ie_data(pmlmepriv);
108 vfree(addr: pmlmepriv->free_bss_buf);
109 }
110}
111
112/*
113struct wlan_network *_rtw_dequeue_network(struct __queue *queue)
114{
115 _irqL irqL;
116
117 struct wlan_network *pnetwork;
118
119 spin_lock_bh(&queue->lock);
120
121 if (list_empty(&queue->queue))
122
123 pnetwork = NULL;
124
125 else
126 {
127 pnetwork = container_of(get_next(&queue->queue), struct wlan_network, list);
128
129 list_del_init(&(pnetwork->list));
130 }
131
132 spin_unlock_bh(&queue->lock);
133
134 return pnetwork;
135}
136*/
137
138struct wlan_network *rtw_alloc_network(struct mlme_priv *pmlmepriv)
139{
140 struct wlan_network *pnetwork;
141 struct __queue *free_queue = &pmlmepriv->free_bss_pool;
142 struct list_head *plist = NULL;
143
144 spin_lock_bh(lock: &free_queue->lock);
145
146 if (list_empty(head: &free_queue->queue)) {
147 pnetwork = NULL;
148 goto exit;
149 }
150 plist = get_next(list: &(free_queue->queue));
151
152 pnetwork = container_of(plist, struct wlan_network, list);
153
154 list_del_init(entry: &pnetwork->list);
155
156 pnetwork->network_type = 0;
157 pnetwork->fixed = false;
158 pnetwork->last_scanned = jiffies;
159 pnetwork->aid = 0;
160 pnetwork->join_res = 0;
161
162exit:
163 spin_unlock_bh(lock: &free_queue->lock);
164
165 return pnetwork;
166}
167
168void _rtw_free_network(struct mlme_priv *pmlmepriv, struct wlan_network *pnetwork, u8 isfreeall)
169{
170 unsigned int delta_time;
171 u32 lifetime = SCANQUEUE_LIFETIME;
172 struct __queue *free_queue = &(pmlmepriv->free_bss_pool);
173
174 if (!pnetwork)
175 return;
176
177 if (pnetwork->fixed)
178 return;
179
180 if ((check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) == true) ||
181 (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE) == true))
182 lifetime = 1;
183
184 if (!isfreeall) {
185 delta_time = jiffies_to_msecs(j: jiffies - pnetwork->last_scanned);
186 if (delta_time < lifetime)/* unit:msec */
187 return;
188 }
189
190 spin_lock_bh(lock: &free_queue->lock);
191
192 list_del_init(entry: &(pnetwork->list));
193
194 list_add_tail(new: &(pnetwork->list), head: &(free_queue->queue));
195
196 spin_unlock_bh(lock: &free_queue->lock);
197}
198
199void _rtw_free_network_nolock(struct mlme_priv *pmlmepriv, struct wlan_network *pnetwork)
200{
201
202 struct __queue *free_queue = &(pmlmepriv->free_bss_pool);
203
204 if (!pnetwork)
205 return;
206
207 if (pnetwork->fixed)
208 return;
209
210 /* spin_lock_irqsave(&free_queue->lock, irqL); */
211
212 list_del_init(entry: &(pnetwork->list));
213
214 list_add_tail(new: &(pnetwork->list), head: get_list_head(queue: free_queue));
215
216 /* spin_unlock_irqrestore(&free_queue->lock, irqL); */
217}
218
219/*
220 return the wlan_network with the matching addr
221
222 Shall be called under atomic context... to avoid possible racing condition...
223*/
224struct wlan_network *_rtw_find_network(struct __queue *scanned_queue, u8 *addr)
225{
226 struct list_head *phead, *plist;
227 struct wlan_network *pnetwork = NULL;
228
229 if (is_zero_ether_addr(addr)) {
230 pnetwork = NULL;
231 goto exit;
232 }
233
234 /* spin_lock_bh(&scanned_queue->lock); */
235
236 phead = get_list_head(queue: scanned_queue);
237 list_for_each(plist, phead) {
238 pnetwork = list_entry(plist, struct wlan_network, list);
239
240 if (!memcmp(p: addr, q: pnetwork->network.mac_address, ETH_ALEN))
241 break;
242 }
243
244 if (plist == phead)
245 pnetwork = NULL;
246
247 /* spin_unlock_bh(&scanned_queue->lock); */
248
249exit:
250 return pnetwork;
251}
252
253void rtw_free_network_queue(struct adapter *padapter, u8 isfreeall)
254{
255 struct list_head *phead, *plist, *tmp;
256 struct wlan_network *pnetwork;
257 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
258 struct __queue *scanned_queue = &pmlmepriv->scanned_queue;
259
260 spin_lock_bh(lock: &scanned_queue->lock);
261
262 phead = get_list_head(queue: scanned_queue);
263 list_for_each_safe(plist, tmp, phead) {
264
265 pnetwork = list_entry(plist, struct wlan_network, list);
266
267 _rtw_free_network(pmlmepriv, pnetwork, isfreeall);
268
269 }
270
271 spin_unlock_bh(lock: &scanned_queue->lock);
272}
273
274signed int rtw_if_up(struct adapter *padapter)
275{
276 signed int res;
277
278 if (padapter->bDriverStopped || padapter->bSurpriseRemoved ||
279 (check_fwstate(pmlmepriv: &padapter->mlmepriv, _FW_LINKED) == false))
280 res = false;
281 else
282 res = true;
283
284 return res;
285}
286
287void rtw_generate_random_ibss(u8 *pibss)
288{
289 unsigned long curtime = jiffies;
290
291 pibss[0] = 0x02; /* in ad-hoc mode bit1 must set to 1 */
292 pibss[1] = 0x11;
293 pibss[2] = 0x87;
294 pibss[3] = (u8)(curtime & 0xff) ;/* p[0]; */
295 pibss[4] = (u8)((curtime>>8) & 0xff) ;/* p[1]; */
296 pibss[5] = (u8)((curtime>>16) & 0xff) ;/* p[2]; */
297}
298
299u8 *rtw_get_capability_from_ie(u8 *ie)
300{
301 return ie + 8 + 2;
302}
303
304u16 rtw_get_capability(struct wlan_bssid_ex *bss)
305{
306 __le16 val;
307
308 memcpy((u8 *)&val, rtw_get_capability_from_ie(bss->ies), 2);
309
310 return le16_to_cpu(val);
311}
312
313u8 *rtw_get_beacon_interval_from_ie(u8 *ie)
314{
315 return ie + 8;
316}
317
318void rtw_free_mlme_priv(struct mlme_priv *pmlmepriv)
319{
320 _rtw_free_mlme_priv(pmlmepriv);
321}
322
323/*
324static struct wlan_network *rtw_dequeue_network(struct __queue *queue)
325{
326 struct wlan_network *pnetwork;
327
328 pnetwork = _rtw_dequeue_network(queue);
329 return pnetwork;
330}
331*/
332
333void rtw_free_network_nolock(struct adapter *padapter, struct wlan_network *pnetwork);
334void rtw_free_network_nolock(struct adapter *padapter, struct wlan_network *pnetwork)
335{
336 _rtw_free_network_nolock(pmlmepriv: &(padapter->mlmepriv), pnetwork);
337 rtw_cfg80211_unlink_bss(padapter, pnetwork);
338}
339
340/*
341 return the wlan_network with the matching addr
342
343 Shall be called under atomic context... to avoid possible racing condition...
344*/
345struct wlan_network *rtw_find_network(struct __queue *scanned_queue, u8 *addr)
346{
347 struct wlan_network *pnetwork = _rtw_find_network(scanned_queue, addr);
348
349 return pnetwork;
350}
351
352int rtw_is_same_ibss(struct adapter *adapter, struct wlan_network *pnetwork)
353{
354 int ret = true;
355 struct security_priv *psecuritypriv = &adapter->securitypriv;
356
357 if ((psecuritypriv->dot11PrivacyAlgrthm != _NO_PRIVACY_) &&
358 (pnetwork->network.privacy == 0))
359 ret = false;
360 else if ((psecuritypriv->dot11PrivacyAlgrthm == _NO_PRIVACY_) &&
361 (pnetwork->network.privacy == 1))
362 ret = false;
363 else
364 ret = true;
365
366 return ret;
367
368}
369
370inline int is_same_ess(struct wlan_bssid_ex *a, struct wlan_bssid_ex *b)
371{
372 return (a->ssid.ssid_length == b->ssid.ssid_length)
373 && !memcmp(p: a->ssid.ssid, q: b->ssid.ssid, size: a->ssid.ssid_length);
374}
375
376int is_same_network(struct wlan_bssid_ex *src, struct wlan_bssid_ex *dst, u8 feature)
377{
378 u16 s_cap, d_cap;
379 __le16 tmps, tmpd;
380
381 if (rtw_bug_check(parg1: dst, parg2: src, parg3: &s_cap, parg4: &d_cap) == false)
382 return false;
383
384 memcpy((u8 *)&tmps, rtw_get_capability_from_ie(src->ies), 2);
385 memcpy((u8 *)&tmpd, rtw_get_capability_from_ie(dst->ies), 2);
386
387 s_cap = le16_to_cpu(tmps);
388 d_cap = le16_to_cpu(tmpd);
389
390 return (src->ssid.ssid_length == dst->ssid.ssid_length) &&
391 ((!memcmp(p: src->mac_address, q: dst->mac_address, ETH_ALEN))) &&
392 ((!memcmp(p: src->ssid.ssid, q: dst->ssid.ssid, size: src->ssid.ssid_length))) &&
393 ((s_cap & WLAN_CAPABILITY_IBSS) ==
394 (d_cap & WLAN_CAPABILITY_IBSS)) &&
395 ((s_cap & WLAN_CAPABILITY_ESS) ==
396 (d_cap & WLAN_CAPABILITY_ESS));
397
398}
399
400struct wlan_network *_rtw_find_same_network(struct __queue *scanned_queue, struct wlan_network *network)
401{
402 struct list_head *phead, *plist;
403 struct wlan_network *found = NULL;
404
405 phead = get_list_head(queue: scanned_queue);
406 list_for_each(plist, phead) {
407 found = list_entry(plist, struct wlan_network, list);
408
409 if (is_same_network(src: &network->network, dst: &found->network, feature: 0))
410 break;
411 }
412
413 if (plist == phead)
414 found = NULL;
415
416 return found;
417}
418
419struct wlan_network *rtw_get_oldest_wlan_network(struct __queue *scanned_queue)
420{
421 struct list_head *plist, *phead;
422
423 struct wlan_network *pwlan = NULL;
424 struct wlan_network *oldest = NULL;
425
426 phead = get_list_head(queue: scanned_queue);
427
428 list_for_each(plist, phead) {
429
430 pwlan = list_entry(plist, struct wlan_network, list);
431
432 if (!pwlan->fixed) {
433 if (!oldest || time_after(oldest->last_scanned, pwlan->last_scanned))
434 oldest = pwlan;
435 }
436 }
437 return oldest;
438
439}
440
441void update_network(struct wlan_bssid_ex *dst, struct wlan_bssid_ex *src,
442 struct adapter *padapter, bool update_ie)
443{
444 long rssi_ori = dst->rssi;
445
446 u8 sq_smp = src->phy_info.signal_quality;
447
448 u8 ss_final;
449 u8 sq_final;
450 long rssi_final;
451
452 /* The rule below is 1/5 for sample value, 4/5 for history value */
453 if (check_fwstate(pmlmepriv: &padapter->mlmepriv, _FW_LINKED) && is_same_network(src: &(padapter->mlmepriv.cur_network.network), dst: src, feature: 0)) {
454 /* Take the recvpriv's value for the connected AP*/
455 ss_final = padapter->recvpriv.signal_strength;
456 sq_final = padapter->recvpriv.signal_qual;
457 /* the rssi value here is undecorated, and will be used for antenna diversity */
458 if (sq_smp != 101) /* from the right channel */
459 rssi_final = (src->rssi+dst->rssi*4)/5;
460 else
461 rssi_final = rssi_ori;
462 } else {
463 if (sq_smp != 101) { /* from the right channel */
464 ss_final = ((u32)(src->phy_info.signal_strength)+(u32)(dst->phy_info.signal_strength)*4)/5;
465 sq_final = ((u32)(src->phy_info.signal_quality)+(u32)(dst->phy_info.signal_quality)*4)/5;
466 rssi_final = (src->rssi+dst->rssi*4)/5;
467 } else {
468 /* bss info not receiving from the right channel, use the original RX signal infos */
469 ss_final = dst->phy_info.signal_strength;
470 sq_final = dst->phy_info.signal_quality;
471 rssi_final = dst->rssi;
472 }
473
474 }
475
476 if (update_ie) {
477 dst->reserved[0] = src->reserved[0];
478 dst->reserved[1] = src->reserved[1];
479 memcpy((u8 *)dst, (u8 *)src, get_wlan_bssid_ex_sz(src));
480 }
481
482 dst->phy_info.signal_strength = ss_final;
483 dst->phy_info.signal_quality = sq_final;
484 dst->rssi = rssi_final;
485}
486
487static void update_current_network(struct adapter *adapter, struct wlan_bssid_ex *pnetwork)
488{
489 struct mlme_priv *pmlmepriv = &(adapter->mlmepriv);
490
491 rtw_bug_check(parg1: &(pmlmepriv->cur_network.network),
492 parg2: &(pmlmepriv->cur_network.network),
493 parg3: &(pmlmepriv->cur_network.network),
494 parg4: &(pmlmepriv->cur_network.network));
495
496 if ((check_fwstate(pmlmepriv, _FW_LINKED) == true) && (is_same_network(src: &(pmlmepriv->cur_network.network), dst: pnetwork, feature: 0))) {
497 /* if (pmlmepriv->cur_network.network.ie_length<= pnetwork->ie_length) */
498 {
499 update_network(dst: &(pmlmepriv->cur_network.network), src: pnetwork, padapter: adapter, update_ie: true);
500 rtw_update_protection(padapter: adapter, ie: (pmlmepriv->cur_network.network.ies) + sizeof(struct ndis_802_11_fix_ie),
501 ie_len: pmlmepriv->cur_network.network.ie_length);
502 }
503 }
504}
505
506/*
507Caller must hold pmlmepriv->lock first.
508*/
509void rtw_update_scanned_network(struct adapter *adapter, struct wlan_bssid_ex *target)
510{
511 struct list_head *plist, *phead;
512 u32 bssid_ex_sz;
513 struct mlme_priv *pmlmepriv = &(adapter->mlmepriv);
514 struct __queue *queue = &(pmlmepriv->scanned_queue);
515 struct wlan_network *pnetwork = NULL;
516 struct wlan_network *oldest = NULL;
517 int target_find = 0;
518 u8 feature = 0;
519
520 spin_lock_bh(lock: &queue->lock);
521 phead = get_list_head(queue);
522 list_for_each(plist, phead) {
523 pnetwork = list_entry(plist, struct wlan_network, list);
524
525 rtw_bug_check(parg1: pnetwork, parg2: pnetwork, parg3: pnetwork, parg4: pnetwork);
526
527 if (is_same_network(src: &(pnetwork->network), dst: target, feature)) {
528 target_find = 1;
529 break;
530 }
531
532 if (rtw_roam_flags(adapter)) {
533 /* TODO: don't select network in the same ess as oldest if it's new enough*/
534 }
535
536 if (!oldest || time_after(oldest->last_scanned, pnetwork->last_scanned))
537 oldest = pnetwork;
538
539 }
540
541 /* If we didn't find a match, then get a new network slot to initialize
542 * with this beacon's information */
543 /* if (phead == plist) { */
544 if (!target_find) {
545 if (list_empty(head: &pmlmepriv->free_bss_pool.queue)) {
546 /* If there are no more slots, expire the oldest */
547 /* list_del_init(&oldest->list); */
548 pnetwork = oldest;
549 if (!pnetwork)
550 goto exit;
551
552 memcpy(&(pnetwork->network), target, get_wlan_bssid_ex_sz(target));
553 /* variable initialize */
554 pnetwork->fixed = false;
555 pnetwork->last_scanned = jiffies;
556
557 pnetwork->network_type = 0;
558 pnetwork->aid = 0;
559 pnetwork->join_res = 0;
560
561 /* bss info not receiving from the right channel */
562 if (pnetwork->network.phy_info.signal_quality == 101)
563 pnetwork->network.phy_info.signal_quality = 0;
564 } else {
565 /* Otherwise just pull from the free list */
566
567 pnetwork = rtw_alloc_network(pmlmepriv); /* will update scan_time */
568
569 if (!pnetwork)
570 goto exit;
571
572 bssid_ex_sz = get_wlan_bssid_ex_sz(bss: target);
573 target->length = bssid_ex_sz;
574 memcpy(&(pnetwork->network), target, bssid_ex_sz);
575
576 pnetwork->last_scanned = jiffies;
577
578 /* bss info not receiving from the right channel */
579 if (pnetwork->network.phy_info.signal_quality == 101)
580 pnetwork->network.phy_info.signal_quality = 0;
581
582 list_add_tail(new: &(pnetwork->list), head: &(queue->queue));
583
584 }
585 } else {
586 /* we have an entry and we are going to update it. But this entry may
587 * be already expired. In this case we do the same as we found a new
588 * net and call the new_net handler
589 */
590 bool update_ie = true;
591
592 pnetwork->last_scanned = jiffies;
593
594 /* target.reserved[0]== 1, means that scanned network is a bcn frame. */
595 if (pnetwork->network.ie_length > target->ie_length && target->reserved[0] == 1)
596 update_ie = false;
597
598 /* probe resp(3) > beacon(1) > probe req(2) */
599 if (target->reserved[0] != 2 &&
600 target->reserved[0] >= pnetwork->network.reserved[0]) {
601 update_ie = true;
602 } else {
603 update_ie = false;
604 }
605
606 update_network(dst: &(pnetwork->network), src: target, padapter: adapter, update_ie);
607 }
608
609exit:
610 spin_unlock_bh(lock: &queue->lock);
611}
612
613void rtw_add_network(struct adapter *adapter, struct wlan_bssid_ex *pnetwork);
614void rtw_add_network(struct adapter *adapter, struct wlan_bssid_ex *pnetwork)
615{
616 /* struct __queue *queue = &(pmlmepriv->scanned_queue); */
617
618 /* spin_lock_bh(&queue->lock); */
619
620 update_current_network(adapter, pnetwork);
621
622 rtw_update_scanned_network(adapter, target: pnetwork);
623
624 /* spin_unlock_bh(&queue->lock); */
625}
626
627/* select the desired network based on the capability of the (i)bss. */
628/* check items: (1) security */
629/* (2) network_type */
630/* (3) WMM */
631/* (4) HT */
632/* (5) others */
633int rtw_is_desired_network(struct adapter *adapter, struct wlan_network *pnetwork);
634int rtw_is_desired_network(struct adapter *adapter, struct wlan_network *pnetwork)
635{
636 struct security_priv *psecuritypriv = &adapter->securitypriv;
637 struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
638 u32 desired_encmode;
639 u32 privacy;
640
641 /* u8 wps_ie[512]; */
642 uint wps_ielen;
643
644 int bselected = true;
645
646 desired_encmode = psecuritypriv->ndisencryptstatus;
647 privacy = pnetwork->network.privacy;
648
649 if (check_fwstate(pmlmepriv, WIFI_UNDER_WPS)) {
650 if (rtw_get_wps_ie(in_ie: pnetwork->network.ies+_FIXED_IE_LENGTH_, in_len: pnetwork->network.ie_length-_FIXED_IE_LENGTH_, NULL, wps_ielen: &wps_ielen))
651 return true;
652 else
653 return false;
654
655 }
656 if (adapter->registrypriv.wifi_spec == 1) { /* for correct flow of 8021X to do.... */
657 u8 *p = NULL;
658 uint ie_len = 0;
659
660 if ((desired_encmode == Ndis802_11EncryptionDisabled) && (privacy != 0))
661 bselected = false;
662
663 if (psecuritypriv->ndisauthtype == Ndis802_11AuthModeWPA2PSK) {
664 p = rtw_get_ie(pbuf: pnetwork->network.ies + _BEACON_IE_OFFSET_, index: WLAN_EID_RSN, len: &ie_len, limit: (pnetwork->network.ie_length - _BEACON_IE_OFFSET_));
665 if (p && ie_len > 0)
666 bselected = true;
667 else
668 bselected = false;
669 }
670 }
671
672 if ((desired_encmode != Ndis802_11EncryptionDisabled) && (privacy == 0))
673 bselected = false;
674
675 if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE) == true) {
676 if (pnetwork->network.infrastructure_mode != pmlmepriv->cur_network.network.infrastructure_mode)
677 bselected = false;
678 }
679
680 return bselected;
681}
682
683/* TODO: Perry : For Power Management */
684void rtw_atimdone_event_callback(struct adapter *adapter, u8 *pbuf)
685{
686}
687
688void rtw_survey_event_callback(struct adapter *adapter, u8 *pbuf)
689{
690 u32 len;
691 struct wlan_bssid_ex *pnetwork;
692 struct mlme_priv *pmlmepriv = &(adapter->mlmepriv);
693
694 pnetwork = (struct wlan_bssid_ex *)pbuf;
695
696 len = get_wlan_bssid_ex_sz(bss: pnetwork);
697 if (len > (sizeof(struct wlan_bssid_ex)))
698 return;
699
700 spin_lock_bh(lock: &pmlmepriv->lock);
701
702 /* update IBSS_network 's timestamp */
703 if ((check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE)) == true) {
704 if (!memcmp(p: &(pmlmepriv->cur_network.network.mac_address), q: pnetwork->mac_address, ETH_ALEN)) {
705 struct wlan_network *ibss_wlan = NULL;
706
707 memcpy(pmlmepriv->cur_network.network.ies, pnetwork->ies, 8);
708 spin_lock_bh(lock: &(pmlmepriv->scanned_queue.lock));
709 ibss_wlan = rtw_find_network(scanned_queue: &pmlmepriv->scanned_queue, addr: pnetwork->mac_address);
710 if (ibss_wlan) {
711 memcpy(ibss_wlan->network.ies, pnetwork->ies, 8);
712 spin_unlock_bh(lock: &(pmlmepriv->scanned_queue.lock));
713 goto exit;
714 }
715 spin_unlock_bh(lock: &(pmlmepriv->scanned_queue.lock));
716 }
717 }
718
719 /* lock pmlmepriv->lock when you accessing network_q */
720 if ((check_fwstate(pmlmepriv, _FW_UNDER_LINKING)) == false) {
721 if (pnetwork->ssid.ssid[0] == 0)
722 pnetwork->ssid.ssid_length = 0;
723 rtw_add_network(adapter, pnetwork);
724 }
725
726exit:
727
728 spin_unlock_bh(lock: &pmlmepriv->lock);
729}
730
731void rtw_surveydone_event_callback(struct adapter *adapter, u8 *pbuf)
732{
733 struct mlme_priv *pmlmepriv = &(adapter->mlmepriv);
734
735 spin_lock_bh(lock: &pmlmepriv->lock);
736 if (pmlmepriv->wps_probe_req_ie) {
737 pmlmepriv->wps_probe_req_ie_len = 0;
738 kfree(objp: pmlmepriv->wps_probe_req_ie);
739 pmlmepriv->wps_probe_req_ie = NULL;
740 }
741
742 if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY)) {
743 spin_unlock_bh(lock: &pmlmepriv->lock);
744 del_timer_sync(timer: &pmlmepriv->scan_to_timer);
745 spin_lock_bh(lock: &pmlmepriv->lock);
746 _clr_fwstate_(pmlmepriv, _FW_UNDER_SURVEY);
747 }
748
749 rtw_set_signal_stat_timer(&adapter->recvpriv);
750
751 if (pmlmepriv->to_join) {
752 if ((check_fwstate(pmlmepriv, WIFI_ADHOC_STATE) == true)) {
753 if (check_fwstate(pmlmepriv, _FW_LINKED) == false) {
754 set_fwstate(pmlmepriv, _FW_UNDER_LINKING);
755
756 if (rtw_select_and_join_from_scanned_queue(pmlmepriv) == _SUCCESS) {
757 _set_timer(ptimer: &pmlmepriv->assoc_timer, MAX_JOIN_TIMEOUT);
758 } else {
759 u8 ret = _SUCCESS;
760 struct wlan_bssid_ex *pdev_network = &(adapter->registrypriv.dev_network);
761 u8 *pibss = adapter->registrypriv.dev_network.mac_address;
762
763 /* pmlmepriv->fw_state ^= _FW_UNDER_SURVEY;because don't set assoc_timer */
764 _clr_fwstate_(pmlmepriv, _FW_UNDER_SURVEY);
765
766 memcpy(&pdev_network->ssid, &pmlmepriv->assoc_ssid, sizeof(struct ndis_802_11_ssid));
767
768 rtw_update_registrypriv_dev_network(adapter);
769 rtw_generate_random_ibss(pibss);
770
771 pmlmepriv->fw_state = WIFI_ADHOC_MASTER_STATE;
772
773 pmlmepriv->to_join = false;
774
775 ret = rtw_createbss_cmd(padapter: adapter);
776 if (ret != _SUCCESS)
777 goto unlock;
778 }
779 }
780 } else {
781 int s_ret;
782
783 set_fwstate(pmlmepriv, _FW_UNDER_LINKING);
784 pmlmepriv->to_join = false;
785 s_ret = rtw_select_and_join_from_scanned_queue(pmlmepriv);
786 if (s_ret == _SUCCESS) {
787 _set_timer(ptimer: &pmlmepriv->assoc_timer, MAX_JOIN_TIMEOUT);
788 } else if (s_ret == 2) {/* there is no need to wait for join */
789 _clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING);
790 rtw_indicate_connect(adapter);
791 } else {
792 if (rtw_to_roam(adapter) != 0) {
793 if (rtw_dec_to_roam(adapter) == 0
794 || _SUCCESS != rtw_sitesurvey_cmd(padapter: adapter, ssid: &pmlmepriv->assoc_ssid, ssid_num: 1, NULL, ch_num: 0)
795 ) {
796 rtw_set_to_roam(adapter, to_roam: 0);
797 rtw_free_assoc_resources(adapter, lock_scanned_queue: 1);
798 rtw_indicate_disconnect(adapter);
799 } else {
800 pmlmepriv->to_join = true;
801 }
802 } else
803 rtw_indicate_disconnect(adapter);
804
805 _clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING);
806 }
807 }
808 } else {
809 if (rtw_chk_roam_flags(adapter, RTW_ROAM_ACTIVE)) {
810 if (check_fwstate(pmlmepriv, WIFI_STATION_STATE)
811 && check_fwstate(pmlmepriv, _FW_LINKED)) {
812 if (rtw_select_roaming_candidate(pmlmepriv) == _SUCCESS) {
813 receive_disconnect(padapter: adapter, MacAddr: pmlmepriv->cur_network.network.mac_address
814 , WLAN_REASON_ACTIVE_ROAM);
815 }
816 }
817 }
818 }
819
820unlock:
821 spin_unlock_bh(lock: &pmlmepriv->lock);
822
823 rtw_os_xmit_schedule(padapter: adapter);
824
825 rtw_cfg80211_surveydone_event_callback(padapter: adapter);
826
827 rtw_indicate_scan_done(padapter: adapter, aborted: false);
828}
829
830void rtw_dummy_event_callback(struct adapter *adapter, u8 *pbuf)
831{
832}
833
834void rtw_fwdbg_event_callback(struct adapter *adapter, u8 *pbuf)
835{
836}
837
838static void free_scanqueue(struct mlme_priv *pmlmepriv)
839{
840 struct __queue *free_queue = &pmlmepriv->free_bss_pool;
841 struct __queue *scan_queue = &pmlmepriv->scanned_queue;
842 struct list_head *plist, *phead, *ptemp;
843
844 spin_lock_bh(lock: &scan_queue->lock);
845 spin_lock_bh(lock: &free_queue->lock);
846
847 phead = get_list_head(queue: scan_queue);
848 plist = get_next(list: phead);
849
850 while (plist != phead) {
851 ptemp = get_next(list: plist);
852 list_del_init(entry: plist);
853 list_add_tail(new: plist, head: &free_queue->queue);
854 plist = ptemp;
855 }
856
857 spin_unlock_bh(lock: &free_queue->lock);
858 spin_unlock_bh(lock: &scan_queue->lock);
859}
860
861static void rtw_reset_rx_info(struct debug_priv *pdbgpriv)
862{
863 pdbgpriv->dbg_rx_ampdu_drop_count = 0;
864 pdbgpriv->dbg_rx_ampdu_forced_indicate_count = 0;
865 pdbgpriv->dbg_rx_ampdu_loss_count = 0;
866 pdbgpriv->dbg_rx_dup_mgt_frame_drop_count = 0;
867 pdbgpriv->dbg_rx_ampdu_window_shift_cnt = 0;
868}
869
870static void find_network(struct adapter *adapter)
871{
872 struct wlan_network *pwlan = NULL;
873 struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
874 struct wlan_network *tgt_network = &pmlmepriv->cur_network;
875
876 pwlan = rtw_find_network(scanned_queue: &pmlmepriv->scanned_queue, addr: tgt_network->network.mac_address);
877 if (pwlan)
878 pwlan->fixed = false;
879
880 if (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) &&
881 (adapter->stapriv.asoc_sta_count == 1))
882 rtw_free_network_nolock(padapter: adapter, pnetwork: pwlan);
883}
884
885/*
886*rtw_free_assoc_resources: the caller has to lock pmlmepriv->lock
887*/
888void rtw_free_assoc_resources(struct adapter *adapter, int lock_scanned_queue)
889{
890 struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
891 struct wlan_network *tgt_network = &pmlmepriv->cur_network;
892 struct dvobj_priv *psdpriv = adapter->dvobj;
893 struct debug_priv *pdbgpriv = &psdpriv->drv_dbg;
894
895 if (check_fwstate(pmlmepriv, WIFI_STATION_STATE|WIFI_AP_STATE)) {
896 struct sta_info *psta;
897
898 psta = rtw_get_stainfo(pstapriv: &adapter->stapriv, hwaddr: tgt_network->network.mac_address);
899 rtw_free_stainfo(padapter: adapter, psta);
900 }
901
902 if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE|WIFI_ADHOC_MASTER_STATE|WIFI_AP_STATE)) {
903 struct sta_info *psta;
904
905 rtw_free_all_stainfo(padapter: adapter);
906
907 psta = rtw_get_bcmc_stainfo(padapter: adapter);
908 rtw_free_stainfo(padapter: adapter, psta);
909
910 rtw_init_bcmc_stainfo(padapter: adapter);
911 }
912
913 find_network(adapter);
914
915 if (lock_scanned_queue)
916 adapter->securitypriv.key_mask = 0;
917
918 rtw_reset_rx_info(pdbgpriv);
919}
920
921/*
922*rtw_indicate_connect: the caller has to lock pmlmepriv->lock
923*/
924void rtw_indicate_connect(struct adapter *padapter)
925{
926 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
927
928 pmlmepriv->to_join = false;
929
930 if (!check_fwstate(pmlmepriv: &padapter->mlmepriv, _FW_LINKED)) {
931
932 set_fwstate(pmlmepriv, _FW_LINKED);
933
934 rtw_os_indicate_connect(adapter: padapter);
935 }
936
937 rtw_set_to_roam(adapter: padapter, to_roam: 0);
938 rtw_set_scan_deny(adapter: padapter, ms: 3000);
939
940}
941
942/*
943*rtw_indicate_disconnect: the caller has to lock pmlmepriv->lock
944*/
945void rtw_indicate_disconnect(struct adapter *padapter)
946{
947 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
948
949 _clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING|WIFI_UNDER_WPS);
950
951 if (rtw_to_roam(adapter: padapter) > 0)
952 _clr_fwstate_(pmlmepriv, _FW_LINKED);
953
954 if (check_fwstate(pmlmepriv: &padapter->mlmepriv, _FW_LINKED)
955 || (rtw_to_roam(adapter: padapter) <= 0)
956 ) {
957 rtw_os_indicate_disconnect(adapter: padapter);
958
959 /* set ips_deny_time to avoid enter IPS before LPS leave */
960 rtw_set_ips_deny(padapter, ms: 3000);
961
962 _clr_fwstate_(pmlmepriv, _FW_LINKED);
963
964 rtw_clear_scan_deny(adapter: padapter);
965 }
966
967 rtw_lps_ctrl_wk_cmd(padapter, lps_ctrl_type: LPS_CTRL_DISCONNECT, enqueue: 1);
968}
969
970inline void rtw_indicate_scan_done(struct adapter *padapter, bool aborted)
971{
972 rtw_os_indicate_scan_done(padapter, aborted);
973
974 if (is_primary_adapter(padapter) &&
975 (!adapter_to_pwrctl(padapter)->bInSuspend) &&
976 (!check_fwstate(pmlmepriv: &padapter->mlmepriv,
977 WIFI_ASOC_STATE|WIFI_UNDER_LINKING))) {
978 rtw_set_ips_deny(padapter, ms: 0);
979 _set_timer(ptimer: &padapter->mlmepriv.dynamic_chk_timer, delay_time: 1);
980 }
981}
982
983void rtw_scan_abort(struct adapter *adapter)
984{
985 unsigned long start;
986 struct mlme_priv *pmlmepriv = &(adapter->mlmepriv);
987 struct mlme_ext_priv *pmlmeext = &(adapter->mlmeextpriv);
988
989 start = jiffies;
990 pmlmeext->scan_abort = true;
991 while (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY)
992 && jiffies_to_msecs(j: start) <= 200) {
993
994 if (adapter->bDriverStopped || adapter->bSurpriseRemoved)
995 break;
996
997 msleep(msecs: 20);
998 }
999
1000 if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY))
1001 rtw_indicate_scan_done(padapter: adapter, aborted: true);
1002
1003 pmlmeext->scan_abort = false;
1004}
1005
1006static struct sta_info *rtw_joinbss_update_stainfo(struct adapter *padapter, struct wlan_network *pnetwork)
1007{
1008 int i;
1009 struct sta_info *bmc_sta, *psta = NULL;
1010 struct recv_reorder_ctrl *preorder_ctrl;
1011 struct sta_priv *pstapriv = &padapter->stapriv;
1012 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
1013
1014 psta = rtw_get_stainfo(pstapriv, hwaddr: pnetwork->network.mac_address);
1015 if (!psta)
1016 psta = rtw_alloc_stainfo(pstapriv, hwaddr: pnetwork->network.mac_address);
1017
1018 if (psta) { /* update ptarget_sta */
1019
1020 psta->aid = pnetwork->join_res;
1021
1022 update_sta_info(padapter, psta);
1023
1024 /* update station supportRate */
1025 psta->bssratelen = rtw_get_rateset_len(rateset: pnetwork->network.supported_rates);
1026 memcpy(psta->bssrateset, pnetwork->network.supported_rates, psta->bssratelen);
1027 rtw_hal_update_sta_rate_mask(padapter, psta);
1028
1029 psta->wireless_mode = pmlmeext->cur_wireless_mode;
1030 psta->raid = networktype_to_raid_ex(adapter: padapter, psta);
1031
1032 /* sta mode */
1033 rtw_hal_set_odm_var(padapter, eVariable: HAL_ODM_STA_INFO, pValue1: psta, bSet: true);
1034
1035 /* security related */
1036 if (padapter->securitypriv.dot11AuthAlgrthm == dot11AuthAlgrthm_8021X) {
1037 padapter->securitypriv.binstallGrpkey = false;
1038 padapter->securitypriv.busetkipkey = false;
1039 padapter->securitypriv.bgrpkey_handshake = false;
1040
1041 psta->ieee8021x_blocked = true;
1042 psta->dot118021XPrivacy = padapter->securitypriv.dot11PrivacyAlgrthm;
1043
1044 memset((u8 *)&psta->dot118021x_UncstKey, 0, sizeof(union Keytype));
1045
1046 memset((u8 *)&psta->dot11tkiprxmickey, 0, sizeof(union Keytype));
1047 memset((u8 *)&psta->dot11tkiptxmickey, 0, sizeof(union Keytype));
1048
1049 memset((u8 *)&psta->dot11txpn, 0, sizeof(union pn48));
1050 psta->dot11txpn.val = psta->dot11txpn.val + 1;
1051 memset((u8 *)&psta->dot11wtxpn, 0, sizeof(union pn48));
1052 memset((u8 *)&psta->dot11rxpn, 0, sizeof(union pn48));
1053 }
1054
1055 /* Commented by Albert 2012/07/21 */
1056 /* When doing the WPS, the wps_ie_len won't equal to 0 */
1057 /* And the Wi-Fi driver shouldn't allow the data packet to be transmitted. */
1058 if (padapter->securitypriv.wps_ie_len != 0) {
1059 psta->ieee8021x_blocked = true;
1060 padapter->securitypriv.wps_ie_len = 0;
1061 }
1062
1063 /* for A-MPDU Rx reordering buffer control for bmc_sta & sta_info */
1064 /* if A-MPDU Rx is enabled, resetting rx_ordering_ctrl wstart_b(indicate_seq) to default value = 0xffff */
1065 /* todo: check if AP can send A-MPDU packets */
1066 for (i = 0; i < 16 ; i++) {
1067 /* preorder_ctrl = &precvpriv->recvreorder_ctrl[i]; */
1068 preorder_ctrl = &psta->recvreorder_ctrl[i];
1069 preorder_ctrl->enable = false;
1070 preorder_ctrl->indicate_seq = 0xffff;
1071 preorder_ctrl->wend_b = 0xffff;
1072 preorder_ctrl->wsize_b = 64;/* max_ampdu_sz;ex. 32(kbytes) -> wsize_b =32 */
1073 }
1074
1075 bmc_sta = rtw_get_bcmc_stainfo(padapter);
1076 if (bmc_sta) {
1077 for (i = 0; i < 16 ; i++) {
1078 /* preorder_ctrl = &precvpriv->recvreorder_ctrl[i]; */
1079 preorder_ctrl = &bmc_sta->recvreorder_ctrl[i];
1080 preorder_ctrl->enable = false;
1081 preorder_ctrl->indicate_seq = 0xffff;
1082 preorder_ctrl->wend_b = 0xffff;
1083 preorder_ctrl->wsize_b = 64;/* max_ampdu_sz;ex. 32(kbytes) -> wsize_b =32 */
1084 }
1085 }
1086 }
1087
1088 return psta;
1089
1090}
1091
1092/* pnetwork : returns from rtw_joinbss_event_callback */
1093/* ptarget_wlan: found from scanned_queue */
1094static void rtw_joinbss_update_network(struct adapter *padapter, struct wlan_network *ptarget_wlan, struct wlan_network *pnetwork)
1095{
1096 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
1097 struct wlan_network *cur_network = &(pmlmepriv->cur_network);
1098
1099 /* why not use ptarget_wlan?? */
1100 memcpy(&cur_network->network, &pnetwork->network, pnetwork->network.length);
1101 /* some ies in pnetwork is wrong, so we should use ptarget_wlan ies */
1102 cur_network->network.ie_length = ptarget_wlan->network.ie_length;
1103 memcpy(&cur_network->network.ies[0], &ptarget_wlan->network.ies[0], MAX_IE_SZ);
1104
1105 cur_network->aid = pnetwork->join_res;
1106
1107 rtw_set_signal_stat_timer(&padapter->recvpriv);
1108
1109 padapter->recvpriv.signal_strength = ptarget_wlan->network.phy_info.signal_strength;
1110 padapter->recvpriv.signal_qual = ptarget_wlan->network.phy_info.signal_quality;
1111 /* the ptarget_wlan->network.rssi is raw data, we use ptarget_wlan->network.phy_info.signal_strength instead (has scaled) */
1112 padapter->recvpriv.rssi = translate_percentage_to_dbm(SignalStrengthIndex: ptarget_wlan->network.phy_info.signal_strength);
1113
1114 rtw_set_signal_stat_timer(&padapter->recvpriv);
1115
1116 /* update fw_state will clr _FW_UNDER_LINKING here indirectly */
1117 switch (pnetwork->network.infrastructure_mode) {
1118 case Ndis802_11Infrastructure:
1119
1120 if (pmlmepriv->fw_state&WIFI_UNDER_WPS)
1121 pmlmepriv->fw_state = WIFI_STATION_STATE|WIFI_UNDER_WPS;
1122 else
1123 pmlmepriv->fw_state = WIFI_STATION_STATE;
1124
1125 break;
1126 case Ndis802_11IBSS:
1127 pmlmepriv->fw_state = WIFI_ADHOC_STATE;
1128 break;
1129 default:
1130 pmlmepriv->fw_state = WIFI_NULL_STATE;
1131 break;
1132 }
1133
1134 rtw_update_protection(padapter, ie: (cur_network->network.ies) + sizeof(struct ndis_802_11_fix_ie),
1135 ie_len: (cur_network->network.ie_length));
1136
1137 rtw_update_ht_cap(padapter, pie: cur_network->network.ies, ie_len: cur_network->network.ie_length, channel: (u8) cur_network->network.configuration.ds_config);
1138}
1139
1140/* Notes: the function could be > passive_level (the same context as Rx tasklet) */
1141/* pnetwork : returns from rtw_joinbss_event_callback */
1142/* ptarget_wlan: found from scanned_queue */
1143/* if join_res > 0, for (fw_state ==WIFI_STATION_STATE), we check if "ptarget_sta" & "ptarget_wlan" exist. */
1144/* if join_res > 0, for (fw_state ==WIFI_ADHOC_STATE), we only check if "ptarget_wlan" exist. */
1145/* if join_res > 0, update "cur_network->network" from "pnetwork->network" if (ptarget_wlan != NULL). */
1146/* */
1147/* define REJOIN */
1148void rtw_joinbss_event_prehandle(struct adapter *adapter, u8 *pbuf)
1149{
1150 static u8 __maybe_unused retry;
1151 struct sta_info *ptarget_sta = NULL, *pcur_sta = NULL;
1152 struct sta_priv *pstapriv = &adapter->stapriv;
1153 struct mlme_priv *pmlmepriv = &(adapter->mlmepriv);
1154 struct wlan_network *pnetwork = (struct wlan_network *)pbuf;
1155 struct wlan_network *cur_network = &(pmlmepriv->cur_network);
1156 struct wlan_network *pcur_wlan = NULL, *ptarget_wlan = NULL;
1157 unsigned int the_same_macaddr = false;
1158
1159 rtw_get_encrypt_decrypt_from_registrypriv(adapter);
1160
1161 the_same_macaddr = !memcmp(p: pnetwork->network.mac_address, q: cur_network->network.mac_address, ETH_ALEN);
1162
1163 pnetwork->network.length = get_wlan_bssid_ex_sz(bss: &pnetwork->network);
1164 if (pnetwork->network.length > sizeof(struct wlan_bssid_ex))
1165 return;
1166
1167 spin_lock_bh(lock: &pmlmepriv->lock);
1168
1169 pmlmepriv->LinkDetectInfo.TrafficTransitionCount = 0;
1170 pmlmepriv->LinkDetectInfo.LowPowerTransitionCount = 0;
1171
1172 if (pnetwork->join_res > 0) {
1173 spin_lock_bh(lock: &(pmlmepriv->scanned_queue.lock));
1174 retry = 0;
1175 if (check_fwstate(pmlmepriv, _FW_UNDER_LINKING)) {
1176 /* s1. find ptarget_wlan */
1177 if (check_fwstate(pmlmepriv, _FW_LINKED)) {
1178 if (the_same_macaddr) {
1179 ptarget_wlan = rtw_find_network(scanned_queue: &pmlmepriv->scanned_queue, addr: cur_network->network.mac_address);
1180 } else {
1181 pcur_wlan = rtw_find_network(scanned_queue: &pmlmepriv->scanned_queue, addr: cur_network->network.mac_address);
1182 if (pcur_wlan)
1183 pcur_wlan->fixed = false;
1184
1185 pcur_sta = rtw_get_stainfo(pstapriv, hwaddr: cur_network->network.mac_address);
1186 if (pcur_sta)
1187 rtw_free_stainfo(padapter: adapter, psta: pcur_sta);
1188
1189 ptarget_wlan = rtw_find_network(scanned_queue: &pmlmepriv->scanned_queue, addr: pnetwork->network.mac_address);
1190 if (check_fwstate(pmlmepriv, WIFI_STATION_STATE) == true) {
1191 if (ptarget_wlan)
1192 ptarget_wlan->fixed = true;
1193 }
1194 }
1195
1196 } else {
1197 ptarget_wlan = _rtw_find_same_network(scanned_queue: &pmlmepriv->scanned_queue, network: pnetwork);
1198 if (check_fwstate(pmlmepriv, WIFI_STATION_STATE) == true) {
1199 if (ptarget_wlan)
1200 ptarget_wlan->fixed = true;
1201 }
1202 }
1203
1204 /* s2. update cur_network */
1205 if (ptarget_wlan) {
1206 rtw_joinbss_update_network(padapter: adapter, ptarget_wlan, pnetwork);
1207 } else {
1208 netdev_dbg(adapter->pnetdev,
1209 "Can't find ptarget_wlan when joinbss_event callback\n");
1210 spin_unlock_bh(lock: &(pmlmepriv->scanned_queue.lock));
1211 goto ignore_joinbss_callback;
1212 }
1213
1214 /* s3. find ptarget_sta & update ptarget_sta after update cur_network only for station mode */
1215 if (check_fwstate(pmlmepriv, WIFI_STATION_STATE) == true) {
1216 ptarget_sta = rtw_joinbss_update_stainfo(padapter: adapter, pnetwork);
1217 if (!ptarget_sta) {
1218 spin_unlock_bh(lock: &(pmlmepriv->scanned_queue.lock));
1219 goto ignore_joinbss_callback;
1220 }
1221 }
1222
1223 /* s4. indicate connect */
1224 if (check_fwstate(pmlmepriv, WIFI_STATION_STATE) == true) {
1225 pmlmepriv->cur_network_scanned = ptarget_wlan;
1226 rtw_indicate_connect(padapter: adapter);
1227 }
1228
1229 spin_unlock_bh(lock: &pmlmepriv->scanned_queue.lock);
1230
1231 spin_unlock_bh(lock: &pmlmepriv->lock);
1232 /* s5. Cancel assoc_timer */
1233 del_timer_sync(timer: &pmlmepriv->assoc_timer);
1234 spin_lock_bh(lock: &pmlmepriv->lock);
1235 } else {
1236 spin_unlock_bh(lock: &(pmlmepriv->scanned_queue.lock));
1237 }
1238 } else if (pnetwork->join_res == -4) {
1239 rtw_reset_securitypriv(adapter);
1240 _set_timer(ptimer: &pmlmepriv->assoc_timer, delay_time: 1);
1241
1242 /* rtw_free_assoc_resources(adapter, 1); */
1243
1244 if ((check_fwstate(pmlmepriv, _FW_UNDER_LINKING)) == true)
1245 _clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING);
1246
1247 } else {/* if join_res < 0 (join fails), then try again */
1248
1249 #ifdef REJOIN
1250 res = _FAIL;
1251 if (retry < 2)
1252 res = rtw_select_and_join_from_scanned_queue(pmlmepriv);
1253
1254 if (res == _SUCCESS) {
1255 /* extend time of assoc_timer */
1256 _set_timer(&pmlmepriv->assoc_timer, MAX_JOIN_TIMEOUT);
1257 retry++;
1258 } else if (res == 2) {/* there is no need to wait for join */
1259 _clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING);
1260 rtw_indicate_connect(adapter);
1261 } else {
1262 #endif
1263
1264 _set_timer(ptimer: &pmlmepriv->assoc_timer, delay_time: 1);
1265 /* rtw_free_assoc_resources(adapter, 1); */
1266 _clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING);
1267
1268 #ifdef REJOIN
1269 retry = 0;
1270 }
1271 #endif
1272 }
1273
1274ignore_joinbss_callback:
1275
1276 spin_unlock_bh(lock: &pmlmepriv->lock);
1277}
1278
1279void rtw_joinbss_event_callback(struct adapter *adapter, u8 *pbuf)
1280{
1281 struct wlan_network *pnetwork = (struct wlan_network *)pbuf;
1282
1283 mlmeext_joinbss_event_callback(padapter: adapter, join_res: pnetwork->join_res);
1284
1285 rtw_os_xmit_schedule(padapter: adapter);
1286}
1287
1288/* FOR STA, AP , AD-HOC mode */
1289void rtw_sta_media_status_rpt(struct adapter *adapter, struct sta_info *psta, u32 mstatus)
1290{
1291 u16 media_status_rpt;
1292
1293 if (!psta)
1294 return;
1295
1296 media_status_rpt = (u16)((psta->mac_id<<8)|mstatus); /* MACID|OPMODE:1 connect */
1297 rtw_hal_set_hwreg(padapter: adapter, variable: HW_VAR_H2C_MEDIA_STATUS_RPT, val: (u8 *)&media_status_rpt);
1298}
1299
1300void rtw_stassoc_event_callback(struct adapter *adapter, u8 *pbuf)
1301{
1302 struct sta_info *psta;
1303 struct mlme_priv *pmlmepriv = &(adapter->mlmepriv);
1304 struct stassoc_event *pstassoc = (struct stassoc_event *)pbuf;
1305 struct wlan_network *cur_network = &(pmlmepriv->cur_network);
1306 struct wlan_network *ptarget_wlan = NULL;
1307
1308 if (rtw_access_ctrl(padapter: adapter, mac_addr: pstassoc->macaddr) == false)
1309 return;
1310
1311 if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) {
1312 psta = rtw_get_stainfo(pstapriv: &adapter->stapriv, hwaddr: pstassoc->macaddr);
1313 if (psta) {
1314 u8 *passoc_req = NULL;
1315 u32 assoc_req_len = 0;
1316
1317 rtw_sta_media_status_rpt(adapter, psta, mstatus: 1);
1318
1319 ap_sta_info_defer_update(padapter: adapter, psta);
1320
1321 /* report to upper layer */
1322 spin_lock_bh(lock: &psta->lock);
1323 if (psta->passoc_req && psta->assoc_req_len > 0) {
1324 passoc_req = rtw_zmalloc(psta->assoc_req_len);
1325 if (passoc_req) {
1326 assoc_req_len = psta->assoc_req_len;
1327 memcpy(passoc_req, psta->passoc_req, assoc_req_len);
1328
1329 kfree(objp: psta->passoc_req);
1330 psta->passoc_req = NULL;
1331 psta->assoc_req_len = 0;
1332 }
1333 }
1334 spin_unlock_bh(lock: &psta->lock);
1335
1336 if (passoc_req && assoc_req_len > 0) {
1337 rtw_cfg80211_indicate_sta_assoc(padapter: adapter, pmgmt_frame: passoc_req, frame_len: assoc_req_len);
1338
1339 kfree(objp: passoc_req);
1340 }
1341 }
1342 return;
1343 }
1344
1345 /* for AD-HOC mode */
1346 psta = rtw_get_stainfo(pstapriv: &adapter->stapriv, hwaddr: pstassoc->macaddr);
1347 if (psta) {
1348 /* the sta have been in sta_info_queue => do nothing */
1349
1350 return; /* between drv has received this event before and fw have not yet to set key to CAM_ENTRY) */
1351 }
1352
1353 psta = rtw_alloc_stainfo(pstapriv: &adapter->stapriv, hwaddr: pstassoc->macaddr);
1354 if (!psta)
1355 return;
1356
1357 /* to do : init sta_info variable */
1358 psta->qos_option = 0;
1359 psta->mac_id = (uint)pstassoc->cam_id;
1360 /* psta->aid = (uint)pstassoc->cam_id; */
1361
1362 /* for ad-hoc mode */
1363 rtw_hal_set_odm_var(padapter: adapter, eVariable: HAL_ODM_STA_INFO, pValue1: psta, bSet: true);
1364
1365 rtw_sta_media_status_rpt(adapter, psta, mstatus: 1);
1366
1367 if (adapter->securitypriv.dot11AuthAlgrthm == dot11AuthAlgrthm_8021X)
1368 psta->dot118021XPrivacy = adapter->securitypriv.dot11PrivacyAlgrthm;
1369
1370 psta->ieee8021x_blocked = false;
1371
1372 spin_lock_bh(lock: &pmlmepriv->lock);
1373
1374 if ((check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) == true) ||
1375 (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE) == true)) {
1376 if (adapter->stapriv.asoc_sta_count == 2) {
1377 spin_lock_bh(lock: &(pmlmepriv->scanned_queue.lock));
1378 ptarget_wlan = rtw_find_network(scanned_queue: &pmlmepriv->scanned_queue, addr: cur_network->network.mac_address);
1379 pmlmepriv->cur_network_scanned = ptarget_wlan;
1380 if (ptarget_wlan)
1381 ptarget_wlan->fixed = true;
1382 spin_unlock_bh(lock: &(pmlmepriv->scanned_queue.lock));
1383 /* a sta + bc/mc_stainfo (not Ibss_stainfo) */
1384 rtw_indicate_connect(padapter: adapter);
1385 }
1386 }
1387
1388 spin_unlock_bh(lock: &pmlmepriv->lock);
1389
1390 mlmeext_sta_add_event_callback(padapter: adapter, psta);
1391}
1392
1393void rtw_stadel_event_callback(struct adapter *adapter, u8 *pbuf)
1394{
1395 int mac_id = (-1);
1396 struct sta_info *psta;
1397 struct wlan_network *pwlan = NULL;
1398 struct wlan_bssid_ex *pdev_network = NULL;
1399 u8 *pibss = NULL;
1400 struct mlme_priv *pmlmepriv = &(adapter->mlmepriv);
1401 struct stadel_event *pstadel = (struct stadel_event *)pbuf;
1402 struct wlan_network *tgt_network = &(pmlmepriv->cur_network);
1403 struct mlme_ext_priv *pmlmeext = &adapter->mlmeextpriv;
1404 struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
1405
1406 psta = rtw_get_stainfo(pstapriv: &adapter->stapriv, hwaddr: pstadel->macaddr);
1407 if (psta)
1408 mac_id = psta->mac_id;
1409 else
1410 mac_id = pstadel->mac_id;
1411
1412 if (mac_id >= 0) {
1413 u16 media_status;
1414
1415 media_status = (mac_id<<8)|0; /* MACID|OPMODE:0 means disconnect */
1416 /* for STA, AP, ADHOC mode, report disconnect stauts to FW */
1417 rtw_hal_set_hwreg(padapter: adapter, variable: HW_VAR_H2C_MEDIA_STATUS_RPT, val: (u8 *)&media_status);
1418 }
1419
1420 /* if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) */
1421 if ((pmlmeinfo->state&0x03) == WIFI_FW_AP_STATE)
1422 return;
1423
1424 mlmeext_sta_del_event_callback(padapter: adapter);
1425
1426 spin_lock_bh(lock: &pmlmepriv->lock);
1427
1428 if (check_fwstate(pmlmepriv, WIFI_STATION_STATE)) {
1429 u16 reason = *((unsigned short *)(pstadel->rsvd));
1430 bool roam = false;
1431 struct wlan_network *roam_target = NULL;
1432
1433 if (adapter->registrypriv.wifi_spec == 1) {
1434 roam = false;
1435 } else if (reason == WLAN_REASON_EXPIRATION_CHK && rtw_chk_roam_flags(adapter, RTW_ROAM_ON_EXPIRED)) {
1436 roam = true;
1437 } else if (reason == WLAN_REASON_ACTIVE_ROAM && rtw_chk_roam_flags(adapter, RTW_ROAM_ACTIVE)) {
1438 roam = true;
1439 roam_target = pmlmepriv->roam_network;
1440 }
1441
1442 if (roam) {
1443 if (rtw_to_roam(adapter) > 0)
1444 rtw_dec_to_roam(adapter); /* this stadel_event is caused by roaming, decrease to_roam */
1445 else if (rtw_to_roam(adapter) == 0)
1446 rtw_set_to_roam(adapter, to_roam: adapter->registrypriv.max_roaming_times);
1447 } else {
1448 rtw_set_to_roam(adapter, to_roam: 0);
1449 }
1450
1451 rtw_free_uc_swdec_pending_queue(adapter);
1452
1453 rtw_free_assoc_resources(adapter, lock_scanned_queue: 1);
1454 rtw_indicate_disconnect(padapter: adapter);
1455
1456 spin_lock_bh(lock: &(pmlmepriv->scanned_queue.lock));
1457 /* remove the network entry in scanned_queue */
1458 pwlan = rtw_find_network(scanned_queue: &pmlmepriv->scanned_queue, addr: tgt_network->network.mac_address);
1459 if (pwlan) {
1460 pwlan->fixed = false;
1461 rtw_free_network_nolock(padapter: adapter, pnetwork: pwlan);
1462 }
1463 spin_unlock_bh(lock: &(pmlmepriv->scanned_queue.lock));
1464
1465 _rtw_roaming(adapter, tgt_network: roam_target);
1466 }
1467
1468 if (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) ||
1469 check_fwstate(pmlmepriv, WIFI_ADHOC_STATE)) {
1470
1471 rtw_free_stainfo(padapter: adapter, psta);
1472
1473 if (adapter->stapriv.asoc_sta_count == 1) {/* a sta + bc/mc_stainfo (not Ibss_stainfo) */
1474 u8 ret = _SUCCESS;
1475 /* rtw_indicate_disconnect(adapter);removed@20091105 */
1476 spin_lock_bh(lock: &(pmlmepriv->scanned_queue.lock));
1477 /* free old ibss network */
1478 /* pwlan = rtw_find_network(&pmlmepriv->scanned_queue, pstadel->macaddr); */
1479 pwlan = rtw_find_network(scanned_queue: &pmlmepriv->scanned_queue, addr: tgt_network->network.mac_address);
1480 if (pwlan) {
1481 pwlan->fixed = false;
1482 rtw_free_network_nolock(padapter: adapter, pnetwork: pwlan);
1483 }
1484 spin_unlock_bh(lock: &(pmlmepriv->scanned_queue.lock));
1485 /* re-create ibss */
1486 pdev_network = &(adapter->registrypriv.dev_network);
1487 pibss = adapter->registrypriv.dev_network.mac_address;
1488
1489 memcpy(pdev_network, &tgt_network->network, get_wlan_bssid_ex_sz(&tgt_network->network));
1490
1491 memcpy(&pdev_network->ssid, &pmlmepriv->assoc_ssid, sizeof(struct ndis_802_11_ssid));
1492
1493 rtw_update_registrypriv_dev_network(adapter);
1494
1495 rtw_generate_random_ibss(pibss);
1496
1497 if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE)) {
1498 set_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE);
1499 _clr_fwstate_(pmlmepriv, WIFI_ADHOC_STATE);
1500 }
1501
1502 ret = rtw_createbss_cmd(padapter: adapter);
1503 if (ret != _SUCCESS)
1504 goto unlock;
1505 }
1506
1507 }
1508
1509unlock:
1510 spin_unlock_bh(lock: &pmlmepriv->lock);
1511}
1512
1513void rtw_cpwm_event_callback(struct adapter *padapter, u8 *pbuf)
1514{
1515 struct reportpwrstate_parm *preportpwrstate;
1516
1517 preportpwrstate = (struct reportpwrstate_parm *)pbuf;
1518 preportpwrstate->state |= (u8)(adapter_to_pwrctl(padapter)->cpwm_tog + 0x80);
1519 cpwm_int_hdl(padapter, preportpwrstate);
1520}
1521
1522void rtw_wmm_event_callback(struct adapter *padapter, u8 *pbuf)
1523{
1524 WMMOnAssocRsp(padapter);
1525}
1526
1527/*
1528* _rtw_join_timeout_handler - Timeout/failure handler for CMD JoinBss
1529* @adapter: pointer to struct adapter structure
1530*/
1531void _rtw_join_timeout_handler(struct timer_list *t)
1532{
1533 struct adapter *adapter = from_timer(adapter, t,
1534 mlmepriv.assoc_timer);
1535 struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
1536
1537 if (adapter->bDriverStopped || adapter->bSurpriseRemoved)
1538 return;
1539
1540 spin_lock_bh(lock: &pmlmepriv->lock);
1541
1542 if (rtw_to_roam(adapter) > 0) { /* join timeout caused by roaming */
1543 while (1) {
1544 rtw_dec_to_roam(adapter);
1545 if (rtw_to_roam(adapter) != 0) { /* try another */
1546 int do_join_r;
1547
1548 do_join_r = rtw_do_join(padapter: adapter);
1549 if (do_join_r != _SUCCESS)
1550 continue;
1551
1552 break;
1553 } else {
1554 rtw_indicate_disconnect(padapter: adapter);
1555 break;
1556 }
1557 }
1558
1559 } else {
1560 rtw_indicate_disconnect(padapter: adapter);
1561 free_scanqueue(pmlmepriv);/* */
1562
1563 /* indicate disconnect for the case that join_timeout and check_fwstate != FW_LINKED */
1564 rtw_cfg80211_indicate_disconnect(padapter: adapter);
1565
1566 }
1567
1568 spin_unlock_bh(lock: &pmlmepriv->lock);
1569}
1570
1571/*
1572* rtw_scan_timeout_handler - Timeout/Failure handler for CMD SiteSurvey
1573* @adapter: pointer to struct adapter structure
1574*/
1575void rtw_scan_timeout_handler(struct timer_list *t)
1576{
1577 struct adapter *adapter = from_timer(adapter, t,
1578 mlmepriv.scan_to_timer);
1579 struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
1580
1581 spin_lock_bh(lock: &pmlmepriv->lock);
1582
1583 _clr_fwstate_(pmlmepriv, _FW_UNDER_SURVEY);
1584
1585 spin_unlock_bh(lock: &pmlmepriv->lock);
1586
1587 rtw_indicate_scan_done(padapter: adapter, aborted: true);
1588}
1589
1590void rtw_mlme_reset_auto_scan_int(struct adapter *adapter)
1591{
1592 struct mlme_priv *mlme = &adapter->mlmepriv;
1593 struct mlme_ext_priv *pmlmeext = &adapter->mlmeextpriv;
1594 struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
1595
1596 if (pmlmeinfo->VHT_enable) /* disable auto scan when connect to 11AC AP */
1597 mlme->auto_scan_int_ms = 0;
1598 else if (adapter->registrypriv.wifi_spec && is_client_associated_to_ap(padapter: adapter) == true)
1599 mlme->auto_scan_int_ms = 60*1000;
1600 else if (rtw_chk_roam_flags(adapter, RTW_ROAM_ACTIVE)) {
1601 if (check_fwstate(pmlmepriv: mlme, WIFI_STATION_STATE) && check_fwstate(pmlmepriv: mlme, _FW_LINKED))
1602 mlme->auto_scan_int_ms = mlme->roam_scan_int_ms;
1603 } else
1604 mlme->auto_scan_int_ms = 0; /* disabled */
1605}
1606
1607static void rtw_auto_scan_handler(struct adapter *padapter)
1608{
1609 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1610
1611 rtw_mlme_reset_auto_scan_int(adapter: padapter);
1612
1613 if (pmlmepriv->auto_scan_int_ms != 0
1614 && jiffies_to_msecs(j: jiffies - pmlmepriv->scan_start_time) > pmlmepriv->auto_scan_int_ms) {
1615
1616 if (!padapter->registrypriv.wifi_spec) {
1617 if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY | _FW_UNDER_LINKING) == true)
1618 goto exit;
1619
1620 if (pmlmepriv->LinkDetectInfo.bBusyTraffic)
1621 goto exit;
1622 }
1623
1624 rtw_set_802_11_bssid_list_scan(padapter, NULL, ssid_max_num: 0);
1625 }
1626
1627exit:
1628 return;
1629}
1630
1631void rtw_dynamic_check_timer_handler(struct adapter *adapter)
1632{
1633 if (!adapter)
1634 return;
1635
1636 if (!adapter->hw_init_completed)
1637 return;
1638
1639 if (adapter->bDriverStopped || adapter->bSurpriseRemoved)
1640 return;
1641
1642 if (adapter->net_closed)
1643 return;
1644
1645 if ((adapter_to_pwrctl(adapter)->fw_current_in_ps_mode)
1646 && !(hal_btcoex_IsBtControlLps(padapter: adapter))
1647 ) {
1648 u8 bEnterPS;
1649
1650 linked_status_chk(padapter: adapter);
1651
1652 bEnterPS = traffic_status_watchdog(padapter: adapter, from_timer: 1);
1653 if (bEnterPS) {
1654 /* rtw_lps_ctrl_wk_cmd(adapter, LPS_CTRL_ENTER, 1); */
1655 rtw_hal_dm_watchdog_in_lps(padapter: adapter);
1656 } else {
1657 /* call rtw_lps_ctrl_wk_cmd(padapter, LPS_CTRL_LEAVE, 1) in traffic_status_watchdog() */
1658 }
1659
1660 } else {
1661 if (is_primary_adapter(adapter))
1662 rtw_dynamic_chk_wk_cmd(adapter);
1663 }
1664
1665 /* auto site survey */
1666 rtw_auto_scan_handler(padapter: adapter);
1667}
1668
1669inline bool rtw_is_scan_deny(struct adapter *adapter)
1670{
1671 struct mlme_priv *mlmepriv = &adapter->mlmepriv;
1672
1673 return (atomic_read(v: &mlmepriv->set_scan_deny) != 0) ? true : false;
1674}
1675
1676inline void rtw_clear_scan_deny(struct adapter *adapter)
1677{
1678 struct mlme_priv *mlmepriv = &adapter->mlmepriv;
1679
1680 atomic_set(v: &mlmepriv->set_scan_deny, i: 0);
1681}
1682
1683void rtw_set_scan_deny(struct adapter *adapter, u32 ms)
1684{
1685 struct mlme_priv *mlmepriv = &adapter->mlmepriv;
1686
1687 atomic_set(v: &mlmepriv->set_scan_deny, i: 1);
1688 _set_timer(ptimer: &mlmepriv->set_scan_deny_timer, delay_time: ms);
1689}
1690
1691/*
1692* Select a new roaming candidate from the original @param candidate and @param competitor
1693* @return true: candidate is updated
1694* @return false: candidate is not updated
1695*/
1696static int rtw_check_roaming_candidate(struct mlme_priv *mlme
1697 , struct wlan_network **candidate, struct wlan_network *competitor)
1698{
1699 int updated = false;
1700 struct adapter *adapter = container_of(mlme, struct adapter, mlmepriv);
1701
1702 if (is_same_ess(a: &competitor->network, b: &mlme->cur_network.network) == false)
1703 goto exit;
1704
1705 if (rtw_is_desired_network(adapter, pnetwork: competitor) == false)
1706 goto exit;
1707
1708 /* got specific addr to roam */
1709 if (!is_zero_mac_addr(addr: mlme->roam_tgt_addr)) {
1710 if (!memcmp(p: mlme->roam_tgt_addr, q: competitor->network.mac_address, ETH_ALEN))
1711 goto update;
1712 else
1713 goto exit;
1714 }
1715 if (jiffies_to_msecs(j: jiffies - competitor->last_scanned) >= mlme->roam_scanr_exp_ms)
1716 goto exit;
1717
1718 if (competitor->network.rssi - mlme->cur_network_scanned->network.rssi < mlme->roam_rssi_diff_th)
1719 goto exit;
1720
1721 if (*candidate && (*candidate)->network.rssi >= competitor->network.rssi)
1722 goto exit;
1723
1724update:
1725 *candidate = competitor;
1726 updated = true;
1727
1728exit:
1729 return updated;
1730}
1731
1732int rtw_select_roaming_candidate(struct mlme_priv *mlme)
1733{
1734 int ret = _FAIL;
1735 struct list_head *phead;
1736 struct __queue *queue = &(mlme->scanned_queue);
1737 struct wlan_network *pnetwork = NULL;
1738 struct wlan_network *candidate = NULL;
1739
1740 if (!mlme->cur_network_scanned) {
1741 rtw_warn_on(1);
1742 return ret;
1743 }
1744
1745 spin_lock_bh(lock: &(mlme->scanned_queue.lock));
1746 phead = get_list_head(queue);
1747
1748 list_for_each(mlme->pscanned, phead) {
1749
1750 pnetwork = list_entry(mlme->pscanned, struct wlan_network,
1751 list);
1752
1753 rtw_check_roaming_candidate(mlme, candidate: &candidate, competitor: pnetwork);
1754
1755 }
1756
1757 if (!candidate) {
1758 ret = _FAIL;
1759 goto exit;
1760 } else {
1761 mlme->roam_network = candidate;
1762
1763 if (!memcmp(p: candidate->network.mac_address, q: mlme->roam_tgt_addr, ETH_ALEN))
1764 eth_zero_addr(addr: mlme->roam_tgt_addr);
1765 }
1766
1767 ret = _SUCCESS;
1768exit:
1769 spin_unlock_bh(lock: &(mlme->scanned_queue.lock));
1770
1771 return ret;
1772}
1773
1774/*
1775* Select a new join candidate from the original @param candidate and @param competitor
1776* @return true: candidate is updated
1777* @return false: candidate is not updated
1778*/
1779static int rtw_check_join_candidate(struct mlme_priv *mlme
1780 , struct wlan_network **candidate, struct wlan_network *competitor)
1781{
1782 int updated = false;
1783 struct adapter *adapter = container_of(mlme, struct adapter, mlmepriv);
1784
1785 /* check bssid, if needed */
1786 if (mlme->assoc_by_bssid) {
1787 if (memcmp(p: competitor->network.mac_address, q: mlme->assoc_bssid, ETH_ALEN))
1788 goto exit;
1789 }
1790
1791 /* check ssid, if needed */
1792 if (mlme->assoc_ssid.ssid[0] && mlme->assoc_ssid.ssid_length) {
1793 if (competitor->network.ssid.ssid_length != mlme->assoc_ssid.ssid_length
1794 || memcmp(p: competitor->network.ssid.ssid, q: mlme->assoc_ssid.ssid, size: mlme->assoc_ssid.ssid_length)
1795 )
1796 goto exit;
1797 }
1798
1799 if (rtw_is_desired_network(adapter, pnetwork: competitor) == false)
1800 goto exit;
1801
1802 if (rtw_to_roam(adapter) > 0) {
1803 if (jiffies_to_msecs(j: jiffies - competitor->last_scanned) >= mlme->roam_scanr_exp_ms
1804 || is_same_ess(a: &competitor->network, b: &mlme->cur_network.network) == false
1805 )
1806 goto exit;
1807 }
1808
1809 if (!*candidate || (*candidate)->network.rssi < competitor->network.rssi) {
1810 *candidate = competitor;
1811 updated = true;
1812 }
1813
1814exit:
1815 return updated;
1816}
1817
1818/*
1819Calling context:
1820The caller of the sub-routine will be in critical section...
1821The caller must hold the following spinlock
1822pmlmepriv->lock
1823*/
1824
1825int rtw_select_and_join_from_scanned_queue(struct mlme_priv *pmlmepriv)
1826{
1827 int ret;
1828 struct list_head *phead;
1829 struct adapter *adapter;
1830 struct __queue *queue = &(pmlmepriv->scanned_queue);
1831 struct wlan_network *pnetwork = NULL;
1832 struct wlan_network *candidate = NULL;
1833
1834 adapter = (struct adapter *)pmlmepriv->nic_hdl;
1835
1836 spin_lock_bh(lock: &(pmlmepriv->scanned_queue.lock));
1837
1838 if (pmlmepriv->roam_network) {
1839 candidate = pmlmepriv->roam_network;
1840 pmlmepriv->roam_network = NULL;
1841 goto candidate_exist;
1842 }
1843
1844 phead = get_list_head(queue);
1845 list_for_each(pmlmepriv->pscanned, phead) {
1846
1847 pnetwork = list_entry(pmlmepriv->pscanned,
1848 struct wlan_network, list);
1849
1850 rtw_check_join_candidate(mlme: pmlmepriv, candidate: &candidate, competitor: pnetwork);
1851
1852 }
1853
1854 if (!candidate) {
1855 ret = _FAIL;
1856 goto exit;
1857 } else {
1858 goto candidate_exist;
1859 }
1860
1861candidate_exist:
1862
1863 /* check for situation of _FW_LINKED */
1864 if (check_fwstate(pmlmepriv, _FW_LINKED) == true) {
1865 rtw_disassoc_cmd(padapter: adapter, deauth_timeout_ms: 0, enqueue: true);
1866 rtw_indicate_disconnect(padapter: adapter);
1867 rtw_free_assoc_resources(adapter, lock_scanned_queue: 0);
1868 }
1869
1870 set_fwstate(pmlmepriv, _FW_UNDER_LINKING);
1871 ret = rtw_joinbss_cmd(padapter: adapter, pnetwork: candidate);
1872
1873exit:
1874 spin_unlock_bh(lock: &(pmlmepriv->scanned_queue.lock));
1875 return ret;
1876}
1877
1878signed int rtw_set_auth(struct adapter *adapter, struct security_priv *psecuritypriv)
1879{
1880 struct cmd_obj *pcmd;
1881 struct setauth_parm *psetauthparm;
1882 struct cmd_priv *pcmdpriv = &(adapter->cmdpriv);
1883 signed int res = _SUCCESS;
1884
1885 pcmd = rtw_zmalloc(sizeof(struct cmd_obj));
1886 if (!pcmd) {
1887 res = _FAIL; /* try again */
1888 goto exit;
1889 }
1890
1891 psetauthparm = rtw_zmalloc(sizeof(struct setauth_parm));
1892 if (!psetauthparm) {
1893 kfree(objp: pcmd);
1894 res = _FAIL;
1895 goto exit;
1896 }
1897
1898 psetauthparm->mode = (unsigned char)psecuritypriv->dot11AuthAlgrthm;
1899
1900 pcmd->cmdcode = _SetAuth_CMD_;
1901 pcmd->parmbuf = (unsigned char *)psetauthparm;
1902 pcmd->cmdsz = (sizeof(struct setauth_parm));
1903 pcmd->rsp = NULL;
1904 pcmd->rspsz = 0;
1905
1906 INIT_LIST_HEAD(list: &pcmd->list);
1907
1908 res = rtw_enqueue_cmd(pcmdpriv, obj: pcmd);
1909
1910exit:
1911 return res;
1912}
1913
1914signed int rtw_set_key(struct adapter *adapter, struct security_priv *psecuritypriv, signed int keyid, u8 set_tx, bool enqueue)
1915{
1916 u8 keylen;
1917 struct cmd_obj *pcmd;
1918 struct setkey_parm *psetkeyparm;
1919 struct cmd_priv *pcmdpriv = &(adapter->cmdpriv);
1920 signed int res = _SUCCESS;
1921
1922 psetkeyparm = rtw_zmalloc(sizeof(struct setkey_parm));
1923 if (!psetkeyparm) {
1924 res = _FAIL;
1925 goto exit;
1926 }
1927
1928 if (psecuritypriv->dot11AuthAlgrthm == dot11AuthAlgrthm_8021X)
1929 psetkeyparm->algorithm = (unsigned char)psecuritypriv->dot118021XGrpPrivacy;
1930 else
1931 psetkeyparm->algorithm = (u8)psecuritypriv->dot11PrivacyAlgrthm;
1932
1933 psetkeyparm->keyid = (u8)keyid;/* 0~3 */
1934 psetkeyparm->set_tx = set_tx;
1935 if (is_wep_enc(psetkeyparm->algorithm))
1936 adapter->securitypriv.key_mask |= BIT(psetkeyparm->keyid);
1937
1938 switch (psetkeyparm->algorithm) {
1939
1940 case _WEP40_:
1941 keylen = 5;
1942 memcpy(&(psetkeyparm->key[0]), &(psecuritypriv->dot11DefKey[keyid].skey[0]), keylen);
1943 break;
1944 case _WEP104_:
1945 keylen = 13;
1946 memcpy(&(psetkeyparm->key[0]), &(psecuritypriv->dot11DefKey[keyid].skey[0]), keylen);
1947 break;
1948 case _TKIP_:
1949 keylen = 16;
1950 memcpy(&psetkeyparm->key, &psecuritypriv->dot118021XGrpKey[keyid], keylen);
1951 psetkeyparm->grpkey = 1;
1952 break;
1953 case _AES_:
1954 keylen = 16;
1955 memcpy(&psetkeyparm->key, &psecuritypriv->dot118021XGrpKey[keyid], keylen);
1956 psetkeyparm->grpkey = 1;
1957 break;
1958 default:
1959 res = _FAIL;
1960 kfree(objp: psetkeyparm);
1961 goto exit;
1962 }
1963
1964 if (enqueue) {
1965 pcmd = rtw_zmalloc(sizeof(struct cmd_obj));
1966 if (!pcmd) {
1967 kfree(objp: psetkeyparm);
1968 res = _FAIL; /* try again */
1969 goto exit;
1970 }
1971
1972 pcmd->cmdcode = _SetKey_CMD_;
1973 pcmd->parmbuf = (u8 *)psetkeyparm;
1974 pcmd->cmdsz = (sizeof(struct setkey_parm));
1975 pcmd->rsp = NULL;
1976 pcmd->rspsz = 0;
1977
1978 INIT_LIST_HEAD(list: &pcmd->list);
1979
1980 res = rtw_enqueue_cmd(pcmdpriv, obj: pcmd);
1981 } else {
1982 setkey_hdl(padapter: adapter, pbuf: (u8 *)psetkeyparm);
1983 kfree(objp: psetkeyparm);
1984 }
1985exit:
1986 return res;
1987}
1988
1989/* adjust ies for rtw_joinbss_cmd in WMM */
1990int rtw_restruct_wmm_ie(struct adapter *adapter, u8 *in_ie, u8 *out_ie, uint in_len, uint initial_out_len)
1991{
1992 unsigned int ielength = 0;
1993 unsigned int i, j;
1994
1995 i = 12; /* after the fixed IE */
1996 while (i < in_len) {
1997 ielength = initial_out_len;
1998
1999 if (in_ie[i] == 0xDD && in_ie[i+2] == 0x00 && in_ie[i+3] == 0x50 && in_ie[i+4] == 0xF2 && in_ie[i+5] == 0x02 && i+5 < in_len) { /* WMM element ID and OUI */
2000 for (j = i; j < i + 9; j++) {
2001 out_ie[ielength] = in_ie[j];
2002 ielength++;
2003 }
2004 out_ie[initial_out_len + 1] = 0x07;
2005 out_ie[initial_out_len + 6] = 0x00;
2006 out_ie[initial_out_len + 8] = 0x00;
2007
2008 break;
2009 }
2010
2011 i += (in_ie[i+1]+2); /* to the next IE element */
2012 }
2013
2014 return ielength;
2015
2016}
2017
2018/* */
2019/* Ported from 8185: IsInPreAuthKeyList(). (Renamed from SecIsInPreAuthKeyList(), 2006-10-13.) */
2020/* Added by Annie, 2006-05-07. */
2021/* */
2022/* Search by BSSID, */
2023/* Return Value: */
2024/* -1 :if there is no pre-auth key in the table */
2025/* >= 0 :if there is pre-auth key, and return the entry id */
2026/* */
2027/* */
2028
2029static int SecIsInPMKIDList(struct adapter *Adapter, u8 *bssid)
2030{
2031 struct security_priv *p = &Adapter->securitypriv;
2032 int i;
2033
2034 for (i = 0; i < NUM_PMKID_CACHE; i++)
2035 if ((p->PMKIDList[i].bUsed) &&
2036 (!memcmp(p: p->PMKIDList[i].Bssid, q: bssid, ETH_ALEN)))
2037 return i;
2038 return -1;
2039}
2040
2041/* */
2042/* Check the RSN IE length */
2043/* If the RSN IE length <= 20, the RSN IE didn't include the PMKID information */
2044/* 0-11th element in the array are the fixed IE */
2045/* 12th element in the array is the IE */
2046/* 13th element in the array is the IE length */
2047/* */
2048
2049static int rtw_append_pmkid(struct adapter *Adapter, int iEntry, u8 *ie, uint ie_len)
2050{
2051 struct security_priv *psecuritypriv = &Adapter->securitypriv;
2052
2053 if (ie[13] <= 20) {
2054 /* The RSN IE didn't include the PMK ID, append the PMK information */
2055 ie[ie_len] = 1;
2056 ie_len++;
2057 ie[ie_len] = 0; /* PMKID count = 0x0100 */
2058 ie_len++;
2059 memcpy(&ie[ie_len], &psecuritypriv->PMKIDList[iEntry].PMKID, 16);
2060 ie_len += 16;
2061 ie[13] += 18;/* PMKID length = 2+16 */
2062 }
2063 return ie_len;
2064}
2065
2066signed int rtw_restruct_sec_ie(struct adapter *adapter, u8 *in_ie, u8 *out_ie, uint in_len)
2067{
2068 u8 authmode = 0x0;
2069 uint ielength;
2070 int iEntry;
2071
2072 struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
2073 struct security_priv *psecuritypriv = &adapter->securitypriv;
2074 uint ndisauthmode = psecuritypriv->ndisauthtype;
2075
2076 /* copy fixed ie only */
2077 memcpy(out_ie, in_ie, 12);
2078 ielength = 12;
2079 if ((ndisauthmode == Ndis802_11AuthModeWPA) || (ndisauthmode == Ndis802_11AuthModeWPAPSK))
2080 authmode = WLAN_EID_VENDOR_SPECIFIC;
2081 if ((ndisauthmode == Ndis802_11AuthModeWPA2) || (ndisauthmode == Ndis802_11AuthModeWPA2PSK))
2082 authmode = WLAN_EID_RSN;
2083
2084 if (check_fwstate(pmlmepriv, WIFI_UNDER_WPS)) {
2085 memcpy(out_ie+ielength, psecuritypriv->wps_ie, psecuritypriv->wps_ie_len);
2086
2087 ielength += psecuritypriv->wps_ie_len;
2088 } else if ((authmode == WLAN_EID_VENDOR_SPECIFIC) || (authmode == WLAN_EID_RSN)) {
2089 /* copy RSN or SSN */
2090 memcpy(&out_ie[ielength], &psecuritypriv->supplicant_ie[0], psecuritypriv->supplicant_ie[1]+2);
2091 /* debug for CONFIG_IEEE80211W
2092 {
2093 int jj;
2094 printk("supplicant_ie_length =%d &&&&&&&&&&&&&&&&&&&\n", psecuritypriv->supplicant_ie[1]+2);
2095 for (jj = 0; jj < psecuritypriv->supplicant_ie[1]+2; jj++)
2096 printk(" %02x ", psecuritypriv->supplicant_ie[jj]);
2097 printk("\n");
2098 }*/
2099 ielength += psecuritypriv->supplicant_ie[1]+2;
2100 rtw_report_sec_ie(adapter, authmode, sec_ie: psecuritypriv->supplicant_ie);
2101 }
2102
2103 iEntry = SecIsInPMKIDList(Adapter: adapter, bssid: pmlmepriv->assoc_bssid);
2104 if (iEntry < 0) {
2105 return ielength;
2106 } else {
2107 if (authmode == WLAN_EID_RSN)
2108 ielength = rtw_append_pmkid(Adapter: adapter, iEntry, ie: out_ie, ie_len: ielength);
2109 }
2110 return ielength;
2111}
2112
2113void rtw_init_registrypriv_dev_network(struct adapter *adapter)
2114{
2115 struct registry_priv *pregistrypriv = &adapter->registrypriv;
2116 struct eeprom_priv *peepriv = &adapter->eeprompriv;
2117 struct wlan_bssid_ex *pdev_network = &pregistrypriv->dev_network;
2118 u8 *myhwaddr = myid(peepriv);
2119
2120 memcpy(pdev_network->mac_address, myhwaddr, ETH_ALEN);
2121
2122 memcpy(&pdev_network->ssid, &pregistrypriv->ssid, sizeof(struct ndis_802_11_ssid));
2123
2124 pdev_network->configuration.length = sizeof(struct ndis_802_11_conf);
2125 pdev_network->configuration.beacon_period = 100;
2126}
2127
2128void rtw_update_registrypriv_dev_network(struct adapter *adapter)
2129{
2130 int sz = 0;
2131 struct registry_priv *pregistrypriv = &adapter->registrypriv;
2132 struct wlan_bssid_ex *pdev_network = &pregistrypriv->dev_network;
2133 struct security_priv *psecuritypriv = &adapter->securitypriv;
2134 struct wlan_network *cur_network = &adapter->mlmepriv.cur_network;
2135 /* struct xmit_priv *pxmitpriv = &adapter->xmitpriv; */
2136
2137 pdev_network->privacy = (psecuritypriv->dot11PrivacyAlgrthm > 0 ? 1 : 0) ; /* adhoc no 802.1x */
2138
2139 pdev_network->rssi = 0;
2140
2141 switch (pregistrypriv->wireless_mode) {
2142 case WIRELESS_11B:
2143 pdev_network->network_type_in_use = (Ndis802_11DS);
2144 break;
2145 case WIRELESS_11G:
2146 case WIRELESS_11BG:
2147 case WIRELESS_11_24N:
2148 case WIRELESS_11G_24N:
2149 case WIRELESS_11BG_24N:
2150 pdev_network->network_type_in_use = (Ndis802_11OFDM24);
2151 break;
2152 default:
2153 /* TODO */
2154 break;
2155 }
2156
2157 pdev_network->configuration.ds_config = (pregistrypriv->channel);
2158
2159 if (cur_network->network.infrastructure_mode == Ndis802_11IBSS)
2160 pdev_network->configuration.atim_window = (0);
2161
2162 pdev_network->infrastructure_mode = (cur_network->network.infrastructure_mode);
2163
2164 /* 1. Supported rates */
2165 /* 2. IE */
2166
2167 /* rtw_set_supported_rate(pdev_network->supported_rates, pregistrypriv->wireless_mode) ; will be called in rtw_generate_ie */
2168 sz = rtw_generate_ie(pregistrypriv);
2169
2170 pdev_network->ie_length = sz;
2171
2172 pdev_network->length = get_wlan_bssid_ex_sz(bss: (struct wlan_bssid_ex *)pdev_network);
2173
2174 /* notes: translate ie_length & length after assign the length to cmdsz in createbss_cmd(); */
2175 /* pdev_network->ie_length = cpu_to_le32(sz); */
2176}
2177
2178void rtw_get_encrypt_decrypt_from_registrypriv(struct adapter *adapter)
2179{
2180}
2181
2182/* the function is at passive_level */
2183void rtw_joinbss_reset(struct adapter *padapter)
2184{
2185 u8 threshold;
2186 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
2187
2188 struct ht_priv *phtpriv = &pmlmepriv->htpriv;
2189
2190 /* todo: if you want to do something io/reg/hw setting before join_bss, please add code here */
2191
2192 pmlmepriv->num_FortyMHzIntolerant = 0;
2193
2194 pmlmepriv->num_sta_no_ht = 0;
2195
2196 phtpriv->ampdu_enable = false;/* reset to disabled */
2197
2198 /* TH = 1 => means that invalidate usb rx aggregation */
2199 /* TH = 0 => means that validate usb rx aggregation, use init value. */
2200 if (phtpriv->ht_option) {
2201 if (padapter->registrypriv.wifi_spec == 1)
2202 threshold = 1;
2203 else
2204 threshold = 0;
2205 rtw_hal_set_hwreg(padapter, variable: HW_VAR_RXDMA_AGG_PG_TH, val: (u8 *)(&threshold));
2206 } else {
2207 threshold = 1;
2208 rtw_hal_set_hwreg(padapter, variable: HW_VAR_RXDMA_AGG_PG_TH, val: (u8 *)(&threshold));
2209 }
2210}
2211
2212void rtw_ht_use_default_setting(struct adapter *padapter)
2213{
2214 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
2215 struct ht_priv *phtpriv = &pmlmepriv->htpriv;
2216 struct registry_priv *pregistrypriv = &padapter->registrypriv;
2217 bool bHwLDPCSupport = false, bHwSTBCSupport = false;
2218 bool bHwSupportBeamformer = false, bHwSupportBeamformee = false;
2219
2220 if (pregistrypriv->wifi_spec)
2221 phtpriv->bss_coexist = 1;
2222 else
2223 phtpriv->bss_coexist = 0;
2224
2225 phtpriv->sgi_40m = TEST_FLAG(pregistrypriv->short_gi, BIT1) ? true : false;
2226 phtpriv->sgi_20m = TEST_FLAG(pregistrypriv->short_gi, BIT0) ? true : false;
2227
2228 /* LDPC support */
2229 rtw_hal_get_def_var(padapter, eVariable: HAL_DEF_RX_LDPC, pValue: (u8 *)&bHwLDPCSupport);
2230 CLEAR_FLAGS(phtpriv->ldpc_cap);
2231 if (bHwLDPCSupport) {
2232 if (TEST_FLAG(pregistrypriv->ldpc_cap, BIT4))
2233 SET_FLAG(phtpriv->ldpc_cap, LDPC_HT_ENABLE_RX);
2234 }
2235 rtw_hal_get_def_var(padapter, eVariable: HAL_DEF_TX_LDPC, pValue: (u8 *)&bHwLDPCSupport);
2236 if (bHwLDPCSupport) {
2237 if (TEST_FLAG(pregistrypriv->ldpc_cap, BIT5))
2238 SET_FLAG(phtpriv->ldpc_cap, LDPC_HT_ENABLE_TX);
2239 }
2240
2241 /* STBC */
2242 rtw_hal_get_def_var(padapter, eVariable: HAL_DEF_TX_STBC, pValue: (u8 *)&bHwSTBCSupport);
2243 CLEAR_FLAGS(phtpriv->stbc_cap);
2244 if (bHwSTBCSupport) {
2245 if (TEST_FLAG(pregistrypriv->stbc_cap, BIT5))
2246 SET_FLAG(phtpriv->stbc_cap, STBC_HT_ENABLE_TX);
2247 }
2248 rtw_hal_get_def_var(padapter, eVariable: HAL_DEF_RX_STBC, pValue: (u8 *)&bHwSTBCSupport);
2249 if (bHwSTBCSupport) {
2250 if (TEST_FLAG(pregistrypriv->stbc_cap, BIT4))
2251 SET_FLAG(phtpriv->stbc_cap, STBC_HT_ENABLE_RX);
2252 }
2253
2254 /* Beamforming setting */
2255 rtw_hal_get_def_var(padapter, eVariable: HAL_DEF_EXPLICIT_BEAMFORMER, pValue: (u8 *)&bHwSupportBeamformer);
2256 rtw_hal_get_def_var(padapter, eVariable: HAL_DEF_EXPLICIT_BEAMFORMEE, pValue: (u8 *)&bHwSupportBeamformee);
2257 CLEAR_FLAGS(phtpriv->beamform_cap);
2258 if (TEST_FLAG(pregistrypriv->beamform_cap, BIT4) && bHwSupportBeamformer)
2259 SET_FLAG(phtpriv->beamform_cap, BEAMFORMING_HT_BEAMFORMER_ENABLE);
2260
2261 if (TEST_FLAG(pregistrypriv->beamform_cap, BIT5) && bHwSupportBeamformee)
2262 SET_FLAG(phtpriv->beamform_cap, BEAMFORMING_HT_BEAMFORMEE_ENABLE);
2263}
2264
2265void rtw_build_wmm_ie_ht(struct adapter *padapter, u8 *out_ie, uint *pout_len)
2266{
2267 unsigned char WMM_IE[] = {0x00, 0x50, 0xf2, 0x02, 0x00, 0x01, 0x00};
2268 int out_len;
2269
2270 if (padapter->mlmepriv.qospriv.qos_option == 0) {
2271 out_len = *pout_len;
2272 rtw_set_ie(pbuf: out_ie+out_len, index: WLAN_EID_VENDOR_SPECIFIC,
2273 _WMM_IE_Length_, source: WMM_IE, frlen: pout_len);
2274
2275 padapter->mlmepriv.qospriv.qos_option = 1;
2276 }
2277}
2278
2279/* the function is >= passive_level */
2280unsigned int rtw_restructure_ht_ie(struct adapter *padapter, u8 *in_ie, u8 *out_ie, uint in_len, uint *pout_len, u8 channel)
2281{
2282 u32 ielen, out_len;
2283 enum ieee80211_max_ampdu_length_exp max_rx_ampdu_factor;
2284 unsigned char *p;
2285 struct ieee80211_ht_cap ht_capie;
2286 u8 cbw40_enable = 0, stbc_rx_enable = 0, operation_bw = 0;
2287 struct registry_priv *pregistrypriv = &padapter->registrypriv;
2288 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
2289 struct ht_priv *phtpriv = &pmlmepriv->htpriv;
2290 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
2291
2292 phtpriv->ht_option = false;
2293
2294 out_len = *pout_len;
2295
2296 memset(&ht_capie, 0, sizeof(struct ieee80211_ht_cap));
2297
2298 ht_capie.cap_info = cpu_to_le16(IEEE80211_HT_CAP_DSSSCCK40);
2299
2300 if (phtpriv->sgi_20m)
2301 ht_capie.cap_info |= cpu_to_le16(IEEE80211_HT_CAP_SGI_20);
2302
2303 /* Get HT BW */
2304 if (!in_ie) {
2305 /* TDLS: TODO 20/40 issue */
2306 if (check_fwstate(pmlmepriv, WIFI_STATION_STATE)) {
2307 operation_bw = padapter->mlmeextpriv.cur_bwmode;
2308 if (operation_bw > CHANNEL_WIDTH_40)
2309 operation_bw = CHANNEL_WIDTH_40;
2310 } else
2311 /* TDLS: TODO 40? */
2312 operation_bw = CHANNEL_WIDTH_40;
2313 } else {
2314 p = rtw_get_ie(pbuf: in_ie, index: WLAN_EID_HT_OPERATION, len: &ielen, limit: in_len);
2315 if (p && (ielen == sizeof(struct ieee80211_ht_addt_info))) {
2316 struct HT_info_element *pht_info = (struct HT_info_element *)(p+2);
2317
2318 if (pht_info->infos[0] & BIT(2)) {
2319 switch (pht_info->infos[0] & 0x3) {
2320 case 1:
2321 case 3:
2322 operation_bw = CHANNEL_WIDTH_40;
2323 break;
2324 default:
2325 operation_bw = CHANNEL_WIDTH_20;
2326 break;
2327 }
2328 } else {
2329 operation_bw = CHANNEL_WIDTH_20;
2330 }
2331 }
2332 }
2333
2334 /* to disable 40M Hz support while gd_bw_40MHz_en = 0 */
2335 if (channel > 14) {
2336 if ((pregistrypriv->bw_mode & 0xf0) > 0)
2337 cbw40_enable = 1;
2338 } else {
2339 if ((pregistrypriv->bw_mode & 0x0f) > 0)
2340 cbw40_enable = 1;
2341 }
2342
2343 if ((cbw40_enable == 1) && (operation_bw == CHANNEL_WIDTH_40)) {
2344 ht_capie.cap_info |= cpu_to_le16(IEEE80211_HT_CAP_SUP_WIDTH);
2345 if (phtpriv->sgi_40m)
2346 ht_capie.cap_info |= cpu_to_le16(IEEE80211_HT_CAP_SGI_40);
2347 }
2348
2349 if (TEST_FLAG(phtpriv->stbc_cap, STBC_HT_ENABLE_TX))
2350 ht_capie.cap_info |= cpu_to_le16(IEEE80211_HT_CAP_TX_STBC);
2351
2352 /* todo: disable SM power save mode */
2353 ht_capie.cap_info |= cpu_to_le16(IEEE80211_HT_CAP_SM_PS);
2354
2355 if (TEST_FLAG(phtpriv->stbc_cap, STBC_HT_ENABLE_RX)) {
2356 if ((channel <= 14 && pregistrypriv->rx_stbc == 0x1) || /* enable for 2.4GHz */
2357 (pregistrypriv->wifi_spec == 1))
2358 stbc_rx_enable = 1;
2359 }
2360
2361 /* fill default supported_mcs_set */
2362 memcpy(&ht_capie.mcs, pmlmeext->default_supported_mcs_set, 16);
2363
2364 /* update default supported_mcs_set */
2365 if (stbc_rx_enable)
2366 ht_capie.cap_info |= cpu_to_le16(IEEE80211_HT_CAP_RX_STBC_1R);/* RX STBC One spatial stream */
2367
2368 set_mcs_rate_by_mask(mcs_set: ht_capie.mcs.rx_mask, MCS_RATE_1R);
2369
2370 {
2371 u32 rx_packet_offset, max_recvbuf_sz;
2372
2373 rtw_hal_get_def_var(padapter, eVariable: HAL_DEF_RX_PACKET_OFFSET, pValue: &rx_packet_offset);
2374 rtw_hal_get_def_var(padapter, eVariable: HAL_DEF_MAX_RECVBUF_SZ, pValue: &max_recvbuf_sz);
2375 }
2376
2377 if (padapter->driver_rx_ampdu_factor != 0xFF)
2378 max_rx_ampdu_factor =
2379 (enum ieee80211_max_ampdu_length_exp)padapter->driver_rx_ampdu_factor;
2380 else
2381 rtw_hal_get_def_var(padapter, eVariable: HW_VAR_MAX_RX_AMPDU_FACTOR,
2382 pValue: &max_rx_ampdu_factor);
2383
2384 /* rtw_hal_get_def_var(padapter, HW_VAR_MAX_RX_AMPDU_FACTOR, &max_rx_ampdu_factor); */
2385 ht_capie.ampdu_params_info = (max_rx_ampdu_factor&0x03);
2386
2387 if (padapter->securitypriv.dot11PrivacyAlgrthm == _AES_)
2388 ht_capie.ampdu_params_info |= (IEEE80211_HT_CAP_AMPDU_DENSITY&(0x07<<2));
2389 else
2390 ht_capie.ampdu_params_info |= (IEEE80211_HT_CAP_AMPDU_DENSITY&0x00);
2391
2392 rtw_set_ie(pbuf: out_ie+out_len, index: WLAN_EID_HT_CAPABILITY,
2393 len: sizeof(struct ieee80211_ht_cap), source: (unsigned char *)&ht_capie, frlen: pout_len);
2394
2395 phtpriv->ht_option = true;
2396
2397 if (in_ie) {
2398 p = rtw_get_ie(pbuf: in_ie, index: WLAN_EID_HT_OPERATION, len: &ielen, limit: in_len);
2399 if (p && (ielen == sizeof(struct ieee80211_ht_addt_info))) {
2400 out_len = *pout_len;
2401 rtw_set_ie(pbuf: out_ie+out_len, index: WLAN_EID_HT_OPERATION, len: ielen, source: p+2, frlen: pout_len);
2402 }
2403 }
2404
2405 return phtpriv->ht_option;
2406
2407}
2408
2409/* the function is > passive_level (in critical_section) */
2410void rtw_update_ht_cap(struct adapter *padapter, u8 *pie, uint ie_len, u8 channel)
2411{
2412 u8 *p, max_ampdu_sz;
2413 int len;
2414 /* struct sta_info *bmc_sta, *psta; */
2415 struct ieee80211_ht_cap *pht_capie;
2416 /* struct recv_reorder_ctrl *preorder_ctrl; */
2417 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
2418 struct ht_priv *phtpriv = &pmlmepriv->htpriv;
2419 /* struct recv_priv *precvpriv = &padapter->recvpriv; */
2420 struct registry_priv *pregistrypriv = &padapter->registrypriv;
2421 /* struct wlan_network *pcur_network = &(pmlmepriv->cur_network);; */
2422 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
2423 struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
2424 u8 cbw40_enable = 0;
2425
2426 if (!phtpriv->ht_option)
2427 return;
2428
2429 if ((!pmlmeinfo->HT_info_enable) || (!pmlmeinfo->HT_caps_enable))
2430 return;
2431
2432 /* maybe needs check if ap supports rx ampdu. */
2433 if (!(phtpriv->ampdu_enable) && pregistrypriv->ampdu_enable == 1)
2434 phtpriv->ampdu_enable = true;
2435
2436 /* check Max Rx A-MPDU Size */
2437 len = 0;
2438 p = rtw_get_ie(pbuf: pie+sizeof(struct ndis_802_11_fix_ie), index: WLAN_EID_HT_CAPABILITY, len: &len, limit: ie_len-sizeof(struct ndis_802_11_fix_ie));
2439 if (p && len > 0) {
2440 pht_capie = (struct ieee80211_ht_cap *)(p+2);
2441 max_ampdu_sz = (pht_capie->ampdu_params_info & IEEE80211_HT_CAP_AMPDU_FACTOR);
2442 max_ampdu_sz = 1 << (max_ampdu_sz+3); /* max_ampdu_sz (kbytes); */
2443
2444 phtpriv->rx_ampdu_maxlen = max_ampdu_sz;
2445
2446 }
2447
2448 len = 0;
2449 p = rtw_get_ie(pbuf: pie+sizeof(struct ndis_802_11_fix_ie), index: WLAN_EID_HT_OPERATION, len: &len, limit: ie_len-sizeof(struct ndis_802_11_fix_ie));
2450 if (p && len > 0) {
2451 /* todo: */
2452 }
2453
2454 if (channel > 14) {
2455 if ((pregistrypriv->bw_mode & 0xf0) > 0)
2456 cbw40_enable = 1;
2457 } else {
2458 if ((pregistrypriv->bw_mode & 0x0f) > 0)
2459 cbw40_enable = 1;
2460 }
2461
2462 /* update cur_bwmode & cur_ch_offset */
2463 if ((cbw40_enable) &&
2464 (le16_to_cpu(pmlmeinfo->HT_caps.u.HT_cap_element.HT_caps_info) &
2465 BIT(1)) && (pmlmeinfo->HT_info.infos[0] & BIT(2))) {
2466 int i;
2467
2468 /* update the MCS set */
2469 for (i = 0; i < 16; i++)
2470 pmlmeinfo->HT_caps.u.HT_cap_element.MCS_rate[i] &= pmlmeext->default_supported_mcs_set[i];
2471
2472 /* update the MCS rates */
2473 set_mcs_rate_by_mask(mcs_set: pmlmeinfo->HT_caps.u.HT_cap_element.MCS_rate, MCS_RATE_1R);
2474
2475 /* switch to the 40M Hz mode according to the AP */
2476 /* pmlmeext->cur_bwmode = CHANNEL_WIDTH_40; */
2477 switch ((pmlmeinfo->HT_info.infos[0] & 0x3)) {
2478 case EXTCHNL_OFFSET_UPPER:
2479 pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_LOWER;
2480 break;
2481
2482 case EXTCHNL_OFFSET_LOWER:
2483 pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_UPPER;
2484 break;
2485
2486 default:
2487 pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
2488 break;
2489 }
2490 }
2491
2492 /* */
2493 /* Config SM Power Save setting */
2494 /* */
2495 pmlmeinfo->SM_PS =
2496 (le16_to_cpu(pmlmeinfo->HT_caps.u.HT_cap_element.HT_caps_info) &
2497 0x0C) >> 2;
2498
2499 /* */
2500 /* Config current HT Protection mode. */
2501 /* */
2502 pmlmeinfo->HT_protection = pmlmeinfo->HT_info.infos[1] & 0x3;
2503}
2504
2505void rtw_issue_addbareq_cmd(struct adapter *padapter, struct xmit_frame *pxmitframe)
2506{
2507 u8 issued;
2508 int priority;
2509 struct sta_info *psta;
2510 struct ht_priv *phtpriv;
2511 struct pkt_attrib *pattrib = &pxmitframe->attrib;
2512 s32 bmcst = is_multicast_ether_addr(addr: pattrib->ra);
2513
2514 /* if (bmcst || (padapter->mlmepriv.LinkDetectInfo.bTxBusyTraffic == false)) */
2515 if (bmcst || (padapter->mlmepriv.LinkDetectInfo.NumTxOkInPeriod < 100))
2516 return;
2517
2518 priority = pattrib->priority;
2519
2520 psta = rtw_get_stainfo(pstapriv: &padapter->stapriv, hwaddr: pattrib->ra);
2521 if (pattrib->psta != psta)
2522 return;
2523
2524 if (!psta)
2525 return;
2526
2527 if (!(psta->state & _FW_LINKED))
2528 return;
2529
2530 phtpriv = &psta->htpriv;
2531
2532 if (phtpriv->ht_option && phtpriv->ampdu_enable) {
2533 issued = (phtpriv->agg_enable_bitmap>>priority)&0x1;
2534 issued |= (phtpriv->candidate_tid_bitmap>>priority)&0x1;
2535
2536 if (issued == 0) {
2537 psta->htpriv.candidate_tid_bitmap |= BIT((u8)priority);
2538 rtw_addbareq_cmd(padapter, tid: (u8) priority, addr: pattrib->ra);
2539 }
2540 }
2541
2542}
2543
2544void rtw_append_exented_cap(struct adapter *padapter, u8 *out_ie, uint *pout_len)
2545{
2546 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
2547 struct ht_priv *phtpriv = &pmlmepriv->htpriv;
2548 u8 cap_content[8] = {0};
2549
2550 if (phtpriv->bss_coexist)
2551 SET_EXT_CAPABILITY_ELE_BSS_COEXIST(cap_content, 1);
2552
2553 rtw_set_ie(pbuf: out_ie + *pout_len, index: WLAN_EID_EXT_CAPABILITY, len: 8, source: cap_content, frlen: pout_len);
2554}
2555
2556inline void rtw_set_to_roam(struct adapter *adapter, u8 to_roam)
2557{
2558 if (to_roam == 0)
2559 adapter->mlmepriv.to_join = false;
2560 adapter->mlmepriv.to_roam = to_roam;
2561}
2562
2563inline u8 rtw_dec_to_roam(struct adapter *adapter)
2564{
2565 adapter->mlmepriv.to_roam--;
2566 return adapter->mlmepriv.to_roam;
2567}
2568
2569inline u8 rtw_to_roam(struct adapter *adapter)
2570{
2571 return adapter->mlmepriv.to_roam;
2572}
2573
2574void rtw_roaming(struct adapter *padapter, struct wlan_network *tgt_network)
2575{
2576 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
2577
2578 spin_lock_bh(lock: &pmlmepriv->lock);
2579 _rtw_roaming(adapter: padapter, tgt_network);
2580 spin_unlock_bh(lock: &pmlmepriv->lock);
2581}
2582void _rtw_roaming(struct adapter *padapter, struct wlan_network *tgt_network)
2583{
2584 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
2585 struct wlan_network *cur_network = &pmlmepriv->cur_network;
2586
2587 if (rtw_to_roam(adapter: padapter) > 0) {
2588 memcpy(&pmlmepriv->assoc_ssid, &cur_network->network.ssid, sizeof(struct ndis_802_11_ssid));
2589
2590 pmlmepriv->assoc_by_bssid = false;
2591
2592 while (rtw_do_join(padapter) != _SUCCESS) {
2593 rtw_dec_to_roam(adapter: padapter);
2594 if (rtw_to_roam(adapter: padapter) <= 0) {
2595 rtw_indicate_disconnect(padapter);
2596 break;
2597 }
2598 }
2599 }
2600}
2601
2602signed int rtw_linked_check(struct adapter *padapter)
2603{
2604 if ((check_fwstate(pmlmepriv: &padapter->mlmepriv, WIFI_AP_STATE) == true) ||
2605 (check_fwstate(pmlmepriv: &padapter->mlmepriv, WIFI_ADHOC_STATE|WIFI_ADHOC_MASTER_STATE) == true)) {
2606 if (padapter->stapriv.asoc_sta_count > 2)
2607 return true;
2608 } else { /* Station mode */
2609 if (check_fwstate(pmlmepriv: &padapter->mlmepriv, _FW_LINKED) == true)
2610 return true;
2611 }
2612 return false;
2613}
2614

source code of linux/drivers/staging/rtl8723bs/core/rtw_mlme.c