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