]> git.proxmox.com Git - mirror_ubuntu-artful-kernel.git/blame - drivers/staging/rtl8723au/core/rtw_mlme.c
staging: rtl8723au: rtw_restructure_ht_ie23a(): use cfg80211_find_ie()
[mirror_ubuntu-artful-kernel.git] / drivers / staging / rtl8723au / core / rtw_mlme.c
CommitLineData
5e93f352
LF
1/******************************************************************************
2 *
3 * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of version 2 of the GNU General Public License as
7 * published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 ******************************************************************************/
15#define _RTW_MLME_C_
16
17#include <osdep_service.h>
18#include <drv_types.h>
19#include <recv_osdep.h>
20#include <xmit_osdep.h>
21#include <hal_intf.h>
22#include <mlme_osdep.h>
23#include <sta_info.h>
24#include <linux/ieee80211.h>
25#include <wifi.h>
26#include <wlan_bssdef.h>
27#include <rtw_ioctl_set.h>
28
29extern u8 rtw_do_join23a(struct rtw_adapter * padapter);
30
31static void rtw_init_mlme_timer(struct rtw_adapter *padapter)
32{
33 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
34
35 setup_timer(&pmlmepriv->assoc_timer, rtw23a_join_to_handler,
36 (unsigned long)padapter);
37
38 setup_timer(&pmlmepriv->scan_to_timer, rtw_scan_timeout_handler23a,
39 (unsigned long)padapter);
40
41 setup_timer(&pmlmepriv->dynamic_chk_timer,
42 rtw_dynamic_check_timer_handler, (unsigned long)padapter);
43
44 setup_timer(&pmlmepriv->set_scan_deny_timer,
45 rtw_set_scan_deny_timer_hdl, (unsigned long)padapter);
46}
47
48int _rtw_init_mlme_priv23a(struct rtw_adapter *padapter)
49{
50 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
51 int res = _SUCCESS;
52
53 pmlmepriv->nic_hdl = padapter;
54
55 pmlmepriv->fw_state = 0;
56 pmlmepriv->cur_network.network.InfrastructureMode = Ndis802_11AutoUnknown;
57 pmlmepriv->scan_mode=SCAN_ACTIVE;/* 1: active, 0: pasive. Maybe someday we should rename this varable to "active_mode" (Jeff) */
58
59 spin_lock_init(&pmlmepriv->lock);
60 _rtw_init_queue23a(&pmlmepriv->scanned_queue);
61
62 memset(&pmlmepriv->assoc_ssid, 0, sizeof(struct cfg80211_ssid));
63
64 /* allocate DMA-able/Non-Page memory for cmd_buf and rsp_buf */
65
66 rtw_clear_scan_deny(padapter);
67
68 rtw_init_mlme_timer(padapter);
69 return res;
70}
71
c17416ef 72#ifdef CONFIG_8723AU_AP_MODE
5e93f352
LF
73static void rtw_free_mlme_ie_data(u8 **ppie, u32 *plen)
74{
75 if(*ppie)
76 {
77 kfree(*ppie);
78 *plen = 0;
79 *ppie=NULL;
80 }
81}
c17416ef 82#endif
5e93f352
LF
83
84void rtw23a_free_mlme_priv_ie_data(struct mlme_priv *pmlmepriv)
85{
86#ifdef CONFIG_8723AU_AP_MODE
87 kfree(pmlmepriv->assoc_req);
88 kfree(pmlmepriv->assoc_rsp);
89 rtw_free_mlme_ie_data(&pmlmepriv->wps_beacon_ie, &pmlmepriv->wps_beacon_ie_len);
90 rtw_free_mlme_ie_data(&pmlmepriv->wps_probe_req_ie, &pmlmepriv->wps_probe_req_ie_len);
91 rtw_free_mlme_ie_data(&pmlmepriv->wps_probe_resp_ie, &pmlmepriv->wps_probe_resp_ie_len);
92 rtw_free_mlme_ie_data(&pmlmepriv->wps_assoc_resp_ie, &pmlmepriv->wps_assoc_resp_ie_len);
93
94 rtw_free_mlme_ie_data(&pmlmepriv->p2p_beacon_ie, &pmlmepriv->p2p_beacon_ie_len);
95 rtw_free_mlme_ie_data(&pmlmepriv->p2p_probe_req_ie, &pmlmepriv->p2p_probe_req_ie_len);
96 rtw_free_mlme_ie_data(&pmlmepriv->p2p_probe_resp_ie, &pmlmepriv->p2p_probe_resp_ie_len);
97 rtw_free_mlme_ie_data(&pmlmepriv->p2p_go_probe_resp_ie, &pmlmepriv->p2p_go_probe_resp_ie_len);
98 rtw_free_mlme_ie_data(&pmlmepriv->p2p_assoc_req_ie, &pmlmepriv->p2p_assoc_req_ie_len);
5e93f352 99
5e93f352
LF
100 rtw_free_mlme_ie_data(&pmlmepriv->wfd_beacon_ie, &pmlmepriv->wfd_beacon_ie_len);
101 rtw_free_mlme_ie_data(&pmlmepriv->wfd_probe_req_ie, &pmlmepriv->wfd_probe_req_ie_len);
102 rtw_free_mlme_ie_data(&pmlmepriv->wfd_probe_resp_ie, &pmlmepriv->wfd_probe_resp_ie_len);
103 rtw_free_mlme_ie_data(&pmlmepriv->wfd_go_probe_resp_ie, &pmlmepriv->wfd_go_probe_resp_ie_len);
104 rtw_free_mlme_ie_data(&pmlmepriv->wfd_assoc_req_ie, &pmlmepriv->wfd_assoc_req_ie_len);
105#endif
106}
107
108void _rtw_free_mlme_priv23a(struct mlme_priv *pmlmepriv)
109{
110
111 rtw23a_free_mlme_priv_ie_data(pmlmepriv);
112
113}
114
115struct wlan_network *rtw_alloc_network(struct mlme_priv *pmlmepriv)
116{
117 struct wlan_network *pnetwork;
118
119 pnetwork = kzalloc(sizeof(struct wlan_network), GFP_ATOMIC);
120 if (pnetwork) {
121 INIT_LIST_HEAD(&pnetwork->list);
122 pnetwork->network_type = 0;
123 pnetwork->fixed = false;
124 pnetwork->last_scanned = jiffies;
125 pnetwork->aid = 0;
126 pnetwork->join_res = 0;
127 }
128
129 return pnetwork;
130}
131
132void _rtw_free_network23a(struct mlme_priv *pmlmepriv,
133 struct wlan_network *pnetwork, u8 isfreeall)
134{
135 u32 lifetime = SCANQUEUE_LIFETIME;
136
137 if (!pnetwork)
138 return;
139
140 if (pnetwork->fixed == true)
141 return;
142
143 if ((check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) == true) ||
144 (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE) == true))
145 lifetime = 1;
146
147 list_del_init(&pnetwork->list);
148
149 kfree(pnetwork);
150}
151
152void _rtw_free_network23a_nolock23a(struct mlme_priv *pmlmepriv,
153 struct wlan_network *pnetwork)
154{
155
156 if (pnetwork == NULL)
157 return;
158
159 if (pnetwork->fixed == true)
160 return;
161
162 list_del_init(&pnetwork->list);
163
164 kfree(pnetwork);
165}
166
167/*
168 return the wlan_network with the matching addr
169
170 Shall be calle under atomic context... to avoid possible racing condition...
171*/
172struct wlan_network *
173_rtw_find_network23a(struct rtw_queue *scanned_queue, u8 *addr)
174{
175 struct list_head *phead, *plist;
176 struct wlan_network *pnetwork = NULL;
177
178 if (is_zero_ether_addr(addr)) {
179 pnetwork = NULL;
180 goto exit;
181 }
182
183 /* spin_lock_bh(&scanned_queue->lock); */
184
185 phead = get_list_head(scanned_queue);
186 plist = phead->next;
187
188 while (plist != phead) {
189 pnetwork = container_of(plist, struct wlan_network, list);
190
191 if (ether_addr_equal(addr, pnetwork->network.MacAddress))
192 break;
193
194 plist = plist->next;
195 }
196
197 if(plist == phead)
198 pnetwork = NULL;
199
200 /* spin_unlock_bh(&scanned_queue->lock); */
201
202exit:
203
204 return pnetwork;
205}
206
207void _rtw_free_network23a_queue23a(struct rtw_adapter *padapter, u8 isfreeall)
208{
209 struct list_head *phead, *plist, *ptmp;
210 struct wlan_network *pnetwork;
211 struct mlme_priv* pmlmepriv = &padapter->mlmepriv;
212 struct rtw_queue *scanned_queue = &pmlmepriv->scanned_queue;
213
214 spin_lock_bh(&scanned_queue->lock);
215
216 phead = get_list_head(scanned_queue);
217
218 list_for_each_safe(plist, ptmp, phead) {
219 pnetwork = container_of(plist, struct wlan_network, list);
220
221 _rtw_free_network23a(pmlmepriv,pnetwork, isfreeall);
222 }
223
224 spin_unlock_bh(&scanned_queue->lock);
225
226}
227
228int rtw_if_up23a(struct rtw_adapter *padapter) {
229
230 int res;
231
232 if(padapter->bDriverStopped || padapter->bSurpriseRemoved ||
233 (check_fwstate(&padapter->mlmepriv, _FW_LINKED)== false)) {
234 RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("rtw_if_up23a:bDriverStopped(%d) OR bSurpriseRemoved(%d)", padapter->bDriverStopped, padapter->bSurpriseRemoved));
235 res=false;
236 }
237 else
238 res= true;
239
240 return res;
241}
242
243void rtw_generate_random_ibss23a(u8* pibss)
244{
245 unsigned long curtime = jiffies;
246
247 pibss[0] = 0x02; /* in ad-hoc mode bit1 must set to 1 */
248 pibss[1] = 0x11;
249 pibss[2] = 0x87;
250 pibss[3] = (u8)(curtime & 0xff) ;/* p[0]; */
251 pibss[4] = (u8)((curtime>>8) & 0xff) ;/* p[1]; */
252 pibss[5] = (u8)((curtime>>16) & 0xff) ;/* p[2]; */
253
254 return;
255}
256
257u8 *rtw_get_capability23a_from_ie(u8 *ie)
258{
259 return ie + 8 + 2;
260}
261
262u16 rtw_get_capability23a(struct wlan_bssid_ex *bss)
263{
264 u16 val;
265
266 memcpy((u8 *)&val, rtw_get_capability23a_from_ie(bss->IEs), 2);
267
268 return le16_to_cpu(val);
269}
270
271u8 *rtw_get_timestampe_from_ie23a(u8 *ie)
272{
273 return ie + 0;
274}
275
276u8 *rtw_get_beacon_interval23a_from_ie(u8 *ie)
277{
278 return ie + 8;
279}
280
281int rtw_init_mlme_priv23a (struct rtw_adapter *padapter)/* struct mlme_priv *pmlmepriv) */
282{
283 int res;
284
285 res = _rtw_init_mlme_priv23a(padapter);/* (pmlmepriv); */
286
287 return res;
288}
289
290void rtw_free_mlme_priv23a (struct mlme_priv *pmlmepriv)
291{
292
293 RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("rtw_free_mlme_priv23a\n"));
294 _rtw_free_mlme_priv23a(pmlmepriv);
295
296}
297
298void rtw_free_network(struct mlme_priv *pmlmepriv, struct wlan_network *pnetwork, u8 is_freeall);
299void rtw_free_network(struct mlme_priv *pmlmepriv, struct wlan_network *pnetwork, u8 is_freeall)/* struct wlan_network *pnetwork, _queue *free_queue) */
300{
301
302 RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_,
303 ("rtw_free_network ==> ssid = %s\n\n" ,
304 pnetwork->network.Ssid.ssid));
305 _rtw_free_network23a(pmlmepriv, pnetwork, is_freeall);
306
307}
308
309void rtw_free_network_nolock(struct mlme_priv *pmlmepriv, struct wlan_network *pnetwork);
310void rtw_free_network_nolock(struct mlme_priv *pmlmepriv, struct wlan_network *pnetwork)
311{
312
313 /* RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("rtw_free_network ==> ssid = %s\n\n" , pnetwork->network.Ssid.ssid)); */
314 _rtw_free_network23a_nolock23a(pmlmepriv, pnetwork);
315
316}
317
318void rtw_free_network_queue23a(struct rtw_adapter* dev, u8 isfreeall)
319{
320
321 _rtw_free_network23a_queue23a(dev, isfreeall);
322
323}
324
325/*
326 return the wlan_network with the matching addr
327
328 Shall be calle under atomic context... to avoid possible racing condition...
329*/
330struct wlan_network *
331rtw_find_network23a(struct rtw_queue *scanned_queue, u8 *addr)
332{
333 struct wlan_network *pnetwork;
334
335 pnetwork = _rtw_find_network23a(scanned_queue, addr);
336
337 return pnetwork;
338}
339
340int rtw_is_same_ibss23a(struct rtw_adapter *adapter, struct wlan_network *pnetwork)
341{
342 int ret = true;
343 struct security_priv *psecuritypriv = &adapter->securitypriv;
344
345 if ((psecuritypriv->dot11PrivacyAlgrthm != _NO_PRIVACY_) &&
346 (pnetwork->network.Privacy == 0))
347 {
348 ret = false;
349 }
350 else if ((psecuritypriv->dot11PrivacyAlgrthm == _NO_PRIVACY_) &&
351 (pnetwork->network.Privacy == 1))
352 {
353 ret = false;
354 }
355 else
356 {
357 ret = true;
358 }
359
360 return ret;
361}
362
363inline int is_same_ess(struct wlan_bssid_ex *a, struct wlan_bssid_ex *b);
364inline int is_same_ess(struct wlan_bssid_ex *a, struct wlan_bssid_ex *b)
365{
366 /* RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("(%s,%d)(%s,%d)\n", */
367 /* a->Ssid.Ssid, a->Ssid.SsidLength, b->Ssid.Ssid, b->Ssid.SsidLength)); */
368 return (a->Ssid.ssid_len == b->Ssid.ssid_len) &&
369 !memcmp(a->Ssid.ssid, b->Ssid.ssid, a->Ssid.ssid_len);
370}
371
372int is_same_network23a(struct wlan_bssid_ex *src, struct wlan_bssid_ex *dst)
373{
374 u16 s_cap, d_cap;
375
376 memcpy((u8 *)&s_cap, rtw_get_capability23a_from_ie(src->IEs), 2);
377 memcpy((u8 *)&d_cap, rtw_get_capability23a_from_ie(dst->IEs), 2);
378
379 s_cap = le16_to_cpu(s_cap);
380 d_cap = le16_to_cpu(d_cap);
381
382 return ((src->Ssid.ssid_len == dst->Ssid.ssid_len) &&
383 /* (src->Configuration.DSConfig == dst->Configuration.DSConfig) && */
384 ether_addr_equal(src->MacAddress, dst->MacAddress) &&
385 ((!memcmp(src->Ssid.ssid, dst->Ssid.ssid, src->Ssid.ssid_len))) &&
386 ((s_cap & WLAN_CAPABILITY_IBSS) ==
387 (d_cap & WLAN_CAPABILITY_IBSS)) &&
388 ((s_cap & WLAN_CAPABILITY_ESS) ==
389 (d_cap & WLAN_CAPABILITY_ESS)));
390}
391
392struct wlan_network *rtw_get_oldest_wlan_network23a(struct rtw_queue *scanned_queue)
393{
394 struct list_head *plist, *phead;
395
396 struct wlan_network *pwlan;
397 struct wlan_network *oldest = NULL;
398
399 phead = get_list_head(scanned_queue);
400
401 list_for_each(plist, phead) {
402 pwlan = container_of(plist, struct wlan_network, list);
403
404 if (pwlan->fixed != true) {
405 if (!oldest || time_after(oldest->last_scanned,
406 pwlan->last_scanned))
407 oldest = pwlan;
408 }
409 }
410
411 return oldest;
412}
413
414void update_network23a(struct wlan_bssid_ex *dst, struct wlan_bssid_ex *src,
415 struct rtw_adapter * padapter, bool update_ie)
416{
417 u8 ss_ori = dst->PhyInfo.SignalStrength;
418 u8 sq_ori = dst->PhyInfo.SignalQuality;
419 long rssi_ori = dst->Rssi;
420
421 u8 ss_smp = src->PhyInfo.SignalStrength;
422 u8 sq_smp = src->PhyInfo.SignalQuality;
423 long rssi_smp = src->Rssi;
424
425 u8 ss_final;
426 u8 sq_final;
427 long rssi_final;
428
429 DBG_8723A("%s %s(%pM, ch%u) ss_ori:%3u, sq_ori:%3u, rssi_ori:%3ld, ss_smp:%3u, sq_smp:%3u, rssi_smp:%3ld\n",
430 __func__, src->Ssid.ssid, src->MacAddress,
431 src->Configuration.DSConfig, ss_ori, sq_ori, rssi_ori,
432 ss_smp, sq_smp, rssi_smp
433 );
434
435 /* The rule below is 1/5 for sample value, 4/5 for history value */
436 if (check_fwstate(&padapter->mlmepriv, _FW_LINKED) && is_same_network23a(&padapter->mlmepriv.cur_network.network, src)) {
437 /* Take the recvpriv's value for the connected AP*/
438 ss_final = padapter->recvpriv.signal_strength;
439 sq_final = padapter->recvpriv.signal_qual;
440 /* the rssi value here is undecorated, and will be used for antenna diversity */
441 if (sq_smp != 101) /* from the right channel */
442 rssi_final = (src->Rssi+dst->Rssi*4)/5;
443 else
444 rssi_final = rssi_ori;
445 }
446 else {
447 if (sq_smp != 101) { /* from the right channel */
448 ss_final = ((u32)(src->PhyInfo.SignalStrength)+(u32)(dst->PhyInfo.SignalStrength)*4)/5;
449 sq_final = ((u32)(src->PhyInfo.SignalQuality)+(u32)(dst->PhyInfo.SignalQuality)*4)/5;
450 rssi_final = (src->Rssi+dst->Rssi*4)/5;
451 } else {
452 /* bss info not receving from the right channel, use the original RX signal infos */
453 ss_final = dst->PhyInfo.SignalStrength;
454 sq_final = dst->PhyInfo.SignalQuality;
455 rssi_final = dst->Rssi;
456 }
457
458 }
459
460 if (update_ie)
461 memcpy((u8 *)dst, (u8 *)src, get_wlan_bssid_ex_sz(src));
462
463 dst->PhyInfo.SignalStrength = ss_final;
464 dst->PhyInfo.SignalQuality = sq_final;
465 dst->Rssi = rssi_final;
466
467 DBG_8723A("%s %s(%pM), SignalStrength:%u, SignalQuality:%u, RawRSSI:%ld\n",
468 __func__, dst->Ssid.ssid, dst->MacAddress,
469 dst->PhyInfo.SignalStrength,
470 dst->PhyInfo.SignalQuality, dst->Rssi);
471
472}
473
474static void update_current_network(struct rtw_adapter *adapter, struct wlan_bssid_ex *pnetwork)
475{
476 struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
477
478 if ((check_fwstate(pmlmepriv, _FW_LINKED)== true) && (is_same_network23a(&pmlmepriv->cur_network.network, pnetwork)))
479 {
480 /* RT_TRACE(_module_rtl871x_mlme_c_,_drv_err_,"Same Network\n"); */
481
482 /* if(pmlmepriv->cur_network.network.IELength<= pnetwork->IELength) */
483 {
484 update_network23a(&pmlmepriv->cur_network.network, pnetwork,adapter, true);
485 rtw_update_protection23a(adapter, (pmlmepriv->cur_network.network.IEs) + sizeof (struct ndis_802_11_fixed_ies),
486 pmlmepriv->cur_network.network.IELength);
487 }
488 }
489
490}
491
492/*
493
494Caller must hold pmlmepriv->lock first.
495
496*/
497void rtw_update_scanned_network23a(struct rtw_adapter *adapter, struct wlan_bssid_ex *target)
498{
499 struct list_head *plist, *phead;
500 struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
501 struct wlan_network *pnetwork = NULL;
502 struct wlan_network *oldest = NULL;
503 struct rtw_queue *queue = &pmlmepriv->scanned_queue;
504 u32 bssid_ex_sz;
505 int found = 0;
506
507 spin_lock_bh(&queue->lock);
508 phead = get_list_head(queue);
509
510 list_for_each(plist, phead) {
511 pnetwork = container_of(plist, struct wlan_network, list);
512
513 if (is_same_network23a(&pnetwork->network, target)) {
514 found = 1;
515 break;
516 }
517 if (!oldest || time_after(oldest->last_scanned,
518 pnetwork->last_scanned))
519 oldest = pnetwork;
520 }
521
522 /* If we didn't find a match, then get a new network slot to initialize
523 * with this beacon's information */
524 if (!found) {
525 pnetwork = rtw_alloc_network(pmlmepriv);
526 if (!pnetwork) {
527 if (!oldest) {
528 RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_,
529 ("\n\n\nsomething wrong here\n\n\n"));
530 goto exit;
531 }
532 pnetwork = oldest;
533 } else
534 list_add_tail(&pnetwork->list, &queue->queue);
535
536 bssid_ex_sz = get_wlan_bssid_ex_sz(target);
537 target->Length = bssid_ex_sz;
538 memcpy(&pnetwork->network, target, bssid_ex_sz);
539
540 /* variable initialize */
541 pnetwork->fixed = false;
542 pnetwork->last_scanned = jiffies;
543
544 pnetwork->network_type = 0;
545 pnetwork->aid = 0;
546 pnetwork->join_res = 0;
547
548 /* bss info not receving from the right channel */
549 if (pnetwork->network.PhyInfo.SignalQuality == 101)
550 pnetwork->network.PhyInfo.SignalQuality = 0;
551 } else {
552 /*
553 * we have an entry and we are going to update it. But
554 * this entry may be already expired. In this case we
555 * do the same as we found a new net and call the
556 * new_net handler
557 */
558 bool update_ie = true;
559
560 pnetwork->last_scanned = jiffies;
561
562 /* target.reserved == 1, means that scanned network is
563 * a bcn frame. */
564 if ((pnetwork->network.IELength>target->IELength) &&
565 (target->reserved == 1))
566 update_ie = false;
567
568 update_network23a(&pnetwork->network, target,adapter, update_ie);
569 }
570
571exit:
572 spin_unlock_bh(&queue->lock);
573
574}
575
576void rtw_add_network(struct rtw_adapter *adapter, struct wlan_bssid_ex *pnetwork)
577{
578 update_current_network(adapter, pnetwork);
579 rtw_update_scanned_network23a(adapter, pnetwork);
580}
581
582/* select the desired network based on the capability of the (i)bss. */
583/* check items: (1) security */
584/* (2) network_type */
585/* (3) WMM */
586/* (4) HT */
587/* (5) others */
588int rtw_is_desired_network(struct rtw_adapter *adapter, struct wlan_network *pnetwork)
589{
590 struct security_priv *psecuritypriv = &adapter->securitypriv;
591 struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
592 u32 desired_encmode;
593 u32 privacy;
594
595 /* u8 wps_ie[512]; */
596 uint wps_ielen;
597
598 int bselected = true;
599
600 desired_encmode = psecuritypriv->ndisencryptstatus;
601 privacy = pnetwork->network.Privacy;
602
603 if (check_fwstate(pmlmepriv, WIFI_UNDER_WPS))
604 {
605 if (rtw_get_wps_ie23a(pnetwork->network.IEs+_FIXED_IE_LENGTH_, pnetwork->network.IELength-_FIXED_IE_LENGTH_, NULL, &wps_ielen)!= NULL)
606 {
607 return true;
608 }
609 else
610 {
611 return false;
612 }
613 }
614 if (adapter->registrypriv.wifi_spec == 1) /* for correct flow of 8021X to do.... */
615 {
616 if ((desired_encmode == Ndis802_11EncryptionDisabled) && (privacy != 0))
617 bselected = false;
618 }
619
620 if ((desired_encmode != Ndis802_11EncryptionDisabled) && (privacy == 0)) {
621 DBG_8723A("desired_encmode: %d, privacy: %d\n", desired_encmode, privacy);
622 bselected = false;
623 }
624
625 if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE) == true)
626 {
627 if (pnetwork->network.InfrastructureMode != pmlmepriv->cur_network.network.InfrastructureMode)
628 bselected = false;
629 }
630
631 return bselected;
632}
633
634/* TODO: Perry : For Power Management */
635void rtw_atimdone_event_callback23a(struct rtw_adapter *adapter , u8 *pbuf)
636{
637
638 RT_TRACE(_module_rtl871x_mlme_c_,_drv_err_,("receive atimdone_evet\n"));
639
640 return;
641}
642
643void rtw_survey_event_cb23a(struct rtw_adapter *adapter, u8 *pbuf)
644{
645 u32 len;
646 struct wlan_bssid_ex *pnetwork;
647 struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
648
649 pnetwork = (struct wlan_bssid_ex *)pbuf;
650
651 RT_TRACE(_module_rtl871x_mlme_c_,_drv_info_,("rtw_survey_event_cb23a, ssid=%s\n", pnetwork->Ssid.ssid));
652
653 len = get_wlan_bssid_ex_sz(pnetwork);
654 if(len > (sizeof(struct wlan_bssid_ex)))
655 {
656 RT_TRACE(_module_rtl871x_mlme_c_,_drv_err_,("\n ****rtw_survey_event_cb23a: return a wrong bss ***\n"));
657 return;
658 }
659
660 spin_lock_bh(&pmlmepriv->lock);
661
662 /* update IBSS_network 's timestamp */
663 if ((check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE)) == true)
664 {
665 /* RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_,"rtw_survey_event_cb23a : WIFI_ADHOC_MASTER_STATE\n\n"); */
666 if (ether_addr_equal(pmlmepriv->cur_network.network.MacAddress,
667 pnetwork->MacAddress)) {
668 struct wlan_network* ibss_wlan = NULL;
669
670 memcpy(pmlmepriv->cur_network.network.IEs, pnetwork->IEs, 8);
671 spin_lock_bh(&pmlmepriv->scanned_queue.lock);
672 ibss_wlan = rtw_find_network23a(&pmlmepriv->scanned_queue, pnetwork->MacAddress);
673 if (ibss_wlan)
674 {
675 memcpy(ibss_wlan->network.IEs , pnetwork->IEs, 8);
676 spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
677 goto exit;
678 }
679 spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
680 }
681 }
682
683 /* lock pmlmepriv->lock when you accessing network_q */
684 if ((check_fwstate(pmlmepriv, _FW_UNDER_LINKING)) == false)
685 {
686 if (pnetwork->Ssid.ssid[0] == 0)
687 pnetwork->Ssid.ssid_len = 0;
688
689 rtw_add_network(adapter, pnetwork);
690 }
691
692exit:
693
694 spin_unlock_bh(&pmlmepriv->lock);
695
696 return;
697}
698
699void rtw_surveydone_event_callback23a(struct rtw_adapter *adapter, u8 *pbuf)
700{
701 struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
702 struct mlme_ext_priv *pmlmeext = &adapter->mlmeextpriv;
703
704 spin_lock_bh(&pmlmepriv->lock);
705
706 if (pmlmepriv->wps_probe_req_ie) {
707 pmlmepriv->wps_probe_req_ie_len = 0;
708 kfree(pmlmepriv->wps_probe_req_ie);
709 pmlmepriv->wps_probe_req_ie = NULL;
710 }
711
712 RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("rtw_surveydone_event_callback23a: fw_state:%x\n\n", get_fwstate(pmlmepriv)));
713
714 if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY)) {
715 del_timer_sync(&pmlmepriv->scan_to_timer);
716
717 _clr_fwstate_(pmlmepriv, _FW_UNDER_SURVEY);
718 } else {
719
720 RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("nic status =%x, survey done event comes too late!\n", get_fwstate(pmlmepriv)));
721 }
722
723 rtw_set_signal_stat_timer(&adapter->recvpriv);
724
725 if (pmlmepriv->to_join == true) {
726 if ((check_fwstate(pmlmepriv, WIFI_ADHOC_STATE) == true)) {
727 if (check_fwstate(pmlmepriv, _FW_LINKED) == false) {
728 set_fwstate(pmlmepriv, _FW_UNDER_LINKING);
729
730 if (rtw_select_and_join_from_scanned_queue23a(pmlmepriv) == _SUCCESS) {
731 mod_timer(&pmlmepriv->assoc_timer,
732 jiffies + msecs_to_jiffies(MAX_JOIN_TIMEOUT));
733 } else {
734 struct wlan_bssid_ex *pdev_network = &adapter->registrypriv.dev_network;
735 u8 *pibss = adapter->registrypriv.dev_network.MacAddress;
736
737 _clr_fwstate_(pmlmepriv, _FW_UNDER_SURVEY);
738
739 RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("switching to adhoc master\n"));
740
741 memset(&pdev_network->Ssid, 0, sizeof(struct cfg80211_ssid));
742 memcpy(&pdev_network->Ssid, &pmlmepriv->assoc_ssid, sizeof(struct cfg80211_ssid));
743
744 rtw_update_registrypriv_dev_network23a(adapter);
745 rtw_generate_random_ibss23a(pibss);
746
747 pmlmepriv->fw_state = WIFI_ADHOC_MASTER_STATE;
748
749 if (rtw_createbss_cmd23a(adapter)!= _SUCCESS)
750 {
751 RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("Error =>rtw_createbss_cmd23a status FAIL\n"));
752 }
753
754 pmlmepriv->to_join = false;
755 }
756 }
757 } else {
758 int ret;
759 set_fwstate(pmlmepriv, _FW_UNDER_LINKING);
760 pmlmepriv->to_join = false;
761 ret = rtw_select_and_join_from_scanned_queue23a(pmlmepriv);
762 if (ret == _SUCCESS) {
763 unsigned long e;
764 e = msecs_to_jiffies(MAX_JOIN_TIMEOUT);
765 mod_timer(&pmlmepriv->assoc_timer, jiffies + e);
766 } else if (ret == 2)/* there is no need to wait for join */
767 {
768 _clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING);
769 rtw_indicate_connect23a(adapter);
770 } else {
771 DBG_8723A("try_to_join, but select scanning queue fail, to_roaming:%d\n", rtw_to_roaming(adapter));
772 if (rtw_to_roaming(adapter) != 0) {
773 if (--pmlmepriv->to_roaming == 0
774 || _SUCCESS != rtw_sitesurvey_cmd23a(adapter, &pmlmepriv->assoc_ssid, 1, NULL, 0)
775 ) {
776 rtw_set_roaming(adapter, 0);
777 rtw_free_assoc_resources23a(adapter, 1);
778 rtw_indicate_disconnect23a(adapter);
779 } else {
780 pmlmepriv->to_join = true;
781 }
782 }
783 _clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING);
784 }
785 }
786 }
787
788 spin_unlock_bh(&pmlmepriv->lock);
789
5e93f352
LF
790 rtw_os_xmit_schedule23a(adapter);
791
792 if(pmlmeext->sitesurvey_res.bss_cnt == 0)
793 rtw_hal_sreset_reset23a(adapter);
794
795 rtw_cfg80211_surveydone_event_callback(adapter);
796
797}
798
799void rtw_dummy_event_callback23a(struct rtw_adapter *adapter , u8 *pbuf)
800{
801}
802
803void rtw23a_fwdbg_event_callback(struct rtw_adapter *adapter , u8 *pbuf)
804{
805}
806
807static void free_scanqueue(struct mlme_priv *pmlmepriv)
808{
809 struct wlan_network *pnetwork;
810 struct rtw_queue *scan_queue = &pmlmepriv->scanned_queue;
811 struct list_head *plist, *phead, *ptemp;
812
813 RT_TRACE(_module_rtl871x_mlme_c_, _drv_notice_, ("+free_scanqueue\n"));
814 spin_lock_bh(&scan_queue->lock);
815
816 phead = get_list_head(scan_queue);
817
818 list_for_each_safe(plist, ptemp, phead) {
819 list_del_init(plist);
820 pnetwork = container_of(plist, struct wlan_network, list);
821 kfree(pnetwork);
822 }
823
824 spin_unlock_bh(&scan_queue->lock);
825
826}
827
828/*
829*rtw_free_assoc_resources23a: the caller has to lock pmlmepriv->lock
830*/
831void rtw_free_assoc_resources23a(struct rtw_adapter *adapter, int lock_scanned_queue)
832{
833 struct wlan_network* pwlan = NULL;
834 struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
835 struct sta_priv *pstapriv = &adapter->stapriv;
836 struct wlan_network *tgt_network = &pmlmepriv->cur_network;
837
838 RT_TRACE(_module_rtl871x_mlme_c_, _drv_notice_, ("+rtw_free_assoc_resources23a\n"));
839 RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("tgt_network->network.MacAddress="MAC_FMT" ssid=%s\n",
840 MAC_ARG(tgt_network->network.MacAddress), tgt_network->network.Ssid.ssid));
841
842 if(check_fwstate(pmlmepriv, WIFI_STATION_STATE|WIFI_AP_STATE))
843 {
844 struct sta_info* psta;
845
846 psta = rtw_get_stainfo23a(&adapter->stapriv, tgt_network->network.MacAddress);
847
848 {
849 spin_lock_bh(&pstapriv->sta_hash_lock);
850 rtw_free_stainfo23a(adapter, psta);
851 }
852
853 spin_unlock_bh(&pstapriv->sta_hash_lock);
854
855 }
856
857 if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE|WIFI_ADHOC_MASTER_STATE|WIFI_AP_STATE))
858 {
859 struct sta_info* psta;
860
861 rtw_free_all_stainfo23a(adapter);
862
863 psta = rtw_get_bcmc_stainfo23a(adapter);
864 spin_lock_bh(&pstapriv->sta_hash_lock);
865 rtw_free_stainfo23a(adapter, psta);
866 spin_unlock_bh(&pstapriv->sta_hash_lock);
867
868 rtw_init_bcmc_stainfo23a(adapter);
869 }
870
871 if(lock_scanned_queue)
872 spin_lock_bh(&pmlmepriv->scanned_queue.lock);
873
874 pwlan = rtw_find_network23a(&pmlmepriv->scanned_queue, tgt_network->network.MacAddress);
875 if(pwlan)
876 pwlan->fixed = false;
877 else
878 RT_TRACE(_module_rtl871x_mlme_c_,_drv_err_,("rtw_free_assoc_resources23a : pwlan== NULL\n\n"));
879
880 if (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) && (adapter->stapriv.asoc_sta_count == 1))
881 rtw_free_network_nolock(pmlmepriv, pwlan);
882
883 if(lock_scanned_queue)
884 spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
885
886 pmlmepriv->key_mask = 0;
887
888}
889
890/*
891*rtw_indicate_connect23a: the caller has to lock pmlmepriv->lock
892*/
893void rtw_indicate_connect23a(struct rtw_adapter *padapter)
894{
895 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
896
897 RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("+rtw_indicate_connect23a\n"));
898
899 pmlmepriv->to_join = false;
900
901 if(!check_fwstate(&padapter->mlmepriv, _FW_LINKED)) {
902 set_fwstate(pmlmepriv, _FW_LINKED);
903
904 rtw_led_control(padapter, LED_CTL_LINK);
905
483557be
JS
906 rtw_cfg80211_indicate_connect(padapter);
907
908 netif_carrier_on(padapter->pnetdev);
909
910 if (padapter->pid[2] != 0)
911 kill_pid(find_vpid(padapter->pid[2]), SIGALRM, 1);
5e93f352
LF
912 }
913
914 rtw_set_roaming(padapter, 0);
915
916 rtw_set_scan_deny(padapter, 3000);
917
918 RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("-rtw_indicate_connect23a: fw_state=0x%08x\n", get_fwstate(pmlmepriv)));
919
920}
921
922/*
923*rtw_indicate_disconnect23a: the caller has to lock pmlmepriv->lock
924*/
925void rtw_indicate_disconnect23a(struct rtw_adapter *padapter)
926{
927 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
928
929 RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("+rtw_indicate_disconnect23a\n"));
930
931 _clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING|WIFI_UNDER_WPS);
932
933 /* DBG_8723A("clear wps when %s\n", __func__); */
934
935 if (rtw_to_roaming(padapter) > 0)
936 _clr_fwstate_(pmlmepriv, _FW_LINKED);
937
938 if (check_fwstate(&padapter->mlmepriv, _FW_LINKED) ||
939 (rtw_to_roaming(padapter) <= 0)) {
940 rtw_os_indicate_disconnect23a(padapter);
941
942 /* set ips_deny_time to avoid enter IPS before LPS leave */
943 padapter->pwrctrlpriv.ips_deny_time =
c17416ef 944 jiffies + msecs_to_jiffies(3000);
5e93f352
LF
945
946 _clr_fwstate_(pmlmepriv, _FW_LINKED);
947
948 rtw_led_control(padapter, LED_CTL_NO_LINK);
949
950 rtw_clear_scan_deny(padapter);
951
952 }
953
5e93f352
LF
954 rtw_lps_ctrl_wk_cmd23a(padapter, LPS_CTRL_DISCONNECT, 1);
955
956}
957
5e93f352
LF
958void rtw_scan_abort23a(struct rtw_adapter *adapter)
959{
960 unsigned long start;
961 struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
962 struct mlme_ext_priv *pmlmeext = &adapter->mlmeextpriv;
963
964 start = jiffies;
965 pmlmeext->scan_abort = true;
966 while (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY) &&
967 jiffies_to_msecs(jiffies - start) <= 200) {
968
969 if (adapter->bDriverStopped || adapter->bSurpriseRemoved)
970 break;
971
972 DBG_8723A(FUNC_NDEV_FMT"fw_state = _FW_UNDER_SURVEY!\n", FUNC_NDEV_ARG(adapter->pnetdev));
973 msleep(20);
974 }
975
976 if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY)) {
977 if (!adapter->bDriverStopped && !adapter->bSurpriseRemoved)
978 DBG_8723A(FUNC_NDEV_FMT"waiting for scan_abort time out!\n", FUNC_NDEV_ARG(adapter->pnetdev));
810c832f
JS
979 rtw_cfg80211_indicate_scan_done(wdev_to_priv(adapter->rtw_wdev),
980 true);
5e93f352
LF
981 }
982 pmlmeext->scan_abort = false;
983}
984
985static struct sta_info *rtw_joinbss_update_stainfo(struct rtw_adapter *padapter, struct wlan_network *pnetwork)
986{
987 int i;
988 struct sta_info *bmc_sta, *psta = NULL;
989 struct recv_reorder_ctrl *preorder_ctrl;
990 struct sta_priv *pstapriv = &padapter->stapriv;
991
992 psta = rtw_get_stainfo23a(pstapriv, pnetwork->network.MacAddress);
993 if (psta == NULL) {
994 psta = rtw_alloc_stainfo23a(pstapriv, pnetwork->network.MacAddress);
995 }
996
997 if (psta) /* update ptarget_sta */
998 {
999 DBG_8723A("%s\n", __func__);
1000
1001 psta->aid = pnetwork->join_res;
1002 psta->mac_id = 0;
1003
1004 /* sta mode */
1005 rtw_hal_set_odm_var23a(padapter, HAL_ODM_STA_INFO, psta, true);
1006
1007 /* security related */
1008 if (padapter->securitypriv.dot11AuthAlgrthm == dot11AuthAlgrthm_8021X)
1009 {
1010 padapter->securitypriv.binstallGrpkey = false;
1011 padapter->securitypriv.busetkipkey = false;
1012 padapter->securitypriv.bgrpkey_handshake = false;
1013
1014 psta->ieee8021x_blocked = true;
1015 psta->dot118021XPrivacy = padapter->securitypriv.dot11PrivacyAlgrthm;
1016
1017 memset((u8 *)&psta->dot118021x_UncstKey, 0, sizeof (union Keytype));
1018
1019 memset((u8 *)&psta->dot11tkiprxmickey, 0, sizeof (union Keytype));
1020 memset((u8 *)&psta->dot11tkiptxmickey, 0, sizeof (union Keytype));
1021
1022 memset((u8 *)&psta->dot11txpn, 0, sizeof (union pn48));
1023 memset((u8 *)&psta->dot11rxpn, 0, sizeof (union pn48));
1024 }
1025
1026 /* Commented by Albert 2012/07/21 */
1027 /* When doing the WPS, the wps_ie_len won't equal to 0 */
1028 /* And the Wi-Fi driver shouldn't allow the data packet to be tramsmitted. */
1029 if (padapter->securitypriv.wps_ie_len != 0)
1030 {
1031 psta->ieee8021x_blocked = true;
1032 padapter->securitypriv.wps_ie_len = 0;
1033 }
1034
1035 /* for A-MPDU Rx reordering buffer control for bmc_sta & sta_info */
1036 /* if A-MPDU Rx is enabled, reseting rx_ordering_ctrl wstart_b(indicate_seq) to default value = 0xffff */
1037 /* todo: check if AP can send A-MPDU packets */
1038 for (i = 0; i < 16 ; i++)
1039 {
1040 /* preorder_ctrl = &precvpriv->recvreorder_ctrl[i]; */
1041 preorder_ctrl = &psta->recvreorder_ctrl[i];
1042 preorder_ctrl->enable = false;
1043 preorder_ctrl->indicate_seq = 0xffff;
1044 preorder_ctrl->wend_b = 0xffff;
1045 preorder_ctrl->wsize_b = 64;/* max_ampdu_sz; ex. 32(kbytes) -> wsize_b = 32 */
1046 }
1047
1048 bmc_sta = rtw_get_bcmc_stainfo23a(padapter);
1049 if (bmc_sta)
1050 {
1051 for (i = 0; i < 16 ; i++)
1052 {
1053 /* preorder_ctrl = &precvpriv->recvreorder_ctrl[i]; */
1054 preorder_ctrl = &bmc_sta->recvreorder_ctrl[i];
1055 preorder_ctrl->enable = false;
1056 preorder_ctrl->indicate_seq = 0xffff;
1057 preorder_ctrl->wend_b = 0xffff;
1058 preorder_ctrl->wsize_b = 64;/* max_ampdu_sz; ex. 32(kbytes) -> wsize_b = 32 */
1059 }
1060 }
1061
1062 /* misc. */
1063 update_sta_info23a(padapter, psta);
1064
1065 }
1066
1067 return psta;
1068}
1069
1070/* pnetwork : returns from rtw23a_joinbss_event_cb */
1071/* ptarget_wlan: found from scanned_queue */
1072static void rtw_joinbss_update_network23a(struct rtw_adapter *padapter, struct wlan_network *ptarget_wlan, struct wlan_network *pnetwork)
1073{
1074 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1075 struct wlan_network *cur_network = &pmlmepriv->cur_network;
1076
1077 DBG_8723A("%s\n", __func__);
1078
1079 RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("\nfw_state:%x, BSSID:"MAC_FMT"\n"
1080 , get_fwstate(pmlmepriv), MAC_ARG(pnetwork->network.MacAddress)));
1081
1082 /* why not use ptarget_wlan?? */
1083 memcpy(&cur_network->network, &pnetwork->network, pnetwork->network.Length);
1084 /* some IEs in pnetwork is wrong, so we should use ptarget_wlan IEs */
1085 cur_network->network.IELength = ptarget_wlan->network.IELength;
1086 memcpy(&cur_network->network.IEs[0], &ptarget_wlan->network.IEs[0], MAX_IE_SZ);
1087
1088 cur_network->aid = pnetwork->join_res;
1089
1090 rtw_set_signal_stat_timer(&padapter->recvpriv);
1091 padapter->recvpriv.signal_strength = ptarget_wlan->network.PhyInfo.SignalStrength;
1092 padapter->recvpriv.signal_qual = ptarget_wlan->network.PhyInfo.SignalQuality;
1093 /* the ptarget_wlan->network.Rssi is raw data, we use ptarget_wlan->network.PhyInfo.SignalStrength instead (has scaled) */
1094 padapter->recvpriv.rssi = translate_percentage_to_dbm(ptarget_wlan->network.PhyInfo.SignalStrength);
1095 DBG_8723A("%s signal_strength:%3u, rssi:%3d, signal_qual:%3u\n",
1096 __func__, padapter->recvpriv.signal_strength,
1097 padapter->recvpriv.rssi, padapter->recvpriv.signal_qual);
1098 rtw_set_signal_stat_timer(&padapter->recvpriv);
1099
1100 /* update fw_state will clr _FW_UNDER_LINKING here indirectly */
1101 switch (pnetwork->network.InfrastructureMode) {
1102 case Ndis802_11Infrastructure:
1103 if (pmlmepriv->fw_state&WIFI_UNDER_WPS)
1104 pmlmepriv->fw_state = WIFI_STATION_STATE|WIFI_UNDER_WPS;
1105 else
1106 pmlmepriv->fw_state = WIFI_STATION_STATE;
1107 break;
1108 case Ndis802_11IBSS:
1109 pmlmepriv->fw_state = WIFI_ADHOC_STATE;
1110 break;
1111 default:
1112 pmlmepriv->fw_state = WIFI_NULL_STATE;
1113 RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("Invalid network_mode\n"));
1114 break;
1115 }
1116
1117 rtw_update_protection23a(padapter, (cur_network->network.IEs) + sizeof (struct ndis_802_11_fixed_ies),
1118 (cur_network->network.IELength));
1119
1120 rtw_update_ht_cap23a(padapter, cur_network->network.IEs, cur_network->network.IELength);
1121}
1122
1123/* Notes: the fucntion could be > passive_level (the same context as Rx tasklet) */
1124/* pnetwork : returns from rtw23a_joinbss_event_cb */
1125/* ptarget_wlan: found from scanned_queue */
1126/* if join_res > 0, for (fw_state==WIFI_STATION_STATE), we check if "ptarget_sta" & "ptarget_wlan" exist. */
1127/* if join_res > 0, for (fw_state==WIFI_ADHOC_STATE), we only check if "ptarget_wlan" exist. */
1128/* if join_res > 0, update "cur_network->network" from "pnetwork->network" if (ptarget_wlan !=NULL). */
1129
1130void rtw_joinbss_event_prehandle23a(struct rtw_adapter *adapter, u8 *pbuf)
1131{
1132 static u8 retry=0;
1133 struct sta_info *ptarget_sta= NULL, *pcur_sta = NULL;
1134 struct sta_priv *pstapriv = &adapter->stapriv;
1135 struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
1136 struct wlan_network *pnetwork = (struct wlan_network *)pbuf;
1137 struct wlan_network *cur_network = &pmlmepriv->cur_network;
1138 struct wlan_network *pcur_wlan = NULL, *ptarget_wlan = NULL;
1139 unsigned int the_same_macaddr = false;
1140
1141 RT_TRACE(_module_rtl871x_mlme_c_,_drv_info_,("joinbss event call back received with res=%d\n", pnetwork->join_res));
1142
1143 rtw_get_encrypt_decrypt_from_registrypriv23a(adapter);
1144
1145 if (pmlmepriv->assoc_ssid.ssid_len == 0) {
1146 RT_TRACE(_module_rtl871x_mlme_c_,_drv_err_,("@@@@@ joinbss event call back for Any SSid\n"));
1147 } else {
1148 RT_TRACE(_module_rtl871x_mlme_c_,_drv_err_,
1149 ("@@@@@ rtw23a_joinbss_event_cb for SSid:%s\n",
1150 pmlmepriv->assoc_ssid.ssid));
1151 }
1152
1153 if (ether_addr_equal(pnetwork->network.MacAddress,
1154 cur_network->network.MacAddress))
1155 the_same_macaddr = true;
1156 else
1157 the_same_macaddr = false;
1158
1159 pnetwork->network.Length = get_wlan_bssid_ex_sz(&pnetwork->network);
1160 if(pnetwork->network.Length > sizeof(struct wlan_bssid_ex))
1161 {
1162 RT_TRACE(_module_rtl871x_mlme_c_,_drv_err_,("\n\n ***joinbss_evt_callback return a wrong bss ***\n\n"));
1163 return;
1164 }
1165
1166 spin_lock_bh(&pmlmepriv->lock);
1167
1168 RT_TRACE(_module_rtl871x_mlme_c_,_drv_info_,("\n rtw23a_joinbss_event_cb !! _enter_critical\n"));
1169
1170 if(pnetwork->join_res > 0)
1171 {
1172 spin_lock_bh(&pmlmepriv->scanned_queue.lock);
1173 retry = 0;
1174 if (check_fwstate(pmlmepriv,_FW_UNDER_LINKING))
1175 {
1176 /* s1. find ptarget_wlan */
1177 if(check_fwstate(pmlmepriv, _FW_LINKED))
1178 {
1179 if(the_same_macaddr == true)
1180 {
1181 ptarget_wlan = rtw_find_network23a(&pmlmepriv->scanned_queue, cur_network->network.MacAddress);
1182 }
1183 else
1184 {
1185 pcur_wlan = rtw_find_network23a(&pmlmepriv->scanned_queue, cur_network->network.MacAddress);
1186 if(pcur_wlan) pcur_wlan->fixed = false;
1187
1188 pcur_sta = rtw_get_stainfo23a(pstapriv, cur_network->network.MacAddress);
1189 if(pcur_sta) {
1190 spin_lock_bh(&pstapriv->sta_hash_lock);
1191 rtw_free_stainfo23a(adapter, pcur_sta);
1192 spin_unlock_bh(&pstapriv->sta_hash_lock);
1193 }
1194
1195 ptarget_wlan = rtw_find_network23a(&pmlmepriv->scanned_queue, pnetwork->network.MacAddress);
1196 if(check_fwstate(pmlmepriv, WIFI_STATION_STATE) == true) {
1197 if(ptarget_wlan) ptarget_wlan->fixed = true;
1198 }
1199 }
1200
1201 }
1202 else
1203 {
1204 ptarget_wlan = rtw_find_network23a(&pmlmepriv->scanned_queue, pnetwork->network.MacAddress);
1205 if(check_fwstate(pmlmepriv, WIFI_STATION_STATE) == true) {
1206 if(ptarget_wlan) ptarget_wlan->fixed = true;
1207 }
1208 }
1209
1210 /* s2. update cur_network */
1211 if(ptarget_wlan)
1212 {
1213 rtw_joinbss_update_network23a(adapter, ptarget_wlan, pnetwork);
1214 }
1215 else
1216 {
1217 RT_TRACE(_module_rtl871x_mlme_c_,_drv_err_,("Can't find ptarget_wlan when joinbss_event callback\n"));
1218 spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
1219 goto ignore_joinbss_callback;
1220 }
1221
1222 /* s3. find ptarget_sta & update ptarget_sta after update cur_network only for station mode */
1223 if(check_fwstate(pmlmepriv, WIFI_STATION_STATE) == true)
1224 {
1225 ptarget_sta = rtw_joinbss_update_stainfo(adapter, pnetwork);
1226 if(ptarget_sta==NULL)
1227 {
1228 RT_TRACE(_module_rtl871x_mlme_c_,_drv_err_,("Can't update stainfo when joinbss_event callback\n"));
1229 spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
1230 goto ignore_joinbss_callback;
1231 }
1232 }
1233
1234 /* s4. indicate connect */
1235 if (check_fwstate(pmlmepriv, WIFI_STATION_STATE) == true)
1236 {
1237 rtw_indicate_connect23a(adapter);
1238 } else {
1239 /* adhoc mode will rtw_indicate_connect23a when rtw_stassoc_event_callback23a */
1240 RT_TRACE(_module_rtl871x_mlme_c_,_drv_info_,("adhoc mode, fw_state:%x", get_fwstate(pmlmepriv)));
1241 }
1242
1243 /* s5. Cancle assoc_timer */
1244 del_timer_sync(&pmlmepriv->assoc_timer);
1245
1246 RT_TRACE(_module_rtl871x_mlme_c_,_drv_info_,("Cancle assoc_timer\n"));
1247 } else {
1248 RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_,
1249 ("rtw23a_joinbss_event_cb err: fw_state:%x",
1250 get_fwstate(pmlmepriv)));
1251 spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
1252 goto ignore_joinbss_callback;
1253 }
1254 spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
1255 } else if(pnetwork->join_res == -4) {
1256 rtw_reset_securitypriv23a(adapter);
1257 mod_timer(&pmlmepriv->assoc_timer,
1258 jiffies + msecs_to_jiffies(1));
1259
1260 /* rtw_free_assoc_resources23a(adapter, 1); */
1261
1262 if((check_fwstate(pmlmepriv, _FW_UNDER_LINKING))) {
1263 RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_,
1264 ("fail! clear _FW_UNDER_LINKING ^^^fw_state=%x\n",
1265 get_fwstate(pmlmepriv)));
1266 _clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING);
1267 }
1268
1269 } else {
1270 /* if join_res < 0 (join fails), then try again */
1271 mod_timer(&pmlmepriv->assoc_timer,
1272 jiffies + msecs_to_jiffies(1));
1273 _clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING);
1274 }
1275
1276ignore_joinbss_callback:
1277
1278 spin_unlock_bh(&pmlmepriv->lock);
1279}
1280
1281void rtw23a_joinbss_event_cb(struct rtw_adapter *adapter, u8 *pbuf)
1282{
1283 struct wlan_network *pnetwork = (struct wlan_network *)pbuf;
1284
1285 mlmeext_joinbss_event_callback23a(adapter, pnetwork->join_res);
1286
1287 rtw_os_xmit_schedule23a(adapter);
1288
1289}
1290
5e93f352
LF
1291void rtw_stassoc_event_callback23a(struct rtw_adapter *adapter, u8 *pbuf)
1292{
1293 struct sta_info *psta;
1294 struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
1295 struct stassoc_event *pstassoc = (struct stassoc_event*)pbuf;
1296 struct wlan_network *cur_network = &pmlmepriv->cur_network;
1297 struct wlan_network *ptarget_wlan = NULL;
1298
1299 if(rtw_access_ctrl23a(adapter, pstassoc->macaddr) == false)
1300 return;
1301
1302#ifdef CONFIG_8723AU_AP_MODE
1303 if(check_fwstate(pmlmepriv, WIFI_AP_STATE))
1304 {
1305 psta = rtw_get_stainfo23a(&adapter->stapriv, pstassoc->macaddr);
1306 if (psta) {
1307 /* bss_cap_update_on_sta_join23a(adapter, psta); */
1308 /* sta_info_update23a(adapter, psta); */
1309 ap_sta_info_defer_update23a(adapter, psta);
5e93f352
LF
1310 }
1311 return;
1312 }
1313#endif
1314 /* for AD-HOC mode */
1315 psta = rtw_get_stainfo23a(&adapter->stapriv, pstassoc->macaddr);
1316 if (psta != NULL) {
1317 /* the sta have been in sta_info_queue => do nothing */
1318 RT_TRACE(_module_rtl871x_mlme_c_,_drv_err_,("Error: rtw_stassoc_event_callback23a: sta has been in sta_hash_queue\n"));
1319 return; /* between drv has received this event before and fw have not yet to set key to CAM_ENTRY) */
1320 }
1321
1322 psta = rtw_alloc_stainfo23a(&adapter->stapriv, pstassoc->macaddr);
1323 if (psta == NULL) {
1324 RT_TRACE(_module_rtl871x_mlme_c_,_drv_err_,("Can't alloc sta_info when rtw_stassoc_event_callback23a\n"));
1325 return;
1326 }
1327
1328 /* to do : init sta_info variable */
1329 psta->qos_option = 0;
1330 psta->mac_id = (uint)pstassoc->cam_id;
1331 /* psta->aid = (uint)pstassoc->cam_id; */
1332 DBG_8723A("%s\n",__func__);
1333 /* for ad-hoc mode */
1334 rtw_hal_set_odm_var23a(adapter,HAL_ODM_STA_INFO,psta,true);
1335
5e93f352
LF
1336 if(adapter->securitypriv.dot11AuthAlgrthm==dot11AuthAlgrthm_8021X)
1337 psta->dot118021XPrivacy = adapter->securitypriv.dot11PrivacyAlgrthm;
1338
1339 psta->ieee8021x_blocked = false;
1340
1341 spin_lock_bh(&pmlmepriv->lock);
1342
1343 if ( (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE)==true ) ||
1344 (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE)==true ) )
1345 {
1346 if(adapter->stapriv.asoc_sta_count== 2)
1347 {
1348 spin_lock_bh(&pmlmepriv->scanned_queue.lock);
1349 ptarget_wlan = rtw_find_network23a(&pmlmepriv->scanned_queue, cur_network->network.MacAddress);
1350 if(ptarget_wlan) ptarget_wlan->fixed = true;
1351 spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
1352 /* a sta + bc/mc_stainfo (not Ibss_stainfo) */
1353 rtw_indicate_connect23a(adapter);
1354 }
1355 }
1356
1357 spin_unlock_bh(&pmlmepriv->lock);
1358
1359 mlmeext_sta_add_event_callback23a(adapter, psta);
1360}
1361
1362void rtw_stadel_event_callback23a(struct rtw_adapter *adapter, u8 *pbuf)
1363{
1364 int mac_id=-1;
1365 struct sta_info *psta;
1366 struct wlan_network* pwlan = NULL;
1367 struct wlan_bssid_ex *pdev_network=NULL;
1368 u8* pibss = NULL;
1369 struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
1370 struct stadel_event *pstadel = (struct stadel_event*)pbuf;
1371 struct sta_priv *pstapriv = &adapter->stapriv;
1372 struct wlan_network *tgt_network = &pmlmepriv->cur_network;
1373
1374 psta = rtw_get_stainfo23a(&adapter->stapriv, pstadel->macaddr);
1375 if(psta)
1376 mac_id = psta->mac_id;
1377 else
1378 mac_id = pstadel->mac_id;
1379
1380 DBG_8723A("%s(mac_id=%d)=" MAC_FMT "\n", __func__, mac_id, MAC_ARG(pstadel->macaddr));
1381
5e93f352
LF
1382 if (check_fwstate(pmlmepriv, WIFI_AP_STATE))
1383 {
1384 return;
1385 }
1386
1387 mlmeext_sta_del_event_callback23a(adapter);
1388
1389 spin_lock_bh(&pmlmepriv->lock);
1390
1391 if (check_fwstate(pmlmepriv, WIFI_STATION_STATE))
1392 {
1393 if (rtw_to_roaming(adapter) > 0)
1394 pmlmepriv->to_roaming--; /* this stadel_event is caused by roaming, decrease to_roaming */
1395 else if (rtw_to_roaming(adapter) == 0)
1396 rtw_set_roaming(adapter, adapter->registrypriv.max_roaming_times);
1397 if (*((unsigned short *)(pstadel->rsvd)) != WLAN_REASON_EXPIRATION_CHK)
1398 rtw_set_roaming(adapter, 0); /* don't roam */
1399
1400 rtw_free_uc_swdec_pending_queue23a(adapter);
1401
1402 rtw_free_assoc_resources23a(adapter, 1);
1403 rtw_indicate_disconnect23a(adapter);
1404 spin_lock_bh(&pmlmepriv->scanned_queue.lock);
1405 /* remove the network entry in scanned_queue */
1406 pwlan = rtw_find_network23a(&pmlmepriv->scanned_queue, tgt_network->network.MacAddress);
1407 if (pwlan) {
1408 pwlan->fixed = false;
1409 rtw_free_network_nolock(pmlmepriv, pwlan);
1410 }
1411 spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
1412
1413 _rtw23a_roaming(adapter, tgt_network);
1414 }
1415
1416 if (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) ||
1417 check_fwstate(pmlmepriv, WIFI_ADHOC_STATE))
1418 {
1419
1420 spin_lock_bh(&pstapriv->sta_hash_lock);
1421 rtw_free_stainfo23a(adapter, psta);
1422 spin_unlock_bh(&pstapriv->sta_hash_lock);
1423
1424 if (adapter->stapriv.asoc_sta_count == 1) /* a sta + bc/mc_stainfo (not Ibss_stainfo) */
1425 {
1426 spin_lock_bh(&pmlmepriv->scanned_queue.lock);
1427 /* free old ibss network */
1428 /* pwlan = rtw_find_network23a(&pmlmepriv->scanned_queue, pstadel->macaddr); */
1429 pwlan = rtw_find_network23a(&pmlmepriv->scanned_queue, tgt_network->network.MacAddress);
1430 if (pwlan)
1431 {
1432 pwlan->fixed = false;
1433 rtw_free_network_nolock(pmlmepriv, pwlan);
1434 }
1435 spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
1436 /* re-create ibss */
1437 pdev_network = &adapter->registrypriv.dev_network;
1438 pibss = adapter->registrypriv.dev_network.MacAddress;
1439
1440 memcpy(pdev_network, &tgt_network->network, get_wlan_bssid_ex_sz(&tgt_network->network));
1441
1442 memset(&pdev_network->Ssid, 0,
1443 sizeof(struct cfg80211_ssid));
1444 memcpy(&pdev_network->Ssid, &pmlmepriv->assoc_ssid,
1445 sizeof(struct cfg80211_ssid));
1446
1447 rtw_update_registrypriv_dev_network23a(adapter);
1448
1449 rtw_generate_random_ibss23a(pibss);
1450
1451 if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE))
1452 {
1453 set_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE);
1454 _clr_fwstate_(pmlmepriv, WIFI_ADHOC_STATE);
1455 }
1456
1457 if (rtw_createbss_cmd23a(adapter)!= _SUCCESS)
1458 {
1459
1460 RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_, ("***Error =>stadel_event_callback: rtw_createbss_cmd23a status FAIL***\n "));
1461
1462 }
1463
1464 }
1465
1466 }
1467
1468 spin_unlock_bh(&pmlmepriv->lock);
1469
1470}
1471
1472void rtw_cpwm_event_callback23a(struct rtw_adapter *padapter, u8 *pbuf)
1473{
1474
1475 RT_TRACE(_module_rtl871x_mlme_c_,_drv_err_,("+rtw_cpwm_event_callback23a !!!\n"));
1476
1477}
1478
1479/*
1480* rtw23a_join_to_handler - Timeout/faliure handler for CMD JoinBss
1481* @adapter: pointer to _adapter structure
1482*/
1483void rtw23a_join_to_handler (unsigned long data)
1484{
1485 struct rtw_adapter *adapter = (struct rtw_adapter *)data;
1486 struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
1487 int do_join_r;
1488
1489 DBG_8723A("%s, fw_state=%x\n", __func__, get_fwstate(pmlmepriv));
1490
1491 if(adapter->bDriverStopped ||adapter->bSurpriseRemoved)
1492 return;
1493
1494 spin_lock_bh(&pmlmepriv->lock);
1495
1496 if (rtw_to_roaming(adapter) > 0) { /* join timeout caused by roaming */
1497 while(1) {
1498 pmlmepriv->to_roaming--;
1499 if (rtw_to_roaming(adapter) != 0) { /* try another */
1500 DBG_8723A("%s try another roaming\n", __func__);
1501 if (_SUCCESS!= (do_join_r = rtw_do_join23a(adapter))) {
1502 DBG_8723A("%s roaming do_join return %d\n", __func__ , do_join_r);
1503 continue;
1504 }
1505 break;
1506 } else {
1507 DBG_8723A("%s We've try roaming but fail\n", __func__);
1508 rtw_indicate_disconnect23a(adapter);
1509 break;
1510 }
1511 }
1512 } else {
1513 rtw_indicate_disconnect23a(adapter);
1514 free_scanqueue(pmlmepriv);/* */
1515
1516 /* indicate disconnect for the case that join_timeout and check_fwstate != FW_LINKED */
1517 rtw_cfg80211_indicate_disconnect(adapter);
1518 }
1519
1520 spin_unlock_bh(&pmlmepriv->lock);
1521
1522}
1523
1524/*
1525* rtw_scan_timeout_handler23a - Timeout/Faliure handler for CMD SiteSurvey
1526* @data: pointer to _adapter structure
1527*/
1528void rtw_scan_timeout_handler23a(unsigned long data)
1529{
1530 struct rtw_adapter *adapter = (struct rtw_adapter *)data;
1531 struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
1532
1533 DBG_8723A(FUNC_ADPT_FMT" fw_state =%x\n", FUNC_ADPT_ARG(adapter), get_fwstate(pmlmepriv));
1534
1535 spin_lock_bh(&pmlmepriv->lock);
1536
1537 _clr_fwstate_(pmlmepriv, _FW_UNDER_SURVEY);
1538
1539 spin_unlock_bh(&pmlmepriv->lock);
1540
810c832f 1541 rtw_cfg80211_indicate_scan_done(wdev_to_priv(adapter->rtw_wdev), true);
5e93f352
LF
1542}
1543
1544static void rtw_auto_scan_handler(struct rtw_adapter *padapter)
1545{
1546 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1547
1548 /* auto site survey per 60sec */
1549 if (pmlmepriv->scan_interval > 0) {
1550 pmlmepriv->scan_interval--;
1551 if (pmlmepriv->scan_interval == 0) {
1552 DBG_8723A("%s\n", __func__);
1553 rtw_set_802_11_bssid23a_list_scan(padapter, NULL, 0);
1554 pmlmepriv->scan_interval = SCAN_INTERVAL;/* 30*2 sec = 60sec */
1555 }
1556 }
1557}
1558
1559void rtw_dynamic_check_timer_handler(unsigned long data)
1560{
1561 struct rtw_adapter *adapter = (struct rtw_adapter *)data;
1562 struct registry_priv *pregistrypriv = &adapter->registrypriv;
1563
1564 if (adapter->hw_init_completed == false)
1565 goto out;
1566
1567 if ((adapter->bDriverStopped == true)||(adapter->bSurpriseRemoved == true))
1568 goto out;
1569
1570 if (adapter->net_closed == true)
1571 goto out;
1572
1573 rtw_dynamic_chk_wk_cmd23a(adapter);
1574
98fb8129
JS
1575 if (pregistrypriv->wifi_spec == 1) {
1576 /* auto site survey */
1577 rtw_auto_scan_handler(adapter);
5e93f352
LF
1578 }
1579out:
1580 mod_timer(&adapter->mlmepriv.dynamic_chk_timer,
1581 jiffies + msecs_to_jiffies(2000));
1582}
1583
1584inline bool rtw_is_scan_deny(struct rtw_adapter *adapter)
1585{
1586 struct mlme_priv *mlmepriv = &adapter->mlmepriv;
1587 return (atomic_read(&mlmepriv->set_scan_deny) != 0) ? true : false;
1588}
1589
1590void rtw_clear_scan_deny(struct rtw_adapter *adapter)
1591{
1592 struct mlme_priv *mlmepriv = &adapter->mlmepriv;
1593 atomic_set(&mlmepriv->set_scan_deny, 0);
1594 if (0)
1595 DBG_8723A(FUNC_ADPT_FMT"\n", FUNC_ADPT_ARG(adapter));
1596}
1597
1598void rtw_set_scan_deny_timer_hdl(unsigned long data)
1599{
1600 struct rtw_adapter *adapter = (struct rtw_adapter *)data;
1601 rtw_clear_scan_deny(adapter);
1602}
1603
1604void rtw_set_scan_deny(struct rtw_adapter *adapter, u32 ms)
1605{
1606 struct mlme_priv *mlmepriv = &adapter->mlmepriv;
1607
1608 if (0)
1609 DBG_8723A(FUNC_ADPT_FMT"\n", FUNC_ADPT_ARG(adapter));
1610 atomic_set(&mlmepriv->set_scan_deny, 1);
1611 mod_timer(&mlmepriv->set_scan_deny_timer,
1612 jiffies + msecs_to_jiffies(ms));
1613
1614}
1615
1616#if defined(IEEE80211_SCAN_RESULT_EXPIRE)
1617#define RTW_SCAN_RESULT_EXPIRE IEEE80211_SCAN_RESULT_EXPIRE/HZ*1000 -1000 /* 3000 -1000 */
1618#else
1619#define RTW_SCAN_RESULT_EXPIRE 2000
1620#endif
1621
1622/*
1623* Select a new join candidate from the original @param candidate and @param competitor
1624* @return true: candidate is updated
1625* @return false: candidate is not updated
1626*/
1627static int rtw_check_join_candidate(struct mlme_priv *pmlmepriv
1628 , struct wlan_network **candidate, struct wlan_network *competitor)
1629{
1630 int updated = false;
1631 struct rtw_adapter *adapter = container_of(pmlmepriv, struct rtw_adapter, mlmepriv);
1632
1633 /* check bssid, if needed */
1634 if (pmlmepriv->assoc_by_bssid == true) {
1635 if (!ether_addr_equal(competitor->network.MacAddress,
1636 pmlmepriv->assoc_bssid))
1637 goto exit;
1638 }
1639
1640 /* check ssid, if needed */
c17416ef 1641 if (pmlmepriv->assoc_ssid.ssid_len) {
5e93f352
LF
1642 if (competitor->network.Ssid.ssid_len !=
1643 pmlmepriv->assoc_ssid.ssid_len ||
1644 memcmp(competitor->network.Ssid.ssid,
1645 pmlmepriv->assoc_ssid.ssid,
1646 pmlmepriv->assoc_ssid.ssid_len))
1647 goto exit;
1648 }
1649
1650 if (rtw_is_desired_network(adapter, competitor) == false)
1651 goto exit;
1652
1653 if (rtw_to_roaming(adapter) > 0) {
1654 unsigned int passed;
1655
1656 passed = jiffies_to_msecs(jiffies - competitor->last_scanned);
1657 if (passed >= RTW_SCAN_RESULT_EXPIRE ||
1658 is_same_ess(&competitor->network,
1659 &pmlmepriv->cur_network.network) == false)
1660 goto exit;
1661 }
1662
1663 if (*candidate == NULL ||(*candidate)->network.Rssi<competitor->network.Rssi) {
1664 *candidate = competitor;
1665 updated = true;
1666 }
1667
1668 if (updated) {
1669 DBG_8723A("[by_bssid:%u][assoc_ssid:%s][to_roaming:%u] new candidate: %s("MAC_FMT") rssi:%d\n",
1670 pmlmepriv->assoc_by_bssid,
1671 pmlmepriv->assoc_ssid.ssid,
1672 rtw_to_roaming(adapter),
1673 (*candidate)->network.Ssid.ssid,
1674 MAC_ARG((*candidate)->network.MacAddress),
1675 (int)(*candidate)->network.Rssi);
1676 }
1677
1678exit:
1679 return updated;
1680}
1681
1682/*
1683Calling context:
1684The caller of the sub-routine will be in critical section...
1685
1686The caller must hold the following spinlock
1687
1688pmlmepriv->lock
1689
1690*/
1691
1692int rtw_select_and_join_from_scanned_queue23a(struct mlme_priv *pmlmepriv)
1693{
1694 int ret;
1695 struct list_head *phead, *plist, *ptmp;
1696 struct rtw_adapter *adapter;
1697 struct rtw_queue *queue = &pmlmepriv->scanned_queue;
1698 struct wlan_network *pnetwork = NULL;
1699 struct wlan_network *candidate = NULL;
1700
1701 spin_lock_bh(&pmlmepriv->scanned_queue.lock);
1702 phead = get_list_head(queue);
1703 adapter = pmlmepriv->nic_hdl;
1704
1705 list_for_each_safe(plist, ptmp, phead) {
1706 pnetwork = container_of(plist, struct wlan_network, list);
1707 if (!pnetwork) {
1708 RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_,
1709 ("%s return _FAIL:(pnetwork == NULL)\n",
1710 __func__));
1711 ret = _FAIL;
1712 goto exit;
1713 }
1714
1715 rtw_check_join_candidate(pmlmepriv, &candidate, pnetwork);
1716 }
1717
1718 if (!candidate) {
1719 DBG_8723A("%s: return _FAIL(candidate == NULL)\n", __func__);
1720 ret = _FAIL;
1721 goto exit;
1722 } else {
1723 DBG_8723A("%s: candidate: %s("MAC_FMT", ch:%u)\n", __func__,
1724 candidate->network.Ssid.ssid,
1725 MAC_ARG(candidate->network.MacAddress),
1726 candidate->network.Configuration.DSConfig);
1727 }
1728
1729 /* check for situation of _FW_LINKED */
1730 if (check_fwstate(pmlmepriv, _FW_LINKED) == true) {
1731 DBG_8723A("%s: _FW_LINKED while ask_for_joinbss!!!\n",
1732 __func__);
1733
1734 rtw_disassoc_cmd23a(adapter, 0, true);
1735 rtw_indicate_disconnect23a(adapter);
1736 rtw_free_assoc_resources23a(adapter, 0);
1737 }
1738 set_fwstate(pmlmepriv, _FW_UNDER_LINKING);
1739 ret = rtw_joinbss_cmd23a(adapter, candidate);
1740
1741exit:
1742 spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
1743
1744 return ret;
1745}
1746
1747int rtw_set_auth23a(struct rtw_adapter * adapter,
1748 struct security_priv *psecuritypriv)
1749{
1750 struct cmd_obj* pcmd;
1751 struct setauth_parm *psetauthparm;
1752 struct cmd_priv *pcmdpriv = &adapter->cmdpriv;
1753 int res = _SUCCESS;
1754
1755 pcmd = (struct cmd_obj *)kzalloc(sizeof(struct cmd_obj), GFP_KERNEL);
1756 if (!pcmd) {
1757 res = _FAIL; /* try again */
1758 goto exit;
1759 }
1760
1761 psetauthparm = (struct setauth_parm*)
1762 kzalloc(sizeof(struct setauth_parm), GFP_KERNEL);
1763 if (!psetauthparm) {
1764 kfree(pcmd);
1765 res = _FAIL;
1766 goto exit;
1767 }
1768
1769 psetauthparm->mode = (unsigned char)psecuritypriv->dot11AuthAlgrthm;
1770
1771 pcmd->cmdcode = _SetAuth_CMD_;
1772 pcmd->parmbuf = (unsigned char *)psetauthparm;
1773 pcmd->cmdsz = (sizeof(struct setauth_parm));
1774 pcmd->rsp = NULL;
1775 pcmd->rspsz = 0;
1776
1777 INIT_LIST_HEAD(&pcmd->list);
1778
1779 RT_TRACE(_module_rtl871x_mlme_c_,_drv_err_,
1780 ("after enqueue set_auth_cmd, auth_mode=%x\n",
1781 psecuritypriv->dot11AuthAlgrthm));
1782
1783 res = rtw_enqueue_cmd23a(pcmdpriv, pcmd);
1784
1785exit:
1786
1787 return res;
1788}
1789
1790int rtw_set_key23a(struct rtw_adapter *adapter,
1791 struct security_priv *psecuritypriv, int keyid, u8 set_tx)
1792{
1793 u8 keylen;
1794 struct cmd_obj *pcmd;
1795 struct setkey_parm *psetkeyparm;
1796 struct cmd_priv *pcmdpriv = &adapter->cmdpriv;
1797 struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
1798 int res = _SUCCESS;
1799
1800 pcmd = (struct cmd_obj *)kzalloc(sizeof(struct cmd_obj), GFP_KERNEL);
1801 if (!pcmd) {
1802 res = _FAIL; /* try again */
1803 goto exit;
1804 }
c17416ef 1805 psetkeyparm = kzalloc(sizeof(struct setkey_parm), GFP_KERNEL);
5e93f352
LF
1806 if (!psetkeyparm) {
1807 kfree(pcmd);
1808 res = _FAIL;
1809 goto exit;
1810 }
1811
1812 if (psecuritypriv->dot11AuthAlgrthm == dot11AuthAlgrthm_8021X) {
1813 psetkeyparm->algorithm = (unsigned char)
1814 psecuritypriv->dot118021XGrpPrivacy;
1815 RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_,
1816 ("\n rtw_set_key23a: psetkeyparm->algorithm = (unsigned "
1817 "char)psecuritypriv->dot118021XGrpPrivacy =%d\n",
1818 psetkeyparm->algorithm));
1819 } else {
1820 psetkeyparm->algorithm = (u8)psecuritypriv->dot11PrivacyAlgrthm;
1821 RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_,
1822 ("\n rtw_set_key23a: psetkeyparm->algorithm = (u8)"
1823 "psecuritypriv->dot11PrivacyAlgrthm =%d\n",
1824 psetkeyparm->algorithm));
1825 }
1826 psetkeyparm->keyid = (u8)keyid;/* 0~3 */
1827 psetkeyparm->set_tx = set_tx;
1828 if (is_wep_enc(psetkeyparm->algorithm))
1829 pmlmepriv->key_mask |= CHKBIT(psetkeyparm->keyid);
1830
1831 DBG_8723A("==> rtw_set_key23a algorithm(%x), keyid(%x), key_mask(%x)\n",
1832 psetkeyparm->algorithm, psetkeyparm->keyid,
1833 pmlmepriv->key_mask);
1834 RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_,
1835 ("\n rtw_set_key23a: psetkeyparm->algorithm =%d psetkeyparm->"
1836 "keyid = (u8)keyid =%d\n", psetkeyparm->algorithm, keyid));
1837
1838 switch (psetkeyparm->algorithm) {
1839 case _WEP40_:
1840 keylen = 5;
1841 memcpy(&psetkeyparm->key[0],
1842 &psecuritypriv->dot11DefKey[keyid].skey[0], keylen);
1843 break;
1844 case _WEP104_:
1845 keylen = 13;
1846 memcpy(&psetkeyparm->key[0],
1847 &psecuritypriv->dot11DefKey[keyid].skey[0], keylen);
1848 break;
1849 case _TKIP_:
1850 keylen = 16;
1851 memcpy(&psetkeyparm->key,
1852 &psecuritypriv->dot118021XGrpKey[keyid], keylen);
1853 psetkeyparm->grpkey = 1;
1854 break;
1855 case _AES_:
1856 keylen = 16;
1857 memcpy(&psetkeyparm->key,
1858 &psecuritypriv->dot118021XGrpKey[keyid], keylen);
1859 psetkeyparm->grpkey = 1;
1860 break;
1861 default:
1862 RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_,
1863 ("\n rtw_set_key23a:psecuritypriv->dot11PrivacyAlgrthm = "
1864 "%x (must be 1 or 2 or 4 or 5)\n",
1865 psecuritypriv->dot11PrivacyAlgrthm));
1866 res = _FAIL;
c17416ef
LF
1867 kfree(pcmd);
1868 kfree(psetkeyparm);
5e93f352
LF
1869 goto exit;
1870 }
1871
1872 pcmd->cmdcode = _SetKey_CMD_;
1873 pcmd->parmbuf = (u8 *)psetkeyparm;
1874 pcmd->cmdsz = (sizeof(struct setkey_parm));
1875 pcmd->rsp = NULL;
1876 pcmd->rspsz = 0;
1877
1878 INIT_LIST_HEAD(&pcmd->list);
1879
1880 /* sema_init(&pcmd->cmd_sem, 0); */
1881
1882 res = rtw_enqueue_cmd23a(pcmdpriv, pcmd);
1883
1884exit:
1885
1886 return res;
1887}
1888
1889/* adjust IEs for rtw_joinbss_cmd23a in WMM */
1890int rtw_restruct_wmm_ie23a(struct rtw_adapter *adapter, u8 *in_ie,
1891 u8 *out_ie, uint in_len, uint initial_out_len)
1892{
1893 unsigned int ielength = 0;
1894 unsigned int i, j;
1895
1896 i = 12; /* after the fixed IE */
1897 while(i < in_len) {
1898 ielength = initial_out_len;
1899
1900 /* WMM element ID and OUI */
1901 if (in_ie[i] == 0xDD && in_ie[i + 2] == 0x00 &&
1902 in_ie[i + 3] == 0x50 && in_ie[i + 4] == 0xF2 &&
1903 in_ie[i + 5] == 0x02 && i+5 < in_len) {
1904
1905 /* Append WMM IE to the last index of out_ie */
1906 for (j = i; j < i + 9; j++) {
1907 out_ie[ielength] = in_ie[j];
1908 ielength++;
1909 }
1910 out_ie[initial_out_len + 1] = 0x07;
1911 out_ie[initial_out_len + 6] = 0x00;
1912 out_ie[initial_out_len + 8] = 0x00;
1913
1914 break;
1915 }
1916
1917 i += (in_ie[i + 1] + 2); /* to the next IE element */
1918 }
1919
1920 return ielength;
1921}
1922
1923/* */
1924/* Ported from 8185: IsInPreAuthKeyList().
1925 (Renamed from SecIsInPreAuthKeyList(), 2006-10-13.) */
1926/* Added by Annie, 2006-05-07. */
1927/* */
1928/* Search by BSSID, */
1929/* Return Value: */
1930/* -1 :if there is no pre-auth key in the table */
1931/* >= 0 :if there is pre-auth key, and return the entry id */
1932/* */
1933/* */
1934
1935static int SecIsInPMKIDList(struct rtw_adapter *Adapter, u8 *bssid)
1936{
1937 struct security_priv *psecuritypriv = &Adapter->securitypriv;
1938 int i = 0;
1939
1940 do {
1941 if (psecuritypriv->PMKIDList[i].bUsed &&
1942 ether_addr_equal(psecuritypriv->PMKIDList[i].Bssid, bssid)) {
1943 break;
1944 } else {
1945 i++;
1946 /* continue; */
1947 }
1948 } while(i < NUM_PMKID_CACHE);
1949
1950 if (i == NUM_PMKID_CACHE) {
1951 i = -1;/* Could not find. */
1952 } else {
1953 /* There is one Pre-Authentication Key for
1954 the specific BSSID. */
1955 }
1956
1957 return i;
1958}
1959
1960/* */
1961/* Check the RSN IE length */
1962/* If the RSN IE length <= 20, the RSN IE didn't include
1963 the PMKID information */
1964/* 0-11th element in the array are the fixed IE */
1965/* 12th element in the array is the IE */
1966/* 13th element in the array is the IE length */
1967/* */
1968
1969static int rtw_append_pmkid(struct rtw_adapter *Adapter, int iEntry,
1970 u8 *ie, uint ie_len)
1971{
1972 struct security_priv *psecuritypriv = &Adapter->securitypriv;
1973
1974 if (ie[13] <= 20) {
1975 /* The RSN IE didn't include the PMK ID,
1976 append the PMK information */
1977 ie[ie_len] = 1;
1978 ie_len++;
1979 ie[ie_len] = 0; /* PMKID count = 0x0100 */
1980 ie_len++;
1981 memcpy(&ie[ie_len],
1982 &psecuritypriv->PMKIDList[iEntry].PMKID, 16);
1983
1984 ie_len += 16;
1985 ie[13] += 18;/* PMKID length = 2+16 */
1986 }
1987 return ie_len;
1988}
814a1d90
JS
1989
1990static void
1991_rtw_report_sec_ie(struct rtw_adapter *adapter, u8 authmode, u8 *sec_ie)
1992{
1993 uint len;
1994 u8 *buff, *p, i;
1995 union iwreq_data wrqu;
1996
1997 RT_TRACE(_module_mlme_osdep_c_, _drv_info_,
1998 ("+_rtw_report_sec_ie, authmode =%d\n", authmode));
1999
2000 buff = NULL;
9300c94b 2001 if (authmode == WLAN_EID_VENDOR_SPECIFIC) {
814a1d90
JS
2002 RT_TRACE(_module_mlme_osdep_c_, _drv_info_,
2003 ("_rtw_report_sec_ie, authmode =%d\n", authmode));
2004
2005 buff = kzalloc(IW_CUSTOM_MAX, GFP_KERNEL);
2006 if (!buff)
2007 return;
2008 p = buff;
2009
2010 p += sprintf(p, "ASSOCINFO(ReqIEs =");
2011
2012 len = sec_ie[1]+2;
2013 len = (len < IW_CUSTOM_MAX) ? len : IW_CUSTOM_MAX;
2014
2015 for (i = 0; i < len; i++)
2016 p += sprintf(p, "%02x", sec_ie[i]);
2017
2018 p += sprintf(p, ")");
2019
2020 memset(&wrqu, 0, sizeof(wrqu));
2021
2022 wrqu.data.length = p-buff;
2023
2024 wrqu.data.length = (wrqu.data.length < IW_CUSTOM_MAX) ?
2025 wrqu.data.length : IW_CUSTOM_MAX;
2026
2027 kfree(buff);
2028 }
2029}
2030
5e93f352
LF
2031int rtw_restruct_sec_ie23a(struct rtw_adapter *adapter, u8 *in_ie, u8 *out_ie,
2032 uint in_len)
2033{
2034 u8 authmode;
2035 uint ielength;
2036 int iEntry;
2037 struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
2038 struct security_priv *psecuritypriv = &adapter->securitypriv;
2039 uint ndisauthmode = psecuritypriv->ndisauthtype;
2040 uint ndissecuritytype = psecuritypriv->ndisencryptstatus;
2041
2042 RT_TRACE(_module_rtl871x_mlme_c_, _drv_notice_,
2043 ("+rtw_restruct_sec_ie23a: ndisauthmode=%d ndissecuritytype=%d\n",
2044 ndisauthmode, ndissecuritytype));
2045
2046 /* copy fixed ie only */
2047 memcpy(out_ie, in_ie, 12);
2048 ielength = 12;
2049 if ((ndisauthmode==Ndis802_11AuthModeWPA) ||
2050 (ndisauthmode==Ndis802_11AuthModeWPAPSK))
9300c94b 2051 authmode = WLAN_EID_VENDOR_SPECIFIC;
5e93f352
LF
2052 if ((ndisauthmode==Ndis802_11AuthModeWPA2) ||
2053 (ndisauthmode==Ndis802_11AuthModeWPA2PSK))
2054 authmode=_WPA2_IE_ID_;
2055
2056 if (check_fwstate(pmlmepriv, WIFI_UNDER_WPS)) {
2057 memcpy(out_ie + ielength, psecuritypriv->wps_ie,
2058 psecuritypriv->wps_ie_len);
2059
2060 ielength += psecuritypriv->wps_ie_len;
9300c94b
JS
2061 } else if ((authmode == WLAN_EID_VENDOR_SPECIFIC) ||
2062 (authmode==_WPA2_IE_ID_)) {
5e93f352
LF
2063 /* copy RSN or SSN */
2064 memcpy(&out_ie[ielength], &psecuritypriv->supplicant_ie[0],
2065 psecuritypriv->supplicant_ie[1] + 2);
2066 ielength += psecuritypriv->supplicant_ie[1] + 2;
814a1d90
JS
2067 _rtw_report_sec_ie(adapter, authmode,
2068 psecuritypriv->supplicant_ie);
5e93f352
LF
2069 }
2070
2071 iEntry = SecIsInPMKIDList(adapter, pmlmepriv->assoc_bssid);
2072 if (iEntry < 0) {
2073 return ielength;
2074 } else {
2075 if (authmode == _WPA2_IE_ID_) {
2076 ielength=rtw_append_pmkid(adapter, iEntry,
2077 out_ie, ielength);
2078 }
2079 }
2080
2081 return ielength;
2082}
2083
2084void rtw_init_registrypriv_dev_network23a(struct rtw_adapter* adapter)
2085{
2086 struct registry_priv* pregistrypriv = &adapter->registrypriv;
2087 struct eeprom_priv* peepriv = &adapter->eeprompriv;
2088 struct wlan_bssid_ex *pdev_network = &pregistrypriv->dev_network;
2089 u8 *myhwaddr = myid(peepriv);
2090
2091 ether_addr_copy(pdev_network->MacAddress, myhwaddr);
2092
2093 memcpy(&pdev_network->Ssid, &pregistrypriv->ssid,
2094 sizeof(struct cfg80211_ssid));
2095
2096 pdev_network->Configuration.Length=sizeof(struct ndis_802_11_config);
2097 pdev_network->Configuration.BeaconPeriod = 100;
2098 pdev_network->Configuration.FHConfig.Length = 0;
2099 pdev_network->Configuration.FHConfig.HopPattern = 0;
2100 pdev_network->Configuration.FHConfig.HopSet = 0;
2101 pdev_network->Configuration.FHConfig.DwellTime = 0;
2102
2103}
2104
2105void rtw_update_registrypriv_dev_network23a(struct rtw_adapter* adapter)
2106{
2107 int sz = 0;
2108 struct registry_priv* pregistrypriv = &adapter->registrypriv;
2109 struct wlan_bssid_ex *pdev_network = &pregistrypriv->dev_network;
2110 struct security_priv *psecuritypriv = &adapter->securitypriv;
2111 struct wlan_network *cur_network = &adapter->mlmepriv.cur_network;
2112 /* struct xmit_priv *pxmitpriv = &adapter->xmitpriv; */
2113
2114 pdev_network->Privacy =
2115 (psecuritypriv->dot11PrivacyAlgrthm > 0 ? 1 : 0);
2116
2117 pdev_network->Rssi = 0;
2118
2119 switch (pregistrypriv->wireless_mode)
2120 {
2121 case WIRELESS_11B:
2122 pdev_network->NetworkTypeInUse = Ndis802_11DS;
2123 break;
2124 case WIRELESS_11G:
2125 case WIRELESS_11BG:
2126 case WIRELESS_11_24N:
2127 case WIRELESS_11G_24N:
2128 case WIRELESS_11BG_24N:
2129 pdev_network->NetworkTypeInUse = Ndis802_11OFDM24;
2130 break;
2131 case WIRELESS_11A:
2132 case WIRELESS_11A_5N:
2133 pdev_network->NetworkTypeInUse = Ndis802_11OFDM5;
2134 break;
2135 case WIRELESS_11ABGN:
2136 if (pregistrypriv->channel > 14)
2137 pdev_network->NetworkTypeInUse = Ndis802_11OFDM5;
2138 else
2139 pdev_network->NetworkTypeInUse = Ndis802_11OFDM24;
2140 break;
2141 default :
2142 /* TODO */
2143 break;
2144 }
2145
2146 pdev_network->Configuration.DSConfig = pregistrypriv->channel;
2147 RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_,
2148 ("pregistrypriv->channel =%d, pdev_network->Configuration."
2149 "DSConfig = 0x%x\n", pregistrypriv->channel,
2150 pdev_network->Configuration.DSConfig));
2151
2152 if (cur_network->network.InfrastructureMode == Ndis802_11IBSS)
2153 pdev_network->Configuration.ATIMWindow = 0;
2154
2155 pdev_network->InfrastructureMode =
2156 cur_network->network.InfrastructureMode;
2157
2158 /* 1. Supported rates */
2159 /* 2. IE */
2160
2161 sz = rtw_generate_ie23a(pregistrypriv);
2162
2163 pdev_network->IELength = sz;
2164
2165 pdev_network->Length =
2166 get_wlan_bssid_ex_sz((struct wlan_bssid_ex *)pdev_network);
2167
2168 /* notes: translate IELength & Length after assign the
2169 Length to cmdsz in createbss_cmd(); */
2170 /* pdev_network->IELength = cpu_to_le32(sz); */
2171
2172}
2173
2174void rtw_get_encrypt_decrypt_from_registrypriv23a(struct rtw_adapter* adapter)
2175{
2176
2177}
2178
2179/* the fucntion is at passive_level */
2180void rtw_joinbss_reset23a(struct rtw_adapter *padapter)
2181{
2182 u8 threshold;
2183 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
2184 struct ht_priv *phtpriv = &pmlmepriv->htpriv;
2185
2186 /* todo: if you want to do something io/reg/hw setting
2187 before join_bss, please add code here */
2188
2189 pmlmepriv->num_FortyMHzIntolerant = 0;
2190
2191 pmlmepriv->num_sta_no_ht = 0;
2192
2193 phtpriv->ampdu_enable = false;/* reset to disabled */
2194
2195 /* TH = 1 => means that invalidate usb rx aggregation */
2196 /* TH = 0 => means that validate usb rx aggregation, use init value. */
2197 if (phtpriv->ht_option) {
2198 if (padapter->registrypriv.wifi_spec == 1)
2199 threshold = 1;
2200 else
2201 threshold = 0;
1e7b6ebe 2202 } else
5e93f352 2203 threshold = 1;
1e7b6ebe
JS
2204
2205 rtl8723a_set_rxdma_agg_pg_th(padapter, threshold);
5e93f352
LF
2206}
2207
2208/* the fucntion is >= passive_level */
2209unsigned int rtw_restructure_ht_ie23a(struct rtw_adapter *padapter, u8 *in_ie,
7c2f97b2 2210 u8 *out_ie, uint in_len, uint *pout_len)
5e93f352 2211{
7c2f97b2 2212 u32 out_len;
5e93f352 2213 int max_rx_ampdu_factor;
7c2f97b2
JS
2214 unsigned char *pframe;
2215 const u8 *p;
5e93f352
LF
2216 struct ieee80211_ht_cap ht_capie;
2217 unsigned char WMM_IE[] = {0x00, 0x50, 0xf2, 0x02, 0x00, 0x01, 0x00};
2218 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
2219 struct qos_priv *pqospriv = &pmlmepriv->qospriv;
2220 struct ht_priv *phtpriv = &pmlmepriv->htpriv;
2221
2222 phtpriv->ht_option = false;
2223
7c2f97b2 2224 p = cfg80211_find_ie(WLAN_EID_HT_CAPABILITY, in_ie + 12, in_len -12);
5e93f352 2225
7c2f97b2 2226 if (p && p[1] > 0) {
5e93f352
LF
2227 u32 rx_packet_offset, max_recvbuf_sz;
2228 if (pqospriv->qos_option == 0) {
2229 out_len = *pout_len;
2230 pframe = rtw_set_ie23a(out_ie + out_len,
9300c94b 2231 WLAN_EID_VENDOR_SPECIFIC,
5e93f352
LF
2232 _WMM_IE_Length_, WMM_IE, pout_len);
2233
2234 pqospriv->qos_option = 1;
2235 }
2236
2237 out_len = *pout_len;
2238
2239 memset(&ht_capie, 0, sizeof(struct ieee80211_ht_cap));
2240
2241 ht_capie.cap_info = IEEE80211_HT_CAP_SUP_WIDTH_20_40 |
2242 IEEE80211_HT_CAP_SGI_20 | IEEE80211_HT_CAP_SGI_40 |
2243 IEEE80211_HT_CAP_TX_STBC | IEEE80211_HT_CAP_DSSSCCK40;
2244
2245 rtw_hal_get_def_var23a(padapter, HAL_DEF_RX_PACKET_OFFSET,
2246 &rx_packet_offset);
2247 rtw_hal_get_def_var23a(padapter, HAL_DEF_MAX_RECVBUF_SZ,
2248 &max_recvbuf_sz);
2249
2250 rtw_hal_get_def_var23a(padapter, HW_VAR_MAX_RX_AMPDU_FACTOR,
2251 &max_rx_ampdu_factor);
2252 ht_capie.ampdu_params_info = max_rx_ampdu_factor & 0x03;
2253
2254 if (padapter->securitypriv.dot11PrivacyAlgrthm == _AES_)
2255 ht_capie.ampdu_params_info |=
2256 (IEEE80211_HT_AMPDU_PARM_DENSITY& (0x07 << 2));
2257 else
2258 ht_capie.ampdu_params_info |=
2259 (IEEE80211_HT_AMPDU_PARM_DENSITY & 0x00);
2260
a7eab38f 2261 pframe = rtw_set_ie23a(out_ie + out_len, WLAN_EID_HT_CAPABILITY,
5e93f352
LF
2262 sizeof(struct ieee80211_ht_cap),
2263 (unsigned char*)&ht_capie, pout_len);
2264
2265 phtpriv->ht_option = true;
2266
7c2f97b2
JS
2267 p = cfg80211_find_ie(WLAN_EID_HT_OPERATION, in_ie + 12,
2268 in_len -12);
2269 if (p && (p[1] == sizeof(struct ieee80211_ht_addt_info))) {
5e93f352 2270 out_len = *pout_len;
a7eab38f
JS
2271 pframe = rtw_set_ie23a(out_ie + out_len,
2272 WLAN_EID_HT_OPERATION,
7c2f97b2 2273 p[1], p + 2 , pout_len);
5e93f352
LF
2274 }
2275 }
2276
2277 return phtpriv->ht_option;
2278}
2279
2280/* the fucntion is > passive_level (in critical_section) */
2281void rtw_update_ht_cap23a(struct rtw_adapter *padapter, u8 *pie, uint ie_len)
2282{
2283 u8 *p, max_ampdu_sz;
2284 int len;
2285 /* struct sta_info *bmc_sta, *psta; */
2286 struct ieee80211_ht_cap *pht_capie;
2287 struct ieee80211_ht_addt_info *pht_addtinfo;
2288 /* struct recv_reorder_ctrl *preorder_ctrl; */
2289 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
2290 struct ht_priv *phtpriv = &pmlmepriv->htpriv;
2291 /* struct recv_priv *precvpriv = &padapter->recvpriv; */
2292 struct registry_priv *pregistrypriv = &padapter->registrypriv;
2293 /* struct wlan_network *pcur_network = &pmlmepriv->cur_network;; */
2294 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
2295 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
2296
2297 if (!phtpriv->ht_option)
2298 return;
2299
2300 if ((!pmlmeinfo->HT_info_enable) || (!pmlmeinfo->HT_caps_enable))
2301 return;
2302
2303 DBG_8723A("+rtw_update_ht_cap23a()\n");
2304
2305 /* maybe needs check if ap supports rx ampdu. */
2306 if ((phtpriv->ampdu_enable == false) && (pregistrypriv->ampdu_enable == 1)) {
2307 if (pregistrypriv->wifi_spec == 1)
2308 phtpriv->ampdu_enable = false;
2309 else
2310 phtpriv->ampdu_enable = true;
2311 } else if (pregistrypriv->ampdu_enable == 2) {
2312 phtpriv->ampdu_enable = true;
2313 }
2314
2315 /* check Max Rx A-MPDU Size */
2316 len = 0;
a7eab38f
JS
2317 p = rtw_get_ie23a(pie+sizeof (struct ndis_802_11_fixed_ies),
2318 WLAN_EID_HT_CAPABILITY, &len,
2319 ie_len-sizeof (struct ndis_802_11_fixed_ies));
5e93f352
LF
2320 if (p && len > 0) {
2321 pht_capie = (struct ieee80211_ht_cap *)(p+2);
2322 max_ampdu_sz = (pht_capie->ampdu_params_info & IEEE80211_HT_AMPDU_PARM_FACTOR);
2323 max_ampdu_sz = 1 << (max_ampdu_sz+3); /* max_ampdu_sz (kbytes); */
2324
2325 /* DBG_8723A("rtw_update_ht_cap23a(): max_ampdu_sz =%d\n", max_ampdu_sz); */
2326 phtpriv->rx_ampdu_maxlen = max_ampdu_sz;
2327
2328 }
2329
2330 len = 0;
a7eab38f
JS
2331 p = rtw_get_ie23a(pie+sizeof (struct ndis_802_11_fixed_ies),
2332 WLAN_EID_HT_OPERATION, &len,
2333 ie_len-sizeof (struct ndis_802_11_fixed_ies));
5e93f352
LF
2334 if (p && len>0)
2335 {
2336 pht_addtinfo = (struct ieee80211_ht_addt_info *)(p+2);
2337 /* todo: */
2338 }
2339
2340 /* update cur_bwmode & cur_ch_offset */
2341 if ((pregistrypriv->cbw40_enable) &&
2342 (pmlmeinfo->HT_caps.u.HT_cap_element.HT_caps_info & BIT(1)) &&
c2370e83 2343 (pmlmeinfo->HT_info.infos[0] & BIT(2))) {
5e93f352 2344 int i;
c2370e83 2345 u8 rf_type;
5e93f352 2346
c2370e83 2347 rf_type = rtl8723a_get_rf_type(padapter);
5e93f352
LF
2348
2349 /* update the MCS rates */
c2370e83 2350 for (i = 0; i < 16; i++) {
5e93f352
LF
2351 if ((rf_type == RF_1T1R) || (rf_type == RF_1T2R))
2352 pmlmeinfo->HT_caps.u.HT_cap_element.MCS_rate[i] &= MCS_rate_1R23A[i];
2353 else
2354 pmlmeinfo->HT_caps.u.HT_cap_element.MCS_rate[i] &= MCS_rate_2R23A[i];
2355 }
2356 /* switch to the 40M Hz mode accoring to the AP */
2357 pmlmeext->cur_bwmode = HT_CHANNEL_WIDTH_40;
2358 switch ((pmlmeinfo->HT_info.infos[0] & 0x3))
2359 {
b54e8804
JS
2360 case HT_EXTCHNL_OFFSET_UPPER:
2361 pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_LOWER;
2362 break;
5e93f352 2363
b54e8804
JS
2364 case HT_EXTCHNL_OFFSET_LOWER:
2365 pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_UPPER;
2366 break;
5e93f352 2367
b54e8804
JS
2368 default:
2369 pmlmeext->cur_ch_offset =
2370 HAL_PRIME_CHNL_OFFSET_DONT_CARE;
2371 break;
5e93f352
LF
2372 }
2373 }
2374
2375 /* */
2376 /* Config SM Power Save setting */
2377 /* */
2378 pmlmeinfo->SM_PS = (pmlmeinfo->HT_caps.u.HT_cap_element.HT_caps_info & 0x0C) >> 2;
2379 if (pmlmeinfo->SM_PS == WLAN_HT_CAP_SM_PS_STATIC)
2380 DBG_8723A("%s(): WLAN_HT_CAP_SM_PS_STATIC\n", __func__);
2381
2382 /* */
2383 /* Config current HT Protection mode. */
2384 /* */
2385 pmlmeinfo->HT_protection = pmlmeinfo->HT_info.infos[1] & 0x3;
2386}
2387
2388void rtw_issue_addbareq_cmd23a(struct rtw_adapter *padapter, struct xmit_frame *pxmitframe)
2389{
2390 u8 issued;
2391 int priority;
2392 struct sta_info *psta = NULL;
2393 struct ht_priv *phtpriv;
2394 struct pkt_attrib *pattrib = &pxmitframe->attrib;
2395 s32 bmcst = is_multicast_ether_addr(pattrib->ra);
2396
2397 if (bmcst || (padapter->mlmepriv.LinkDetectInfo.NumTxOkInPeriod<100))
2398 return;
2399
2400 priority = pattrib->priority;
2401
2402 if (pattrib->psta)
2403 psta = pattrib->psta;
2404 else
2405 {
2406 DBG_8723A("%s, call rtw_get_stainfo23a()\n", __func__);
2407 psta = rtw_get_stainfo23a(&padapter->stapriv, pattrib->ra);
2408 }
2409
2410 if (psta == NULL)
2411 {
2412 DBG_8723A("%s, psta == NUL\n", __func__);
2413 return;
2414 }
2415
2416 if (!(psta->state &_FW_LINKED))
2417 {
2418 DBG_8723A("%s, psta->state(0x%x) != _FW_LINKED\n", __func__, psta->state);
2419 return;
2420 }
2421
2422 phtpriv = &psta->htpriv;
2423
2424 if ((phtpriv->ht_option == true) && (phtpriv->ampdu_enable == true))
2425 {
2426 issued = (phtpriv->agg_enable_bitmap>>priority)&0x1;
2427 issued |= (phtpriv->candidate_tid_bitmap>>priority)&0x1;
2428
2429 if (0 == issued)
2430 {
2431 DBG_8723A("rtw_issue_addbareq_cmd23a, p =%d\n", priority);
2432 psta->htpriv.candidate_tid_bitmap |= CHKBIT((u8)priority);
2433 rtw_addbareq_cmd23a(padapter, (u8) priority, pattrib->ra);
2434 }
2435 }
2436}
2437
2438inline void rtw_set_roaming(struct rtw_adapter *adapter, u8 to_roaming)
2439{
2440 if (to_roaming == 0)
2441 adapter->mlmepriv.to_join = false;
2442 adapter->mlmepriv.to_roaming = to_roaming;
2443}
2444
2445inline u8 rtw_to_roaming(struct rtw_adapter *adapter)
2446{
2447 return adapter->mlmepriv.to_roaming;
2448}
2449
2450void rtw23a_roaming(struct rtw_adapter *padapter, struct wlan_network *tgt_network)
2451{
2452 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
2453
2454 spin_lock_bh(&pmlmepriv->lock);
2455 _rtw23a_roaming(padapter, tgt_network);
2456 spin_unlock_bh(&pmlmepriv->lock);
2457}
2458void _rtw23a_roaming(struct rtw_adapter *padapter, struct wlan_network *tgt_network)
2459{
2460 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
2461 struct wlan_network *pnetwork;
2462 int do_join_r;
2463
2464 if (tgt_network != NULL)
2465 pnetwork = tgt_network;
2466 else
2467 pnetwork = &pmlmepriv->cur_network;
2468
2469 if (0 < rtw_to_roaming(padapter)) {
2470 DBG_8723A("roaming from %s("MAC_FMT"), length:%d\n",
2471 pnetwork->network.Ssid.ssid,
2472 MAC_ARG(pnetwork->network.MacAddress),
2473 pnetwork->network.Ssid.ssid_len);
2474 memcpy(&pmlmepriv->assoc_ssid, &pnetwork->network.Ssid,
2475 sizeof(struct cfg80211_ssid));
2476
2477 pmlmepriv->assoc_by_bssid = false;
2478
2479 while(1) {
2480 if (_SUCCESS == (do_join_r = rtw_do_join23a(padapter))) {
2481 break;
2482 } else {
2483 DBG_8723A("roaming do_join return %d\n", do_join_r);
2484 pmlmepriv->to_roaming--;
2485
2486 if (0 < rtw_to_roaming(padapter)) {
2487 continue;
2488 } else {
2489 DBG_8723A("%s(%d) -to roaming fail, indicate_disconnect\n", __func__, __LINE__);
2490 rtw_indicate_disconnect23a(padapter);
2491 break;
2492 }
2493 }
2494 }
2495 }
2496}
2497
2498int rtw_linked_check(struct rtw_adapter *padapter)
2499{
2500 if ((check_fwstate(&padapter->mlmepriv, WIFI_AP_STATE)) ||
2501 (check_fwstate(&padapter->mlmepriv, WIFI_ADHOC_STATE|WIFI_ADHOC_MASTER_STATE))) {
2502 if (padapter->stapriv.asoc_sta_count > 2)
2503 return true;
2504 } else { /* Station mode */
2505 if (check_fwstate(&padapter->mlmepriv, _FW_LINKED) == true)
2506 return true;
2507 }
2508 return false;
2509}