1 /******************************************************************************
3 * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
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.
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
14 ******************************************************************************/
17 #include <osdep_service.h>
18 #include <drv_types.h>
19 #include <recv_osdep.h>
20 #include <xmit_osdep.h>
22 #include <mlme_osdep.h>
24 #include <linux/ieee80211.h>
26 #include <wlan_bssdef.h>
27 #include <rtw_sreset.h>
29 static struct wlan_network *
30 rtw_select_candidate_from_queue(struct mlme_priv *pmlmepriv);
31 static int rtw_do_join(struct rtw_adapter *padapter);
33 static void rtw_init_mlme_timer(struct rtw_adapter *padapter)
35 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
37 setup_timer(&pmlmepriv->assoc_timer, rtw23a_join_to_handler,
38 (unsigned long)padapter);
40 setup_timer(&pmlmepriv->scan_to_timer, rtw_scan_timeout_handler23a,
41 (unsigned long)padapter);
43 setup_timer(&pmlmepriv->dynamic_chk_timer,
44 rtw_dynamic_check_timer_handler, (unsigned long)padapter);
46 setup_timer(&pmlmepriv->set_scan_deny_timer,
47 rtw_set_scan_deny_timer_hdl, (unsigned long)padapter);
50 int rtw_init_mlme_priv23a(struct rtw_adapter *padapter)
52 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
54 pmlmepriv->nic_hdl = padapter;
56 pmlmepriv->fw_state = 0;
57 pmlmepriv->cur_network.network.ifmode = NL80211_IFTYPE_UNSPECIFIED;
58 /* 1: active, 0: pasive. Maybe someday we should rename this
59 varable to "active_mode" (Jeff) */
60 pmlmepriv->scan_mode = SCAN_ACTIVE;
62 spin_lock_init(&pmlmepriv->lock);
63 _rtw_init_queue23a(&pmlmepriv->scanned_queue);
65 memset(&pmlmepriv->assoc_ssid, 0, sizeof(struct cfg80211_ssid));
67 rtw_clear_scan_deny(padapter);
69 rtw_init_mlme_timer(padapter);
73 #ifdef CONFIG_8723AU_AP_MODE
74 static void rtw_free_mlme_ie_data(u8 **ppie, u32 *plen)
84 void rtw23a_free_mlme_priv_ie_data(struct mlme_priv *pmlmepriv)
86 #ifdef CONFIG_8723AU_AP_MODE
87 kfree(pmlmepriv->assoc_req);
88 kfree(pmlmepriv->assoc_rsp);
89 rtw_free_mlme_ie_data(&pmlmepriv->wps_probe_req_ie,
90 &pmlmepriv->wps_probe_req_ie_len);
94 void rtw_free_mlme_priv23a(struct mlme_priv *pmlmepriv)
96 RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_,
97 ("rtw_free_mlme_priv23a\n"));
99 rtw23a_free_mlme_priv_ie_data(pmlmepriv);
102 struct wlan_network *rtw_alloc_network(struct mlme_priv *pmlmepriv, gfp_t gfp)
104 struct wlan_network *pnetwork;
106 pnetwork = kzalloc(sizeof(struct wlan_network), gfp);
108 INIT_LIST_HEAD(&pnetwork->list);
109 pnetwork->network_type = 0;
110 pnetwork->fixed = false;
111 pnetwork->last_scanned = jiffies;
112 pnetwork->join_res = 0;
118 static void _rtw_free_network23a(struct mlme_priv *pmlmepriv,
119 struct wlan_network *pnetwork)
124 if (pnetwork->fixed == true)
127 list_del_init(&pnetwork->list);
133 return the wlan_network with the matching addr
135 Shall be called under atomic context... to avoid possible racing condition...
137 struct wlan_network *
138 rtw_find_network23a(struct rtw_queue *scanned_queue, u8 *addr)
140 struct list_head *phead, *plist;
141 struct wlan_network *pnetwork = NULL;
143 if (is_zero_ether_addr(addr)) {
148 /* spin_lock_bh(&scanned_queue->lock); */
150 phead = get_list_head(scanned_queue);
153 while (plist != phead) {
154 pnetwork = container_of(plist, struct wlan_network, list);
156 if (ether_addr_equal(addr, pnetwork->network.MacAddress))
165 /* spin_unlock_bh(&scanned_queue->lock); */
172 void rtw_free_network_queue23a(struct rtw_adapter *padapter)
174 struct list_head *phead, *plist, *ptmp;
175 struct wlan_network *pnetwork;
176 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
177 struct rtw_queue *scanned_queue = &pmlmepriv->scanned_queue;
179 spin_lock_bh(&scanned_queue->lock);
181 phead = get_list_head(scanned_queue);
183 list_for_each_safe(plist, ptmp, phead) {
184 pnetwork = container_of(plist, struct wlan_network, list);
186 _rtw_free_network23a(pmlmepriv, pnetwork);
189 spin_unlock_bh(&scanned_queue->lock);
192 int rtw_if_up23a(struct rtw_adapter *padapter)
196 if (padapter->bDriverStopped || padapter->bSurpriseRemoved ||
197 !check_fwstate(&padapter->mlmepriv, _FW_LINKED)) {
198 RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_,
199 ("rtw_if_up23a:bDriverStopped(%d) OR "
200 "bSurpriseRemoved(%d)", padapter->bDriverStopped,
201 padapter->bSurpriseRemoved));
209 void rtw_generate_random_ibss23a(u8 *pibss)
211 unsigned long curtime = jiffies;
213 pibss[0] = 0x02; /* in ad-hoc mode bit1 must set to 1 */
216 pibss[3] = curtime & 0xff;/* p[0]; */
217 pibss[4] = (curtime >> 8) & 0xff;/* p[1]; */
218 pibss[5] = (curtime >> 16) & 0xff;/* p[2]; */
221 void rtw_set_roaming(struct rtw_adapter *adapter, u8 to_roaming)
224 adapter->mlmepriv.to_join = false;
225 adapter->mlmepriv.to_roaming = to_roaming;
228 static void _rtw_roaming(struct rtw_adapter *padapter,
229 struct wlan_network *tgt_network)
231 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
232 struct wlan_network *pnetwork;
236 pnetwork = tgt_network;
238 pnetwork = &pmlmepriv->cur_network;
240 if (padapter->mlmepriv.to_roaming > 0) {
241 DBG_8723A("roaming from %s("MAC_FMT"), length:%d\n",
242 pnetwork->network.Ssid.ssid,
243 MAC_ARG(pnetwork->network.MacAddress),
244 pnetwork->network.Ssid.ssid_len);
245 memcpy(&pmlmepriv->assoc_ssid, &pnetwork->network.Ssid,
246 sizeof(struct cfg80211_ssid));
248 pmlmepriv->assoc_by_bssid = false;
251 do_join_r = rtw_do_join(padapter);
252 if (do_join_r == _SUCCESS)
255 DBG_8723A("roaming do_join return %d\n",
257 pmlmepriv->to_roaming--;
259 if (padapter->mlmepriv.to_roaming > 0)
262 DBG_8723A("%s(%d) -to roaming fail, "
263 "indicate_disconnect\n",
265 rtw_indicate_disconnect23a(padapter);
273 void rtw23a_roaming(struct rtw_adapter *padapter,
274 struct wlan_network *tgt_network)
276 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
278 spin_lock_bh(&pmlmepriv->lock);
279 _rtw_roaming(padapter, tgt_network);
280 spin_unlock_bh(&pmlmepriv->lock);
283 static void rtw_free_network_nolock(struct mlme_priv *pmlmepriv,
284 struct wlan_network *pnetwork)
286 _rtw_free_network23a(pmlmepriv, pnetwork);
289 bool rtw_is_same_ibss23a(struct rtw_adapter *adapter,
290 struct wlan_network *pnetwork)
293 struct security_priv *psecuritypriv = &adapter->securitypriv;
295 if (psecuritypriv->dot11PrivacyAlgrthm != 0 &&
296 pnetwork->network.Privacy == 0)
298 else if (psecuritypriv->dot11PrivacyAlgrthm == 0 &&
299 pnetwork->network.Privacy == 1)
307 inline int is_same_ess(struct wlan_bssid_ex *a, struct wlan_bssid_ex *b);
308 inline int is_same_ess(struct wlan_bssid_ex *a, struct wlan_bssid_ex *b)
310 return (a->Ssid.ssid_len == b->Ssid.ssid_len) &&
311 !memcmp(a->Ssid.ssid, b->Ssid.ssid, a->Ssid.ssid_len);
314 int is_same_network23a(struct wlan_bssid_ex *src, struct wlan_bssid_ex *dst)
318 s_cap = src->capability;
319 d_cap = dst->capability;
321 return ((src->Ssid.ssid_len == dst->Ssid.ssid_len) &&
322 /* (src->DSConfig == dst->DSConfig) && */
323 ether_addr_equal(src->MacAddress, dst->MacAddress) &&
324 !memcmp(src->Ssid.ssid, dst->Ssid.ssid, src->Ssid.ssid_len) &&
325 (s_cap & WLAN_CAPABILITY_IBSS) ==
326 (d_cap & WLAN_CAPABILITY_IBSS) &&
327 (s_cap & WLAN_CAPABILITY_ESS) == (d_cap & WLAN_CAPABILITY_ESS));
330 struct wlan_network *
331 rtw_get_oldest_wlan_network23a(struct rtw_queue *scanned_queue)
333 struct list_head *plist, *phead;
334 struct wlan_network *pwlan;
335 struct wlan_network *oldest = NULL;
337 phead = get_list_head(scanned_queue);
339 list_for_each(plist, phead) {
340 pwlan = container_of(plist, struct wlan_network, list);
342 if (pwlan->fixed != true) {
343 if (!oldest || time_after(oldest->last_scanned,
344 pwlan->last_scanned))
352 void update_network23a(struct wlan_bssid_ex *dst, struct wlan_bssid_ex *src,
353 struct rtw_adapter *padapter, bool update_ie)
355 u8 ss_ori = dst->SignalStrength;
356 u8 sq_ori = dst->SignalQuality;
357 long rssi_ori = dst->Rssi;
359 u8 ss_smp = src->SignalStrength;
360 u8 sq_smp = src->SignalQuality;
361 long rssi_smp = src->Rssi;
367 DBG_8723A("%s %s(%pM, ch%u) ss_ori:%3u, sq_ori:%3u, rssi_ori:%3ld, "
368 "ss_smp:%3u, sq_smp:%3u, rssi_smp:%3ld\n",
369 __func__, src->Ssid.ssid, src->MacAddress,
370 src->DSConfig, ss_ori, sq_ori, rssi_ori,
371 ss_smp, sq_smp, rssi_smp
374 /* The rule below is 1/5 for sample value, 4/5 for history value */
375 if (check_fwstate(&padapter->mlmepriv, _FW_LINKED) &&
376 is_same_network23a(&padapter->mlmepriv.cur_network.network, src)) {
377 /* Take the recvpriv's value for the connected AP*/
378 ss_final = padapter->recvpriv.signal_strength;
379 sq_final = padapter->recvpriv.signal_qual;
380 /* the rssi value here is undecorated, and will be
381 used for antenna diversity */
382 if (sq_smp != 101) /* from the right channel */
383 rssi_final = (src->Rssi+dst->Rssi*4)/5;
385 rssi_final = rssi_ori;
387 if (sq_smp != 101) { /* from the right channel */
388 ss_final = ((u32)src->SignalStrength +
389 (u32)dst->SignalStrength * 4) / 5;
390 sq_final = ((u32)src->SignalQuality +
391 (u32)dst->SignalQuality * 4) / 5;
392 rssi_final = src->Rssi+dst->Rssi * 4 / 5;
394 /* bss info not receiving from the right channel, use
395 the original RX signal infos */
396 ss_final = dst->SignalStrength;
397 sq_final = dst->SignalQuality;
398 rssi_final = dst->Rssi;
404 memcpy(dst, src, get_wlan_bssid_ex_sz(src));
406 dst->SignalStrength = ss_final;
407 dst->SignalQuality = sq_final;
408 dst->Rssi = rssi_final;
410 DBG_8723A("%s %s(%pM), SignalStrength:%u, SignalQuality:%u, "
411 "RawRSSI:%ld\n", __func__, dst->Ssid.ssid, dst->MacAddress,
412 dst->SignalStrength, dst->SignalQuality, dst->Rssi);
415 static void update_current_network(struct rtw_adapter *adapter,
416 struct wlan_bssid_ex *pnetwork)
418 struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
420 if (check_fwstate(pmlmepriv, _FW_LINKED) &&
421 is_same_network23a(&pmlmepriv->cur_network.network, pnetwork)) {
422 update_network23a(&pmlmepriv->cur_network.network,
423 pnetwork, adapter, true);
425 rtw_update_protection23a(adapter,
426 pmlmepriv->cur_network.network.IEs,
427 pmlmepriv->cur_network.network.IELength);
433 Caller must hold pmlmepriv->lock first.
436 static void rtw_update_scanned_network(struct rtw_adapter *adapter,
437 struct wlan_bssid_ex *target)
439 struct list_head *plist, *phead;
440 struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
441 struct wlan_network *pnetwork = NULL;
442 struct wlan_network *oldest = NULL;
443 struct rtw_queue *queue = &pmlmepriv->scanned_queue;
447 spin_lock_bh(&queue->lock);
448 phead = get_list_head(queue);
450 list_for_each(plist, phead) {
451 pnetwork = container_of(plist, struct wlan_network, list);
453 if (is_same_network23a(&pnetwork->network, target)) {
457 if (!oldest || time_after(oldest->last_scanned,
458 pnetwork->last_scanned))
462 /* If we didn't find a match, then get a new network slot to initialize
463 * with this beacon's information */
465 pnetwork = rtw_alloc_network(pmlmepriv, GFP_ATOMIC);
468 RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_,
469 ("\n\n\nsomething wrong here\n\n\n"));
474 list_add_tail(&pnetwork->list, &queue->queue);
476 bssid_ex_sz = get_wlan_bssid_ex_sz(target);
477 target->Length = bssid_ex_sz;
478 memcpy(&pnetwork->network, target, bssid_ex_sz);
480 /* variable initialize */
481 pnetwork->fixed = false;
482 pnetwork->last_scanned = jiffies;
484 pnetwork->network_type = 0;
485 pnetwork->join_res = 0;
487 /* bss info not receiving from the right channel */
488 if (pnetwork->network.SignalQuality == 101)
489 pnetwork->network.SignalQuality = 0;
492 * we have an entry and we are going to update it. But
493 * this entry may be already expired. In this case we
494 * do the same as we found a new net and call the
497 bool update_ie = true;
499 pnetwork->last_scanned = jiffies;
501 /* target.reserved == 1, means that scanned network is
503 if (pnetwork->network.IELength > target->IELength &&
504 target->reserved == 1)
507 update_network23a(&pnetwork->network, target, adapter,
512 spin_unlock_bh(&queue->lock);
515 static void rtw_add_network(struct rtw_adapter *adapter,
516 struct wlan_bssid_ex *pnetwork)
518 update_current_network(adapter, pnetwork);
519 rtw_update_scanned_network(adapter, pnetwork);
522 /* select the desired network based on the capability of the (i)bss. */
523 /* check items: (1) security */
524 /* (2) network_type */
528 static int rtw_is_desired_network(struct rtw_adapter *adapter,
529 struct wlan_network *pnetwork)
531 struct security_priv *psecuritypriv = &adapter->securitypriv;
532 struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
535 int bselected = true;
537 desired_encmode = psecuritypriv->ndisencryptstatus;
538 privacy = pnetwork->network.Privacy;
540 if (check_fwstate(pmlmepriv, WIFI_UNDER_WPS)) {
541 if (cfg80211_find_vendor_ie(WLAN_OUI_MICROSOFT,
542 WLAN_OUI_TYPE_MICROSOFT_WPA,
543 pnetwork->network.IEs,
544 pnetwork->network.IELength))
549 if (adapter->registrypriv.wifi_spec == 1) {
550 /* for correct flow of 8021X to do.... */
551 if (desired_encmode == Ndis802_11EncryptionDisabled &&
556 if (desired_encmode != Ndis802_11EncryptionDisabled && privacy == 0) {
557 DBG_8723A("desired_encmode: %d, privacy: %d\n",
558 desired_encmode, privacy);
562 if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE)) {
563 if (pnetwork->network.ifmode !=
564 pmlmepriv->cur_network.network.ifmode)
571 /* TODO: Perry : For Power Management */
572 void rtw_atimdone_event_callback23a(struct rtw_adapter *adapter, const u8 *pbuf)
574 RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_,
575 ("receive atimdone_evet\n"));
578 void rtw_survey_event_cb23a(struct rtw_adapter *adapter, const u8 *pbuf)
581 struct wlan_bssid_ex *pnetwork;
582 struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
583 struct survey_event *survey = (struct survey_event *)pbuf;
585 pnetwork = survey->bss;
587 RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_,
588 ("rtw_survey_event_cb23a, ssid=%s\n", pnetwork->Ssid.ssid));
590 len = get_wlan_bssid_ex_sz(pnetwork);
591 if (len > (sizeof(struct wlan_bssid_ex))) {
592 RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_,
593 ("\n ****rtw_survey_event_cb23a: return a wrong "
598 spin_lock_bh(&pmlmepriv->lock);
600 /* update IBSS_network 's timestamp */
601 if (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE)) {
602 /* RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_,
603 "rtw_survey_event_cb23a : WIFI_ADHOC_MASTER_STATE\n\n"); */
604 if (ether_addr_equal(pmlmepriv->cur_network.network.MacAddress,
605 pnetwork->MacAddress)) {
606 struct wlan_network *ibss_wlan;
608 pmlmepriv->cur_network.network.beacon_interval =
609 pnetwork->beacon_interval;
610 pmlmepriv->cur_network.network.capability =
611 pnetwork->capability;
612 pmlmepriv->cur_network.network.tsf = pnetwork->tsf;
613 spin_lock_bh(&pmlmepriv->scanned_queue.lock);
614 ibss_wlan = rtw_find_network23a(
615 &pmlmepriv->scanned_queue,
616 pnetwork->MacAddress);
618 pmlmepriv->cur_network.network.beacon_interval =
619 ibss_wlan->network.beacon_interval;
620 pmlmepriv->cur_network.network.capability =
621 ibss_wlan->network.capability;
622 pmlmepriv->cur_network.network.tsf =
623 ibss_wlan->network.tsf;
624 spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
627 spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
631 /* lock pmlmepriv->lock when you accessing network_q */
632 if (!check_fwstate(pmlmepriv, _FW_UNDER_LINKING)) {
633 if (pnetwork->Ssid.ssid[0] == 0)
634 pnetwork->Ssid.ssid_len = 0;
636 rtw_add_network(adapter, pnetwork);
641 spin_unlock_bh(&pmlmepriv->lock);
648 rtw_surveydone_event_callback23a(struct rtw_adapter *adapter, const u8 *pbuf)
650 struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
651 struct mlme_ext_priv *pmlmeext = &adapter->mlmeextpriv;
654 spin_lock_bh(&pmlmepriv->lock);
656 if (pmlmepriv->wps_probe_req_ie) {
657 pmlmepriv->wps_probe_req_ie_len = 0;
658 kfree(pmlmepriv->wps_probe_req_ie);
659 pmlmepriv->wps_probe_req_ie = NULL;
662 RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_,
663 ("rtw_surveydone_event_callback23a: fw_state:%x\n\n",
664 get_fwstate(pmlmepriv)));
666 if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY)) {
667 del_timer_sync(&pmlmepriv->scan_to_timer);
669 _clr_fwstate_(pmlmepriv, _FW_UNDER_SURVEY);
671 RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_,
672 ("nic status =%x, survey done event comes too late!\n",
673 get_fwstate(pmlmepriv)));
676 rtw_set_signal_stat_timer(&adapter->recvpriv);
678 if (pmlmepriv->to_join == true) {
679 set_fwstate(pmlmepriv, _FW_UNDER_LINKING);
680 if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE)) {
681 ret = rtw_select_and_join_from_scanned_queue23a(
684 rtw_do_join_adhoc(adapter);
686 pmlmepriv->to_join = false;
687 ret = rtw_select_and_join_from_scanned_queue23a(
689 if (ret != _SUCCESS) {
690 DBG_8723A("try_to_join, but select scanning "
691 "queue fail, to_roaming:%d\n",
692 adapter->mlmepriv.to_roaming);
693 if (adapter->mlmepriv.to_roaming) {
694 if (--pmlmepriv->to_roaming == 0 ||
695 rtw_sitesurvey_cmd23a(
697 &pmlmepriv->assoc_ssid, 1,
698 NULL, 0) != _SUCCESS) {
699 rtw_set_roaming(adapter, 0);
700 rtw_free_assoc_resources23a(
702 rtw_indicate_disconnect23a(
705 pmlmepriv->to_join = true;
707 _clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING);
712 spin_unlock_bh(&pmlmepriv->lock);
714 rtw_os_xmit_schedule23a(adapter);
716 if (pmlmeext->sitesurvey_res.bss_cnt == 0)
717 rtw_sreset_reset(adapter);
719 rtw_cfg80211_surveydone_event_callback(adapter);
722 static void free_scanqueue(struct mlme_priv *pmlmepriv)
724 struct wlan_network *pnetwork;
725 struct rtw_queue *scan_queue = &pmlmepriv->scanned_queue;
726 struct list_head *plist, *phead, *ptemp;
728 RT_TRACE(_module_rtl871x_mlme_c_, _drv_notice_, ("+free_scanqueue\n"));
729 spin_lock_bh(&scan_queue->lock);
731 phead = get_list_head(scan_queue);
733 list_for_each_safe(plist, ptemp, phead) {
734 pnetwork = container_of(plist, struct wlan_network, list);
735 pnetwork->fixed = false;
736 _rtw_free_network23a(pmlmepriv, pnetwork);
739 spin_unlock_bh(&scan_queue->lock);
743 *rtw_free_assoc_resources23a: the caller has to lock pmlmepriv->lock
745 void rtw_free_assoc_resources23a(struct rtw_adapter *adapter,
746 int lock_scanned_queue)
748 struct wlan_network *pwlan;
749 struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
750 struct sta_priv *pstapriv = &adapter->stapriv;
751 struct wlan_network *tgt_network = &pmlmepriv->cur_network;
752 struct sta_info *psta;
754 RT_TRACE(_module_rtl871x_mlme_c_, _drv_notice_,
755 ("+rtw_free_assoc_resources23a\n"));
756 RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_,
757 ("tgt_network->network.MacAddress="MAC_FMT" ssid=%s\n",
758 MAC_ARG(tgt_network->network.MacAddress),
759 tgt_network->network.Ssid.ssid));
761 if (check_fwstate(pmlmepriv, WIFI_STATION_STATE|WIFI_AP_STATE)) {
762 psta = rtw_get_stainfo23a(&adapter->stapriv,
763 tgt_network->network.MacAddress);
765 spin_lock_bh(&pstapriv->sta_hash_lock);
766 rtw_free_stainfo23a(adapter, psta);
767 spin_unlock_bh(&pstapriv->sta_hash_lock);
770 if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE |
771 WIFI_ADHOC_MASTER_STATE|WIFI_AP_STATE)) {
772 rtw_free_all_stainfo23a(adapter);
774 psta = rtw_get_bcmc_stainfo23a(adapter);
775 spin_lock_bh(&pstapriv->sta_hash_lock);
776 rtw_free_stainfo23a(adapter, psta);
777 spin_unlock_bh(&pstapriv->sta_hash_lock);
779 rtw_init_bcmc_stainfo23a(adapter);
782 if (lock_scanned_queue)
783 spin_lock_bh(&pmlmepriv->scanned_queue.lock);
785 pwlan = rtw_find_network23a(&pmlmepriv->scanned_queue,
786 tgt_network->network.MacAddress);
788 pwlan->fixed = false;
790 RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_,
791 ("rtw_free_assoc_resources23a : pwlan== NULL\n"));
793 if (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) &&
794 adapter->stapriv.asoc_sta_count == 1)
795 rtw_free_network_nolock(pmlmepriv, pwlan);
797 if (lock_scanned_queue)
798 spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
800 pmlmepriv->key_mask = 0;
804 *rtw_indicate_connect23a: the caller has to lock pmlmepriv->lock
806 void rtw_indicate_connect23a(struct rtw_adapter *padapter)
808 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
810 RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_,
811 ("+rtw_indicate_connect23a\n"));
813 pmlmepriv->to_join = false;
815 if (!check_fwstate(&padapter->mlmepriv, _FW_LINKED)) {
816 set_fwstate(pmlmepriv, _FW_LINKED);
818 rtw_cfg80211_indicate_connect(padapter);
820 netif_carrier_on(padapter->pnetdev);
822 if (padapter->pid[2] != 0)
823 kill_pid(find_vpid(padapter->pid[2]), SIGALRM, 1);
826 rtw_set_roaming(padapter, 0);
828 rtw_set_scan_deny(padapter, 3000);
830 RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_,
831 ("-rtw_indicate_connect23a: fw_state=0x%08x\n",
832 get_fwstate(pmlmepriv)));
836 *rtw_indicate_disconnect23a: the caller has to lock pmlmepriv->lock
838 void rtw_indicate_disconnect23a(struct rtw_adapter *padapter)
840 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
842 RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_,
843 ("+rtw_indicate_disconnect23a\n"));
845 _clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING|WIFI_UNDER_WPS);
847 /* DBG_8723A("clear wps when %s\n", __func__); */
849 if (padapter->mlmepriv.to_roaming > 0)
850 _clr_fwstate_(pmlmepriv, _FW_LINKED);
852 if (check_fwstate(&padapter->mlmepriv, _FW_LINKED) ||
853 padapter->mlmepriv.to_roaming <= 0) {
854 rtw_os_indicate_disconnect23a(padapter);
856 /* set ips_deny_time to avoid enter IPS before LPS leave */
857 padapter->pwrctrlpriv.ips_deny_time =
858 jiffies + msecs_to_jiffies(3000);
860 _clr_fwstate_(pmlmepriv, _FW_LINKED);
862 rtw_clear_scan_deny(padapter);
865 rtw_lps_ctrl_wk_cmd23a(padapter, LPS_CTRL_DISCONNECT, 1);
868 void rtw_scan_abort23a(struct rtw_adapter *adapter)
871 struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
872 struct mlme_ext_priv *pmlmeext = &adapter->mlmeextpriv;
875 pmlmeext->scan_abort = true;
876 while (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY) &&
877 jiffies_to_msecs(jiffies - start) <= 200) {
878 if (adapter->bDriverStopped || adapter->bSurpriseRemoved)
881 DBG_8723A("%s(%s): fw_state = _FW_UNDER_SURVEY!\n",
882 __func__, adapter->pnetdev->name);
886 if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY)) {
887 if (!adapter->bDriverStopped && !adapter->bSurpriseRemoved)
888 DBG_8723A("%s(%s): waiting for scan_abort time out!\n",
889 __func__, adapter->pnetdev->name);
890 rtw_cfg80211_indicate_scan_done(wdev_to_priv(adapter->rtw_wdev),
893 pmlmeext->scan_abort = false;
896 static struct sta_info *
897 rtw_joinbss_update_stainfo(struct rtw_adapter *padapter,
898 struct wlan_network *pnetwork)
901 struct sta_info *bmc_sta, *psta;
902 struct recv_reorder_ctrl *preorder_ctrl;
903 struct sta_priv *pstapriv = &padapter->stapriv;
905 psta = rtw_get_stainfo23a(pstapriv, pnetwork->network.MacAddress);
907 psta = rtw_alloc_stainfo23a(pstapriv,
908 pnetwork->network.MacAddress,
911 if (psta) { /* update ptarget_sta */
912 DBG_8723A("%s\n", __func__);
914 psta->aid = pnetwork->join_res;
918 rtl8723a_SetHalODMVar(padapter, HAL_ODM_STA_INFO, psta, true);
920 /* security related */
921 if (padapter->securitypriv.dot11AuthAlgrthm ==
922 dot11AuthAlgrthm_8021X) {
923 padapter->securitypriv.binstallGrpkey = 0;
924 padapter->securitypriv.busetkipkey = 0;
926 psta->ieee8021x_blocked = true;
927 psta->dot118021XPrivacy =
928 padapter->securitypriv.dot11PrivacyAlgrthm;
930 memset(&psta->dot118021x_UncstKey, 0,
931 sizeof (union Keytype));
933 memset(&psta->dot11tkiprxmickey, 0,
934 sizeof (union Keytype));
935 memset(&psta->dot11tkiptxmickey, 0,
936 sizeof (union Keytype));
938 memset(&psta->dot11txpn, 0, sizeof (union pn48));
939 memset(&psta->dot11rxpn, 0, sizeof (union pn48));
942 /* Commented by Albert 2012/07/21 */
943 /* When doing the WPS, the wps_ie_len won't equal to 0 */
944 /* And the Wi-Fi driver shouldn't allow the data packet
945 to be transmitted. */
946 if (padapter->securitypriv.wps_ie_len != 0) {
947 psta->ieee8021x_blocked = true;
948 padapter->securitypriv.wps_ie_len = 0;
951 /* for A-MPDU Rx reordering buffer control for bmc_sta &
953 /* if A-MPDU Rx is enabled, resetting
954 rx_ordering_ctrl wstart_b(indicate_seq) to default
956 /* todo: check if AP can send A-MPDU packets */
957 for (i = 0; i < 16 ; i++) {
958 /* preorder_ctrl = &precvpriv->recvreorder_ctrl[i]; */
959 preorder_ctrl = &psta->recvreorder_ctrl[i];
960 preorder_ctrl->enable = false;
961 preorder_ctrl->indicate_seq = 0xffff;
962 preorder_ctrl->wend_b = 0xffff;
963 /* max_ampdu_sz; ex. 32(kbytes) -> wsize_b = 32 */
964 preorder_ctrl->wsize_b = 64;
967 bmc_sta = rtw_get_bcmc_stainfo23a(padapter);
969 for (i = 0; i < 16 ; i++) {
970 preorder_ctrl = &bmc_sta->recvreorder_ctrl[i];
971 preorder_ctrl->enable = false;
972 preorder_ctrl->indicate_seq = 0xffff;
973 preorder_ctrl->wend_b = 0xffff;
974 /* max_ampdu_sz; ex. 32(kbytes) ->
976 preorder_ctrl->wsize_b = 64;
981 update_sta_info23a(padapter, psta);
988 /* pnetwork : returns from rtw23a_joinbss_event_cb */
989 /* ptarget_wlan: found from scanned_queue */
991 rtw_joinbss_update_network23a(struct rtw_adapter *padapter,
992 struct wlan_network *ptarget_wlan,
993 struct wlan_network *pnetwork)
995 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
996 struct wlan_network *cur_network = &pmlmepriv->cur_network;
998 DBG_8723A("%s\n", __func__);
1000 RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_,
1001 ("\nfw_state:%x, BSSID:"MAC_FMT"\n", get_fwstate(pmlmepriv),
1002 MAC_ARG(pnetwork->network.MacAddress)));
1004 /* why not use ptarget_wlan?? */
1005 memcpy(&cur_network->network, &pnetwork->network,
1006 pnetwork->network.Length);
1007 /* some IEs in pnetwork is wrong, so we should use ptarget_wlan IEs */
1008 cur_network->network.IELength = ptarget_wlan->network.IELength;
1009 memcpy(&cur_network->network.IEs[0], &ptarget_wlan->network.IEs[0],
1012 cur_network->network.capability = ptarget_wlan->network.capability;
1013 cur_network->network.beacon_interval =
1014 ptarget_wlan->network.beacon_interval;
1015 cur_network->network.tsf = ptarget_wlan->network.tsf;
1017 rtw_set_signal_stat_timer(&padapter->recvpriv);
1018 padapter->recvpriv.signal_strength =
1019 ptarget_wlan->network.SignalStrength;
1020 padapter->recvpriv.signal_qual = ptarget_wlan->network.SignalQuality;
1022 * the ptarget_wlan->network.Rssi is raw data, we use
1023 * ptarget_wlan->network.SignalStrength instead (has scaled)
1025 DBG_8723A("%s signal_strength:%3u, signal_qual:%3u\n",
1026 __func__, padapter->recvpriv.signal_strength,
1027 padapter->recvpriv.signal_qual);
1028 rtw_set_signal_stat_timer(&padapter->recvpriv);
1030 /* update fw_state will clr _FW_UNDER_LINKING here indirectly */
1031 switch (pnetwork->network.ifmode) {
1032 case NL80211_IFTYPE_P2P_CLIENT:
1033 case NL80211_IFTYPE_STATION:
1034 if (pmlmepriv->fw_state & WIFI_UNDER_WPS)
1035 pmlmepriv->fw_state = WIFI_STATION_STATE|WIFI_UNDER_WPS;
1037 pmlmepriv->fw_state = WIFI_STATION_STATE;
1039 case NL80211_IFTYPE_ADHOC:
1040 pmlmepriv->fw_state = WIFI_ADHOC_STATE;
1043 pmlmepriv->fw_state = WIFI_NULL_STATE;
1044 RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_,
1045 ("Invalid network_mode\n"));
1049 rtw_update_protection23a(padapter, cur_network->network.IEs,
1050 cur_network->network.IELength);
1052 rtw_update_ht_cap23a(padapter, cur_network->network.IEs,
1053 cur_network->network.IELength);
1058 * the function could be > passive_level (the same context as Rx tasklet)
1059 * pnetwork : returns from rtw23a_joinbss_event_cb
1060 * ptarget_wlan: found from scanned_queue
1061 * if join_res > 0, for (fw_state==WIFI_STATION_STATE),
1062 * we check if "ptarget_sta" & "ptarget_wlan" exist.
1063 * if join_res > 0, for (fw_state==WIFI_ADHOC_STATE),
1064 * we only check if "ptarget_wlan" exist.
1065 * if join_res > 0, update "cur_network->network" from "pnetwork->network"
1066 * if (ptarget_wlan !=NULL).
1069 void rtw_joinbss_event_prehandle23a(struct rtw_adapter *adapter, u8 *pbuf)
1071 struct sta_info *ptarget_sta, *pcur_sta;
1072 struct sta_priv *pstapriv = &adapter->stapriv;
1073 struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
1074 struct wlan_network *pnetwork = (struct wlan_network *)pbuf;
1075 struct wlan_network *cur_network = &pmlmepriv->cur_network;
1076 struct wlan_network *pcur_wlan, *ptarget_wlan = NULL;
1077 bool the_same_macaddr;
1079 RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_,
1080 ("joinbss event call back received with res=%d\n",
1081 pnetwork->join_res));
1083 if (pmlmepriv->assoc_ssid.ssid_len == 0) {
1084 RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_,
1085 ("@@@@@ joinbss event call back for Any SSid\n"));
1087 RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_,
1088 ("@@@@@ rtw23a_joinbss_event_cb for SSid:%s\n",
1089 pmlmepriv->assoc_ssid.ssid));
1092 if (ether_addr_equal(pnetwork->network.MacAddress,
1093 cur_network->network.MacAddress))
1094 the_same_macaddr = true;
1096 the_same_macaddr = false;
1098 pnetwork->network.Length = get_wlan_bssid_ex_sz(&pnetwork->network);
1099 if (pnetwork->network.Length > sizeof(struct wlan_bssid_ex)) {
1100 RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_,
1101 ("\n\n ***joinbss_evt_callback return a wrong bss "
1106 spin_lock_bh(&pmlmepriv->lock);
1108 RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_,
1109 ("\n rtw23a_joinbss_event_cb !! _enter_critical\n"));
1111 if (pnetwork->join_res > 0) {
1112 spin_lock_bh(&pmlmepriv->scanned_queue.lock);
1113 if (check_fwstate(pmlmepriv, _FW_UNDER_LINKING)) {
1114 /* s1. find ptarget_wlan */
1115 if (check_fwstate(pmlmepriv, _FW_LINKED)) {
1116 if (the_same_macaddr) {
1117 ptarget_wlan = rtw_find_network23a(&pmlmepriv->scanned_queue, cur_network->network.MacAddress);
1119 pcur_wlan = rtw_find_network23a(&pmlmepriv->scanned_queue, cur_network->network.MacAddress);
1121 pcur_wlan->fixed = false;
1123 pcur_sta = rtw_get_stainfo23a(pstapriv, cur_network->network.MacAddress);
1125 spin_lock_bh(&pstapriv->sta_hash_lock);
1126 rtw_free_stainfo23a(adapter,
1128 spin_unlock_bh(&pstapriv->sta_hash_lock);
1131 ptarget_wlan = rtw_find_network23a(&pmlmepriv->scanned_queue, pnetwork->network.MacAddress);
1132 if (check_fwstate(pmlmepriv,
1133 WIFI_STATION_STATE)) {
1135 ptarget_wlan->fixed =
1141 ptarget_wlan = rtw_find_network23a(
1142 &pmlmepriv->scanned_queue,
1143 pnetwork->network.MacAddress);
1144 if (check_fwstate(pmlmepriv,
1145 WIFI_STATION_STATE)) {
1147 ptarget_wlan->fixed = true;
1151 /* s2. update cur_network */
1153 rtw_joinbss_update_network23a(adapter,
1157 RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_,
1158 ("Can't find ptarget_wlan when "
1159 "joinbss_event callback\n"));
1160 spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
1161 goto ignore_joinbss_callback;
1164 /* s3. find ptarget_sta & update ptarget_sta after
1165 update cur_network only for station mode */
1166 if (check_fwstate(pmlmepriv, WIFI_STATION_STATE)) {
1167 ptarget_sta = rtw_joinbss_update_stainfo(
1170 RT_TRACE(_module_rtl871x_mlme_c_,
1172 ("Can't update stainfo when "
1173 "joinbss_event callback\n"));
1174 spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
1175 goto ignore_joinbss_callback;
1179 /* s4. indicate connect */
1180 if (check_fwstate(pmlmepriv, WIFI_STATION_STATE))
1181 rtw_indicate_connect23a(adapter);
1183 /* adhoc mode will rtw_indicate_connect23a
1184 when rtw_stassoc_event_callback23a */
1185 RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_,
1186 ("adhoc mode, fw_state:%x",
1187 get_fwstate(pmlmepriv)));
1190 /* s5. Cancle assoc_timer */
1191 del_timer_sync(&pmlmepriv->assoc_timer);
1193 RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_,
1194 ("Cancle assoc_timer\n"));
1196 RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_,
1197 ("rtw23a_joinbss_event_cb err: fw_state:%x",
1198 get_fwstate(pmlmepriv)));
1199 spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
1200 goto ignore_joinbss_callback;
1202 spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
1203 } else if (pnetwork->join_res == -4) {
1204 rtw_reset_securitypriv23a(adapter);
1205 mod_timer(&pmlmepriv->assoc_timer,
1206 jiffies + msecs_to_jiffies(1));
1208 /* rtw_free_assoc_resources23a(adapter, 1); */
1210 if (check_fwstate(pmlmepriv, _FW_UNDER_LINKING)) {
1211 RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_,
1212 ("fail! clear _FW_UNDER_LINKING ^^^fw_state="
1213 "%x\n", get_fwstate(pmlmepriv)));
1214 _clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING);
1217 /* if join_res < 0 (join fails), then try again */
1218 mod_timer(&pmlmepriv->assoc_timer,
1219 jiffies + msecs_to_jiffies(1));
1220 _clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING);
1223 ignore_joinbss_callback:
1225 spin_unlock_bh(&pmlmepriv->lock);
1228 void rtw23a_joinbss_event_cb(struct rtw_adapter *adapter, const u8 *pbuf)
1230 struct wlan_network *pnetwork = (struct wlan_network *)pbuf;
1232 mlmeext_joinbss_event_callback23a(adapter, pnetwork->join_res);
1234 rtw_os_xmit_schedule23a(adapter);
1237 void rtw_stassoc_event_callback23a(struct rtw_adapter *adapter, const u8 *pbuf)
1239 struct sta_info *psta;
1240 struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
1241 struct stassoc_event *pstassoc = (struct stassoc_event *)pbuf;
1242 struct wlan_network *cur_network = &pmlmepriv->cur_network;
1243 struct wlan_network *ptarget_wlan;
1245 if (rtw_access_ctrl23a(adapter, pstassoc->macaddr) == false)
1248 #ifdef CONFIG_8723AU_AP_MODE
1249 if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) {
1250 psta = rtw_get_stainfo23a(&adapter->stapriv, pstassoc->macaddr);
1252 /* bss_cap_update_on_sta_join23a(adapter, psta); */
1253 /* sta_info_update23a(adapter, psta); */
1254 ap_sta_info_defer_update23a(adapter, psta);
1259 /* for AD-HOC mode */
1260 psta = rtw_get_stainfo23a(&adapter->stapriv, pstassoc->macaddr);
1262 /* the sta have been in sta_info_queue => do nothing */
1263 RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_,
1264 ("Error: rtw_stassoc_event_callback23a: sta has "
1265 "been in sta_hash_queue\n"));
1266 /* between drv has received this event before and
1267 fw have not yet to set key to CAM_ENTRY) */
1271 psta = rtw_alloc_stainfo23a(&adapter->stapriv, pstassoc->macaddr,
1274 RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_,
1275 ("Can't alloc sta_info when "
1276 "rtw_stassoc_event_callback23a\n"));
1280 /* to do : init sta_info variable */
1281 psta->qos_option = 0;
1282 psta->mac_id = (uint)pstassoc->cam_id;
1283 /* psta->aid = (uint)pstassoc->cam_id; */
1284 DBG_8723A("%s\n", __func__);
1285 /* for ad-hoc mode */
1286 rtl8723a_SetHalODMVar(adapter, HAL_ODM_STA_INFO, psta, true);
1288 if (adapter->securitypriv.dot11AuthAlgrthm == dot11AuthAlgrthm_8021X)
1289 psta->dot118021XPrivacy =
1290 adapter->securitypriv.dot11PrivacyAlgrthm;
1292 psta->ieee8021x_blocked = false;
1294 spin_lock_bh(&pmlmepriv->lock);
1296 if (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) ||
1297 check_fwstate(pmlmepriv, WIFI_ADHOC_STATE)) {
1298 if (adapter->stapriv.asoc_sta_count == 2) {
1299 spin_lock_bh(&pmlmepriv->scanned_queue.lock);
1301 rtw_find_network23a(&pmlmepriv->scanned_queue,
1302 cur_network->network.MacAddress);
1304 ptarget_wlan->fixed = true;
1305 spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
1306 /* a sta + bc/mc_stainfo (not Ibss_stainfo) */
1307 rtw_indicate_connect23a(adapter);
1311 spin_unlock_bh(&pmlmepriv->lock);
1313 mlmeext_sta_add_event_callback23a(adapter, psta);
1316 void rtw_stadel_event_callback23a(struct rtw_adapter *adapter, const u8 *pbuf)
1319 struct sta_info *psta;
1320 struct wlan_network *pwlan;
1321 struct wlan_bssid_ex *pdev_network;
1322 struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
1323 struct stadel_event *pstadel = (struct stadel_event *)pbuf;
1324 struct sta_priv *pstapriv = &adapter->stapriv;
1325 struct wlan_network *tgt_network = &pmlmepriv->cur_network;
1327 psta = rtw_get_stainfo23a(&adapter->stapriv, pstadel->macaddr);
1329 mac_id = psta->mac_id;
1331 mac_id = pstadel->mac_id;
1333 DBG_8723A("%s(mac_id=%d)=" MAC_FMT "\n", __func__, mac_id,
1334 MAC_ARG(pstadel->macaddr));
1336 if (check_fwstate(pmlmepriv, WIFI_AP_STATE))
1339 mlmeext_sta_del_event_callback23a(adapter);
1341 spin_lock_bh(&pmlmepriv->lock);
1343 if (check_fwstate(pmlmepriv, WIFI_STATION_STATE)) {
1344 if (adapter->mlmepriv.to_roaming > 0) {
1345 /* this stadel_event is caused by roaming,
1346 decrease to_roaming */
1347 pmlmepriv->to_roaming--;
1348 } else if (adapter->mlmepriv.to_roaming == 0)
1349 rtw_set_roaming(adapter, adapter->registrypriv.max_roaming_times);
1350 if (*((u16 *)pstadel->rsvd) != WLAN_REASON_EXPIRATION_CHK)
1351 rtw_set_roaming(adapter, 0); /* don't roam */
1353 rtw_free_uc_swdec_pending_queue23a(adapter);
1355 rtw_free_assoc_resources23a(adapter, 1);
1356 rtw_indicate_disconnect23a(adapter);
1357 spin_lock_bh(&pmlmepriv->scanned_queue.lock);
1358 /* remove the network entry in scanned_queue */
1359 pwlan = rtw_find_network23a(&pmlmepriv->scanned_queue,
1360 tgt_network->network.MacAddress);
1362 pwlan->fixed = false;
1363 rtw_free_network_nolock(pmlmepriv, pwlan);
1365 spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
1367 _rtw_roaming(adapter, tgt_network);
1370 if (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) ||
1371 check_fwstate(pmlmepriv, WIFI_ADHOC_STATE)) {
1373 spin_lock_bh(&pstapriv->sta_hash_lock);
1374 rtw_free_stainfo23a(adapter, psta);
1375 spin_unlock_bh(&pstapriv->sta_hash_lock);
1377 /* a sta + bc/mc_stainfo (not Ibss_stainfo) */
1378 if (adapter->stapriv.asoc_sta_count == 1) {
1379 spin_lock_bh(&pmlmepriv->scanned_queue.lock);
1380 /* free old ibss network */
1381 /* pwlan = rtw_find_network23a(
1382 &pmlmepriv->scanned_queue, pstadel->macaddr); */
1383 pwlan = rtw_find_network23a(&pmlmepriv->scanned_queue,
1384 tgt_network->network.MacAddress);
1386 pwlan->fixed = false;
1387 rtw_free_network_nolock(pmlmepriv, pwlan);
1389 spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
1390 /* re-create ibss */
1391 pdev_network = &adapter->registrypriv.dev_network;
1393 memcpy(pdev_network, &tgt_network->network,
1394 get_wlan_bssid_ex_sz(&tgt_network->network));
1396 rtw_do_join_adhoc(adapter);
1400 spin_unlock_bh(&pmlmepriv->lock);
1404 * rtw23a_join_to_handler - Timeout/failure handler for CMD JoinBss
1405 * @adapter: pointer to _adapter structure
1407 void rtw23a_join_to_handler (unsigned long data)
1409 struct rtw_adapter *adapter = (struct rtw_adapter *)data;
1410 struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
1413 DBG_8723A("%s, fw_state=%x\n", __func__, get_fwstate(pmlmepriv));
1415 if (adapter->bDriverStopped || adapter->bSurpriseRemoved)
1418 spin_lock_bh(&pmlmepriv->lock);
1420 if (adapter->mlmepriv.to_roaming > 0) {
1421 /* join timeout caused by roaming */
1423 pmlmepriv->to_roaming--;
1424 if (adapter->mlmepriv.to_roaming != 0) {
1426 DBG_8723A("%s try another roaming\n", __func__);
1427 do_join_r = rtw_do_join(adapter);
1428 if (do_join_r != _SUCCESS) {
1429 DBG_8723A("%s roaming do_join return "
1430 "%d\n", __func__ , do_join_r);
1435 DBG_8723A("%s We've try roaming but fail\n",
1437 rtw_indicate_disconnect23a(adapter);
1442 rtw_indicate_disconnect23a(adapter);
1443 free_scanqueue(pmlmepriv);/* */
1445 /* indicate disconnect for the case that join_timeout and
1446 check_fwstate != FW_LINKED */
1447 rtw_cfg80211_indicate_disconnect(adapter);
1450 spin_unlock_bh(&pmlmepriv->lock);
1455 * rtw_scan_timeout_handler23a - Timeout/Failure handler for CMD SiteSurvey
1456 * @data: pointer to _adapter structure
1458 void rtw_scan_timeout_handler23a(unsigned long data)
1460 struct rtw_adapter *adapter = (struct rtw_adapter *)data;
1461 struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
1463 DBG_8723A("%s(%s): fw_state =%x\n", __func__, adapter->pnetdev->name,
1464 get_fwstate(pmlmepriv));
1466 spin_lock_bh(&pmlmepriv->lock);
1468 _clr_fwstate_(pmlmepriv, _FW_UNDER_SURVEY);
1470 spin_unlock_bh(&pmlmepriv->lock);
1472 rtw_cfg80211_indicate_scan_done(wdev_to_priv(adapter->rtw_wdev), true);
1475 void rtw_dynamic_check_timer_handler(unsigned long data)
1477 struct rtw_adapter *adapter = (struct rtw_adapter *)data;
1479 if (adapter->hw_init_completed == false)
1482 if (adapter->bDriverStopped == true ||
1483 adapter->bSurpriseRemoved == true)
1486 if (adapter->net_closed == true)
1489 rtw_dynamic_chk_wk_cmd23a(adapter);
1492 mod_timer(&adapter->mlmepriv.dynamic_chk_timer,
1493 jiffies + msecs_to_jiffies(2000));
1496 inline bool rtw_is_scan_deny(struct rtw_adapter *adapter)
1498 struct mlme_priv *mlmepriv = &adapter->mlmepriv;
1500 return (atomic_read(&mlmepriv->set_scan_deny) != 0) ? true : false;
1503 void rtw_clear_scan_deny(struct rtw_adapter *adapter)
1505 struct mlme_priv *mlmepriv = &adapter->mlmepriv;
1507 atomic_set(&mlmepriv->set_scan_deny, 0);
1510 void rtw_set_scan_deny_timer_hdl(unsigned long data)
1512 struct rtw_adapter *adapter = (struct rtw_adapter *)data;
1514 rtw_clear_scan_deny(adapter);
1517 void rtw_set_scan_deny(struct rtw_adapter *adapter, u32 ms)
1519 struct mlme_priv *mlmepriv = &adapter->mlmepriv;
1521 atomic_set(&mlmepriv->set_scan_deny, 1);
1522 mod_timer(&mlmepriv->set_scan_deny_timer,
1523 jiffies + msecs_to_jiffies(ms));
1526 #if defined(IEEE80211_SCAN_RESULT_EXPIRE)
1527 #define RTW_SCAN_RESULT_EXPIRE \
1528 ((IEEE80211_SCAN_RESULT_EXPIRE / (HZ*1000)) - 1000) /* 3000 -1000 */
1530 #define RTW_SCAN_RESULT_EXPIRE 2000
1534 * Select a new join candidate from the original @param candidate and
1536 * @return true: candidate is updated
1537 * @return false: candidate is not updated
1539 static int rtw_check_join_candidate(struct mlme_priv *pmlmepriv,
1540 struct wlan_network **candidate,
1541 struct wlan_network *competitor)
1543 int updated = false;
1544 struct rtw_adapter *adapter;
1546 adapter = container_of(pmlmepriv, struct rtw_adapter, mlmepriv);
1548 /* check bssid, if needed */
1549 if (pmlmepriv->assoc_by_bssid == true) {
1550 if (!ether_addr_equal(competitor->network.MacAddress,
1551 pmlmepriv->assoc_bssid))
1555 /* check ssid, if needed */
1556 if (pmlmepriv->assoc_ssid.ssid_len) {
1557 if (competitor->network.Ssid.ssid_len !=
1558 pmlmepriv->assoc_ssid.ssid_len ||
1559 memcmp(competitor->network.Ssid.ssid,
1560 pmlmepriv->assoc_ssid.ssid,
1561 pmlmepriv->assoc_ssid.ssid_len))
1565 if (rtw_is_desired_network(adapter, competitor) == false)
1568 if (adapter->mlmepriv.to_roaming > 0) {
1569 unsigned int passed;
1571 passed = jiffies_to_msecs(jiffies - competitor->last_scanned);
1572 if (passed >= RTW_SCAN_RESULT_EXPIRE ||
1573 is_same_ess(&competitor->network,
1574 &pmlmepriv->cur_network.network) == false)
1579 (*candidate)->network.Rssi<competitor->network.Rssi) {
1580 *candidate = competitor;
1585 DBG_8723A("[by_bssid:%u][assoc_ssid:%s][to_roaming:%u] "
1586 "new candidate: %s("MAC_FMT") rssi:%d\n",
1587 pmlmepriv->assoc_by_bssid,
1588 pmlmepriv->assoc_ssid.ssid,
1589 adapter->mlmepriv.to_roaming,
1590 (*candidate)->network.Ssid.ssid,
1591 MAC_ARG((*candidate)->network.MacAddress),
1592 (int)(*candidate)->network.Rssi);
1601 The caller of the sub-routine will be in critical section...
1603 The caller must hold the following spinlock
1609 static int rtw_do_join(struct rtw_adapter *padapter)
1611 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1614 pmlmepriv->cur_network.join_res = -2;
1616 set_fwstate(pmlmepriv, _FW_UNDER_LINKING);
1618 pmlmepriv->to_join = true;
1620 ret = rtw_select_and_join_from_scanned_queue23a(pmlmepriv);
1621 if (ret == _SUCCESS) {
1622 pmlmepriv->to_join = false;
1624 if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE)) {
1625 /* switch to ADHOC_MASTER */
1626 ret = rtw_do_join_adhoc(padapter);
1627 if (ret != _SUCCESS)
1630 /* can't associate ; reset under-linking */
1631 _clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING);
1634 pmlmepriv->to_join = false;
1642 static struct wlan_network *
1643 rtw_select_candidate_from_queue(struct mlme_priv *pmlmepriv)
1645 struct wlan_network *pnetwork, *candidate = NULL;
1646 struct rtw_queue *queue = &pmlmepriv->scanned_queue;
1647 struct list_head *phead, *plist, *ptmp;
1649 spin_lock_bh(&pmlmepriv->scanned_queue.lock);
1650 phead = get_list_head(queue);
1652 list_for_each_safe(plist, ptmp, phead) {
1653 pnetwork = container_of(plist, struct wlan_network, list);
1655 RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_,
1656 ("%s: return _FAIL:(pnetwork == NULL)\n",
1661 rtw_check_join_candidate(pmlmepriv, &candidate, pnetwork);
1665 spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
1670 int rtw_do_join_adhoc(struct rtw_adapter *adapter)
1672 struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
1673 struct wlan_bssid_ex *pdev_network;
1677 pdev_network = &adapter->registrypriv.dev_network;
1678 ibss = adapter->registrypriv.dev_network.MacAddress;
1680 _clr_fwstate_(pmlmepriv, _FW_UNDER_SURVEY);
1682 RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_,
1683 ("switching to adhoc master\n"));
1685 memcpy(&pdev_network->Ssid, &pmlmepriv->assoc_ssid,
1686 sizeof(struct cfg80211_ssid));
1688 rtw_update_registrypriv_dev_network23a(adapter);
1689 rtw_generate_random_ibss23a(ibss);
1691 pmlmepriv->fw_state = WIFI_ADHOC_MASTER_STATE;
1693 ret = rtw_createbss_cmd23a(adapter);
1694 if (ret != _SUCCESS) {
1695 RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_,
1696 ("Error =>rtw_createbss_cmd23a status FAIL\n"));
1698 pmlmepriv->to_join = false;
1704 int rtw_do_join_network(struct rtw_adapter *adapter,
1705 struct wlan_network *candidate)
1709 /* check for situation of _FW_LINKED */
1710 if (check_fwstate(&adapter->mlmepriv, _FW_LINKED)) {
1711 DBG_8723A("%s: _FW_LINKED while ask_for_joinbss!\n", __func__);
1713 rtw_disassoc_cmd23a(adapter, 0, true);
1714 rtw_indicate_disconnect23a(adapter);
1715 rtw_free_assoc_resources23a(adapter, 0);
1717 set_fwstate(&adapter->mlmepriv, _FW_UNDER_LINKING);
1719 ret = rtw_joinbss_cmd23a(adapter, candidate);
1721 if (ret == _SUCCESS)
1722 mod_timer(&adapter->mlmepriv.assoc_timer,
1723 jiffies + msecs_to_jiffies(MAX_JOIN_TIMEOUT));
1728 int rtw_select_and_join_from_scanned_queue23a(struct mlme_priv *pmlmepriv)
1730 struct rtw_adapter *adapter;
1731 struct wlan_network *candidate = NULL;
1734 adapter = pmlmepriv->nic_hdl;
1736 candidate = rtw_select_candidate_from_queue(pmlmepriv);
1738 DBG_8723A("%s: return _FAIL(candidate == NULL)\n", __func__);
1742 DBG_8723A("%s: candidate: %s("MAC_FMT", ch:%u)\n", __func__,
1743 candidate->network.Ssid.ssid,
1744 MAC_ARG(candidate->network.MacAddress),
1745 candidate->network.DSConfig);
1748 ret = rtw_do_join_network(adapter, candidate);
1754 int rtw_set_auth23a(struct rtw_adapter *adapter,
1755 struct security_priv *psecuritypriv)
1757 struct cmd_obj *pcmd;
1758 struct setauth_parm *psetauthparm;
1759 struct cmd_priv *pcmdpriv = &adapter->cmdpriv;
1762 pcmd = kzalloc(sizeof(struct cmd_obj), GFP_KERNEL);
1764 res = _FAIL; /* try again */
1768 psetauthparm = kzalloc(sizeof(struct setauth_parm), GFP_KERNEL);
1769 if (!psetauthparm) {
1775 psetauthparm->mode = (unsigned char)psecuritypriv->dot11AuthAlgrthm;
1777 pcmd->cmdcode = _SetAuth_CMD_;
1778 pcmd->parmbuf = (unsigned char *)psetauthparm;
1779 pcmd->cmdsz = (sizeof(struct setauth_parm));
1783 RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_,
1784 ("after enqueue set_auth_cmd, auth_mode=%x\n",
1785 psecuritypriv->dot11AuthAlgrthm));
1787 res = rtw_enqueue_cmd23a(pcmdpriv, pcmd);
1794 int rtw_set_key23a(struct rtw_adapter *adapter,
1795 struct security_priv *psecuritypriv, int keyid, u8 set_tx)
1798 struct cmd_obj *pcmd;
1799 struct setkey_parm *psetkeyparm;
1800 struct cmd_priv *pcmdpriv = &adapter->cmdpriv;
1801 struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
1809 pcmd = kzalloc(sizeof(struct cmd_obj), GFP_KERNEL);
1811 res = _FAIL; /* try again */
1814 psetkeyparm = kzalloc(sizeof(struct setkey_parm), GFP_KERNEL);
1821 if (psecuritypriv->dot11AuthAlgrthm == dot11AuthAlgrthm_8021X) {
1822 psetkeyparm->algorithm = (unsigned char)
1823 psecuritypriv->dot118021XGrpPrivacy;
1824 RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_,
1825 ("\n rtw_set_key23a: psetkeyparm->algorithm = "
1826 "(unsigned char)psecuritypriv->dot118021XGrpPrivacy "
1827 "=%d\n", psetkeyparm->algorithm));
1829 psetkeyparm->algorithm = (u8)psecuritypriv->dot11PrivacyAlgrthm;
1830 RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_,
1831 ("\n rtw_set_key23a: psetkeyparm->algorithm = (u8)"
1832 "psecuritypriv->dot11PrivacyAlgrthm =%d\n",
1833 psetkeyparm->algorithm));
1835 psetkeyparm->keyid = keyid;/* 0~3 */
1836 psetkeyparm->set_tx = set_tx;
1837 if (is_wep_enc(psetkeyparm->algorithm))
1838 pmlmepriv->key_mask |= BIT(psetkeyparm->keyid);
1840 DBG_8723A("==> rtw_set_key23a algorithm(%x), keyid(%x), key_mask(%x)\n",
1841 psetkeyparm->algorithm, psetkeyparm->keyid,
1842 pmlmepriv->key_mask);
1843 RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_,
1844 ("\n rtw_set_key23a: psetkeyparm->algorithm =%d psetkeyparm->"
1845 "keyid = (u8)keyid =%d\n", psetkeyparm->algorithm, keyid));
1847 switch (psetkeyparm->algorithm) {
1848 case WLAN_CIPHER_SUITE_WEP40:
1850 memcpy(&psetkeyparm->key[0],
1851 &psecuritypriv->wep_key[keyid].key, keylen);
1853 case WLAN_CIPHER_SUITE_WEP104:
1855 memcpy(&psetkeyparm->key[0],
1856 &psecuritypriv->wep_key[keyid].key, keylen);
1858 case WLAN_CIPHER_SUITE_TKIP:
1860 memcpy(&psetkeyparm->key,
1861 &psecuritypriv->dot118021XGrpKey[keyid], keylen);
1862 psetkeyparm->grpkey = 1;
1864 case WLAN_CIPHER_SUITE_CCMP:
1866 memcpy(&psetkeyparm->key,
1867 &psecuritypriv->dot118021XGrpKey[keyid], keylen);
1868 psetkeyparm->grpkey = 1;
1871 RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_,
1872 ("\n rtw_set_key23a:psecuritypriv->dot11PrivacyAlgrthm"
1873 " = %x (must be 1 or 2 or 4 or 5)\n",
1874 psecuritypriv->dot11PrivacyAlgrthm));
1881 pcmd->cmdcode = _SetKey_CMD_;
1882 pcmd->parmbuf = (u8 *)psetkeyparm;
1883 pcmd->cmdsz = (sizeof(struct setkey_parm));
1887 /* sema_init(&pcmd->cmd_sem, 0); */
1889 res = rtw_enqueue_cmd23a(pcmdpriv, pcmd);
1896 /* adjust IEs for rtw_joinbss_cmd23a in WMM */
1897 int rtw_restruct_wmm_ie23a(struct rtw_adapter *adapter, u8 *in_ie,
1898 u8 *out_ie, uint in_len, uint initial_out_len)
1903 ielength = initial_out_len;
1905 p = cfg80211_find_vendor_ie(WLAN_OUI_MICROSOFT,
1906 WLAN_OUI_TYPE_MICROSOFT_WMM,
1910 memcpy(out_ie + initial_out_len, p, 9);
1912 out_ie[initial_out_len + 1] = 7;
1913 out_ie[initial_out_len + 6] = 0;
1914 out_ie[initial_out_len + 8] = 0;
1923 /* Ported from 8185: IsInPreAuthKeyList().
1924 (Renamed from SecIsInPreAuthKeyList(), 2006-10-13.) */
1925 /* Added by Annie, 2006-05-07. */
1927 /* Search by BSSID, */
1929 /* -1 :if there is no pre-auth key in the table */
1930 /* >= 0 :if there is pre-auth key, and return the entry id */
1934 static int SecIsInPMKIDList(struct rtw_adapter *Adapter, u8 *bssid)
1936 struct security_priv *psecuritypriv = &Adapter->securitypriv;
1940 if (psecuritypriv->PMKIDList[i].bUsed &&
1941 ether_addr_equal(psecuritypriv->PMKIDList[i].Bssid, bssid)) {
1947 } while (i < NUM_PMKID_CACHE);
1949 if (i == NUM_PMKID_CACHE)
1950 i = -1;/* Could not find. */
1952 /* There is one Pre-Authentication Key for
1953 the specific BSSID. */
1960 /* Check the RSN IE length */
1961 /* If the RSN IE length <= 20, the RSN IE didn't include
1962 the PMKID information */
1963 /* 0-11th element in the array are the fixed IE */
1964 /* 12th element in the array is the IE */
1965 /* 13th element in the array is the IE length */
1968 static int rtw_append_pmkid(struct rtw_adapter *Adapter, int iEntry,
1969 u8 *ie, uint ie_len)
1971 struct security_priv *psecuritypriv = &Adapter->securitypriv;
1974 /* The RSN IE didn't include the PMK ID,
1975 append the PMK information */
1978 ie[ie_len] = 0; /* PMKID count = 0x0100 */
1981 &psecuritypriv->PMKIDList[iEntry].PMKID, 16);
1984 ie[1] += 18;/* PMKID length = 2+16 */
1989 int rtw_restruct_sec_ie23a(struct rtw_adapter *adapter, u8 *in_ie, u8 *out_ie,
1995 struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
1996 struct security_priv *psecuritypriv = &adapter->securitypriv;
1997 uint ndisauthmode = psecuritypriv->ndisauthtype;
1998 uint ndissecuritytype = psecuritypriv->ndisencryptstatus;
2000 RT_TRACE(_module_rtl871x_mlme_c_, _drv_notice_,
2001 ("+rtw_restruct_sec_ie23a: ndisauthmode=%d "
2002 "ndissecuritytype=%d\n", ndisauthmode, ndissecuritytype));
2005 if (ndisauthmode == Ndis802_11AuthModeWPA ||
2006 ndisauthmode == Ndis802_11AuthModeWPAPSK)
2007 authmode = WLAN_EID_VENDOR_SPECIFIC;
2008 if (ndisauthmode == Ndis802_11AuthModeWPA2 ||
2009 ndisauthmode == Ndis802_11AuthModeWPA2PSK)
2010 authmode = WLAN_EID_RSN;
2012 if (check_fwstate(pmlmepriv, WIFI_UNDER_WPS)) {
2013 memcpy(out_ie + ielength, psecuritypriv->wps_ie,
2014 psecuritypriv->wps_ie_len);
2016 ielength += psecuritypriv->wps_ie_len;
2017 } else if (authmode == WLAN_EID_VENDOR_SPECIFIC ||
2018 authmode == WLAN_EID_RSN) {
2019 /* copy RSN or SSN */
2020 memcpy(&out_ie[ielength], &psecuritypriv->supplicant_ie[0],
2021 psecuritypriv->supplicant_ie[1] + 2);
2022 ielength += psecuritypriv->supplicant_ie[1] + 2;
2025 iEntry = SecIsInPMKIDList(adapter, pmlmepriv->assoc_bssid);
2029 if (authmode == WLAN_EID_RSN)
2030 ielength = rtw_append_pmkid(adapter, iEntry,
2037 void rtw_init_registrypriv_dev_network23a(struct rtw_adapter *adapter)
2039 struct registry_priv *pregistrypriv = &adapter->registrypriv;
2040 struct eeprom_priv *peepriv = &adapter->eeprompriv;
2041 struct wlan_bssid_ex *pdev_network = &pregistrypriv->dev_network;
2042 u8 *myhwaddr = myid(peepriv);
2044 ether_addr_copy(pdev_network->MacAddress, myhwaddr);
2046 memcpy(&pdev_network->Ssid, &pregistrypriv->ssid,
2047 sizeof(struct cfg80211_ssid));
2049 pdev_network->beacon_interval = 100;
2052 void rtw_update_registrypriv_dev_network23a(struct rtw_adapter *adapter)
2055 struct registry_priv *pregistrypriv = &adapter->registrypriv;
2056 struct wlan_bssid_ex *pdev_network = &pregistrypriv->dev_network;
2057 struct security_priv *psecuritypriv = &adapter->securitypriv;
2058 struct wlan_network *cur_network = &adapter->mlmepriv.cur_network;
2059 /* struct xmit_priv *pxmitpriv = &adapter->xmitpriv; */
2061 pdev_network->Privacy =
2062 (psecuritypriv->dot11PrivacyAlgrthm > 0 ? 1 : 0);
2064 pdev_network->Rssi = 0;
2066 pdev_network->DSConfig = pregistrypriv->channel;
2067 RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_,
2068 ("pregistrypriv->channel =%d, pdev_network->DSConfig = 0x%x\n",
2069 pregistrypriv->channel, pdev_network->DSConfig));
2071 if (cur_network->network.ifmode == NL80211_IFTYPE_ADHOC)
2072 pdev_network->ATIMWindow = 0;
2074 pdev_network->ifmode = cur_network->network.ifmode;
2076 /* 1. Supported rates */
2079 sz = rtw_generate_ie23a(pregistrypriv);
2081 pdev_network->IELength = sz;
2083 pdev_network->Length =
2084 get_wlan_bssid_ex_sz(pdev_network);
2086 /* notes: translate IELength & Length after assign the
2087 Length to cmdsz in createbss_cmd(); */
2088 /* pdev_network->IELength = cpu_to_le32(sz); */
2091 /* the function is at passive_level */
2092 void rtw_joinbss_reset23a(struct rtw_adapter *padapter)
2095 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
2096 struct ht_priv *phtpriv = &pmlmepriv->htpriv;
2098 /* todo: if you want to do something io/reg/hw setting
2099 before join_bss, please add code here */
2101 pmlmepriv->num_FortyMHzIntolerant = 0;
2103 pmlmepriv->num_sta_no_ht = 0;
2105 phtpriv->ampdu_enable = false;/* reset to disabled */
2107 /* TH = 1 => means that invalidate usb rx aggregation */
2108 /* TH = 0 => means that validate usb rx aggregation, use init value. */
2109 if (phtpriv->ht_option) {
2110 if (padapter->registrypriv.wifi_spec == 1)
2117 rtl8723a_set_rxdma_agg_pg_th(padapter, threshold);
2120 /* the function is >= passive_level */
2121 bool rtw_restructure_ht_ie23a(struct rtw_adapter *padapter, u8 *in_ie,
2122 u8 *out_ie, uint in_len, uint *pout_len)
2125 int max_rx_ampdu_factor;
2126 unsigned char *pframe;
2128 struct ieee80211_ht_cap ht_capie;
2129 u8 WMM_IE[7] = {0x00, 0x50, 0xf2, 0x02, 0x00, 0x01, 0x00};
2130 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
2131 struct ht_priv *phtpriv = &pmlmepriv->htpriv;
2133 phtpriv->ht_option = false;
2135 p = cfg80211_find_ie(WLAN_EID_HT_CAPABILITY, in_ie, in_len);
2137 if (p && p[1] > 0) {
2138 u32 rx_packet_offset, max_recvbuf_sz;
2140 if (pmlmepriv->qos_option == 0) {
2141 out_len = *pout_len;
2142 pframe = rtw_set_ie23a(out_ie + out_len,
2143 WLAN_EID_VENDOR_SPECIFIC,
2144 sizeof(WMM_IE), WMM_IE,
2147 pmlmepriv->qos_option = 1;
2150 out_len = *pout_len;
2152 memset(&ht_capie, 0, sizeof(struct ieee80211_ht_cap));
2154 ht_capie.cap_info = cpu_to_le16(IEEE80211_HT_CAP_SUP_WIDTH_20_40 |
2155 IEEE80211_HT_CAP_SGI_20 | IEEE80211_HT_CAP_SGI_40 |
2156 IEEE80211_HT_CAP_TX_STBC | IEEE80211_HT_CAP_DSSSCCK40);
2158 GetHalDefVar8192CUsb(padapter, HAL_DEF_RX_PACKET_OFFSET,
2160 GetHalDefVar8192CUsb(padapter, HAL_DEF_MAX_RECVBUF_SZ,
2163 GetHalDefVar8192CUsb(padapter, HW_VAR_MAX_RX_AMPDU_FACTOR,
2164 &max_rx_ampdu_factor);
2165 ht_capie.ampdu_params_info = max_rx_ampdu_factor & 0x03;
2167 if (padapter->securitypriv.dot11PrivacyAlgrthm ==
2168 WLAN_CIPHER_SUITE_CCMP)
2169 ht_capie.ampdu_params_info |=
2170 (IEEE80211_HT_AMPDU_PARM_DENSITY& (0x07 << 2));
2172 ht_capie.ampdu_params_info |=
2173 (IEEE80211_HT_AMPDU_PARM_DENSITY & 0x00);
2175 pframe = rtw_set_ie23a(out_ie + out_len, WLAN_EID_HT_CAPABILITY,
2176 sizeof(struct ieee80211_ht_cap),
2177 (unsigned char *)&ht_capie, pout_len);
2179 phtpriv->ht_option = true;
2181 p = cfg80211_find_ie(WLAN_EID_HT_OPERATION, in_ie, in_len);
2182 if (p && (p[1] == sizeof(struct ieee80211_ht_operation))) {
2183 out_len = *pout_len;
2184 pframe = rtw_set_ie23a(out_ie + out_len,
2185 WLAN_EID_HT_OPERATION,
2186 p[1], p + 2 , pout_len);
2190 return phtpriv->ht_option;
2193 /* the function is > passive_level (in critical_section) */
2194 void rtw_update_ht_cap23a(struct rtw_adapter *padapter, u8 *pie, uint ie_len)
2198 struct ieee80211_ht_cap *pht_capie;
2199 struct ieee80211_ht_operation *pht_addtinfo;
2200 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
2201 struct ht_priv *phtpriv = &pmlmepriv->htpriv;
2202 struct registry_priv *pregistrypriv = &padapter->registrypriv;
2203 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
2204 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
2206 if (!phtpriv->ht_option)
2209 if ((!pmlmeinfo->HT_info_enable) || (!pmlmeinfo->HT_caps_enable))
2212 DBG_8723A("+rtw_update_ht_cap23a()\n");
2214 /* maybe needs check if ap supports rx ampdu. */
2215 if (!phtpriv->ampdu_enable && pregistrypriv->ampdu_enable == 1) {
2216 if (pregistrypriv->wifi_spec == 1)
2217 phtpriv->ampdu_enable = false;
2219 phtpriv->ampdu_enable = true;
2220 } else if (pregistrypriv->ampdu_enable == 2)
2221 phtpriv->ampdu_enable = true;
2223 /* check Max Rx A-MPDU Size */
2224 p = cfg80211_find_ie(WLAN_EID_HT_CAPABILITY, pie, ie_len);
2226 if (p && p[1] > 0) {
2227 pht_capie = (struct ieee80211_ht_cap *)(p + 2);
2228 max_ampdu_sz = pht_capie->ampdu_params_info &
2229 IEEE80211_HT_AMPDU_PARM_FACTOR;
2230 /* max_ampdu_sz (kbytes); */
2231 max_ampdu_sz = 1 << (max_ampdu_sz + 3);
2233 phtpriv->rx_ampdu_maxlen = max_ampdu_sz;
2236 p = cfg80211_find_ie(WLAN_EID_HT_OPERATION, pie, ie_len);
2237 if (p && p[1] > 0) {
2238 pht_addtinfo = (struct ieee80211_ht_operation *)(p + 2);
2242 /* update cur_bwmode & cur_ch_offset */
2243 if (pregistrypriv->cbw40_enable &&
2244 pmlmeinfo->ht_cap.cap_info &
2245 cpu_to_le16(IEEE80211_HT_CAP_SUP_WIDTH_20_40) &&
2246 pmlmeinfo->HT_info.ht_param & IEEE80211_HT_PARAM_CHAN_WIDTH_ANY) {
2250 rf_type = rtl8723a_get_rf_type(padapter);
2252 /* update the MCS rates */
2253 for (i = 0; i < IEEE80211_HT_MCS_MASK_LEN; i++) {
2254 if (rf_type == RF_1T1R || rf_type == RF_1T2R)
2255 pmlmeinfo->ht_cap.mcs.rx_mask[i] &=
2258 pmlmeinfo->ht_cap.mcs.rx_mask[i] &=
2261 /* switch to the 40M Hz mode according to the AP */
2262 pmlmeext->cur_bwmode = HT_CHANNEL_WIDTH_40;
2263 switch (pmlmeinfo->HT_info.ht_param &
2264 IEEE80211_HT_PARAM_CHA_SEC_OFFSET) {
2265 case IEEE80211_HT_PARAM_CHA_SEC_ABOVE:
2266 pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_LOWER;
2269 case IEEE80211_HT_PARAM_CHA_SEC_BELOW:
2270 pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_UPPER;
2274 pmlmeext->cur_ch_offset =
2275 HAL_PRIME_CHNL_OFFSET_DONT_CARE;
2281 /* Config SM Power Save setting */
2284 (le16_to_cpu(pmlmeinfo->ht_cap.cap_info) &
2285 IEEE80211_HT_CAP_SM_PS) >> IEEE80211_HT_CAP_SM_PS_SHIFT;
2286 if (pmlmeinfo->SM_PS == WLAN_HT_CAP_SM_PS_STATIC)
2287 DBG_8723A("%s(): WLAN_HT_CAP_SM_PS_STATIC\n", __func__);
2290 /* Config current HT Protection mode. */
2292 pmlmeinfo->HT_protection =
2293 le16_to_cpu(pmlmeinfo->HT_info.operation_mode) &
2294 IEEE80211_HT_OP_MODE_PROTECTION;
2297 void rtw_issue_addbareq_cmd23a(struct rtw_adapter *padapter,
2298 struct xmit_frame *pxmitframe)
2302 struct sta_info *psta;
2303 struct ht_priv *phtpriv;
2304 struct pkt_attrib *pattrib = &pxmitframe->attrib;
2305 s32 bmcst = is_multicast_ether_addr(pattrib->ra);
2307 if (bmcst || padapter->mlmepriv.LinkDetectInfo.NumTxOkInPeriod < 100)
2310 priority = pattrib->priority;
2313 psta = pattrib->psta;
2315 DBG_8723A("%s, call rtw_get_stainfo23a()\n", __func__);
2316 psta = rtw_get_stainfo23a(&padapter->stapriv, pattrib->ra);
2320 DBG_8723A("%s, psta == NUL\n", __func__);
2324 if (!(psta->state &_FW_LINKED)) {
2325 DBG_8723A("%s, psta->state(0x%x) != _FW_LINKED\n",
2326 __func__, psta->state);
2330 phtpriv = &psta->htpriv;
2332 if (phtpriv->ht_option && phtpriv->ampdu_enable) {
2333 issued = (phtpriv->agg_enable_bitmap>>priority)&0x1;
2334 issued |= (phtpriv->candidate_tid_bitmap>>priority)&0x1;
2337 DBG_8723A("rtw_issue_addbareq_cmd23a, p =%d\n",
2339 psta->htpriv.candidate_tid_bitmap |= BIT(priority);
2340 rtw_addbareq_cmd23a(padapter, (u8) priority,
2346 int rtw_linked_check(struct rtw_adapter *padapter)
2348 if (check_fwstate(&padapter->mlmepriv, WIFI_AP_STATE) ||
2349 check_fwstate(&padapter->mlmepriv,
2350 WIFI_ADHOC_STATE|WIFI_ADHOC_MASTER_STATE)) {
2351 if (padapter->stapriv.asoc_sta_count > 2)
2353 } else { /* Station mode */
2354 if (check_fwstate(&padapter->mlmepriv, _FW_LINKED))