blob: 734972cae87c33b9229c70c483d84284369c07ce [file] [log] [blame]
Larry Finger5e93f352014-03-28 21:37:38 -05001/******************************************************************************
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>
Jes Sorensenb7c19c22014-05-16 10:04:00 +020027#include <rtw_sreset.h>
Larry Finger5e93f352014-03-28 21:37:38 -050028
Jes Sorensen0e634a02014-06-09 15:16:49 +020029static struct wlan_network *
30rtw_select_candidate_from_queue(struct mlme_priv *pmlmepriv);
Jes Sorensene007b4c2014-06-09 15:17:00 +020031static int rtw_do_join(struct rtw_adapter *padapter);
Jes Sorensen0e634a02014-06-09 15:16:49 +020032
Larry Finger5e93f352014-03-28 21:37:38 -050033static void rtw_init_mlme_timer(struct rtw_adapter *padapter)
34{
Jes Sorensen8b3d9cd2014-05-31 18:05:09 +020035 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
Larry Finger5e93f352014-03-28 21:37:38 -050036
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
Jes Sorensena7efff22014-04-26 18:55:46 +020050int rtw_init_mlme_priv23a(struct rtw_adapter *padapter)
Larry Finger5e93f352014-03-28 21:37:38 -050051{
52 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
Larry Finger5e93f352014-03-28 21:37:38 -050053
54 pmlmepriv->nic_hdl = padapter;
55
56 pmlmepriv->fw_state = 0;
Jes Sorensenefc71442014-05-21 09:37:26 +020057 pmlmepriv->cur_network.network.ifmode = NL80211_IFTYPE_UNSPECIFIED;
Jes Sorensen480c8652014-04-15 19:44:45 +020058 /* 1: active, 0: pasive. Maybe someday we should rename this
59 varable to "active_mode" (Jeff) */
60 pmlmepriv->scan_mode = SCAN_ACTIVE;
Larry Finger5e93f352014-03-28 21:37:38 -050061
62 spin_lock_init(&pmlmepriv->lock);
63 _rtw_init_queue23a(&pmlmepriv->scanned_queue);
64
65 memset(&pmlmepriv->assoc_ssid, 0, sizeof(struct cfg80211_ssid));
66
Larry Finger5e93f352014-03-28 21:37:38 -050067 rtw_clear_scan_deny(padapter);
68
69 rtw_init_mlme_timer(padapter);
Roberta Dobrescu038b7032014-10-26 23:30:09 +020070 return _SUCCESS;
Larry Finger5e93f352014-03-28 21:37:38 -050071}
72
Larry Fingerc17416e2014-03-28 21:37:42 -050073#ifdef CONFIG_8723AU_AP_MODE
Larry Finger5e93f352014-03-28 21:37:38 -050074static void rtw_free_mlme_ie_data(u8 **ppie, u32 *plen)
75{
Jes Sorensen480c8652014-04-15 19:44:45 +020076 if (*ppie) {
Larry Finger5e93f352014-03-28 21:37:38 -050077 kfree(*ppie);
78 *plen = 0;
Jes Sorensen480c8652014-04-15 19:44:45 +020079 *ppie = NULL;
Larry Finger5e93f352014-03-28 21:37:38 -050080 }
81}
Larry Fingerc17416e2014-03-28 21:37:42 -050082#endif
Larry Finger5e93f352014-03-28 21:37:38 -050083
84void rtw23a_free_mlme_priv_ie_data(struct mlme_priv *pmlmepriv)
85{
86#ifdef CONFIG_8723AU_AP_MODE
87 kfree(pmlmepriv->assoc_req);
88 kfree(pmlmepriv->assoc_rsp);
Jes Sorensen480c8652014-04-15 19:44:45 +020089 rtw_free_mlme_ie_data(&pmlmepriv->wps_probe_req_ie,
90 &pmlmepriv->wps_probe_req_ie_len);
Larry Finger5e93f352014-03-28 21:37:38 -050091#endif
92}
93
Jes Sorensene4183612014-04-15 19:44:47 +020094void rtw_free_mlme_priv23a(struct mlme_priv *pmlmepriv)
Larry Finger5e93f352014-03-28 21:37:38 -050095{
Jes Sorensene4183612014-04-15 19:44:47 +020096 RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_,
97 ("rtw_free_mlme_priv23a\n"));
98
Larry Finger5e93f352014-03-28 21:37:38 -050099 rtw23a_free_mlme_priv_ie_data(pmlmepriv);
Larry Finger5e93f352014-03-28 21:37:38 -0500100}
101
Clément Calmels809d2082014-06-26 10:20:46 +0200102struct wlan_network *rtw_alloc_network(struct mlme_priv *pmlmepriv, gfp_t gfp)
Larry Finger5e93f352014-03-28 21:37:38 -0500103{
104 struct wlan_network *pnetwork;
105
Jes Sorensenec838b02014-05-09 15:03:46 +0200106 pnetwork = kzalloc(sizeof(struct wlan_network), gfp);
Larry Finger5e93f352014-03-28 21:37:38 -0500107 if (pnetwork) {
108 INIT_LIST_HEAD(&pnetwork->list);
109 pnetwork->network_type = 0;
110 pnetwork->fixed = false;
111 pnetwork->last_scanned = jiffies;
Larry Finger5e93f352014-03-28 21:37:38 -0500112 pnetwork->join_res = 0;
113 }
114
115 return pnetwork;
116}
117
Jes Sorensendff22262014-04-15 19:44:52 +0200118static void _rtw_free_network23a(struct mlme_priv *pmlmepriv,
Jes Sorensen2ccac5f2014-04-26 18:55:50 +0200119 struct wlan_network *pnetwork)
Larry Finger5e93f352014-03-28 21:37:38 -0500120{
Larry Finger5e93f352014-03-28 21:37:38 -0500121 if (!pnetwork)
122 return;
123
124 if (pnetwork->fixed == true)
125 return;
126
Larry Finger5e93f352014-03-28 21:37:38 -0500127 list_del_init(&pnetwork->list);
128
129 kfree(pnetwork);
130}
131
Larry Finger5e93f352014-03-28 21:37:38 -0500132/*
Jes Sorensen480c8652014-04-15 19:44:45 +0200133 return the wlan_network with the matching addr
Larry Finger5e93f352014-03-28 21:37:38 -0500134
Masanari Iida7c17d2d2014-07-22 23:42:24 +0900135 Shall be called under atomic context... to avoid possible racing condition...
Larry Finger5e93f352014-03-28 21:37:38 -0500136*/
137struct wlan_network *
Jes Sorensenf56d9682014-04-26 18:55:48 +0200138rtw_find_network23a(struct rtw_queue *scanned_queue, u8 *addr)
Larry Finger5e93f352014-03-28 21:37:38 -0500139{
140 struct list_head *phead, *plist;
141 struct wlan_network *pnetwork = NULL;
142
143 if (is_zero_ether_addr(addr)) {
144 pnetwork = NULL;
145 goto exit;
146 }
147
148 /* spin_lock_bh(&scanned_queue->lock); */
149
150 phead = get_list_head(scanned_queue);
151 plist = phead->next;
152
153 while (plist != phead) {
154 pnetwork = container_of(plist, struct wlan_network, list);
155
156 if (ether_addr_equal(addr, pnetwork->network.MacAddress))
157 break;
158
159 plist = plist->next;
Greg Donalda82b4b02014-09-08 20:50:23 -0500160 }
Larry Finger5e93f352014-03-28 21:37:38 -0500161
Jes Sorensen480c8652014-04-15 19:44:45 +0200162 if (plist == phead)
Larry Finger5e93f352014-03-28 21:37:38 -0500163 pnetwork = NULL;
164
165 /* spin_unlock_bh(&scanned_queue->lock); */
166
167exit:
168
169 return pnetwork;
170}
171
Jes Sorensen528e5c12014-04-26 18:55:51 +0200172void rtw_free_network_queue23a(struct rtw_adapter *padapter)
Larry Finger5e93f352014-03-28 21:37:38 -0500173{
174 struct list_head *phead, *plist, *ptmp;
175 struct wlan_network *pnetwork;
Jes Sorensen480c8652014-04-15 19:44:45 +0200176 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
Larry Finger5e93f352014-03-28 21:37:38 -0500177 struct rtw_queue *scanned_queue = &pmlmepriv->scanned_queue;
178
179 spin_lock_bh(&scanned_queue->lock);
180
181 phead = get_list_head(scanned_queue);
182
183 list_for_each_safe(plist, ptmp, phead) {
184 pnetwork = container_of(plist, struct wlan_network, list);
185
Jes Sorensen2ccac5f2014-04-26 18:55:50 +0200186 _rtw_free_network23a(pmlmepriv, pnetwork);
Larry Finger5e93f352014-03-28 21:37:38 -0500187 }
188
189 spin_unlock_bh(&scanned_queue->lock);
Larry Finger5e93f352014-03-28 21:37:38 -0500190}
191
Jes Sorensen480c8652014-04-15 19:44:45 +0200192int rtw_if_up23a(struct rtw_adapter *padapter)
193{
Larry Finger5e93f352014-03-28 21:37:38 -0500194 int res;
195
Jes Sorensen480c8652014-04-15 19:44:45 +0200196 if (padapter->bDriverStopped || padapter->bSurpriseRemoved ||
Jes Sorensen0618dbc2014-05-25 22:43:06 +0200197 !check_fwstate(&padapter->mlmepriv, _FW_LINKED)) {
Jes Sorensen480c8652014-04-15 19:44:45 +0200198 RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_,
199 ("rtw_if_up23a:bDriverStopped(%d) OR "
200 "bSurpriseRemoved(%d)", padapter->bDriverStopped,
201 padapter->bSurpriseRemoved));
202 res = false;
203 } else
204 res = true;
Larry Finger5e93f352014-03-28 21:37:38 -0500205
206 return res;
207}
208
Greg Donald4e66cf02014-08-22 10:57:49 -0500209void rtw_generate_random_ibss23a(u8 *pibss)
Larry Finger5e93f352014-03-28 21:37:38 -0500210{
211 unsigned long curtime = jiffies;
212
213 pibss[0] = 0x02; /* in ad-hoc mode bit1 must set to 1 */
214 pibss[1] = 0x11;
215 pibss[2] = 0x87;
Jes Sorensen480c8652014-04-15 19:44:45 +0200216 pibss[3] = curtime & 0xff;/* p[0]; */
217 pibss[4] = (curtime >> 8) & 0xff;/* p[1]; */
218 pibss[5] = (curtime >> 16) & 0xff;/* p[2]; */
Larry Finger5e93f352014-03-28 21:37:38 -0500219}
220
Jes Sorensena9339fd2014-04-15 19:44:51 +0200221void rtw_set_roaming(struct rtw_adapter *adapter, u8 to_roaming)
222{
223 if (to_roaming == 0)
224 adapter->mlmepriv.to_join = false;
225 adapter->mlmepriv.to_roaming = to_roaming;
226}
227
Jes Sorensenafa7e482014-04-15 19:44:50 +0200228static void _rtw_roaming(struct rtw_adapter *padapter,
229 struct wlan_network *tgt_network)
230{
231 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
232 struct wlan_network *pnetwork;
233 int do_join_r;
234
235 if (tgt_network)
236 pnetwork = tgt_network;
237 else
238 pnetwork = &pmlmepriv->cur_network;
239
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));
247
248 pmlmepriv->assoc_by_bssid = false;
249
250 while (1) {
Jes Sorensene007b4c2014-06-09 15:17:00 +0200251 do_join_r = rtw_do_join(padapter);
Jes Sorensenafa7e482014-04-15 19:44:50 +0200252 if (do_join_r == _SUCCESS)
253 break;
254 else {
255 DBG_8723A("roaming do_join return %d\n",
256 do_join_r);
257 pmlmepriv->to_roaming--;
258
259 if (padapter->mlmepriv.to_roaming > 0)
260 continue;
261 else {
262 DBG_8723A("%s(%d) -to roaming fail, "
263 "indicate_disconnect\n",
264 __func__, __LINE__);
265 rtw_indicate_disconnect23a(padapter);
266 break;
267 }
268 }
269 }
270 }
271}
272
273void rtw23a_roaming(struct rtw_adapter *padapter,
274 struct wlan_network *tgt_network)
275{
276 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
277
278 spin_lock_bh(&pmlmepriv->lock);
279 _rtw_roaming(padapter, tgt_network);
280 spin_unlock_bh(&pmlmepriv->lock);
281}
282
Larry Fingerc0b99be2014-04-26 18:55:17 +0200283static void rtw_free_network_nolock(struct mlme_priv *pmlmepriv,
284 struct wlan_network *pnetwork)
Larry Finger5e93f352014-03-28 21:37:38 -0500285{
Jes Sorensen2d5eafc2014-04-26 18:55:52 +0200286 _rtw_free_network23a(pmlmepriv, pnetwork);
Larry Finger5e93f352014-03-28 21:37:38 -0500287}
288
Jes Sorensenec36ce22014-06-09 15:16:36 +0200289bool rtw_is_same_ibss23a(struct rtw_adapter *adapter,
290 struct wlan_network *pnetwork)
Larry Finger5e93f352014-03-28 21:37:38 -0500291{
Jes Sorensenec36ce22014-06-09 15:16:36 +0200292 int ret;
Larry Finger5e93f352014-03-28 21:37:38 -0500293 struct security_priv *psecuritypriv = &adapter->securitypriv;
294
Jes Sorensen9e3d6df2014-05-21 09:37:34 +0200295 if (psecuritypriv->dot11PrivacyAlgrthm != 0 &&
Jes Sorensen480c8652014-04-15 19:44:45 +0200296 pnetwork->network.Privacy == 0)
Larry Finger5e93f352014-03-28 21:37:38 -0500297 ret = false;
Jes Sorensen9e3d6df2014-05-21 09:37:34 +0200298 else if (psecuritypriv->dot11PrivacyAlgrthm == 0 &&
Jes Sorensen480c8652014-04-15 19:44:45 +0200299 pnetwork->network.Privacy == 1)
Larry Finger5e93f352014-03-28 21:37:38 -0500300 ret = false;
Larry Finger5e93f352014-03-28 21:37:38 -0500301 else
Larry Finger5e93f352014-03-28 21:37:38 -0500302 ret = true;
Larry Finger5e93f352014-03-28 21:37:38 -0500303
304 return ret;
305}
306
307inline int is_same_ess(struct wlan_bssid_ex *a, struct wlan_bssid_ex *b);
308inline int is_same_ess(struct wlan_bssid_ex *a, struct wlan_bssid_ex *b)
309{
Larry Finger5e93f352014-03-28 21:37:38 -0500310 return (a->Ssid.ssid_len == b->Ssid.ssid_len) &&
311 !memcmp(a->Ssid.ssid, b->Ssid.ssid, a->Ssid.ssid_len);
312}
313
314int is_same_network23a(struct wlan_bssid_ex *src, struct wlan_bssid_ex *dst)
315{
Jes Sorensen480c8652014-04-15 19:44:45 +0200316 u16 s_cap, d_cap;
Larry Finger5e93f352014-03-28 21:37:38 -0500317
Jes Sorensenccb1bdc2014-06-19 11:37:25 +0200318 s_cap = src->capability;
319 d_cap = dst->capability;
Larry Finger5e93f352014-03-28 21:37:38 -0500320
321 return ((src->Ssid.ssid_len == dst->Ssid.ssid_len) &&
Jes Sorensen37cb9822014-05-21 09:37:40 +0200322 /* (src->DSConfig == dst->DSConfig) && */
Larry Finger5e93f352014-03-28 21:37:38 -0500323 ether_addr_equal(src->MacAddress, dst->MacAddress) &&
Jes Sorensen8b3d9cd2014-05-31 18:05:09 +0200324 !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));
Larry Finger5e93f352014-03-28 21:37:38 -0500328}
329
Jes Sorensen480c8652014-04-15 19:44:45 +0200330struct wlan_network *
331rtw_get_oldest_wlan_network23a(struct rtw_queue *scanned_queue)
Larry Finger5e93f352014-03-28 21:37:38 -0500332{
333 struct list_head *plist, *phead;
Larry Finger5e93f352014-03-28 21:37:38 -0500334 struct wlan_network *pwlan;
335 struct wlan_network *oldest = NULL;
336
337 phead = get_list_head(scanned_queue);
338
339 list_for_each(plist, phead) {
340 pwlan = container_of(plist, struct wlan_network, list);
341
342 if (pwlan->fixed != true) {
343 if (!oldest || time_after(oldest->last_scanned,
344 pwlan->last_scanned))
345 oldest = pwlan;
346 }
347 }
348
349 return oldest;
350}
351
352void update_network23a(struct wlan_bssid_ex *dst, struct wlan_bssid_ex *src,
Jes Sorensen480c8652014-04-15 19:44:45 +0200353 struct rtw_adapter *padapter, bool update_ie)
Larry Finger5e93f352014-03-28 21:37:38 -0500354{
Jes Sorensen60b152c2014-10-10 21:41:36 +0200355 u8 ss_ori = dst->SignalStrength;
356 u8 sq_ori = dst->SignalQuality;
Larry Finger5e93f352014-03-28 21:37:38 -0500357 long rssi_ori = dst->Rssi;
358
Jes Sorensen60b152c2014-10-10 21:41:36 +0200359 u8 ss_smp = src->SignalStrength;
360 u8 sq_smp = src->SignalQuality;
Larry Finger5e93f352014-03-28 21:37:38 -0500361 long rssi_smp = src->Rssi;
362
363 u8 ss_final;
364 u8 sq_final;
365 long rssi_final;
366
Jes Sorensen480c8652014-04-15 19:44:45 +0200367 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",
Larry Finger5e93f352014-03-28 21:37:38 -0500369 __func__, src->Ssid.ssid, src->MacAddress,
Jes Sorensen37cb9822014-05-21 09:37:40 +0200370 src->DSConfig, ss_ori, sq_ori, rssi_ori,
Larry Finger5e93f352014-03-28 21:37:38 -0500371 ss_smp, sq_smp, rssi_smp
372 );
373
374 /* The rule below is 1/5 for sample value, 4/5 for history value */
Jes Sorensen480c8652014-04-15 19:44:45 +0200375 if (check_fwstate(&padapter->mlmepriv, _FW_LINKED) &&
376 is_same_network23a(&padapter->mlmepriv.cur_network.network, src)) {
Larry Finger5e93f352014-03-28 21:37:38 -0500377 /* Take the recvpriv's value for the connected AP*/
378 ss_final = padapter->recvpriv.signal_strength;
379 sq_final = padapter->recvpriv.signal_qual;
Jes Sorensen480c8652014-04-15 19:44:45 +0200380 /* the rssi value here is undecorated, and will be
381 used for antenna diversity */
Larry Finger5e93f352014-03-28 21:37:38 -0500382 if (sq_smp != 101) /* from the right channel */
383 rssi_final = (src->Rssi+dst->Rssi*4)/5;
384 else
385 rssi_final = rssi_ori;
Jes Sorensen480c8652014-04-15 19:44:45 +0200386 } else {
Larry Finger5e93f352014-03-28 21:37:38 -0500387 if (sq_smp != 101) { /* from the right channel */
Jes Sorensen60b152c2014-10-10 21:41:36 +0200388 ss_final = ((u32)src->SignalStrength +
389 (u32)dst->SignalStrength * 4) / 5;
390 sq_final = ((u32)src->SignalQuality +
391 (u32)dst->SignalQuality * 4) / 5;
Jes Sorensen480c8652014-04-15 19:44:45 +0200392 rssi_final = src->Rssi+dst->Rssi * 4 / 5;
Larry Finger5e93f352014-03-28 21:37:38 -0500393 } else {
Masanari Iida7c17d2d2014-07-22 23:42:24 +0900394 /* bss info not receiving from the right channel, use
Jes Sorensen480c8652014-04-15 19:44:45 +0200395 the original RX signal infos */
Jes Sorensen60b152c2014-10-10 21:41:36 +0200396 ss_final = dst->SignalStrength;
397 sq_final = dst->SignalQuality;
Larry Finger5e93f352014-03-28 21:37:38 -0500398 rssi_final = dst->Rssi;
399 }
400
401 }
402
403 if (update_ie)
Jes Sorensen480c8652014-04-15 19:44:45 +0200404 memcpy(dst, src, get_wlan_bssid_ex_sz(src));
Larry Finger5e93f352014-03-28 21:37:38 -0500405
Jes Sorensen60b152c2014-10-10 21:41:36 +0200406 dst->SignalStrength = ss_final;
407 dst->SignalQuality = sq_final;
Larry Finger5e93f352014-03-28 21:37:38 -0500408 dst->Rssi = rssi_final;
409
Jes Sorensen480c8652014-04-15 19:44:45 +0200410 DBG_8723A("%s %s(%pM), SignalStrength:%u, SignalQuality:%u, "
411 "RawRSSI:%ld\n", __func__, dst->Ssid.ssid, dst->MacAddress,
Jes Sorensen60b152c2014-10-10 21:41:36 +0200412 dst->SignalStrength, dst->SignalQuality, dst->Rssi);
Larry Finger5e93f352014-03-28 21:37:38 -0500413}
414
Jes Sorensen480c8652014-04-15 19:44:45 +0200415static void update_current_network(struct rtw_adapter *adapter,
416 struct wlan_bssid_ex *pnetwork)
Larry Finger5e93f352014-03-28 21:37:38 -0500417{
Jes Sorensen480c8652014-04-15 19:44:45 +0200418 struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
Larry Finger5e93f352014-03-28 21:37:38 -0500419
Jes Sorensen480c8652014-04-15 19:44:45 +0200420 if (check_fwstate(pmlmepriv, _FW_LINKED) &&
421 is_same_network23a(&pmlmepriv->cur_network.network, pnetwork)) {
422 update_network23a(&pmlmepriv->cur_network.network,
Greg Donaldc895a5d2014-09-16 18:37:41 -0500423 pnetwork, adapter, true);
Jes Sorensenc164bcf2014-05-21 09:37:41 +0200424
Jes Sorensen480c8652014-04-15 19:44:45 +0200425 rtw_update_protection23a(adapter,
Jes Sorensen68e6c792014-06-24 15:03:29 +0200426 pmlmepriv->cur_network.network.IEs,
Jes Sorensen480c8652014-04-15 19:44:45 +0200427 pmlmepriv->cur_network.network.IELength);
Larry Finger5e93f352014-03-28 21:37:38 -0500428 }
Larry Finger5e93f352014-03-28 21:37:38 -0500429}
430
431/*
432
433Caller must hold pmlmepriv->lock first.
434
435*/
Jes Sorensen8ab7bdb2014-06-09 15:16:27 +0200436static void rtw_update_scanned_network(struct rtw_adapter *adapter,
437 struct wlan_bssid_ex *target)
Larry Finger5e93f352014-03-28 21:37:38 -0500438{
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;
444 u32 bssid_ex_sz;
445 int found = 0;
446
447 spin_lock_bh(&queue->lock);
448 phead = get_list_head(queue);
449
450 list_for_each(plist, phead) {
451 pnetwork = container_of(plist, struct wlan_network, list);
452
453 if (is_same_network23a(&pnetwork->network, target)) {
454 found = 1;
455 break;
456 }
457 if (!oldest || time_after(oldest->last_scanned,
458 pnetwork->last_scanned))
459 oldest = pnetwork;
460 }
461
462 /* If we didn't find a match, then get a new network slot to initialize
463 * with this beacon's information */
464 if (!found) {
Jes Sorensenec838b02014-05-09 15:03:46 +0200465 pnetwork = rtw_alloc_network(pmlmepriv, GFP_ATOMIC);
Larry Finger5e93f352014-03-28 21:37:38 -0500466 if (!pnetwork) {
467 if (!oldest) {
468 RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_,
469 ("\n\n\nsomething wrong here\n\n\n"));
470 goto exit;
471 }
472 pnetwork = oldest;
473 } else
474 list_add_tail(&pnetwork->list, &queue->queue);
475
476 bssid_ex_sz = get_wlan_bssid_ex_sz(target);
477 target->Length = bssid_ex_sz;
478 memcpy(&pnetwork->network, target, bssid_ex_sz);
479
480 /* variable initialize */
481 pnetwork->fixed = false;
482 pnetwork->last_scanned = jiffies;
483
484 pnetwork->network_type = 0;
Larry Finger5e93f352014-03-28 21:37:38 -0500485 pnetwork->join_res = 0;
486
Masanari Iida7c17d2d2014-07-22 23:42:24 +0900487 /* bss info not receiving from the right channel */
Jes Sorensen60b152c2014-10-10 21:41:36 +0200488 if (pnetwork->network.SignalQuality == 101)
489 pnetwork->network.SignalQuality = 0;
Larry Finger5e93f352014-03-28 21:37:38 -0500490 } else {
491 /*
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
495 * new_net handler
496 */
497 bool update_ie = true;
498
499 pnetwork->last_scanned = jiffies;
500
501 /* target.reserved == 1, means that scanned network is
502 * a bcn frame. */
Jes Sorensen480c8652014-04-15 19:44:45 +0200503 if (pnetwork->network.IELength > target->IELength &&
504 target->reserved == 1)
Larry Finger5e93f352014-03-28 21:37:38 -0500505 update_ie = false;
506
Greg Donaldc895a5d2014-09-16 18:37:41 -0500507 update_network23a(&pnetwork->network, target, adapter,
Jes Sorensen480c8652014-04-15 19:44:45 +0200508 update_ie);
Larry Finger5e93f352014-03-28 21:37:38 -0500509 }
510
511exit:
512 spin_unlock_bh(&queue->lock);
Larry Finger5e93f352014-03-28 21:37:38 -0500513}
514
Larry Fingerc0b99be2014-04-26 18:55:17 +0200515static void rtw_add_network(struct rtw_adapter *adapter,
516 struct wlan_bssid_ex *pnetwork)
Larry Finger5e93f352014-03-28 21:37:38 -0500517{
518 update_current_network(adapter, pnetwork);
Jes Sorensen8ab7bdb2014-06-09 15:16:27 +0200519 rtw_update_scanned_network(adapter, pnetwork);
Larry Finger5e93f352014-03-28 21:37:38 -0500520}
521
522/* select the desired network based on the capability of the (i)bss. */
523/* check items: (1) security */
524/* (2) network_type */
525/* (3) WMM */
526/* (4) HT */
527/* (5) others */
Larry Fingerc0b99be2014-04-26 18:55:17 +0200528static int rtw_is_desired_network(struct rtw_adapter *adapter,
529 struct wlan_network *pnetwork)
Larry Finger5e93f352014-03-28 21:37:38 -0500530{
531 struct security_priv *psecuritypriv = &adapter->securitypriv;
532 struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
533 u32 desired_encmode;
534 u32 privacy;
Larry Finger5e93f352014-03-28 21:37:38 -0500535 int bselected = true;
536
537 desired_encmode = psecuritypriv->ndisencryptstatus;
538 privacy = pnetwork->network.Privacy;
539
Jes Sorensen480c8652014-04-15 19:44:45 +0200540 if (check_fwstate(pmlmepriv, WIFI_UNDER_WPS)) {
Jes Sorensen9c40e122014-06-09 15:15:55 +0200541 if (cfg80211_find_vendor_ie(WLAN_OUI_MICROSOFT,
542 WLAN_OUI_TYPE_MICROSOFT_WPA,
Jes Sorensen1de65cc2014-06-24 15:03:30 +0200543 pnetwork->network.IEs,
544 pnetwork->network.IELength))
Larry Finger5e93f352014-03-28 21:37:38 -0500545 return true;
Larry Finger5e93f352014-03-28 21:37:38 -0500546 else
Larry Finger5e93f352014-03-28 21:37:38 -0500547 return false;
Larry Finger5e93f352014-03-28 21:37:38 -0500548 }
Jes Sorensen480c8652014-04-15 19:44:45 +0200549 if (adapter->registrypriv.wifi_spec == 1) {
550 /* for correct flow of 8021X to do.... */
551 if (desired_encmode == Ndis802_11EncryptionDisabled &&
552 privacy != 0)
Greg Donalda82b4b02014-09-08 20:50:23 -0500553 bselected = false;
Larry Finger5e93f352014-03-28 21:37:38 -0500554 }
555
Jes Sorensen8b3d9cd2014-05-31 18:05:09 +0200556 if (desired_encmode != Ndis802_11EncryptionDisabled && privacy == 0) {
Jes Sorensen480c8652014-04-15 19:44:45 +0200557 DBG_8723A("desired_encmode: %d, privacy: %d\n",
558 desired_encmode, privacy);
Larry Finger5e93f352014-03-28 21:37:38 -0500559 bselected = false;
560 }
561
Jes Sorensen480c8652014-04-15 19:44:45 +0200562 if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE)) {
Jes Sorensenefc71442014-05-21 09:37:26 +0200563 if (pnetwork->network.ifmode !=
564 pmlmepriv->cur_network.network.ifmode)
Larry Finger5e93f352014-03-28 21:37:38 -0500565 bselected = false;
566 }
567
568 return bselected;
569}
570
571/* TODO: Perry : For Power Management */
Jes Sorensene2601962014-05-09 15:03:19 +0200572void rtw_atimdone_event_callback23a(struct rtw_adapter *adapter, const u8 *pbuf)
Larry Finger5e93f352014-03-28 21:37:38 -0500573{
Greg Donaldc895a5d2014-09-16 18:37:41 -0500574 RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_,
575 ("receive atimdone_evet\n"));
Larry Finger5e93f352014-03-28 21:37:38 -0500576}
577
Jes Sorensene2601962014-05-09 15:03:19 +0200578void rtw_survey_event_cb23a(struct rtw_adapter *adapter, const u8 *pbuf)
Larry Finger5e93f352014-03-28 21:37:38 -0500579{
580 u32 len;
581 struct wlan_bssid_ex *pnetwork;
Jes Sorensen8b3d9cd2014-05-31 18:05:09 +0200582 struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
Jes Sorensen7195dc02014-06-09 15:16:28 +0200583 struct survey_event *survey = (struct survey_event *)pbuf;
Larry Finger5e93f352014-03-28 21:37:38 -0500584
Jes Sorensen24687962014-06-09 15:16:29 +0200585 pnetwork = survey->bss;
Larry Finger5e93f352014-03-28 21:37:38 -0500586
Greg Donaldc895a5d2014-09-16 18:37:41 -0500587 RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_,
Jes Sorensen480c8652014-04-15 19:44:45 +0200588 ("rtw_survey_event_cb23a, ssid=%s\n", pnetwork->Ssid.ssid));
Larry Finger5e93f352014-03-28 21:37:38 -0500589
590 len = get_wlan_bssid_ex_sz(pnetwork);
Jes Sorensen480c8652014-04-15 19:44:45 +0200591 if (len > (sizeof(struct wlan_bssid_ex))) {
Greg Donaldc895a5d2014-09-16 18:37:41 -0500592 RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_,
Jes Sorensen480c8652014-04-15 19:44:45 +0200593 ("\n ****rtw_survey_event_cb23a: return a wrong "
594 "bss ***\n"));
Larry Finger5e93f352014-03-28 21:37:38 -0500595 return;
596 }
597
598 spin_lock_bh(&pmlmepriv->lock);
599
600 /* update IBSS_network 's timestamp */
Jes Sorensen480c8652014-04-15 19:44:45 +0200601 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"); */
Larry Finger5e93f352014-03-28 21:37:38 -0500604 if (ether_addr_equal(pmlmepriv->cur_network.network.MacAddress,
605 pnetwork->MacAddress)) {
Greg Donald4e66cf02014-08-22 10:57:49 -0500606 struct wlan_network *ibss_wlan;
Larry Finger5e93f352014-03-28 21:37:38 -0500607
Jes Sorenseneb4f07b2014-06-21 16:50:16 +0200608 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;
Larry Finger5e93f352014-03-28 21:37:38 -0500613 spin_lock_bh(&pmlmepriv->scanned_queue.lock);
Jes Sorensen480c8652014-04-15 19:44:45 +0200614 ibss_wlan = rtw_find_network23a(
615 &pmlmepriv->scanned_queue,
616 pnetwork->MacAddress);
617 if (ibss_wlan) {
Jes Sorenseneb4f07b2014-06-21 16:50:16 +0200618 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;
Larry Finger5e93f352014-03-28 21:37:38 -0500624 spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
625 goto exit;
626 }
627 spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
628 }
629 }
630
631 /* lock pmlmepriv->lock when you accessing network_q */
Jes Sorensen0618dbc2014-05-25 22:43:06 +0200632 if (!check_fwstate(pmlmepriv, _FW_UNDER_LINKING)) {
Greg Donalda82b4b02014-09-08 20:50:23 -0500633 if (pnetwork->Ssid.ssid[0] == 0)
Larry Finger5e93f352014-03-28 21:37:38 -0500634 pnetwork->Ssid.ssid_len = 0;
635
636 rtw_add_network(adapter, pnetwork);
637 }
638
639exit:
640
641 spin_unlock_bh(&pmlmepriv->lock);
642
Jes Sorensen24687962014-06-09 15:16:29 +0200643 kfree(survey->bss);
644 survey->bss = NULL;
Larry Finger5e93f352014-03-28 21:37:38 -0500645}
646
Jes Sorensene2601962014-05-09 15:03:19 +0200647void
648rtw_surveydone_event_callback23a(struct rtw_adapter *adapter, const u8 *pbuf)
Larry Finger5e93f352014-03-28 21:37:38 -0500649{
Jes Sorensen8b3d9cd2014-05-31 18:05:09 +0200650 struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
Larry Finger5e93f352014-03-28 21:37:38 -0500651 struct mlme_ext_priv *pmlmeext = &adapter->mlmeextpriv;
Jes Sorensene5c4db02014-06-09 15:16:55 +0200652 int ret;
Larry Finger5e93f352014-03-28 21:37:38 -0500653
654 spin_lock_bh(&pmlmepriv->lock);
655
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;
660 }
661
Jes Sorensen480c8652014-04-15 19:44:45 +0200662 RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_,
663 ("rtw_surveydone_event_callback23a: fw_state:%x\n\n",
664 get_fwstate(pmlmepriv)));
Larry Finger5e93f352014-03-28 21:37:38 -0500665
666 if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY)) {
667 del_timer_sync(&pmlmepriv->scan_to_timer);
668
669 _clr_fwstate_(pmlmepriv, _FW_UNDER_SURVEY);
670 } else {
Jes Sorensen480c8652014-04-15 19:44:45 +0200671 RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_,
672 ("nic status =%x, survey done event comes too late!\n",
673 get_fwstate(pmlmepriv)));
Larry Finger5e93f352014-03-28 21:37:38 -0500674 }
675
676 rtw_set_signal_stat_timer(&adapter->recvpriv);
677
678 if (pmlmepriv->to_join == true) {
Jes Sorensen66ed1bc2014-06-09 15:16:56 +0200679 set_fwstate(pmlmepriv, _FW_UNDER_LINKING);
Jes Sorensen480c8652014-04-15 19:44:45 +0200680 if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE)) {
Jes Sorensene5c4db02014-06-09 15:16:55 +0200681 ret = rtw_select_and_join_from_scanned_queue23a(
682 pmlmepriv);
683 if (ret != _SUCCESS)
684 rtw_do_join_adhoc(adapter);
Larry Finger5e93f352014-03-28 21:37:38 -0500685 } else {
Larry Finger5e93f352014-03-28 21:37:38 -0500686 pmlmepriv->to_join = false;
Jes Sorensen480c8652014-04-15 19:44:45 +0200687 ret = rtw_select_and_join_from_scanned_queue23a(
688 pmlmepriv);
Jes Sorensen85b3c5e2014-06-09 15:16:57 +0200689 if (ret != _SUCCESS) {
Jes Sorensen480c8652014-04-15 19:44:45 +0200690 DBG_8723A("try_to_join, but select scanning "
691 "queue fail, to_roaming:%d\n",
Jes Sorensen56828792014-04-15 19:44:46 +0200692 adapter->mlmepriv.to_roaming);
693 if (adapter->mlmepriv.to_roaming) {
Jes Sorensen480c8652014-04-15 19:44:45 +0200694 if (--pmlmepriv->to_roaming == 0 ||
695 rtw_sitesurvey_cmd23a(
696 adapter,
697 &pmlmepriv->assoc_ssid, 1,
698 NULL, 0) != _SUCCESS) {
Larry Finger5e93f352014-03-28 21:37:38 -0500699 rtw_set_roaming(adapter, 0);
Jes Sorensen480c8652014-04-15 19:44:45 +0200700 rtw_free_assoc_resources23a(
701 adapter, 1);
702 rtw_indicate_disconnect23a(
703 adapter);
704 } else
Larry Finger5e93f352014-03-28 21:37:38 -0500705 pmlmepriv->to_join = true;
Larry Finger5e93f352014-03-28 21:37:38 -0500706 }
707 _clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING);
708 }
709 }
710 }
711
712 spin_unlock_bh(&pmlmepriv->lock);
713
Larry Finger5e93f352014-03-28 21:37:38 -0500714 rtw_os_xmit_schedule23a(adapter);
715
Jes Sorensen480c8652014-04-15 19:44:45 +0200716 if (pmlmeext->sitesurvey_res.bss_cnt == 0)
Jes Sorensenb7c19c22014-05-16 10:04:00 +0200717 rtw_sreset_reset(adapter);
Larry Finger5e93f352014-03-28 21:37:38 -0500718
719 rtw_cfg80211_surveydone_event_callback(adapter);
Larry Finger5e93f352014-03-28 21:37:38 -0500720}
721
Jes Sorensen480c8652014-04-15 19:44:45 +0200722static void free_scanqueue(struct mlme_priv *pmlmepriv)
Larry Finger5e93f352014-03-28 21:37:38 -0500723{
724 struct wlan_network *pnetwork;
725 struct rtw_queue *scan_queue = &pmlmepriv->scanned_queue;
726 struct list_head *plist, *phead, *ptemp;
727
728 RT_TRACE(_module_rtl871x_mlme_c_, _drv_notice_, ("+free_scanqueue\n"));
729 spin_lock_bh(&scan_queue->lock);
730
731 phead = get_list_head(scan_queue);
732
733 list_for_each_safe(plist, ptemp, phead) {
Larry Finger5e93f352014-03-28 21:37:38 -0500734 pnetwork = container_of(plist, struct wlan_network, list);
Jes Sorensen46805ac2014-06-09 15:16:32 +0200735 pnetwork->fixed = false;
736 _rtw_free_network23a(pmlmepriv, pnetwork);
Greg Donalda82b4b02014-09-08 20:50:23 -0500737 }
Larry Finger5e93f352014-03-28 21:37:38 -0500738
739 spin_unlock_bh(&scan_queue->lock);
Larry Finger5e93f352014-03-28 21:37:38 -0500740}
741
742/*
Jes Sorensen480c8652014-04-15 19:44:45 +0200743 *rtw_free_assoc_resources23a: the caller has to lock pmlmepriv->lock
744 */
745void rtw_free_assoc_resources23a(struct rtw_adapter *adapter,
746 int lock_scanned_queue)
Larry Finger5e93f352014-03-28 21:37:38 -0500747{
Greg Donald4e66cf02014-08-22 10:57:49 -0500748 struct wlan_network *pwlan;
Jes Sorensen480c8652014-04-15 19:44:45 +0200749 struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
750 struct sta_priv *pstapriv = &adapter->stapriv;
Larry Finger5e93f352014-03-28 21:37:38 -0500751 struct wlan_network *tgt_network = &pmlmepriv->cur_network;
Greg Donald4e66cf02014-08-22 10:57:49 -0500752 struct sta_info *psta;
Larry Finger5e93f352014-03-28 21:37:38 -0500753
Jes Sorensen480c8652014-04-15 19:44:45 +0200754 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));
Larry Finger5e93f352014-03-28 21:37:38 -0500760
Jes Sorensen480c8652014-04-15 19:44:45 +0200761 if (check_fwstate(pmlmepriv, WIFI_STATION_STATE|WIFI_AP_STATE)) {
762 psta = rtw_get_stainfo23a(&adapter->stapriv,
763 tgt_network->network.MacAddress);
Larry Finger5e93f352014-03-28 21:37:38 -0500764
Jes Sorensen480c8652014-04-15 19:44:45 +0200765 spin_lock_bh(&pstapriv->sta_hash_lock);
766 rtw_free_stainfo23a(adapter, psta);
Larry Finger5e93f352014-03-28 21:37:38 -0500767 spin_unlock_bh(&pstapriv->sta_hash_lock);
Larry Finger5e93f352014-03-28 21:37:38 -0500768 }
769
Jes Sorensen480c8652014-04-15 19:44:45 +0200770 if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE |
771 WIFI_ADHOC_MASTER_STATE|WIFI_AP_STATE)) {
Larry Finger5e93f352014-03-28 21:37:38 -0500772 rtw_free_all_stainfo23a(adapter);
773
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);
778
779 rtw_init_bcmc_stainfo23a(adapter);
780 }
781
Jes Sorensen480c8652014-04-15 19:44:45 +0200782 if (lock_scanned_queue)
Larry Finger5e93f352014-03-28 21:37:38 -0500783 spin_lock_bh(&pmlmepriv->scanned_queue.lock);
784
Jes Sorensen480c8652014-04-15 19:44:45 +0200785 pwlan = rtw_find_network23a(&pmlmepriv->scanned_queue,
786 tgt_network->network.MacAddress);
787 if (pwlan)
Larry Finger5e93f352014-03-28 21:37:38 -0500788 pwlan->fixed = false;
789 else
Greg Donaldc895a5d2014-09-16 18:37:41 -0500790 RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_,
Jes Sorensen480c8652014-04-15 19:44:45 +0200791 ("rtw_free_assoc_resources23a : pwlan== NULL\n"));
Larry Finger5e93f352014-03-28 21:37:38 -0500792
Jes Sorensen480c8652014-04-15 19:44:45 +0200793 if (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) &&
794 adapter->stapriv.asoc_sta_count == 1)
Larry Finger5e93f352014-03-28 21:37:38 -0500795 rtw_free_network_nolock(pmlmepriv, pwlan);
796
Jes Sorensen480c8652014-04-15 19:44:45 +0200797 if (lock_scanned_queue)
Larry Finger5e93f352014-03-28 21:37:38 -0500798 spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
799
800 pmlmepriv->key_mask = 0;
Larry Finger5e93f352014-03-28 21:37:38 -0500801}
802
803/*
804*rtw_indicate_connect23a: the caller has to lock pmlmepriv->lock
805*/
806void rtw_indicate_connect23a(struct rtw_adapter *padapter)
807{
Jes Sorensen480c8652014-04-15 19:44:45 +0200808 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
Larry Finger5e93f352014-03-28 21:37:38 -0500809
Jes Sorensen480c8652014-04-15 19:44:45 +0200810 RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_,
811 ("+rtw_indicate_connect23a\n"));
Larry Finger5e93f352014-03-28 21:37:38 -0500812
813 pmlmepriv->to_join = false;
814
Jes Sorensen480c8652014-04-15 19:44:45 +0200815 if (!check_fwstate(&padapter->mlmepriv, _FW_LINKED)) {
Larry Finger5e93f352014-03-28 21:37:38 -0500816 set_fwstate(pmlmepriv, _FW_LINKED);
817
Jes Sorensen483557b2014-04-09 23:21:02 +0200818 rtw_cfg80211_indicate_connect(padapter);
819
820 netif_carrier_on(padapter->pnetdev);
821
822 if (padapter->pid[2] != 0)
823 kill_pid(find_vpid(padapter->pid[2]), SIGALRM, 1);
Larry Finger5e93f352014-03-28 21:37:38 -0500824 }
825
826 rtw_set_roaming(padapter, 0);
827
828 rtw_set_scan_deny(padapter, 3000);
829
Jes Sorensen480c8652014-04-15 19:44:45 +0200830 RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_,
831 ("-rtw_indicate_connect23a: fw_state=0x%08x\n",
832 get_fwstate(pmlmepriv)));
Larry Finger5e93f352014-03-28 21:37:38 -0500833}
834
835/*
Jes Sorensen480c8652014-04-15 19:44:45 +0200836 *rtw_indicate_disconnect23a: the caller has to lock pmlmepriv->lock
837 */
Larry Finger5e93f352014-03-28 21:37:38 -0500838void rtw_indicate_disconnect23a(struct rtw_adapter *padapter)
839{
Jes Sorensen8b3d9cd2014-05-31 18:05:09 +0200840 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
Larry Finger5e93f352014-03-28 21:37:38 -0500841
Jes Sorensen480c8652014-04-15 19:44:45 +0200842 RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_,
843 ("+rtw_indicate_disconnect23a\n"));
Larry Finger5e93f352014-03-28 21:37:38 -0500844
845 _clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING|WIFI_UNDER_WPS);
846
Greg Donalda82b4b02014-09-08 20:50:23 -0500847 /* DBG_8723A("clear wps when %s\n", __func__); */
Larry Finger5e93f352014-03-28 21:37:38 -0500848
Jes Sorensen56828792014-04-15 19:44:46 +0200849 if (padapter->mlmepriv.to_roaming > 0)
Larry Finger5e93f352014-03-28 21:37:38 -0500850 _clr_fwstate_(pmlmepriv, _FW_LINKED);
851
852 if (check_fwstate(&padapter->mlmepriv, _FW_LINKED) ||
Jes Sorensen56828792014-04-15 19:44:46 +0200853 padapter->mlmepriv.to_roaming <= 0) {
Larry Finger5e93f352014-03-28 21:37:38 -0500854 rtw_os_indicate_disconnect23a(padapter);
855
856 /* set ips_deny_time to avoid enter IPS before LPS leave */
857 padapter->pwrctrlpriv.ips_deny_time =
Larry Fingerc17416e2014-03-28 21:37:42 -0500858 jiffies + msecs_to_jiffies(3000);
Larry Finger5e93f352014-03-28 21:37:38 -0500859
860 _clr_fwstate_(pmlmepriv, _FW_LINKED);
861
Larry Finger5e93f352014-03-28 21:37:38 -0500862 rtw_clear_scan_deny(padapter);
Larry Finger5e93f352014-03-28 21:37:38 -0500863 }
864
Larry Finger5e93f352014-03-28 21:37:38 -0500865 rtw_lps_ctrl_wk_cmd23a(padapter, LPS_CTRL_DISCONNECT, 1);
Larry Finger5e93f352014-03-28 21:37:38 -0500866}
867
Larry Finger5e93f352014-03-28 21:37:38 -0500868void rtw_scan_abort23a(struct rtw_adapter *adapter)
869{
870 unsigned long start;
871 struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
872 struct mlme_ext_priv *pmlmeext = &adapter->mlmeextpriv;
873
874 start = jiffies;
875 pmlmeext->scan_abort = true;
876 while (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY) &&
877 jiffies_to_msecs(jiffies - start) <= 200) {
Larry Finger5e93f352014-03-28 21:37:38 -0500878 if (adapter->bDriverStopped || adapter->bSurpriseRemoved)
879 break;
880
Jes Sorensena790d582014-05-09 15:04:04 +0200881 DBG_8723A("%s(%s): fw_state = _FW_UNDER_SURVEY!\n",
882 __func__, adapter->pnetdev->name);
Larry Finger5e93f352014-03-28 21:37:38 -0500883 msleep(20);
884 }
885
886 if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY)) {
887 if (!adapter->bDriverStopped && !adapter->bSurpriseRemoved)
Jes Sorensena790d582014-05-09 15:04:04 +0200888 DBG_8723A("%s(%s): waiting for scan_abort time out!\n",
889 __func__, adapter->pnetdev->name);
Jes Sorensen810c8322014-04-09 23:21:00 +0200890 rtw_cfg80211_indicate_scan_done(wdev_to_priv(adapter->rtw_wdev),
891 true);
Larry Finger5e93f352014-03-28 21:37:38 -0500892 }
893 pmlmeext->scan_abort = false;
894}
895
Jes Sorensen480c8652014-04-15 19:44:45 +0200896static struct sta_info *
897rtw_joinbss_update_stainfo(struct rtw_adapter *padapter,
898 struct wlan_network *pnetwork)
Larry Finger5e93f352014-03-28 21:37:38 -0500899{
900 int i;
Jes Sorensen480c8652014-04-15 19:44:45 +0200901 struct sta_info *bmc_sta, *psta;
Larry Finger5e93f352014-03-28 21:37:38 -0500902 struct recv_reorder_ctrl *preorder_ctrl;
903 struct sta_priv *pstapriv = &padapter->stapriv;
904
905 psta = rtw_get_stainfo23a(pstapriv, pnetwork->network.MacAddress);
Jes Sorensen480c8652014-04-15 19:44:45 +0200906 if (!psta)
907 psta = rtw_alloc_stainfo23a(pstapriv,
Jes Sorensen6e8bc712014-05-09 15:03:49 +0200908 pnetwork->network.MacAddress,
909 GFP_ATOMIC);
Larry Finger5e93f352014-03-28 21:37:38 -0500910
Jes Sorensen480c8652014-04-15 19:44:45 +0200911 if (psta) { /* update ptarget_sta */
Larry Finger5e93f352014-03-28 21:37:38 -0500912 DBG_8723A("%s\n", __func__);
913
914 psta->aid = pnetwork->join_res;
Jes Sorensendbe98492014-05-16 10:04:13 +0200915 psta->mac_id = 0;
Larry Finger5e93f352014-03-28 21:37:38 -0500916
917 /* sta mode */
Jes Sorensendbe98492014-05-16 10:04:13 +0200918 rtl8723a_SetHalODMVar(padapter, HAL_ODM_STA_INFO, psta, true);
Larry Finger5e93f352014-03-28 21:37:38 -0500919
920 /* security related */
Jes Sorensen480c8652014-04-15 19:44:45 +0200921 if (padapter->securitypriv.dot11AuthAlgrthm ==
922 dot11AuthAlgrthm_8021X) {
Jes Sorensen9216c512014-05-21 09:37:29 +0200923 padapter->securitypriv.binstallGrpkey = 0;
924 padapter->securitypriv.busetkipkey = 0;
Larry Finger5e93f352014-03-28 21:37:38 -0500925
926 psta->ieee8021x_blocked = true;
Jes Sorensen480c8652014-04-15 19:44:45 +0200927 psta->dot118021XPrivacy =
928 padapter->securitypriv.dot11PrivacyAlgrthm;
Larry Finger5e93f352014-03-28 21:37:38 -0500929
Jes Sorensen480c8652014-04-15 19:44:45 +0200930 memset(&psta->dot118021x_UncstKey, 0,
931 sizeof (union Keytype));
Larry Finger5e93f352014-03-28 21:37:38 -0500932
Jes Sorensen480c8652014-04-15 19:44:45 +0200933 memset(&psta->dot11tkiprxmickey, 0,
934 sizeof (union Keytype));
935 memset(&psta->dot11tkiptxmickey, 0,
936 sizeof (union Keytype));
Larry Finger5e93f352014-03-28 21:37:38 -0500937
Jes Sorensen480c8652014-04-15 19:44:45 +0200938 memset(&psta->dot11txpn, 0, sizeof (union pn48));
939 memset(&psta->dot11rxpn, 0, sizeof (union pn48));
Larry Finger5e93f352014-03-28 21:37:38 -0500940 }
941
942 /* Commented by Albert 2012/07/21 */
943 /* When doing the WPS, the wps_ie_len won't equal to 0 */
Jes Sorensen480c8652014-04-15 19:44:45 +0200944 /* And the Wi-Fi driver shouldn't allow the data packet
Masanari Iida7c17d2d2014-07-22 23:42:24 +0900945 to be transmitted. */
Jes Sorensen480c8652014-04-15 19:44:45 +0200946 if (padapter->securitypriv.wps_ie_len != 0) {
Larry Finger5e93f352014-03-28 21:37:38 -0500947 psta->ieee8021x_blocked = true;
948 padapter->securitypriv.wps_ie_len = 0;
949 }
950
Jes Sorensen480c8652014-04-15 19:44:45 +0200951 /* for A-MPDU Rx reordering buffer control for bmc_sta &
952 * sta_info */
Masanari Iida7c17d2d2014-07-22 23:42:24 +0900953 /* if A-MPDU Rx is enabled, resetting
Jes Sorensen480c8652014-04-15 19:44:45 +0200954 rx_ordering_ctrl wstart_b(indicate_seq) to default
955 value = 0xffff */
Larry Finger5e93f352014-03-28 21:37:38 -0500956 /* todo: check if AP can send A-MPDU packets */
Jes Sorensen480c8652014-04-15 19:44:45 +0200957 for (i = 0; i < 16 ; i++) {
Larry Finger5e93f352014-03-28 21:37:38 -0500958 /* 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;
Jes Sorensen480c8652014-04-15 19:44:45 +0200963 /* max_ampdu_sz; ex. 32(kbytes) -> wsize_b = 32 */
964 preorder_ctrl->wsize_b = 64;
Larry Finger5e93f352014-03-28 21:37:38 -0500965 }
966
967 bmc_sta = rtw_get_bcmc_stainfo23a(padapter);
Jes Sorensen480c8652014-04-15 19:44:45 +0200968 if (bmc_sta) {
969 for (i = 0; i < 16 ; i++) {
Larry Finger5e93f352014-03-28 21:37:38 -0500970 preorder_ctrl = &bmc_sta->recvreorder_ctrl[i];
971 preorder_ctrl->enable = false;
972 preorder_ctrl->indicate_seq = 0xffff;
973 preorder_ctrl->wend_b = 0xffff;
Jes Sorensen480c8652014-04-15 19:44:45 +0200974 /* max_ampdu_sz; ex. 32(kbytes) ->
975 wsize_b = 32 */
976 preorder_ctrl->wsize_b = 64;
Larry Finger5e93f352014-03-28 21:37:38 -0500977 }
978 }
979
980 /* misc. */
981 update_sta_info23a(padapter, psta);
982
983 }
984
985 return psta;
986}
987
988/* pnetwork : returns from rtw23a_joinbss_event_cb */
989/* ptarget_wlan: found from scanned_queue */
Jes Sorensen480c8652014-04-15 19:44:45 +0200990static void
991rtw_joinbss_update_network23a(struct rtw_adapter *padapter,
992 struct wlan_network *ptarget_wlan,
993 struct wlan_network *pnetwork)
Larry Finger5e93f352014-03-28 21:37:38 -0500994{
995 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
996 struct wlan_network *cur_network = &pmlmepriv->cur_network;
997
998 DBG_8723A("%s\n", __func__);
999
Jes Sorensen480c8652014-04-15 19:44:45 +02001000 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)));
Larry Finger5e93f352014-03-28 21:37:38 -05001003
1004 /* why not use ptarget_wlan?? */
Jes Sorensen480c8652014-04-15 19:44:45 +02001005 memcpy(&cur_network->network, &pnetwork->network,
1006 pnetwork->network.Length);
Larry Finger5e93f352014-03-28 21:37:38 -05001007 /* some IEs in pnetwork is wrong, so we should use ptarget_wlan IEs */
1008 cur_network->network.IELength = ptarget_wlan->network.IELength;
Jes Sorensen480c8652014-04-15 19:44:45 +02001009 memcpy(&cur_network->network.IEs[0], &ptarget_wlan->network.IEs[0],
1010 MAX_IE_SZ);
Larry Finger5e93f352014-03-28 21:37:38 -05001011
Jes Sorensen2bde0522014-06-21 16:50:17 +02001012 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;
Larry Finger5e93f352014-03-28 21:37:38 -05001016
1017 rtw_set_signal_stat_timer(&padapter->recvpriv);
Jes Sorensen480c8652014-04-15 19:44:45 +02001018 padapter->recvpriv.signal_strength =
Jes Sorensen60b152c2014-10-10 21:41:36 +02001019 ptarget_wlan->network.SignalStrength;
1020 padapter->recvpriv.signal_qual = ptarget_wlan->network.SignalQuality;
Jes Sorensen480c8652014-04-15 19:44:45 +02001021 /*
1022 * the ptarget_wlan->network.Rssi is raw data, we use
Jes Sorensen60b152c2014-10-10 21:41:36 +02001023 * ptarget_wlan->network.SignalStrength instead (has scaled)
Jes Sorensen480c8652014-04-15 19:44:45 +02001024 */
1025 padapter->recvpriv.rssi = translate_percentage_to_dbm(
Jes Sorensen60b152c2014-10-10 21:41:36 +02001026 ptarget_wlan->network.SignalStrength);
Larry Finger5e93f352014-03-28 21:37:38 -05001027 DBG_8723A("%s signal_strength:%3u, rssi:%3d, signal_qual:%3u\n",
1028 __func__, padapter->recvpriv.signal_strength,
1029 padapter->recvpriv.rssi, padapter->recvpriv.signal_qual);
1030 rtw_set_signal_stat_timer(&padapter->recvpriv);
1031
1032 /* update fw_state will clr _FW_UNDER_LINKING here indirectly */
Jes Sorensenefc71442014-05-21 09:37:26 +02001033 switch (pnetwork->network.ifmode) {
1034 case NL80211_IFTYPE_P2P_CLIENT:
1035 case NL80211_IFTYPE_STATION:
1036 if (pmlmepriv->fw_state & WIFI_UNDER_WPS)
Larry Finger5e93f352014-03-28 21:37:38 -05001037 pmlmepriv->fw_state = WIFI_STATION_STATE|WIFI_UNDER_WPS;
1038 else
1039 pmlmepriv->fw_state = WIFI_STATION_STATE;
1040 break;
Jes Sorensenefc71442014-05-21 09:37:26 +02001041 case NL80211_IFTYPE_ADHOC:
Larry Finger5e93f352014-03-28 21:37:38 -05001042 pmlmepriv->fw_state = WIFI_ADHOC_STATE;
1043 break;
1044 default:
1045 pmlmepriv->fw_state = WIFI_NULL_STATE;
Jes Sorensen480c8652014-04-15 19:44:45 +02001046 RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_,
1047 ("Invalid network_mode\n"));
Larry Finger5e93f352014-03-28 21:37:38 -05001048 break;
1049 }
1050
Jes Sorensen68e6c792014-06-24 15:03:29 +02001051 rtw_update_protection23a(padapter, cur_network->network.IEs,
1052 cur_network->network.IELength);
Larry Finger5e93f352014-03-28 21:37:38 -05001053
Jes Sorensen480c8652014-04-15 19:44:45 +02001054 rtw_update_ht_cap23a(padapter, cur_network->network.IEs,
1055 cur_network->network.IELength);
Larry Finger5e93f352014-03-28 21:37:38 -05001056}
1057
Jes Sorensen480c8652014-04-15 19:44:45 +02001058/*
1059 * Notes:
Masanari Iida7c17d2d2014-07-22 23:42:24 +09001060 * the function could be > passive_level (the same context as Rx tasklet)
Jes Sorensen480c8652014-04-15 19:44:45 +02001061 * pnetwork : returns from rtw23a_joinbss_event_cb
1062 * ptarget_wlan: found from scanned_queue
1063 * if join_res > 0, for (fw_state==WIFI_STATION_STATE),
1064 * we check if "ptarget_sta" & "ptarget_wlan" exist.
1065 * if join_res > 0, for (fw_state==WIFI_ADHOC_STATE),
1066 * we only check if "ptarget_wlan" exist.
1067 * if join_res > 0, update "cur_network->network" from "pnetwork->network"
1068 * if (ptarget_wlan !=NULL).
1069 */
Larry Finger5e93f352014-03-28 21:37:38 -05001070
1071void rtw_joinbss_event_prehandle23a(struct rtw_adapter *adapter, u8 *pbuf)
1072{
Jes Sorensen480c8652014-04-15 19:44:45 +02001073 struct sta_info *ptarget_sta, *pcur_sta;
1074 struct sta_priv *pstapriv = &adapter->stapriv;
1075 struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
1076 struct wlan_network *pnetwork = (struct wlan_network *)pbuf;
Larry Finger5e93f352014-03-28 21:37:38 -05001077 struct wlan_network *cur_network = &pmlmepriv->cur_network;
Jes Sorensen480c8652014-04-15 19:44:45 +02001078 struct wlan_network *pcur_wlan, *ptarget_wlan = NULL;
1079 bool the_same_macaddr;
Larry Finger5e93f352014-03-28 21:37:38 -05001080
Greg Donaldc895a5d2014-09-16 18:37:41 -05001081 RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_,
Jes Sorensen480c8652014-04-15 19:44:45 +02001082 ("joinbss event call back received with res=%d\n",
1083 pnetwork->join_res));
Larry Finger5e93f352014-03-28 21:37:38 -05001084
Larry Finger5e93f352014-03-28 21:37:38 -05001085 if (pmlmepriv->assoc_ssid.ssid_len == 0) {
Greg Donaldc895a5d2014-09-16 18:37:41 -05001086 RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_,
Jes Sorensen480c8652014-04-15 19:44:45 +02001087 ("@@@@@ joinbss event call back for Any SSid\n"));
Larry Finger5e93f352014-03-28 21:37:38 -05001088 } else {
Greg Donaldc895a5d2014-09-16 18:37:41 -05001089 RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_,
Larry Finger5e93f352014-03-28 21:37:38 -05001090 ("@@@@@ rtw23a_joinbss_event_cb for SSid:%s\n",
1091 pmlmepriv->assoc_ssid.ssid));
1092 }
1093
1094 if (ether_addr_equal(pnetwork->network.MacAddress,
1095 cur_network->network.MacAddress))
1096 the_same_macaddr = true;
1097 else
1098 the_same_macaddr = false;
1099
1100 pnetwork->network.Length = get_wlan_bssid_ex_sz(&pnetwork->network);
Jes Sorensen480c8652014-04-15 19:44:45 +02001101 if (pnetwork->network.Length > sizeof(struct wlan_bssid_ex)) {
Greg Donaldc895a5d2014-09-16 18:37:41 -05001102 RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_,
Jes Sorensen480c8652014-04-15 19:44:45 +02001103 ("\n\n ***joinbss_evt_callback return a wrong bss "
1104 "***\n\n"));
Larry Finger5e93f352014-03-28 21:37:38 -05001105 return;
1106 }
1107
1108 spin_lock_bh(&pmlmepriv->lock);
1109
Greg Donaldc895a5d2014-09-16 18:37:41 -05001110 RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_,
Jes Sorensen480c8652014-04-15 19:44:45 +02001111 ("\n rtw23a_joinbss_event_cb !! _enter_critical\n"));
Larry Finger5e93f352014-03-28 21:37:38 -05001112
Jes Sorensen480c8652014-04-15 19:44:45 +02001113 if (pnetwork->join_res > 0) {
Larry Finger5e93f352014-03-28 21:37:38 -05001114 spin_lock_bh(&pmlmepriv->scanned_queue.lock);
Greg Donaldc895a5d2014-09-16 18:37:41 -05001115 if (check_fwstate(pmlmepriv, _FW_UNDER_LINKING)) {
Larry Finger5e93f352014-03-28 21:37:38 -05001116 /* s1. find ptarget_wlan */
Jes Sorensen480c8652014-04-15 19:44:45 +02001117 if (check_fwstate(pmlmepriv, _FW_LINKED)) {
Roberta Dobrescu08551cb2014-10-26 23:30:05 +02001118 if (the_same_macaddr) {
Larry Finger5e93f352014-03-28 21:37:38 -05001119 ptarget_wlan = rtw_find_network23a(&pmlmepriv->scanned_queue, cur_network->network.MacAddress);
Jes Sorensen480c8652014-04-15 19:44:45 +02001120 } else {
Larry Finger5e93f352014-03-28 21:37:38 -05001121 pcur_wlan = rtw_find_network23a(&pmlmepriv->scanned_queue, cur_network->network.MacAddress);
Jes Sorensen480c8652014-04-15 19:44:45 +02001122 if (pcur_wlan)
1123 pcur_wlan->fixed = false;
Larry Finger5e93f352014-03-28 21:37:38 -05001124
1125 pcur_sta = rtw_get_stainfo23a(pstapriv, cur_network->network.MacAddress);
Jes Sorensen480c8652014-04-15 19:44:45 +02001126 if (pcur_sta) {
Larry Finger5e93f352014-03-28 21:37:38 -05001127 spin_lock_bh(&pstapriv->sta_hash_lock);
Jes Sorensen480c8652014-04-15 19:44:45 +02001128 rtw_free_stainfo23a(adapter,
1129 pcur_sta);
Larry Finger5e93f352014-03-28 21:37:38 -05001130 spin_unlock_bh(&pstapriv->sta_hash_lock);
1131 }
1132
1133 ptarget_wlan = rtw_find_network23a(&pmlmepriv->scanned_queue, pnetwork->network.MacAddress);
Jes Sorensen480c8652014-04-15 19:44:45 +02001134 if (check_fwstate(pmlmepriv,
1135 WIFI_STATION_STATE)) {
1136 if (ptarget_wlan)
1137 ptarget_wlan->fixed =
1138 true;
Larry Finger5e93f352014-03-28 21:37:38 -05001139 }
1140 }
1141
Jes Sorensen480c8652014-04-15 19:44:45 +02001142 } else {
1143 ptarget_wlan = rtw_find_network23a(
1144 &pmlmepriv->scanned_queue,
1145 pnetwork->network.MacAddress);
1146 if (check_fwstate(pmlmepriv,
1147 WIFI_STATION_STATE)) {
1148 if (ptarget_wlan)
1149 ptarget_wlan->fixed = true;
Larry Finger5e93f352014-03-28 21:37:38 -05001150 }
1151 }
1152
1153 /* s2. update cur_network */
Jes Sorensen480c8652014-04-15 19:44:45 +02001154 if (ptarget_wlan)
1155 rtw_joinbss_update_network23a(adapter,
1156 ptarget_wlan,
1157 pnetwork);
1158 else {
Greg Donaldc895a5d2014-09-16 18:37:41 -05001159 RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_,
Jes Sorensen480c8652014-04-15 19:44:45 +02001160 ("Can't find ptarget_wlan when "
1161 "joinbss_event callback\n"));
Larry Finger5e93f352014-03-28 21:37:38 -05001162 spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
1163 goto ignore_joinbss_callback;
1164 }
1165
Jes Sorensen480c8652014-04-15 19:44:45 +02001166 /* s3. find ptarget_sta & update ptarget_sta after
1167 update cur_network only for station mode */
1168 if (check_fwstate(pmlmepriv, WIFI_STATION_STATE)) {
1169 ptarget_sta = rtw_joinbss_update_stainfo(
1170 adapter, pnetwork);
1171 if (!ptarget_sta) {
1172 RT_TRACE(_module_rtl871x_mlme_c_,
1173 _drv_err_,
1174 ("Can't update stainfo when "
1175 "joinbss_event callback\n"));
Larry Finger5e93f352014-03-28 21:37:38 -05001176 spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
1177 goto ignore_joinbss_callback;
1178 }
1179 }
1180
1181 /* s4. indicate connect */
Jes Sorensen480c8652014-04-15 19:44:45 +02001182 if (check_fwstate(pmlmepriv, WIFI_STATION_STATE))
Larry Finger5e93f352014-03-28 21:37:38 -05001183 rtw_indicate_connect23a(adapter);
Jes Sorensen480c8652014-04-15 19:44:45 +02001184 else {
1185 /* adhoc mode will rtw_indicate_connect23a
1186 when rtw_stassoc_event_callback23a */
Greg Donaldc895a5d2014-09-16 18:37:41 -05001187 RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_,
Jes Sorensen480c8652014-04-15 19:44:45 +02001188 ("adhoc mode, fw_state:%x",
1189 get_fwstate(pmlmepriv)));
Larry Finger5e93f352014-03-28 21:37:38 -05001190 }
1191
1192 /* s5. Cancle assoc_timer */
1193 del_timer_sync(&pmlmepriv->assoc_timer);
1194
Greg Donaldc895a5d2014-09-16 18:37:41 -05001195 RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_,
Jes Sorensen480c8652014-04-15 19:44:45 +02001196 ("Cancle assoc_timer\n"));
Larry Finger5e93f352014-03-28 21:37:38 -05001197 } else {
1198 RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_,
1199 ("rtw23a_joinbss_event_cb err: fw_state:%x",
1200 get_fwstate(pmlmepriv)));
1201 spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
1202 goto ignore_joinbss_callback;
1203 }
1204 spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
Jes Sorensen480c8652014-04-15 19:44:45 +02001205 } else if (pnetwork->join_res == -4) {
Larry Finger5e93f352014-03-28 21:37:38 -05001206 rtw_reset_securitypriv23a(adapter);
1207 mod_timer(&pmlmepriv->assoc_timer,
1208 jiffies + msecs_to_jiffies(1));
1209
1210 /* rtw_free_assoc_resources23a(adapter, 1); */
1211
Jes Sorensen480c8652014-04-15 19:44:45 +02001212 if (check_fwstate(pmlmepriv, _FW_UNDER_LINKING)) {
Larry Finger5e93f352014-03-28 21:37:38 -05001213 RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_,
Jes Sorensen480c8652014-04-15 19:44:45 +02001214 ("fail! clear _FW_UNDER_LINKING ^^^fw_state="
1215 "%x\n", get_fwstate(pmlmepriv)));
Larry Finger5e93f352014-03-28 21:37:38 -05001216 _clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING);
1217 }
Larry Finger5e93f352014-03-28 21:37:38 -05001218 } else {
1219 /* if join_res < 0 (join fails), then try again */
1220 mod_timer(&pmlmepriv->assoc_timer,
1221 jiffies + msecs_to_jiffies(1));
1222 _clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING);
1223 }
1224
1225ignore_joinbss_callback:
1226
1227 spin_unlock_bh(&pmlmepriv->lock);
1228}
1229
Jes Sorensene2601962014-05-09 15:03:19 +02001230void rtw23a_joinbss_event_cb(struct rtw_adapter *adapter, const u8 *pbuf)
Larry Finger5e93f352014-03-28 21:37:38 -05001231{
Jes Sorensen480c8652014-04-15 19:44:45 +02001232 struct wlan_network *pnetwork = (struct wlan_network *)pbuf;
Larry Finger5e93f352014-03-28 21:37:38 -05001233
1234 mlmeext_joinbss_event_callback23a(adapter, pnetwork->join_res);
1235
1236 rtw_os_xmit_schedule23a(adapter);
Larry Finger5e93f352014-03-28 21:37:38 -05001237}
1238
Jes Sorensene2601962014-05-09 15:03:19 +02001239void rtw_stassoc_event_callback23a(struct rtw_adapter *adapter, const u8 *pbuf)
Larry Finger5e93f352014-03-28 21:37:38 -05001240{
1241 struct sta_info *psta;
1242 struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
Greg Donald7e6646d2014-09-06 19:42:03 -05001243 struct stassoc_event *pstassoc = (struct stassoc_event *)pbuf;
Larry Finger5e93f352014-03-28 21:37:38 -05001244 struct wlan_network *cur_network = &pmlmepriv->cur_network;
Jes Sorensen480c8652014-04-15 19:44:45 +02001245 struct wlan_network *ptarget_wlan;
Larry Finger5e93f352014-03-28 21:37:38 -05001246
Jes Sorensen480c8652014-04-15 19:44:45 +02001247 if (rtw_access_ctrl23a(adapter, pstassoc->macaddr) == false)
Larry Finger5e93f352014-03-28 21:37:38 -05001248 return;
1249
1250#ifdef CONFIG_8723AU_AP_MODE
Jes Sorensen480c8652014-04-15 19:44:45 +02001251 if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) {
Larry Finger5e93f352014-03-28 21:37:38 -05001252 psta = rtw_get_stainfo23a(&adapter->stapriv, pstassoc->macaddr);
1253 if (psta) {
1254 /* bss_cap_update_on_sta_join23a(adapter, psta); */
1255 /* sta_info_update23a(adapter, psta); */
1256 ap_sta_info_defer_update23a(adapter, psta);
Larry Finger5e93f352014-03-28 21:37:38 -05001257 }
1258 return;
1259 }
1260#endif
1261 /* for AD-HOC mode */
1262 psta = rtw_get_stainfo23a(&adapter->stapriv, pstassoc->macaddr);
1263 if (psta != NULL) {
1264 /* the sta have been in sta_info_queue => do nothing */
Greg Donaldc895a5d2014-09-16 18:37:41 -05001265 RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_,
Jes Sorensen480c8652014-04-15 19:44:45 +02001266 ("Error: rtw_stassoc_event_callback23a: sta has "
1267 "been in sta_hash_queue\n"));
1268 /* between drv has received this event before and
1269 fw have not yet to set key to CAM_ENTRY) */
1270 return;
Larry Finger5e93f352014-03-28 21:37:38 -05001271 }
1272
Jes Sorensen6e8bc712014-05-09 15:03:49 +02001273 psta = rtw_alloc_stainfo23a(&adapter->stapriv, pstassoc->macaddr,
1274 GFP_KERNEL);
Jes Sorensen480c8652014-04-15 19:44:45 +02001275 if (!psta) {
Greg Donaldc895a5d2014-09-16 18:37:41 -05001276 RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_,
Jes Sorensen480c8652014-04-15 19:44:45 +02001277 ("Can't alloc sta_info when "
1278 "rtw_stassoc_event_callback23a\n"));
Larry Finger5e93f352014-03-28 21:37:38 -05001279 return;
1280 }
1281
1282 /* to do : init sta_info variable */
1283 psta->qos_option = 0;
1284 psta->mac_id = (uint)pstassoc->cam_id;
1285 /* psta->aid = (uint)pstassoc->cam_id; */
Greg Donaldc895a5d2014-09-16 18:37:41 -05001286 DBG_8723A("%s\n", __func__);
Larry Finger5e93f352014-03-28 21:37:38 -05001287 /* for ad-hoc mode */
Jes Sorensendbe98492014-05-16 10:04:13 +02001288 rtl8723a_SetHalODMVar(adapter, HAL_ODM_STA_INFO, psta, true);
Larry Finger5e93f352014-03-28 21:37:38 -05001289
Jes Sorensen480c8652014-04-15 19:44:45 +02001290 if (adapter->securitypriv.dot11AuthAlgrthm == dot11AuthAlgrthm_8021X)
1291 psta->dot118021XPrivacy =
1292 adapter->securitypriv.dot11PrivacyAlgrthm;
Larry Finger5e93f352014-03-28 21:37:38 -05001293
1294 psta->ieee8021x_blocked = false;
1295
1296 spin_lock_bh(&pmlmepriv->lock);
1297
Jes Sorensen480c8652014-04-15 19:44:45 +02001298 if (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) ||
1299 check_fwstate(pmlmepriv, WIFI_ADHOC_STATE)) {
1300 if (adapter->stapriv.asoc_sta_count == 2) {
Larry Finger5e93f352014-03-28 21:37:38 -05001301 spin_lock_bh(&pmlmepriv->scanned_queue.lock);
Jes Sorensen480c8652014-04-15 19:44:45 +02001302 ptarget_wlan =
1303 rtw_find_network23a(&pmlmepriv->scanned_queue,
1304 cur_network->network.MacAddress);
1305 if (ptarget_wlan)
1306 ptarget_wlan->fixed = true;
Larry Finger5e93f352014-03-28 21:37:38 -05001307 spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
1308 /* a sta + bc/mc_stainfo (not Ibss_stainfo) */
1309 rtw_indicate_connect23a(adapter);
1310 }
1311 }
1312
1313 spin_unlock_bh(&pmlmepriv->lock);
1314
1315 mlmeext_sta_add_event_callback23a(adapter, psta);
1316}
1317
Jes Sorensene2601962014-05-09 15:03:19 +02001318void rtw_stadel_event_callback23a(struct rtw_adapter *adapter, const u8 *pbuf)
Larry Finger5e93f352014-03-28 21:37:38 -05001319{
Jes Sorensen480c8652014-04-15 19:44:45 +02001320 int mac_id;
Larry Finger5e93f352014-03-28 21:37:38 -05001321 struct sta_info *psta;
Greg Donald4e66cf02014-08-22 10:57:49 -05001322 struct wlan_network *pwlan;
Jes Sorensen480c8652014-04-15 19:44:45 +02001323 struct wlan_bssid_ex *pdev_network;
Jes Sorensen480c8652014-04-15 19:44:45 +02001324 struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
1325 struct stadel_event *pstadel = (struct stadel_event *)pbuf;
1326 struct sta_priv *pstapriv = &adapter->stapriv;
Larry Finger5e93f352014-03-28 21:37:38 -05001327 struct wlan_network *tgt_network = &pmlmepriv->cur_network;
1328
1329 psta = rtw_get_stainfo23a(&adapter->stapriv, pstadel->macaddr);
Jes Sorensen480c8652014-04-15 19:44:45 +02001330 if (psta)
Larry Finger5e93f352014-03-28 21:37:38 -05001331 mac_id = psta->mac_id;
1332 else
1333 mac_id = pstadel->mac_id;
1334
Jes Sorensen480c8652014-04-15 19:44:45 +02001335 DBG_8723A("%s(mac_id=%d)=" MAC_FMT "\n", __func__, mac_id,
1336 MAC_ARG(pstadel->macaddr));
Larry Finger5e93f352014-03-28 21:37:38 -05001337
Greg Donalda82b4b02014-09-08 20:50:23 -05001338 if (check_fwstate(pmlmepriv, WIFI_AP_STATE))
Larry Finger5e93f352014-03-28 21:37:38 -05001339 return;
Larry Finger5e93f352014-03-28 21:37:38 -05001340
1341 mlmeext_sta_del_event_callback23a(adapter);
1342
1343 spin_lock_bh(&pmlmepriv->lock);
1344
Jes Sorensen480c8652014-04-15 19:44:45 +02001345 if (check_fwstate(pmlmepriv, WIFI_STATION_STATE)) {
Jes Sorensen56828792014-04-15 19:44:46 +02001346 if (adapter->mlmepriv.to_roaming > 0) {
Jes Sorensen480c8652014-04-15 19:44:45 +02001347 /* this stadel_event is caused by roaming,
1348 decrease to_roaming */
1349 pmlmepriv->to_roaming--;
Jes Sorensen56828792014-04-15 19:44:46 +02001350 } else if (adapter->mlmepriv.to_roaming == 0)
Larry Finger5e93f352014-03-28 21:37:38 -05001351 rtw_set_roaming(adapter, adapter->registrypriv.max_roaming_times);
Jes Sorensen480c8652014-04-15 19:44:45 +02001352 if (*((u16 *)pstadel->rsvd) != WLAN_REASON_EXPIRATION_CHK)
Larry Finger5e93f352014-03-28 21:37:38 -05001353 rtw_set_roaming(adapter, 0); /* don't roam */
1354
1355 rtw_free_uc_swdec_pending_queue23a(adapter);
1356
1357 rtw_free_assoc_resources23a(adapter, 1);
1358 rtw_indicate_disconnect23a(adapter);
1359 spin_lock_bh(&pmlmepriv->scanned_queue.lock);
1360 /* remove the network entry in scanned_queue */
Jes Sorensen480c8652014-04-15 19:44:45 +02001361 pwlan = rtw_find_network23a(&pmlmepriv->scanned_queue,
1362 tgt_network->network.MacAddress);
Larry Finger5e93f352014-03-28 21:37:38 -05001363 if (pwlan) {
1364 pwlan->fixed = false;
1365 rtw_free_network_nolock(pmlmepriv, pwlan);
1366 }
1367 spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
1368
Jes Sorensenafa7e482014-04-15 19:44:50 +02001369 _rtw_roaming(adapter, tgt_network);
Larry Finger5e93f352014-03-28 21:37:38 -05001370 }
1371
1372 if (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) ||
Jes Sorensen480c8652014-04-15 19:44:45 +02001373 check_fwstate(pmlmepriv, WIFI_ADHOC_STATE)) {
Larry Finger5e93f352014-03-28 21:37:38 -05001374
1375 spin_lock_bh(&pstapriv->sta_hash_lock);
1376 rtw_free_stainfo23a(adapter, psta);
1377 spin_unlock_bh(&pstapriv->sta_hash_lock);
1378
Jes Sorensen480c8652014-04-15 19:44:45 +02001379 /* a sta + bc/mc_stainfo (not Ibss_stainfo) */
1380 if (adapter->stapriv.asoc_sta_count == 1) {
Larry Finger5e93f352014-03-28 21:37:38 -05001381 spin_lock_bh(&pmlmepriv->scanned_queue.lock);
1382 /* free old ibss network */
Jes Sorensen480c8652014-04-15 19:44:45 +02001383 /* pwlan = rtw_find_network23a(
1384 &pmlmepriv->scanned_queue, pstadel->macaddr); */
1385 pwlan = rtw_find_network23a(&pmlmepriv->scanned_queue,
1386 tgt_network->network.MacAddress);
1387 if (pwlan) {
Larry Finger5e93f352014-03-28 21:37:38 -05001388 pwlan->fixed = false;
1389 rtw_free_network_nolock(pmlmepriv, pwlan);
1390 }
1391 spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
1392 /* re-create ibss */
1393 pdev_network = &adapter->registrypriv.dev_network;
Larry Finger5e93f352014-03-28 21:37:38 -05001394
Jes Sorensen480c8652014-04-15 19:44:45 +02001395 memcpy(pdev_network, &tgt_network->network,
1396 get_wlan_bssid_ex_sz(&tgt_network->network));
Larry Finger5e93f352014-03-28 21:37:38 -05001397
Jes Sorensenfcc60202014-06-09 15:16:53 +02001398 rtw_do_join_adhoc(adapter);
Larry Finger5e93f352014-03-28 21:37:38 -05001399 }
Larry Finger5e93f352014-03-28 21:37:38 -05001400 }
1401
1402 spin_unlock_bh(&pmlmepriv->lock);
Larry Finger5e93f352014-03-28 21:37:38 -05001403}
1404
Larry Finger5e93f352014-03-28 21:37:38 -05001405/*
Masanari Iida7c17d2d2014-07-22 23:42:24 +09001406* rtw23a_join_to_handler - Timeout/failure handler for CMD JoinBss
Larry Finger5e93f352014-03-28 21:37:38 -05001407* @adapter: pointer to _adapter structure
1408*/
1409void rtw23a_join_to_handler (unsigned long data)
1410{
1411 struct rtw_adapter *adapter = (struct rtw_adapter *)data;
Jes Sorensen8b3d9cd2014-05-31 18:05:09 +02001412 struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
Larry Finger5e93f352014-03-28 21:37:38 -05001413 int do_join_r;
1414
1415 DBG_8723A("%s, fw_state=%x\n", __func__, get_fwstate(pmlmepriv));
1416
Jes Sorensen8b3d9cd2014-05-31 18:05:09 +02001417 if (adapter->bDriverStopped || adapter->bSurpriseRemoved)
Larry Finger5e93f352014-03-28 21:37:38 -05001418 return;
1419
1420 spin_lock_bh(&pmlmepriv->lock);
1421
Jes Sorensen56828792014-04-15 19:44:46 +02001422 if (adapter->mlmepriv.to_roaming > 0) {
1423 /* join timeout caused by roaming */
Jes Sorensen480c8652014-04-15 19:44:45 +02001424 while (1) {
Larry Finger5e93f352014-03-28 21:37:38 -05001425 pmlmepriv->to_roaming--;
Jes Sorensen56828792014-04-15 19:44:46 +02001426 if (adapter->mlmepriv.to_roaming != 0) {
1427 /* try another */
Larry Finger5e93f352014-03-28 21:37:38 -05001428 DBG_8723A("%s try another roaming\n", __func__);
Jes Sorensene007b4c2014-06-09 15:17:00 +02001429 do_join_r = rtw_do_join(adapter);
Jes Sorensen480c8652014-04-15 19:44:45 +02001430 if (do_join_r != _SUCCESS) {
1431 DBG_8723A("%s roaming do_join return "
1432 "%d\n", __func__ , do_join_r);
Larry Finger5e93f352014-03-28 21:37:38 -05001433 continue;
1434 }
1435 break;
1436 } else {
Jes Sorensen480c8652014-04-15 19:44:45 +02001437 DBG_8723A("%s We've try roaming but fail\n",
1438 __func__);
Larry Finger5e93f352014-03-28 21:37:38 -05001439 rtw_indicate_disconnect23a(adapter);
1440 break;
1441 }
1442 }
1443 } else {
1444 rtw_indicate_disconnect23a(adapter);
1445 free_scanqueue(pmlmepriv);/* */
1446
Jes Sorensen480c8652014-04-15 19:44:45 +02001447 /* indicate disconnect for the case that join_timeout and
1448 check_fwstate != FW_LINKED */
Larry Finger5e93f352014-03-28 21:37:38 -05001449 rtw_cfg80211_indicate_disconnect(adapter);
1450 }
1451
1452 spin_unlock_bh(&pmlmepriv->lock);
1453
1454}
1455
1456/*
Masanari Iida7c17d2d2014-07-22 23:42:24 +09001457* rtw_scan_timeout_handler23a - Timeout/Failure handler for CMD SiteSurvey
Larry Finger5e93f352014-03-28 21:37:38 -05001458* @data: pointer to _adapter structure
1459*/
1460void rtw_scan_timeout_handler23a(unsigned long data)
1461{
1462 struct rtw_adapter *adapter = (struct rtw_adapter *)data;
Jes Sorensen8b3d9cd2014-05-31 18:05:09 +02001463 struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
Larry Finger5e93f352014-03-28 21:37:38 -05001464
Jes Sorensen9cd613c2014-05-09 15:04:03 +02001465 DBG_8723A("%s(%s): fw_state =%x\n", __func__, adapter->pnetdev->name,
Jes Sorensen480c8652014-04-15 19:44:45 +02001466 get_fwstate(pmlmepriv));
Larry Finger5e93f352014-03-28 21:37:38 -05001467
1468 spin_lock_bh(&pmlmepriv->lock);
1469
1470 _clr_fwstate_(pmlmepriv, _FW_UNDER_SURVEY);
1471
1472 spin_unlock_bh(&pmlmepriv->lock);
1473
Jes Sorensen810c8322014-04-09 23:21:00 +02001474 rtw_cfg80211_indicate_scan_done(wdev_to_priv(adapter->rtw_wdev), true);
Larry Finger5e93f352014-03-28 21:37:38 -05001475}
1476
Larry Finger5e93f352014-03-28 21:37:38 -05001477void rtw_dynamic_check_timer_handler(unsigned long data)
1478{
1479 struct rtw_adapter *adapter = (struct rtw_adapter *)data;
Larry Finger5e93f352014-03-28 21:37:38 -05001480
1481 if (adapter->hw_init_completed == false)
1482 goto out;
1483
Jes Sorensen480c8652014-04-15 19:44:45 +02001484 if (adapter->bDriverStopped == true ||
1485 adapter->bSurpriseRemoved == true)
Larry Finger5e93f352014-03-28 21:37:38 -05001486 goto out;
1487
1488 if (adapter->net_closed == true)
1489 goto out;
1490
1491 rtw_dynamic_chk_wk_cmd23a(adapter);
1492
Larry Finger5e93f352014-03-28 21:37:38 -05001493out:
1494 mod_timer(&adapter->mlmepriv.dynamic_chk_timer,
1495 jiffies + msecs_to_jiffies(2000));
1496}
1497
1498inline bool rtw_is_scan_deny(struct rtw_adapter *adapter)
1499{
1500 struct mlme_priv *mlmepriv = &adapter->mlmepriv;
Yeliz Taneroglu29ed9322014-10-09 01:22:14 +03001501
Larry Finger5e93f352014-03-28 21:37:38 -05001502 return (atomic_read(&mlmepriv->set_scan_deny) != 0) ? true : false;
1503}
1504
1505void rtw_clear_scan_deny(struct rtw_adapter *adapter)
1506{
1507 struct mlme_priv *mlmepriv = &adapter->mlmepriv;
Yeliz Taneroglu29ed9322014-10-09 01:22:14 +03001508
Larry Finger5e93f352014-03-28 21:37:38 -05001509 atomic_set(&mlmepriv->set_scan_deny, 0);
Larry Finger5e93f352014-03-28 21:37:38 -05001510}
1511
1512void rtw_set_scan_deny_timer_hdl(unsigned long data)
1513{
1514 struct rtw_adapter *adapter = (struct rtw_adapter *)data;
Yeliz Taneroglu29ed9322014-10-09 01:22:14 +03001515
Larry Finger5e93f352014-03-28 21:37:38 -05001516 rtw_clear_scan_deny(adapter);
1517}
1518
1519void rtw_set_scan_deny(struct rtw_adapter *adapter, u32 ms)
1520{
1521 struct mlme_priv *mlmepriv = &adapter->mlmepriv;
1522
Larry Finger5e93f352014-03-28 21:37:38 -05001523 atomic_set(&mlmepriv->set_scan_deny, 1);
1524 mod_timer(&mlmepriv->set_scan_deny_timer,
1525 jiffies + msecs_to_jiffies(ms));
Larry Finger5e93f352014-03-28 21:37:38 -05001526}
1527
1528#if defined(IEEE80211_SCAN_RESULT_EXPIRE)
Tina Ruchandanide1de2f2014-10-25 16:56:01 -07001529#define RTW_SCAN_RESULT_EXPIRE \
1530 ((IEEE80211_SCAN_RESULT_EXPIRE / (HZ*1000)) - 1000) /* 3000 -1000 */
Larry Finger5e93f352014-03-28 21:37:38 -05001531#else
1532#define RTW_SCAN_RESULT_EXPIRE 2000
1533#endif
1534
1535/*
Jes Sorensen480c8652014-04-15 19:44:45 +02001536* Select a new join candidate from the original @param candidate and
1537* @param competitor
Larry Finger5e93f352014-03-28 21:37:38 -05001538* @return true: candidate is updated
1539* @return false: candidate is not updated
1540*/
Jes Sorensen480c8652014-04-15 19:44:45 +02001541static int rtw_check_join_candidate(struct mlme_priv *pmlmepriv,
1542 struct wlan_network **candidate,
1543 struct wlan_network *competitor)
Larry Finger5e93f352014-03-28 21:37:38 -05001544{
1545 int updated = false;
Jes Sorensen480c8652014-04-15 19:44:45 +02001546 struct rtw_adapter *adapter;
1547
1548 adapter = container_of(pmlmepriv, struct rtw_adapter, mlmepriv);
Larry Finger5e93f352014-03-28 21:37:38 -05001549
1550 /* check bssid, if needed */
1551 if (pmlmepriv->assoc_by_bssid == true) {
1552 if (!ether_addr_equal(competitor->network.MacAddress,
1553 pmlmepriv->assoc_bssid))
1554 goto exit;
1555 }
1556
1557 /* check ssid, if needed */
Larry Fingerc17416e2014-03-28 21:37:42 -05001558 if (pmlmepriv->assoc_ssid.ssid_len) {
Larry Finger5e93f352014-03-28 21:37:38 -05001559 if (competitor->network.Ssid.ssid_len !=
1560 pmlmepriv->assoc_ssid.ssid_len ||
1561 memcmp(competitor->network.Ssid.ssid,
1562 pmlmepriv->assoc_ssid.ssid,
1563 pmlmepriv->assoc_ssid.ssid_len))
1564 goto exit;
1565 }
1566
Jes Sorensen480c8652014-04-15 19:44:45 +02001567 if (rtw_is_desired_network(adapter, competitor) == false)
Larry Finger5e93f352014-03-28 21:37:38 -05001568 goto exit;
1569
Jes Sorensen56828792014-04-15 19:44:46 +02001570 if (adapter->mlmepriv.to_roaming > 0) {
Larry Finger5e93f352014-03-28 21:37:38 -05001571 unsigned int passed;
1572
1573 passed = jiffies_to_msecs(jiffies - competitor->last_scanned);
1574 if (passed >= RTW_SCAN_RESULT_EXPIRE ||
1575 is_same_ess(&competitor->network,
1576 &pmlmepriv->cur_network.network) == false)
1577 goto exit;
1578 }
1579
Jes Sorensen480c8652014-04-15 19:44:45 +02001580 if (!*candidate ||
1581 (*candidate)->network.Rssi<competitor->network.Rssi) {
Larry Finger5e93f352014-03-28 21:37:38 -05001582 *candidate = competitor;
1583 updated = true;
1584 }
1585
1586 if (updated) {
Jes Sorensen480c8652014-04-15 19:44:45 +02001587 DBG_8723A("[by_bssid:%u][assoc_ssid:%s][to_roaming:%u] "
1588 "new candidate: %s("MAC_FMT") rssi:%d\n",
1589 pmlmepriv->assoc_by_bssid,
1590 pmlmepriv->assoc_ssid.ssid,
Jes Sorensen56828792014-04-15 19:44:46 +02001591 adapter->mlmepriv.to_roaming,
Jes Sorensen480c8652014-04-15 19:44:45 +02001592 (*candidate)->network.Ssid.ssid,
1593 MAC_ARG((*candidate)->network.MacAddress),
1594 (int)(*candidate)->network.Rssi);
Larry Finger5e93f352014-03-28 21:37:38 -05001595 }
1596
1597exit:
1598 return updated;
1599}
1600
1601/*
1602Calling context:
1603The caller of the sub-routine will be in critical section...
1604
1605The caller must hold the following spinlock
1606
1607pmlmepriv->lock
1608
1609*/
1610
Jes Sorensene007b4c2014-06-09 15:17:00 +02001611static int rtw_do_join(struct rtw_adapter *padapter)
1612{
1613 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1614 int ret;
1615
1616 pmlmepriv->cur_network.join_res = -2;
1617
1618 set_fwstate(pmlmepriv, _FW_UNDER_LINKING);
1619
1620 pmlmepriv->to_join = true;
1621
1622 ret = rtw_select_and_join_from_scanned_queue23a(pmlmepriv);
1623 if (ret == _SUCCESS) {
1624 pmlmepriv->to_join = false;
1625 } else {
1626 if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE)) {
1627 /* switch to ADHOC_MASTER */
1628 ret = rtw_do_join_adhoc(padapter);
1629 if (ret != _SUCCESS)
1630 goto exit;
1631 } else {
1632 /* can't associate ; reset under-linking */
1633 _clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING);
1634
1635 ret = _FAIL;
1636 pmlmepriv->to_join = false;
1637 }
1638 }
1639
1640exit:
1641 return ret;
1642}
1643
Jes Sorensen0e634a02014-06-09 15:16:49 +02001644static struct wlan_network *
1645rtw_select_candidate_from_queue(struct mlme_priv *pmlmepriv)
Larry Finger5e93f352014-03-28 21:37:38 -05001646{
Jes Sorensen0e634a02014-06-09 15:16:49 +02001647 struct wlan_network *pnetwork, *candidate = NULL;
Larry Finger5e93f352014-03-28 21:37:38 -05001648 struct rtw_queue *queue = &pmlmepriv->scanned_queue;
Jes Sorensen0e634a02014-06-09 15:16:49 +02001649 struct list_head *phead, *plist, *ptmp;
Larry Finger5e93f352014-03-28 21:37:38 -05001650
1651 spin_lock_bh(&pmlmepriv->scanned_queue.lock);
1652 phead = get_list_head(queue);
Larry Finger5e93f352014-03-28 21:37:38 -05001653
1654 list_for_each_safe(plist, ptmp, phead) {
1655 pnetwork = container_of(plist, struct wlan_network, list);
1656 if (!pnetwork) {
1657 RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_,
Jes Sorensen2febc8672014-06-09 15:16:47 +02001658 ("%s: return _FAIL:(pnetwork == NULL)\n",
Larry Finger5e93f352014-03-28 21:37:38 -05001659 __func__));
Larry Finger5e93f352014-03-28 21:37:38 -05001660 goto exit;
1661 }
1662
1663 rtw_check_join_candidate(pmlmepriv, &candidate, pnetwork);
1664 }
1665
Jes Sorensen0e634a02014-06-09 15:16:49 +02001666exit:
1667 spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
1668 return candidate;
1669}
1670
Jes Sorensenb66dad22014-06-09 15:16:50 +02001671
Jes Sorensenfcc60202014-06-09 15:16:53 +02001672int rtw_do_join_adhoc(struct rtw_adapter *adapter)
1673{
1674 struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
1675 struct wlan_bssid_ex *pdev_network;
1676 u8 *ibss;
1677 int ret;
1678
1679 pdev_network = &adapter->registrypriv.dev_network;
1680 ibss = adapter->registrypriv.dev_network.MacAddress;
1681
1682 _clr_fwstate_(pmlmepriv, _FW_UNDER_SURVEY);
1683
1684 RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_,
1685 ("switching to adhoc master\n"));
1686
1687 memcpy(&pdev_network->Ssid, &pmlmepriv->assoc_ssid,
1688 sizeof(struct cfg80211_ssid));
1689
1690 rtw_update_registrypriv_dev_network23a(adapter);
1691 rtw_generate_random_ibss23a(ibss);
1692
1693 pmlmepriv->fw_state = WIFI_ADHOC_MASTER_STATE;
1694
1695 ret = rtw_createbss_cmd23a(adapter);
1696 if (ret != _SUCCESS) {
1697 RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_,
1698 ("Error =>rtw_createbss_cmd23a status FAIL\n"));
1699 } else {
1700 pmlmepriv->to_join = false;
1701 }
1702
1703 return ret;
1704}
1705
Jes Sorensenb66dad22014-06-09 15:16:50 +02001706int rtw_do_join_network(struct rtw_adapter *adapter,
1707 struct wlan_network *candidate)
1708{
1709 int ret;
1710
1711 /* check for situation of _FW_LINKED */
1712 if (check_fwstate(&adapter->mlmepriv, _FW_LINKED)) {
1713 DBG_8723A("%s: _FW_LINKED while ask_for_joinbss!\n", __func__);
1714
1715 rtw_disassoc_cmd23a(adapter, 0, true);
1716 rtw_indicate_disconnect23a(adapter);
1717 rtw_free_assoc_resources23a(adapter, 0);
1718 }
1719 set_fwstate(&adapter->mlmepriv, _FW_UNDER_LINKING);
1720
1721 ret = rtw_joinbss_cmd23a(adapter, candidate);
1722
1723 if (ret == _SUCCESS)
1724 mod_timer(&adapter->mlmepriv.assoc_timer,
1725 jiffies + msecs_to_jiffies(MAX_JOIN_TIMEOUT));
1726
1727 return ret;
1728}
1729
Jes Sorensen0e634a02014-06-09 15:16:49 +02001730int rtw_select_and_join_from_scanned_queue23a(struct mlme_priv *pmlmepriv)
1731{
1732 struct rtw_adapter *adapter;
1733 struct wlan_network *candidate = NULL;
1734 int ret;
1735
1736 adapter = pmlmepriv->nic_hdl;
1737
1738 candidate = rtw_select_candidate_from_queue(pmlmepriv);
Larry Finger5e93f352014-03-28 21:37:38 -05001739 if (!candidate) {
1740 DBG_8723A("%s: return _FAIL(candidate == NULL)\n", __func__);
1741 ret = _FAIL;
1742 goto exit;
1743 } else {
1744 DBG_8723A("%s: candidate: %s("MAC_FMT", ch:%u)\n", __func__,
1745 candidate->network.Ssid.ssid,
1746 MAC_ARG(candidate->network.MacAddress),
Jes Sorensen37cb9822014-05-21 09:37:40 +02001747 candidate->network.DSConfig);
Larry Finger5e93f352014-03-28 21:37:38 -05001748 }
1749
Jes Sorensenb66dad22014-06-09 15:16:50 +02001750 ret = rtw_do_join_network(adapter, candidate);
Larry Finger5e93f352014-03-28 21:37:38 -05001751
1752exit:
Larry Finger5e93f352014-03-28 21:37:38 -05001753 return ret;
1754}
1755
Greg Donald8e3d1612014-10-02 18:28:41 -05001756int rtw_set_auth23a(struct rtw_adapter *adapter,
Jes Sorensen480c8652014-04-15 19:44:45 +02001757 struct security_priv *psecuritypriv)
Larry Finger5e93f352014-03-28 21:37:38 -05001758{
Greg Donald4e66cf02014-08-22 10:57:49 -05001759 struct cmd_obj *pcmd;
Larry Finger5e93f352014-03-28 21:37:38 -05001760 struct setauth_parm *psetauthparm;
1761 struct cmd_priv *pcmdpriv = &adapter->cmdpriv;
1762 int res = _SUCCESS;
1763
Sachin Kamatdb5767a2014-05-29 17:05:19 +05301764 pcmd = kzalloc(sizeof(struct cmd_obj), GFP_KERNEL);
Larry Finger5e93f352014-03-28 21:37:38 -05001765 if (!pcmd) {
1766 res = _FAIL; /* try again */
1767 goto exit;
1768 }
1769
Sachin Kamat47b0c982014-05-28 17:36:24 +05301770 psetauthparm = kzalloc(sizeof(struct setauth_parm), GFP_KERNEL);
Larry Finger5e93f352014-03-28 21:37:38 -05001771 if (!psetauthparm) {
1772 kfree(pcmd);
1773 res = _FAIL;
1774 goto exit;
1775 }
1776
1777 psetauthparm->mode = (unsigned char)psecuritypriv->dot11AuthAlgrthm;
1778
1779 pcmd->cmdcode = _SetAuth_CMD_;
1780 pcmd->parmbuf = (unsigned char *)psetauthparm;
1781 pcmd->cmdsz = (sizeof(struct setauth_parm));
1782 pcmd->rsp = NULL;
1783 pcmd->rspsz = 0;
1784
Greg Donaldc895a5d2014-09-16 18:37:41 -05001785 RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_,
Larry Finger5e93f352014-03-28 21:37:38 -05001786 ("after enqueue set_auth_cmd, auth_mode=%x\n",
1787 psecuritypriv->dot11AuthAlgrthm));
1788
1789 res = rtw_enqueue_cmd23a(pcmdpriv, pcmd);
1790
1791exit:
1792
1793 return res;
1794}
1795
1796int rtw_set_key23a(struct rtw_adapter *adapter,
Jes Sorensen480c8652014-04-15 19:44:45 +02001797 struct security_priv *psecuritypriv, int keyid, u8 set_tx)
Larry Finger5e93f352014-03-28 21:37:38 -05001798{
1799 u8 keylen;
1800 struct cmd_obj *pcmd;
1801 struct setkey_parm *psetkeyparm;
1802 struct cmd_priv *pcmdpriv = &adapter->cmdpriv;
1803 struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
1804 int res = _SUCCESS;
1805
Jes Sorensen4e489d92014-05-09 15:04:16 +02001806 if (keyid >= 4) {
1807 res = _FAIL;
1808 goto exit;
1809 }
1810
Sachin Kamat47b0c982014-05-28 17:36:24 +05301811 pcmd = kzalloc(sizeof(struct cmd_obj), GFP_KERNEL);
Larry Finger5e93f352014-03-28 21:37:38 -05001812 if (!pcmd) {
1813 res = _FAIL; /* try again */
1814 goto exit;
1815 }
Larry Fingerc17416e2014-03-28 21:37:42 -05001816 psetkeyparm = kzalloc(sizeof(struct setkey_parm), GFP_KERNEL);
Larry Finger5e93f352014-03-28 21:37:38 -05001817 if (!psetkeyparm) {
1818 kfree(pcmd);
1819 res = _FAIL;
1820 goto exit;
1821 }
1822
1823 if (psecuritypriv->dot11AuthAlgrthm == dot11AuthAlgrthm_8021X) {
1824 psetkeyparm->algorithm = (unsigned char)
1825 psecuritypriv->dot118021XGrpPrivacy;
1826 RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_,
Jes Sorensen480c8652014-04-15 19:44:45 +02001827 ("\n rtw_set_key23a: psetkeyparm->algorithm = "
1828 "(unsigned char)psecuritypriv->dot118021XGrpPrivacy "
1829 "=%d\n", psetkeyparm->algorithm));
Larry Finger5e93f352014-03-28 21:37:38 -05001830 } else {
1831 psetkeyparm->algorithm = (u8)psecuritypriv->dot11PrivacyAlgrthm;
1832 RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_,
1833 ("\n rtw_set_key23a: psetkeyparm->algorithm = (u8)"
1834 "psecuritypriv->dot11PrivacyAlgrthm =%d\n",
1835 psetkeyparm->algorithm));
1836 }
Jes Sorensen4e489d92014-05-09 15:04:16 +02001837 psetkeyparm->keyid = keyid;/* 0~3 */
Larry Finger5e93f352014-03-28 21:37:38 -05001838 psetkeyparm->set_tx = set_tx;
1839 if (is_wep_enc(psetkeyparm->algorithm))
Jes Sorensen4e489d92014-05-09 15:04:16 +02001840 pmlmepriv->key_mask |= BIT(psetkeyparm->keyid);
Larry Finger5e93f352014-03-28 21:37:38 -05001841
1842 DBG_8723A("==> rtw_set_key23a algorithm(%x), keyid(%x), key_mask(%x)\n",
1843 psetkeyparm->algorithm, psetkeyparm->keyid,
1844 pmlmepriv->key_mask);
1845 RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_,
1846 ("\n rtw_set_key23a: psetkeyparm->algorithm =%d psetkeyparm->"
1847 "keyid = (u8)keyid =%d\n", psetkeyparm->algorithm, keyid));
1848
1849 switch (psetkeyparm->algorithm) {
Jes Sorensen9e3d6df2014-05-21 09:37:34 +02001850 case WLAN_CIPHER_SUITE_WEP40:
Larry Finger5e93f352014-03-28 21:37:38 -05001851 keylen = 5;
1852 memcpy(&psetkeyparm->key[0],
Jes Sorensene0827902014-05-21 09:37:35 +02001853 &psecuritypriv->wep_key[keyid].key, keylen);
Larry Finger5e93f352014-03-28 21:37:38 -05001854 break;
Jes Sorensen9e3d6df2014-05-21 09:37:34 +02001855 case WLAN_CIPHER_SUITE_WEP104:
Larry Finger5e93f352014-03-28 21:37:38 -05001856 keylen = 13;
1857 memcpy(&psetkeyparm->key[0],
Jes Sorensene0827902014-05-21 09:37:35 +02001858 &psecuritypriv->wep_key[keyid].key, keylen);
Larry Finger5e93f352014-03-28 21:37:38 -05001859 break;
Jes Sorensen9e3d6df2014-05-21 09:37:34 +02001860 case WLAN_CIPHER_SUITE_TKIP:
Larry Finger5e93f352014-03-28 21:37:38 -05001861 keylen = 16;
1862 memcpy(&psetkeyparm->key,
1863 &psecuritypriv->dot118021XGrpKey[keyid], keylen);
1864 psetkeyparm->grpkey = 1;
1865 break;
Jes Sorensen9e3d6df2014-05-21 09:37:34 +02001866 case WLAN_CIPHER_SUITE_CCMP:
Larry Finger5e93f352014-03-28 21:37:38 -05001867 keylen = 16;
1868 memcpy(&psetkeyparm->key,
1869 &psecuritypriv->dot118021XGrpKey[keyid], keylen);
1870 psetkeyparm->grpkey = 1;
1871 break;
1872 default:
1873 RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_,
Jes Sorensen480c8652014-04-15 19:44:45 +02001874 ("\n rtw_set_key23a:psecuritypriv->dot11PrivacyAlgrthm"
1875 " = %x (must be 1 or 2 or 4 or 5)\n",
Larry Finger5e93f352014-03-28 21:37:38 -05001876 psecuritypriv->dot11PrivacyAlgrthm));
1877 res = _FAIL;
Larry Fingerc17416e2014-03-28 21:37:42 -05001878 kfree(pcmd);
1879 kfree(psetkeyparm);
Larry Finger5e93f352014-03-28 21:37:38 -05001880 goto exit;
1881 }
1882
1883 pcmd->cmdcode = _SetKey_CMD_;
1884 pcmd->parmbuf = (u8 *)psetkeyparm;
1885 pcmd->cmdsz = (sizeof(struct setkey_parm));
1886 pcmd->rsp = NULL;
1887 pcmd->rspsz = 0;
1888
Larry Finger5e93f352014-03-28 21:37:38 -05001889 /* sema_init(&pcmd->cmd_sem, 0); */
1890
1891 res = rtw_enqueue_cmd23a(pcmdpriv, pcmd);
1892
1893exit:
1894
1895 return res;
1896}
1897
1898/* adjust IEs for rtw_joinbss_cmd23a in WMM */
1899int rtw_restruct_wmm_ie23a(struct rtw_adapter *adapter, u8 *in_ie,
Jes Sorensen86184b92014-06-24 15:03:55 +02001900 u8 *out_ie, uint in_len, uint initial_out_len)
Larry Finger5e93f352014-03-28 21:37:38 -05001901{
Jes Sorensen86184b92014-06-24 15:03:55 +02001902 int ielength;
1903 const u8 *p;
Larry Finger5e93f352014-03-28 21:37:38 -05001904
Jes Sorensen86184b92014-06-24 15:03:55 +02001905 ielength = initial_out_len;
Larry Finger5e93f352014-03-28 21:37:38 -05001906
Jes Sorensen86184b92014-06-24 15:03:55 +02001907 p = cfg80211_find_vendor_ie(WLAN_OUI_MICROSOFT,
1908 WLAN_OUI_TYPE_MICROSOFT_WMM,
1909 in_ie, in_len);
Larry Finger5e93f352014-03-28 21:37:38 -05001910
Jes Sorensen86184b92014-06-24 15:03:55 +02001911 if (p && p[1]) {
1912 memcpy(out_ie + initial_out_len, p, 9);
Larry Finger5e93f352014-03-28 21:37:38 -05001913
Jes Sorensen86184b92014-06-24 15:03:55 +02001914 out_ie[initial_out_len + 1] = 7;
1915 out_ie[initial_out_len + 6] = 0;
1916 out_ie[initial_out_len + 8] = 0;
Larry Finger5e93f352014-03-28 21:37:38 -05001917
Jes Sorensen86184b92014-06-24 15:03:55 +02001918 ielength += 9;
Larry Finger5e93f352014-03-28 21:37:38 -05001919 }
1920
1921 return ielength;
1922}
1923
1924/* */
1925/* Ported from 8185: IsInPreAuthKeyList().
1926 (Renamed from SecIsInPreAuthKeyList(), 2006-10-13.) */
1927/* Added by Annie, 2006-05-07. */
1928/* */
1929/* Search by BSSID, */
1930/* Return Value: */
1931/* -1 :if there is no pre-auth key in the table */
1932/* >= 0 :if there is pre-auth key, and return the entry id */
1933/* */
1934/* */
1935
1936static int SecIsInPMKIDList(struct rtw_adapter *Adapter, u8 *bssid)
1937{
1938 struct security_priv *psecuritypriv = &Adapter->securitypriv;
1939 int i = 0;
1940
1941 do {
1942 if (psecuritypriv->PMKIDList[i].bUsed &&
1943 ether_addr_equal(psecuritypriv->PMKIDList[i].Bssid, bssid)) {
1944 break;
1945 } else {
1946 i++;
1947 /* continue; */
1948 }
Jes Sorensen480c8652014-04-15 19:44:45 +02001949 } while (i < NUM_PMKID_CACHE);
Larry Finger5e93f352014-03-28 21:37:38 -05001950
Jes Sorensen480c8652014-04-15 19:44:45 +02001951 if (i == NUM_PMKID_CACHE)
Larry Finger5e93f352014-03-28 21:37:38 -05001952 i = -1;/* Could not find. */
Jes Sorensen480c8652014-04-15 19:44:45 +02001953 else {
Larry Finger5e93f352014-03-28 21:37:38 -05001954 /* There is one Pre-Authentication Key for
1955 the specific BSSID. */
1956 }
1957
1958 return i;
1959}
1960
1961/* */
1962/* Check the RSN IE length */
1963/* If the RSN IE length <= 20, the RSN IE didn't include
1964 the PMKID information */
1965/* 0-11th element in the array are the fixed IE */
1966/* 12th element in the array is the IE */
1967/* 13th element in the array is the IE length */
1968/* */
1969
1970static int rtw_append_pmkid(struct rtw_adapter *Adapter, int iEntry,
1971 u8 *ie, uint ie_len)
1972{
1973 struct security_priv *psecuritypriv = &Adapter->securitypriv;
1974
Jes Sorensen98f979f2014-06-24 15:03:56 +02001975 if (ie[1] <= 20) {
Larry Finger5e93f352014-03-28 21:37:38 -05001976 /* The RSN IE didn't include the PMK ID,
1977 append the PMK information */
1978 ie[ie_len] = 1;
1979 ie_len++;
1980 ie[ie_len] = 0; /* PMKID count = 0x0100 */
1981 ie_len++;
1982 memcpy(&ie[ie_len],
1983 &psecuritypriv->PMKIDList[iEntry].PMKID, 16);
1984
1985 ie_len += 16;
Jes Sorensen98f979f2014-06-24 15:03:56 +02001986 ie[1] += 18;/* PMKID length = 2+16 */
Larry Finger5e93f352014-03-28 21:37:38 -05001987 }
1988 return ie_len;
1989}
Jes Sorensen814a1d92014-04-09 23:21:06 +02001990
Larry Finger5e93f352014-03-28 21:37:38 -05001991int rtw_restruct_sec_ie23a(struct rtw_adapter *adapter, u8 *in_ie, u8 *out_ie,
Jes Sorensen480c8652014-04-15 19:44:45 +02001992 uint in_len)
Larry Finger5e93f352014-03-28 21:37:38 -05001993{
1994 u8 authmode;
1995 uint ielength;
1996 int iEntry;
1997 struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
1998 struct security_priv *psecuritypriv = &adapter->securitypriv;
1999 uint ndisauthmode = psecuritypriv->ndisauthtype;
2000 uint ndissecuritytype = psecuritypriv->ndisencryptstatus;
2001
2002 RT_TRACE(_module_rtl871x_mlme_c_, _drv_notice_,
Jes Sorensen480c8652014-04-15 19:44:45 +02002003 ("+rtw_restruct_sec_ie23a: ndisauthmode=%d "
2004 "ndissecuritytype=%d\n", ndisauthmode, ndissecuritytype));
Larry Finger5e93f352014-03-28 21:37:38 -05002005
Jes Sorensen1de65cc2014-06-24 15:03:30 +02002006 ielength = 0;
Jes Sorensen480c8652014-04-15 19:44:45 +02002007 if (ndisauthmode == Ndis802_11AuthModeWPA ||
2008 ndisauthmode == Ndis802_11AuthModeWPAPSK)
Jes Sorensen9300c942014-04-15 19:43:21 +02002009 authmode = WLAN_EID_VENDOR_SPECIFIC;
Jes Sorensen480c8652014-04-15 19:44:45 +02002010 if (ndisauthmode == Ndis802_11AuthModeWPA2 ||
2011 ndisauthmode == Ndis802_11AuthModeWPA2PSK)
Jes Sorensena131aac2014-06-21 16:50:15 +02002012 authmode = WLAN_EID_RSN;
Larry Finger5e93f352014-03-28 21:37:38 -05002013
2014 if (check_fwstate(pmlmepriv, WIFI_UNDER_WPS)) {
2015 memcpy(out_ie + ielength, psecuritypriv->wps_ie,
2016 psecuritypriv->wps_ie_len);
2017
2018 ielength += psecuritypriv->wps_ie_len;
Jes Sorensen480c8652014-04-15 19:44:45 +02002019 } else if (authmode == WLAN_EID_VENDOR_SPECIFIC ||
Jes Sorensena131aac2014-06-21 16:50:15 +02002020 authmode == WLAN_EID_RSN) {
Larry Finger5e93f352014-03-28 21:37:38 -05002021 /* copy RSN or SSN */
2022 memcpy(&out_ie[ielength], &psecuritypriv->supplicant_ie[0],
2023 psecuritypriv->supplicant_ie[1] + 2);
2024 ielength += psecuritypriv->supplicant_ie[1] + 2;
Larry Finger5e93f352014-03-28 21:37:38 -05002025 }
2026
2027 iEntry = SecIsInPMKIDList(adapter, pmlmepriv->assoc_bssid);
Jes Sorensen480c8652014-04-15 19:44:45 +02002028 if (iEntry < 0)
Larry Finger5e93f352014-03-28 21:37:38 -05002029 return ielength;
Jes Sorensen480c8652014-04-15 19:44:45 +02002030 else {
Jes Sorensena131aac2014-06-21 16:50:15 +02002031 if (authmode == WLAN_EID_RSN)
Jes Sorensen480c8652014-04-15 19:44:45 +02002032 ielength = rtw_append_pmkid(adapter, iEntry,
2033 out_ie, ielength);
Larry Finger5e93f352014-03-28 21:37:38 -05002034 }
2035
2036 return ielength;
2037}
2038
Greg Donald4e66cf02014-08-22 10:57:49 -05002039void rtw_init_registrypriv_dev_network23a(struct rtw_adapter *adapter)
Larry Finger5e93f352014-03-28 21:37:38 -05002040{
Greg Donald4e66cf02014-08-22 10:57:49 -05002041 struct registry_priv *pregistrypriv = &adapter->registrypriv;
2042 struct eeprom_priv *peepriv = &adapter->eeprompriv;
Larry Finger5e93f352014-03-28 21:37:38 -05002043 struct wlan_bssid_ex *pdev_network = &pregistrypriv->dev_network;
2044 u8 *myhwaddr = myid(peepriv);
2045
2046 ether_addr_copy(pdev_network->MacAddress, myhwaddr);
2047
2048 memcpy(&pdev_network->Ssid, &pregistrypriv->ssid,
2049 sizeof(struct cfg80211_ssid));
2050
Jes Sorensen143ced22014-06-19 11:37:22 +02002051 pdev_network->beacon_interval = 100;
Larry Finger5e93f352014-03-28 21:37:38 -05002052}
2053
Greg Donald4e66cf02014-08-22 10:57:49 -05002054void rtw_update_registrypriv_dev_network23a(struct rtw_adapter *adapter)
Larry Finger5e93f352014-03-28 21:37:38 -05002055{
2056 int sz = 0;
Greg Donald4e66cf02014-08-22 10:57:49 -05002057 struct registry_priv *pregistrypriv = &adapter->registrypriv;
Larry Finger5e93f352014-03-28 21:37:38 -05002058 struct wlan_bssid_ex *pdev_network = &pregistrypriv->dev_network;
2059 struct security_priv *psecuritypriv = &adapter->securitypriv;
2060 struct wlan_network *cur_network = &adapter->mlmepriv.cur_network;
2061 /* struct xmit_priv *pxmitpriv = &adapter->xmitpriv; */
2062
2063 pdev_network->Privacy =
2064 (psecuritypriv->dot11PrivacyAlgrthm > 0 ? 1 : 0);
2065
2066 pdev_network->Rssi = 0;
2067
Jes Sorensen37cb9822014-05-21 09:37:40 +02002068 pdev_network->DSConfig = pregistrypriv->channel;
Larry Finger5e93f352014-03-28 21:37:38 -05002069 RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_,
Jes Sorensen37cb9822014-05-21 09:37:40 +02002070 ("pregistrypriv->channel =%d, pdev_network->DSConfig = 0x%x\n",
2071 pregistrypriv->channel, pdev_network->DSConfig));
Larry Finger5e93f352014-03-28 21:37:38 -05002072
Jes Sorensenefc71442014-05-21 09:37:26 +02002073 if (cur_network->network.ifmode == NL80211_IFTYPE_ADHOC)
Jes Sorensen37cb9822014-05-21 09:37:40 +02002074 pdev_network->ATIMWindow = 0;
Larry Finger5e93f352014-03-28 21:37:38 -05002075
Jes Sorensenefc71442014-05-21 09:37:26 +02002076 pdev_network->ifmode = cur_network->network.ifmode;
Larry Finger5e93f352014-03-28 21:37:38 -05002077
2078 /* 1. Supported rates */
2079 /* 2. IE */
2080
2081 sz = rtw_generate_ie23a(pregistrypriv);
2082
2083 pdev_network->IELength = sz;
2084
2085 pdev_network->Length =
Jes Sorensen52017952014-04-26 18:55:09 +02002086 get_wlan_bssid_ex_sz(pdev_network);
Larry Finger5e93f352014-03-28 21:37:38 -05002087
2088 /* notes: translate IELength & Length after assign the
2089 Length to cmdsz in createbss_cmd(); */
2090 /* pdev_network->IELength = cpu_to_le32(sz); */
Larry Finger5e93f352014-03-28 21:37:38 -05002091}
2092
Masanari Iida7c17d2d2014-07-22 23:42:24 +09002093/* the function is at passive_level */
Larry Finger5e93f352014-03-28 21:37:38 -05002094void rtw_joinbss_reset23a(struct rtw_adapter *padapter)
2095{
2096 u8 threshold;
2097 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
2098 struct ht_priv *phtpriv = &pmlmepriv->htpriv;
2099
2100 /* todo: if you want to do something io/reg/hw setting
2101 before join_bss, please add code here */
2102
2103 pmlmepriv->num_FortyMHzIntolerant = 0;
2104
2105 pmlmepriv->num_sta_no_ht = 0;
2106
2107 phtpriv->ampdu_enable = false;/* reset to disabled */
2108
2109 /* TH = 1 => means that invalidate usb rx aggregation */
2110 /* TH = 0 => means that validate usb rx aggregation, use init value. */
2111 if (phtpriv->ht_option) {
2112 if (padapter->registrypriv.wifi_spec == 1)
2113 threshold = 1;
2114 else
2115 threshold = 0;
Jes Sorensen1e7b6eb2014-04-09 23:20:36 +02002116 } else
Larry Finger5e93f352014-03-28 21:37:38 -05002117 threshold = 1;
Jes Sorensen1e7b6eb2014-04-09 23:20:36 +02002118
2119 rtl8723a_set_rxdma_agg_pg_th(padapter, threshold);
Larry Finger5e93f352014-03-28 21:37:38 -05002120}
2121
Masanari Iida7c17d2d2014-07-22 23:42:24 +09002122/* the function is >= passive_level */
Jes Sorensen6f765c22014-06-09 15:16:06 +02002123bool rtw_restructure_ht_ie23a(struct rtw_adapter *padapter, u8 *in_ie,
2124 u8 *out_ie, uint in_len, uint *pout_len)
Larry Finger5e93f352014-03-28 21:37:38 -05002125{
Jes Sorensen7c2f97b2014-04-15 19:43:37 +02002126 u32 out_len;
Larry Finger5e93f352014-03-28 21:37:38 -05002127 int max_rx_ampdu_factor;
Jes Sorensen7c2f97b2014-04-15 19:43:37 +02002128 unsigned char *pframe;
2129 const u8 *p;
Larry Finger5e93f352014-03-28 21:37:38 -05002130 struct ieee80211_ht_cap ht_capie;
Jes Sorensenc9324c82014-06-09 15:16:05 +02002131 u8 WMM_IE[7] = {0x00, 0x50, 0xf2, 0x02, 0x00, 0x01, 0x00};
Larry Finger5e93f352014-03-28 21:37:38 -05002132 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
Larry Finger5e93f352014-03-28 21:37:38 -05002133 struct ht_priv *phtpriv = &pmlmepriv->htpriv;
2134
2135 phtpriv->ht_option = false;
2136
Jes Sorensen1de65cc2014-06-24 15:03:30 +02002137 p = cfg80211_find_ie(WLAN_EID_HT_CAPABILITY, in_ie, in_len);
Larry Finger5e93f352014-03-28 21:37:38 -05002138
Jes Sorensen7c2f97b2014-04-15 19:43:37 +02002139 if (p && p[1] > 0) {
Larry Finger5e93f352014-03-28 21:37:38 -05002140 u32 rx_packet_offset, max_recvbuf_sz;
Yeliz Taneroglu29ed9322014-10-09 01:22:14 +03002141
Jes Sorensenbd8ad4a2014-05-09 15:03:21 +02002142 if (pmlmepriv->qos_option == 0) {
Larry Finger5e93f352014-03-28 21:37:38 -05002143 out_len = *pout_len;
2144 pframe = rtw_set_ie23a(out_ie + out_len,
Jes Sorensenc9324c82014-06-09 15:16:05 +02002145 WLAN_EID_VENDOR_SPECIFIC,
2146 sizeof(WMM_IE), WMM_IE,
2147 pout_len);
Larry Finger5e93f352014-03-28 21:37:38 -05002148
Jes Sorensenbd8ad4a2014-05-09 15:03:21 +02002149 pmlmepriv->qos_option = 1;
Larry Finger5e93f352014-03-28 21:37:38 -05002150 }
2151
2152 out_len = *pout_len;
2153
2154 memset(&ht_capie, 0, sizeof(struct ieee80211_ht_cap));
2155
Kinka Huangce6bed62014-11-20 00:27:02 +08002156 ht_capie.cap_info = cpu_to_le16(IEEE80211_HT_CAP_SUP_WIDTH_20_40 |
Larry Finger5e93f352014-03-28 21:37:38 -05002157 IEEE80211_HT_CAP_SGI_20 | IEEE80211_HT_CAP_SGI_40 |
Kinka Huangce6bed62014-11-20 00:27:02 +08002158 IEEE80211_HT_CAP_TX_STBC | IEEE80211_HT_CAP_DSSSCCK40);
Larry Finger5e93f352014-03-28 21:37:38 -05002159
Jes Sorensen39f1a8e2014-05-16 10:04:20 +02002160 GetHalDefVar8192CUsb(padapter, HAL_DEF_RX_PACKET_OFFSET,
2161 &rx_packet_offset);
2162 GetHalDefVar8192CUsb(padapter, HAL_DEF_MAX_RECVBUF_SZ,
2163 &max_recvbuf_sz);
Larry Finger5e93f352014-03-28 21:37:38 -05002164
Jes Sorensen39f1a8e2014-05-16 10:04:20 +02002165 GetHalDefVar8192CUsb(padapter, HW_VAR_MAX_RX_AMPDU_FACTOR,
2166 &max_rx_ampdu_factor);
Larry Finger5e93f352014-03-28 21:37:38 -05002167 ht_capie.ampdu_params_info = max_rx_ampdu_factor & 0x03;
2168
Jes Sorensen9e3d6df2014-05-21 09:37:34 +02002169 if (padapter->securitypriv.dot11PrivacyAlgrthm ==
2170 WLAN_CIPHER_SUITE_CCMP)
Larry Finger5e93f352014-03-28 21:37:38 -05002171 ht_capie.ampdu_params_info |=
2172 (IEEE80211_HT_AMPDU_PARM_DENSITY& (0x07 << 2));
2173 else
2174 ht_capie.ampdu_params_info |=
2175 (IEEE80211_HT_AMPDU_PARM_DENSITY & 0x00);
2176
Jes Sorensena7eab382014-04-15 19:43:25 +02002177 pframe = rtw_set_ie23a(out_ie + out_len, WLAN_EID_HT_CAPABILITY,
Larry Finger5e93f352014-03-28 21:37:38 -05002178 sizeof(struct ieee80211_ht_cap),
Greg Donald7e6646d2014-09-06 19:42:03 -05002179 (unsigned char *)&ht_capie, pout_len);
Larry Finger5e93f352014-03-28 21:37:38 -05002180
2181 phtpriv->ht_option = true;
2182
Jes Sorensen1de65cc2014-06-24 15:03:30 +02002183 p = cfg80211_find_ie(WLAN_EID_HT_OPERATION, in_ie, in_len);
Jes Sorensen6594c962014-05-31 18:05:12 +02002184 if (p && (p[1] == sizeof(struct ieee80211_ht_operation))) {
Larry Finger5e93f352014-03-28 21:37:38 -05002185 out_len = *pout_len;
Jes Sorensena7eab382014-04-15 19:43:25 +02002186 pframe = rtw_set_ie23a(out_ie + out_len,
2187 WLAN_EID_HT_OPERATION,
Jes Sorensen7c2f97b2014-04-15 19:43:37 +02002188 p[1], p + 2 , pout_len);
Larry Finger5e93f352014-03-28 21:37:38 -05002189 }
2190 }
2191
2192 return phtpriv->ht_option;
2193}
2194
Masanari Iida7c17d2d2014-07-22 23:42:24 +09002195/* the function is > passive_level (in critical_section) */
Larry Finger5e93f352014-03-28 21:37:38 -05002196void rtw_update_ht_cap23a(struct rtw_adapter *padapter, u8 *pie, uint ie_len)
2197{
Jes Sorensen2403ea62014-04-15 19:43:38 +02002198 u8 max_ampdu_sz;
2199 const u8 *p;
Larry Finger5e93f352014-03-28 21:37:38 -05002200 struct ieee80211_ht_cap *pht_capie;
Jes Sorensen6594c962014-05-31 18:05:12 +02002201 struct ieee80211_ht_operation *pht_addtinfo;
Jes Sorensen2403ea62014-04-15 19:43:38 +02002202 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
2203 struct ht_priv *phtpriv = &pmlmepriv->htpriv;
Larry Finger5e93f352014-03-28 21:37:38 -05002204 struct registry_priv *pregistrypriv = &padapter->registrypriv;
Jes Sorensen2403ea62014-04-15 19:43:38 +02002205 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
Larry Finger5e93f352014-03-28 21:37:38 -05002206 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
2207
2208 if (!phtpriv->ht_option)
2209 return;
2210
2211 if ((!pmlmeinfo->HT_info_enable) || (!pmlmeinfo->HT_caps_enable))
2212 return;
2213
2214 DBG_8723A("+rtw_update_ht_cap23a()\n");
2215
2216 /* maybe needs check if ap supports rx ampdu. */
Jes Sorensen47e5d2f2014-06-09 15:16:08 +02002217 if (!phtpriv->ampdu_enable && pregistrypriv->ampdu_enable == 1) {
Larry Finger5e93f352014-03-28 21:37:38 -05002218 if (pregistrypriv->wifi_spec == 1)
2219 phtpriv->ampdu_enable = false;
2220 else
2221 phtpriv->ampdu_enable = true;
Jes Sorensen2403ea62014-04-15 19:43:38 +02002222 } else if (pregistrypriv->ampdu_enable == 2)
Larry Finger5e93f352014-03-28 21:37:38 -05002223 phtpriv->ampdu_enable = true;
Larry Finger5e93f352014-03-28 21:37:38 -05002224
2225 /* check Max Rx A-MPDU Size */
Jes Sorensen2403ea62014-04-15 19:43:38 +02002226 p = cfg80211_find_ie(WLAN_EID_HT_CAPABILITY, pie, ie_len);
Larry Finger5e93f352014-03-28 21:37:38 -05002227
Jes Sorensen2403ea62014-04-15 19:43:38 +02002228 if (p && p[1] > 0) {
2229 pht_capie = (struct ieee80211_ht_cap *)(p + 2);
2230 max_ampdu_sz = pht_capie->ampdu_params_info &
2231 IEEE80211_HT_AMPDU_PARM_FACTOR;
2232 /* max_ampdu_sz (kbytes); */
2233 max_ampdu_sz = 1 << (max_ampdu_sz + 3);
2234
Larry Finger5e93f352014-03-28 21:37:38 -05002235 phtpriv->rx_ampdu_maxlen = max_ampdu_sz;
Larry Finger5e93f352014-03-28 21:37:38 -05002236 }
2237
Jes Sorensen2403ea62014-04-15 19:43:38 +02002238 p = cfg80211_find_ie(WLAN_EID_HT_OPERATION, pie, ie_len);
2239 if (p && p[1] > 0) {
Jes Sorensen6594c962014-05-31 18:05:12 +02002240 pht_addtinfo = (struct ieee80211_ht_operation *)(p + 2);
Larry Finger5e93f352014-03-28 21:37:38 -05002241 /* todo: */
2242 }
2243
2244 /* update cur_bwmode & cur_ch_offset */
Jes Sorensen2403ea62014-04-15 19:43:38 +02002245 if (pregistrypriv->cbw40_enable &&
Jes Sorensen65be27d2014-05-31 18:05:11 +02002246 pmlmeinfo->ht_cap.cap_info &
2247 cpu_to_le16(IEEE80211_HT_CAP_SUP_WIDTH_20_40) &&
Jes Sorensen4dc5f8b2014-05-31 18:05:13 +02002248 pmlmeinfo->HT_info.ht_param & IEEE80211_HT_PARAM_CHAN_WIDTH_ANY) {
Larry Finger5e93f352014-03-28 21:37:38 -05002249 int i;
Jes Sorensenc2370e82014-04-09 23:20:53 +02002250 u8 rf_type;
Larry Finger5e93f352014-03-28 21:37:38 -05002251
Jes Sorensenc2370e82014-04-09 23:20:53 +02002252 rf_type = rtl8723a_get_rf_type(padapter);
Larry Finger5e93f352014-03-28 21:37:38 -05002253
2254 /* update the MCS rates */
Jes Sorensen198e95d2014-05-31 18:05:10 +02002255 for (i = 0; i < IEEE80211_HT_MCS_MASK_LEN; i++) {
Jes Sorensen480c8652014-04-15 19:44:45 +02002256 if (rf_type == RF_1T1R || rf_type == RF_1T2R)
Jes Sorensen65be27d2014-05-31 18:05:11 +02002257 pmlmeinfo->ht_cap.mcs.rx_mask[i] &=
2258 MCS_rate_1R23A[i];
Larry Finger5e93f352014-03-28 21:37:38 -05002259 else
Jes Sorensen65be27d2014-05-31 18:05:11 +02002260 pmlmeinfo->ht_cap.mcs.rx_mask[i] &=
2261 MCS_rate_2R23A[i];
Larry Finger5e93f352014-03-28 21:37:38 -05002262 }
Masanari Iida7c17d2d2014-07-22 23:42:24 +09002263 /* switch to the 40M Hz mode according to the AP */
Larry Finger5e93f352014-03-28 21:37:38 -05002264 pmlmeext->cur_bwmode = HT_CHANNEL_WIDTH_40;
Jes Sorensen4dc5f8b2014-05-31 18:05:13 +02002265 switch (pmlmeinfo->HT_info.ht_param &
Jes Sorensenb2775412014-06-03 23:41:22 +02002266 IEEE80211_HT_PARAM_CHA_SEC_OFFSET) {
Jes Sorensen4dc5f8b2014-05-31 18:05:13 +02002267 case IEEE80211_HT_PARAM_CHA_SEC_ABOVE:
Jes Sorensenb54e8802014-04-09 23:20:52 +02002268 pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_LOWER;
2269 break;
Larry Finger5e93f352014-03-28 21:37:38 -05002270
Jes Sorensen4dc5f8b2014-05-31 18:05:13 +02002271 case IEEE80211_HT_PARAM_CHA_SEC_BELOW:
Jes Sorensenb54e8802014-04-09 23:20:52 +02002272 pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_UPPER;
2273 break;
Larry Finger5e93f352014-03-28 21:37:38 -05002274
Jes Sorensenb54e8802014-04-09 23:20:52 +02002275 default:
2276 pmlmeext->cur_ch_offset =
2277 HAL_PRIME_CHNL_OFFSET_DONT_CARE;
2278 break;
Larry Finger5e93f352014-03-28 21:37:38 -05002279 }
2280 }
2281
2282 /* */
2283 /* Config SM Power Save setting */
2284 /* */
Jes Sorensen65be27d2014-05-31 18:05:11 +02002285 pmlmeinfo->SM_PS =
2286 (le16_to_cpu(pmlmeinfo->ht_cap.cap_info) &
2287 IEEE80211_HT_CAP_SM_PS) >> IEEE80211_HT_CAP_SM_PS_SHIFT;
Larry Finger5e93f352014-03-28 21:37:38 -05002288 if (pmlmeinfo->SM_PS == WLAN_HT_CAP_SM_PS_STATIC)
2289 DBG_8723A("%s(): WLAN_HT_CAP_SM_PS_STATIC\n", __func__);
2290
2291 /* */
2292 /* Config current HT Protection mode. */
2293 /* */
Jes Sorensen4dc5f8b2014-05-31 18:05:13 +02002294 pmlmeinfo->HT_protection =
2295 le16_to_cpu(pmlmeinfo->HT_info.operation_mode) &
2296 IEEE80211_HT_OP_MODE_PROTECTION;
Larry Finger5e93f352014-03-28 21:37:38 -05002297}
2298
Jes Sorensen480c8652014-04-15 19:44:45 +02002299void rtw_issue_addbareq_cmd23a(struct rtw_adapter *padapter,
2300 struct xmit_frame *pxmitframe)
Larry Finger5e93f352014-03-28 21:37:38 -05002301{
2302 u8 issued;
2303 int priority;
Jes Sorensen480c8652014-04-15 19:44:45 +02002304 struct sta_info *psta;
Larry Finger5e93f352014-03-28 21:37:38 -05002305 struct ht_priv *phtpriv;
2306 struct pkt_attrib *pattrib = &pxmitframe->attrib;
2307 s32 bmcst = is_multicast_ether_addr(pattrib->ra);
2308
Jes Sorensen480c8652014-04-15 19:44:45 +02002309 if (bmcst || padapter->mlmepriv.LinkDetectInfo.NumTxOkInPeriod < 100)
Larry Finger5e93f352014-03-28 21:37:38 -05002310 return;
2311
2312 priority = pattrib->priority;
2313
2314 if (pattrib->psta)
2315 psta = pattrib->psta;
Jes Sorensen480c8652014-04-15 19:44:45 +02002316 else {
Larry Finger5e93f352014-03-28 21:37:38 -05002317 DBG_8723A("%s, call rtw_get_stainfo23a()\n", __func__);
2318 psta = rtw_get_stainfo23a(&padapter->stapriv, pattrib->ra);
2319 }
2320
Jes Sorensen480c8652014-04-15 19:44:45 +02002321 if (!psta) {
Larry Finger5e93f352014-03-28 21:37:38 -05002322 DBG_8723A("%s, psta == NUL\n", __func__);
2323 return;
2324 }
2325
Jes Sorensen480c8652014-04-15 19:44:45 +02002326 if (!(psta->state &_FW_LINKED)) {
2327 DBG_8723A("%s, psta->state(0x%x) != _FW_LINKED\n",
2328 __func__, psta->state);
Larry Finger5e93f352014-03-28 21:37:38 -05002329 return;
2330 }
2331
2332 phtpriv = &psta->htpriv;
2333
Jes Sorensen47e5d2f2014-06-09 15:16:08 +02002334 if (phtpriv->ht_option && phtpriv->ampdu_enable) {
Larry Finger5e93f352014-03-28 21:37:38 -05002335 issued = (phtpriv->agg_enable_bitmap>>priority)&0x1;
2336 issued |= (phtpriv->candidate_tid_bitmap>>priority)&0x1;
2337
Jes Sorensen480c8652014-04-15 19:44:45 +02002338 if (issued == 0) {
2339 DBG_8723A("rtw_issue_addbareq_cmd23a, p =%d\n",
2340 priority);
Jes Sorensen561fb402014-05-09 15:04:20 +02002341 psta->htpriv.candidate_tid_bitmap |= BIT(priority);
Jes Sorensen480c8652014-04-15 19:44:45 +02002342 rtw_addbareq_cmd23a(padapter, (u8) priority,
2343 pattrib->ra);
Larry Finger5e93f352014-03-28 21:37:38 -05002344 }
2345 }
2346}
2347
Larry Finger5e93f352014-03-28 21:37:38 -05002348int rtw_linked_check(struct rtw_adapter *padapter)
2349{
Jes Sorensen56828792014-04-15 19:44:46 +02002350 if (check_fwstate(&padapter->mlmepriv, WIFI_AP_STATE) ||
2351 check_fwstate(&padapter->mlmepriv,
2352 WIFI_ADHOC_STATE|WIFI_ADHOC_MASTER_STATE)) {
Larry Finger5e93f352014-03-28 21:37:38 -05002353 if (padapter->stapriv.asoc_sta_count > 2)
2354 return true;
2355 } else { /* Station mode */
Jes Sorensen56828792014-04-15 19:44:46 +02002356 if (check_fwstate(&padapter->mlmepriv, _FW_LINKED))
Larry Finger5e93f352014-03-28 21:37:38 -05002357 return true;
2358 }
2359 return false;
2360}