blob: 7299ef0a2e54c735686102d4ad852565c6690d4f [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 */
Jes Sorensenf7bf8c22014-11-30 16:04:53 -05001025 DBG_8723A("%s signal_strength:%3u, signal_qual:%3u\n",
Larry Finger5e93f352014-03-28 21:37:38 -05001026 __func__, padapter->recvpriv.signal_strength,
Jes Sorensenf7bf8c22014-11-30 16:04:53 -05001027 padapter->recvpriv.signal_qual);
Larry Finger5e93f352014-03-28 21:37:38 -05001028 rtw_set_signal_stat_timer(&padapter->recvpriv);
1029
1030 /* update fw_state will clr _FW_UNDER_LINKING here indirectly */
Jes Sorensenefc71442014-05-21 09:37:26 +02001031 switch (pnetwork->network.ifmode) {
1032 case NL80211_IFTYPE_P2P_CLIENT:
1033 case NL80211_IFTYPE_STATION:
1034 if (pmlmepriv->fw_state & WIFI_UNDER_WPS)
Larry Finger5e93f352014-03-28 21:37:38 -05001035 pmlmepriv->fw_state = WIFI_STATION_STATE|WIFI_UNDER_WPS;
1036 else
1037 pmlmepriv->fw_state = WIFI_STATION_STATE;
1038 break;
Jes Sorensenefc71442014-05-21 09:37:26 +02001039 case NL80211_IFTYPE_ADHOC:
Larry Finger5e93f352014-03-28 21:37:38 -05001040 pmlmepriv->fw_state = WIFI_ADHOC_STATE;
1041 break;
1042 default:
1043 pmlmepriv->fw_state = WIFI_NULL_STATE;
Jes Sorensen480c8652014-04-15 19:44:45 +02001044 RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_,
1045 ("Invalid network_mode\n"));
Larry Finger5e93f352014-03-28 21:37:38 -05001046 break;
1047 }
1048
Jes Sorensen68e6c792014-06-24 15:03:29 +02001049 rtw_update_protection23a(padapter, cur_network->network.IEs,
1050 cur_network->network.IELength);
Larry Finger5e93f352014-03-28 21:37:38 -05001051
Jes Sorensen480c8652014-04-15 19:44:45 +02001052 rtw_update_ht_cap23a(padapter, cur_network->network.IEs,
1053 cur_network->network.IELength);
Larry Finger5e93f352014-03-28 21:37:38 -05001054}
1055
Jes Sorensen480c8652014-04-15 19:44:45 +02001056/*
1057 * Notes:
Masanari Iida7c17d2d2014-07-22 23:42:24 +09001058 * the function could be > passive_level (the same context as Rx tasklet)
Jes Sorensen480c8652014-04-15 19:44:45 +02001059 * pnetwork : returns from rtw23a_joinbss_event_cb
1060 * ptarget_wlan: found from scanned_queue
1061 * if join_res > 0, for (fw_state==WIFI_STATION_STATE),
1062 * we check if "ptarget_sta" & "ptarget_wlan" exist.
1063 * if join_res > 0, for (fw_state==WIFI_ADHOC_STATE),
1064 * we only check if "ptarget_wlan" exist.
1065 * if join_res > 0, update "cur_network->network" from "pnetwork->network"
1066 * if (ptarget_wlan !=NULL).
1067 */
Larry Finger5e93f352014-03-28 21:37:38 -05001068
1069void rtw_joinbss_event_prehandle23a(struct rtw_adapter *adapter, u8 *pbuf)
1070{
Jes Sorensen480c8652014-04-15 19:44:45 +02001071 struct sta_info *ptarget_sta, *pcur_sta;
1072 struct sta_priv *pstapriv = &adapter->stapriv;
1073 struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
1074 struct wlan_network *pnetwork = (struct wlan_network *)pbuf;
Larry Finger5e93f352014-03-28 21:37:38 -05001075 struct wlan_network *cur_network = &pmlmepriv->cur_network;
Jes Sorensen480c8652014-04-15 19:44:45 +02001076 struct wlan_network *pcur_wlan, *ptarget_wlan = NULL;
1077 bool the_same_macaddr;
Larry Finger5e93f352014-03-28 21:37:38 -05001078
Greg Donaldc895a5d2014-09-16 18:37:41 -05001079 RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_,
Jes Sorensen480c8652014-04-15 19:44:45 +02001080 ("joinbss event call back received with res=%d\n",
1081 pnetwork->join_res));
Larry Finger5e93f352014-03-28 21:37:38 -05001082
Larry Finger5e93f352014-03-28 21:37:38 -05001083 if (pmlmepriv->assoc_ssid.ssid_len == 0) {
Greg Donaldc895a5d2014-09-16 18:37:41 -05001084 RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_,
Jes Sorensen480c8652014-04-15 19:44:45 +02001085 ("@@@@@ joinbss event call back for Any SSid\n"));
Larry Finger5e93f352014-03-28 21:37:38 -05001086 } else {
Greg Donaldc895a5d2014-09-16 18:37:41 -05001087 RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_,
Larry Finger5e93f352014-03-28 21:37:38 -05001088 ("@@@@@ rtw23a_joinbss_event_cb for SSid:%s\n",
1089 pmlmepriv->assoc_ssid.ssid));
1090 }
1091
1092 if (ether_addr_equal(pnetwork->network.MacAddress,
1093 cur_network->network.MacAddress))
1094 the_same_macaddr = true;
1095 else
1096 the_same_macaddr = false;
1097
1098 pnetwork->network.Length = get_wlan_bssid_ex_sz(&pnetwork->network);
Jes Sorensen480c8652014-04-15 19:44:45 +02001099 if (pnetwork->network.Length > sizeof(struct wlan_bssid_ex)) {
Greg Donaldc895a5d2014-09-16 18:37:41 -05001100 RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_,
Jes Sorensen480c8652014-04-15 19:44:45 +02001101 ("\n\n ***joinbss_evt_callback return a wrong bss "
1102 "***\n\n"));
Larry Finger5e93f352014-03-28 21:37:38 -05001103 return;
1104 }
1105
1106 spin_lock_bh(&pmlmepriv->lock);
1107
Greg Donaldc895a5d2014-09-16 18:37:41 -05001108 RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_,
Jes Sorensen480c8652014-04-15 19:44:45 +02001109 ("\n rtw23a_joinbss_event_cb !! _enter_critical\n"));
Larry Finger5e93f352014-03-28 21:37:38 -05001110
Jes Sorensen480c8652014-04-15 19:44:45 +02001111 if (pnetwork->join_res > 0) {
Larry Finger5e93f352014-03-28 21:37:38 -05001112 spin_lock_bh(&pmlmepriv->scanned_queue.lock);
Greg Donaldc895a5d2014-09-16 18:37:41 -05001113 if (check_fwstate(pmlmepriv, _FW_UNDER_LINKING)) {
Larry Finger5e93f352014-03-28 21:37:38 -05001114 /* s1. find ptarget_wlan */
Jes Sorensen480c8652014-04-15 19:44:45 +02001115 if (check_fwstate(pmlmepriv, _FW_LINKED)) {
Roberta Dobrescu08551cb2014-10-26 23:30:05 +02001116 if (the_same_macaddr) {
Larry Finger5e93f352014-03-28 21:37:38 -05001117 ptarget_wlan = rtw_find_network23a(&pmlmepriv->scanned_queue, cur_network->network.MacAddress);
Jes Sorensen480c8652014-04-15 19:44:45 +02001118 } else {
Larry Finger5e93f352014-03-28 21:37:38 -05001119 pcur_wlan = rtw_find_network23a(&pmlmepriv->scanned_queue, cur_network->network.MacAddress);
Jes Sorensen480c8652014-04-15 19:44:45 +02001120 if (pcur_wlan)
1121 pcur_wlan->fixed = false;
Larry Finger5e93f352014-03-28 21:37:38 -05001122
1123 pcur_sta = rtw_get_stainfo23a(pstapriv, cur_network->network.MacAddress);
Jes Sorensen480c8652014-04-15 19:44:45 +02001124 if (pcur_sta) {
Larry Finger5e93f352014-03-28 21:37:38 -05001125 spin_lock_bh(&pstapriv->sta_hash_lock);
Jes Sorensen480c8652014-04-15 19:44:45 +02001126 rtw_free_stainfo23a(adapter,
1127 pcur_sta);
Larry Finger5e93f352014-03-28 21:37:38 -05001128 spin_unlock_bh(&pstapriv->sta_hash_lock);
1129 }
1130
1131 ptarget_wlan = rtw_find_network23a(&pmlmepriv->scanned_queue, pnetwork->network.MacAddress);
Jes Sorensen480c8652014-04-15 19:44:45 +02001132 if (check_fwstate(pmlmepriv,
1133 WIFI_STATION_STATE)) {
1134 if (ptarget_wlan)
1135 ptarget_wlan->fixed =
1136 true;
Larry Finger5e93f352014-03-28 21:37:38 -05001137 }
1138 }
1139
Jes Sorensen480c8652014-04-15 19:44:45 +02001140 } else {
1141 ptarget_wlan = rtw_find_network23a(
1142 &pmlmepriv->scanned_queue,
1143 pnetwork->network.MacAddress);
1144 if (check_fwstate(pmlmepriv,
1145 WIFI_STATION_STATE)) {
1146 if (ptarget_wlan)
1147 ptarget_wlan->fixed = true;
Larry Finger5e93f352014-03-28 21:37:38 -05001148 }
1149 }
1150
1151 /* s2. update cur_network */
Jes Sorensen480c8652014-04-15 19:44:45 +02001152 if (ptarget_wlan)
1153 rtw_joinbss_update_network23a(adapter,
1154 ptarget_wlan,
1155 pnetwork);
1156 else {
Greg Donaldc895a5d2014-09-16 18:37:41 -05001157 RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_,
Jes Sorensen480c8652014-04-15 19:44:45 +02001158 ("Can't find ptarget_wlan when "
1159 "joinbss_event callback\n"));
Larry Finger5e93f352014-03-28 21:37:38 -05001160 spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
1161 goto ignore_joinbss_callback;
1162 }
1163
Jes Sorensen480c8652014-04-15 19:44:45 +02001164 /* s3. find ptarget_sta & update ptarget_sta after
1165 update cur_network only for station mode */
1166 if (check_fwstate(pmlmepriv, WIFI_STATION_STATE)) {
1167 ptarget_sta = rtw_joinbss_update_stainfo(
1168 adapter, pnetwork);
1169 if (!ptarget_sta) {
1170 RT_TRACE(_module_rtl871x_mlme_c_,
1171 _drv_err_,
1172 ("Can't update stainfo when "
1173 "joinbss_event callback\n"));
Larry Finger5e93f352014-03-28 21:37:38 -05001174 spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
1175 goto ignore_joinbss_callback;
1176 }
1177 }
1178
1179 /* s4. indicate connect */
Jes Sorensen480c8652014-04-15 19:44:45 +02001180 if (check_fwstate(pmlmepriv, WIFI_STATION_STATE))
Larry Finger5e93f352014-03-28 21:37:38 -05001181 rtw_indicate_connect23a(adapter);
Jes Sorensen480c8652014-04-15 19:44:45 +02001182 else {
1183 /* adhoc mode will rtw_indicate_connect23a
1184 when rtw_stassoc_event_callback23a */
Greg Donaldc895a5d2014-09-16 18:37:41 -05001185 RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_,
Jes Sorensen480c8652014-04-15 19:44:45 +02001186 ("adhoc mode, fw_state:%x",
1187 get_fwstate(pmlmepriv)));
Larry Finger5e93f352014-03-28 21:37:38 -05001188 }
1189
1190 /* s5. Cancle assoc_timer */
1191 del_timer_sync(&pmlmepriv->assoc_timer);
1192
Greg Donaldc895a5d2014-09-16 18:37:41 -05001193 RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_,
Jes Sorensen480c8652014-04-15 19:44:45 +02001194 ("Cancle assoc_timer\n"));
Larry Finger5e93f352014-03-28 21:37:38 -05001195 } else {
1196 RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_,
1197 ("rtw23a_joinbss_event_cb err: fw_state:%x",
1198 get_fwstate(pmlmepriv)));
1199 spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
1200 goto ignore_joinbss_callback;
1201 }
1202 spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
Jes Sorensen480c8652014-04-15 19:44:45 +02001203 } else if (pnetwork->join_res == -4) {
Larry Finger5e93f352014-03-28 21:37:38 -05001204 rtw_reset_securitypriv23a(adapter);
1205 mod_timer(&pmlmepriv->assoc_timer,
1206 jiffies + msecs_to_jiffies(1));
1207
1208 /* rtw_free_assoc_resources23a(adapter, 1); */
1209
Jes Sorensen480c8652014-04-15 19:44:45 +02001210 if (check_fwstate(pmlmepriv, _FW_UNDER_LINKING)) {
Larry Finger5e93f352014-03-28 21:37:38 -05001211 RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_,
Jes Sorensen480c8652014-04-15 19:44:45 +02001212 ("fail! clear _FW_UNDER_LINKING ^^^fw_state="
1213 "%x\n", get_fwstate(pmlmepriv)));
Larry Finger5e93f352014-03-28 21:37:38 -05001214 _clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING);
1215 }
Larry Finger5e93f352014-03-28 21:37:38 -05001216 } else {
1217 /* if join_res < 0 (join fails), then try again */
1218 mod_timer(&pmlmepriv->assoc_timer,
1219 jiffies + msecs_to_jiffies(1));
1220 _clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING);
1221 }
1222
1223ignore_joinbss_callback:
1224
1225 spin_unlock_bh(&pmlmepriv->lock);
1226}
1227
Jes Sorensene2601962014-05-09 15:03:19 +02001228void rtw23a_joinbss_event_cb(struct rtw_adapter *adapter, const u8 *pbuf)
Larry Finger5e93f352014-03-28 21:37:38 -05001229{
Jes Sorensen480c8652014-04-15 19:44:45 +02001230 struct wlan_network *pnetwork = (struct wlan_network *)pbuf;
Larry Finger5e93f352014-03-28 21:37:38 -05001231
1232 mlmeext_joinbss_event_callback23a(adapter, pnetwork->join_res);
1233
1234 rtw_os_xmit_schedule23a(adapter);
Larry Finger5e93f352014-03-28 21:37:38 -05001235}
1236
Jes Sorensene2601962014-05-09 15:03:19 +02001237void rtw_stassoc_event_callback23a(struct rtw_adapter *adapter, const u8 *pbuf)
Larry Finger5e93f352014-03-28 21:37:38 -05001238{
1239 struct sta_info *psta;
1240 struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
Greg Donald7e6646d2014-09-06 19:42:03 -05001241 struct stassoc_event *pstassoc = (struct stassoc_event *)pbuf;
Larry Finger5e93f352014-03-28 21:37:38 -05001242 struct wlan_network *cur_network = &pmlmepriv->cur_network;
Jes Sorensen480c8652014-04-15 19:44:45 +02001243 struct wlan_network *ptarget_wlan;
Larry Finger5e93f352014-03-28 21:37:38 -05001244
Jes Sorensen480c8652014-04-15 19:44:45 +02001245 if (rtw_access_ctrl23a(adapter, pstassoc->macaddr) == false)
Larry Finger5e93f352014-03-28 21:37:38 -05001246 return;
1247
1248#ifdef CONFIG_8723AU_AP_MODE
Jes Sorensen480c8652014-04-15 19:44:45 +02001249 if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) {
Larry Finger5e93f352014-03-28 21:37:38 -05001250 psta = rtw_get_stainfo23a(&adapter->stapriv, pstassoc->macaddr);
1251 if (psta) {
1252 /* bss_cap_update_on_sta_join23a(adapter, psta); */
1253 /* sta_info_update23a(adapter, psta); */
1254 ap_sta_info_defer_update23a(adapter, psta);
Larry Finger5e93f352014-03-28 21:37:38 -05001255 }
1256 return;
1257 }
1258#endif
1259 /* for AD-HOC mode */
1260 psta = rtw_get_stainfo23a(&adapter->stapriv, pstassoc->macaddr);
1261 if (psta != NULL) {
1262 /* the sta have been in sta_info_queue => do nothing */
Greg Donaldc895a5d2014-09-16 18:37:41 -05001263 RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_,
Jes Sorensen480c8652014-04-15 19:44:45 +02001264 ("Error: rtw_stassoc_event_callback23a: sta has "
1265 "been in sta_hash_queue\n"));
1266 /* between drv has received this event before and
1267 fw have not yet to set key to CAM_ENTRY) */
1268 return;
Larry Finger5e93f352014-03-28 21:37:38 -05001269 }
1270
Jes Sorensen6e8bc712014-05-09 15:03:49 +02001271 psta = rtw_alloc_stainfo23a(&adapter->stapriv, pstassoc->macaddr,
1272 GFP_KERNEL);
Jes Sorensen480c8652014-04-15 19:44:45 +02001273 if (!psta) {
Greg Donaldc895a5d2014-09-16 18:37:41 -05001274 RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_,
Jes Sorensen480c8652014-04-15 19:44:45 +02001275 ("Can't alloc sta_info when "
1276 "rtw_stassoc_event_callback23a\n"));
Larry Finger5e93f352014-03-28 21:37:38 -05001277 return;
1278 }
1279
1280 /* to do : init sta_info variable */
1281 psta->qos_option = 0;
1282 psta->mac_id = (uint)pstassoc->cam_id;
1283 /* psta->aid = (uint)pstassoc->cam_id; */
Greg Donaldc895a5d2014-09-16 18:37:41 -05001284 DBG_8723A("%s\n", __func__);
Larry Finger5e93f352014-03-28 21:37:38 -05001285 /* for ad-hoc mode */
Jes Sorensendbe98492014-05-16 10:04:13 +02001286 rtl8723a_SetHalODMVar(adapter, HAL_ODM_STA_INFO, psta, true);
Larry Finger5e93f352014-03-28 21:37:38 -05001287
Jes Sorensen480c8652014-04-15 19:44:45 +02001288 if (adapter->securitypriv.dot11AuthAlgrthm == dot11AuthAlgrthm_8021X)
1289 psta->dot118021XPrivacy =
1290 adapter->securitypriv.dot11PrivacyAlgrthm;
Larry Finger5e93f352014-03-28 21:37:38 -05001291
1292 psta->ieee8021x_blocked = false;
1293
1294 spin_lock_bh(&pmlmepriv->lock);
1295
Jes Sorensen480c8652014-04-15 19:44:45 +02001296 if (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) ||
1297 check_fwstate(pmlmepriv, WIFI_ADHOC_STATE)) {
1298 if (adapter->stapriv.asoc_sta_count == 2) {
Larry Finger5e93f352014-03-28 21:37:38 -05001299 spin_lock_bh(&pmlmepriv->scanned_queue.lock);
Jes Sorensen480c8652014-04-15 19:44:45 +02001300 ptarget_wlan =
1301 rtw_find_network23a(&pmlmepriv->scanned_queue,
1302 cur_network->network.MacAddress);
1303 if (ptarget_wlan)
1304 ptarget_wlan->fixed = true;
Larry Finger5e93f352014-03-28 21:37:38 -05001305 spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
1306 /* a sta + bc/mc_stainfo (not Ibss_stainfo) */
1307 rtw_indicate_connect23a(adapter);
1308 }
1309 }
1310
1311 spin_unlock_bh(&pmlmepriv->lock);
1312
1313 mlmeext_sta_add_event_callback23a(adapter, psta);
1314}
1315
Jes Sorensene2601962014-05-09 15:03:19 +02001316void rtw_stadel_event_callback23a(struct rtw_adapter *adapter, const u8 *pbuf)
Larry Finger5e93f352014-03-28 21:37:38 -05001317{
Jes Sorensen480c8652014-04-15 19:44:45 +02001318 int mac_id;
Larry Finger5e93f352014-03-28 21:37:38 -05001319 struct sta_info *psta;
Greg Donald4e66cf02014-08-22 10:57:49 -05001320 struct wlan_network *pwlan;
Jes Sorensen480c8652014-04-15 19:44:45 +02001321 struct wlan_bssid_ex *pdev_network;
Jes Sorensen480c8652014-04-15 19:44:45 +02001322 struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
1323 struct stadel_event *pstadel = (struct stadel_event *)pbuf;
1324 struct sta_priv *pstapriv = &adapter->stapriv;
Larry Finger5e93f352014-03-28 21:37:38 -05001325 struct wlan_network *tgt_network = &pmlmepriv->cur_network;
1326
1327 psta = rtw_get_stainfo23a(&adapter->stapriv, pstadel->macaddr);
Jes Sorensen480c8652014-04-15 19:44:45 +02001328 if (psta)
Larry Finger5e93f352014-03-28 21:37:38 -05001329 mac_id = psta->mac_id;
1330 else
1331 mac_id = pstadel->mac_id;
1332
Jes Sorensen480c8652014-04-15 19:44:45 +02001333 DBG_8723A("%s(mac_id=%d)=" MAC_FMT "\n", __func__, mac_id,
1334 MAC_ARG(pstadel->macaddr));
Larry Finger5e93f352014-03-28 21:37:38 -05001335
Greg Donalda82b4b02014-09-08 20:50:23 -05001336 if (check_fwstate(pmlmepriv, WIFI_AP_STATE))
Larry Finger5e93f352014-03-28 21:37:38 -05001337 return;
Larry Finger5e93f352014-03-28 21:37:38 -05001338
1339 mlmeext_sta_del_event_callback23a(adapter);
1340
1341 spin_lock_bh(&pmlmepriv->lock);
1342
Jes Sorensen480c8652014-04-15 19:44:45 +02001343 if (check_fwstate(pmlmepriv, WIFI_STATION_STATE)) {
Jes Sorensen56828792014-04-15 19:44:46 +02001344 if (adapter->mlmepriv.to_roaming > 0) {
Jes Sorensen480c8652014-04-15 19:44:45 +02001345 /* this stadel_event is caused by roaming,
1346 decrease to_roaming */
1347 pmlmepriv->to_roaming--;
Jes Sorensen56828792014-04-15 19:44:46 +02001348 } else if (adapter->mlmepriv.to_roaming == 0)
Larry Finger5e93f352014-03-28 21:37:38 -05001349 rtw_set_roaming(adapter, adapter->registrypriv.max_roaming_times);
Jes Sorensen480c8652014-04-15 19:44:45 +02001350 if (*((u16 *)pstadel->rsvd) != WLAN_REASON_EXPIRATION_CHK)
Larry Finger5e93f352014-03-28 21:37:38 -05001351 rtw_set_roaming(adapter, 0); /* don't roam */
1352
1353 rtw_free_uc_swdec_pending_queue23a(adapter);
1354
1355 rtw_free_assoc_resources23a(adapter, 1);
1356 rtw_indicate_disconnect23a(adapter);
1357 spin_lock_bh(&pmlmepriv->scanned_queue.lock);
1358 /* remove the network entry in scanned_queue */
Jes Sorensen480c8652014-04-15 19:44:45 +02001359 pwlan = rtw_find_network23a(&pmlmepriv->scanned_queue,
1360 tgt_network->network.MacAddress);
Larry Finger5e93f352014-03-28 21:37:38 -05001361 if (pwlan) {
1362 pwlan->fixed = false;
1363 rtw_free_network_nolock(pmlmepriv, pwlan);
1364 }
1365 spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
1366
Jes Sorensenafa7e482014-04-15 19:44:50 +02001367 _rtw_roaming(adapter, tgt_network);
Larry Finger5e93f352014-03-28 21:37:38 -05001368 }
1369
1370 if (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) ||
Jes Sorensen480c8652014-04-15 19:44:45 +02001371 check_fwstate(pmlmepriv, WIFI_ADHOC_STATE)) {
Larry Finger5e93f352014-03-28 21:37:38 -05001372
1373 spin_lock_bh(&pstapriv->sta_hash_lock);
1374 rtw_free_stainfo23a(adapter, psta);
1375 spin_unlock_bh(&pstapriv->sta_hash_lock);
1376
Jes Sorensen480c8652014-04-15 19:44:45 +02001377 /* a sta + bc/mc_stainfo (not Ibss_stainfo) */
1378 if (adapter->stapriv.asoc_sta_count == 1) {
Larry Finger5e93f352014-03-28 21:37:38 -05001379 spin_lock_bh(&pmlmepriv->scanned_queue.lock);
1380 /* free old ibss network */
Jes Sorensen480c8652014-04-15 19:44:45 +02001381 /* pwlan = rtw_find_network23a(
1382 &pmlmepriv->scanned_queue, pstadel->macaddr); */
1383 pwlan = rtw_find_network23a(&pmlmepriv->scanned_queue,
1384 tgt_network->network.MacAddress);
1385 if (pwlan) {
Larry Finger5e93f352014-03-28 21:37:38 -05001386 pwlan->fixed = false;
1387 rtw_free_network_nolock(pmlmepriv, pwlan);
1388 }
1389 spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
1390 /* re-create ibss */
1391 pdev_network = &adapter->registrypriv.dev_network;
Larry Finger5e93f352014-03-28 21:37:38 -05001392
Jes Sorensen480c8652014-04-15 19:44:45 +02001393 memcpy(pdev_network, &tgt_network->network,
1394 get_wlan_bssid_ex_sz(&tgt_network->network));
Larry Finger5e93f352014-03-28 21:37:38 -05001395
Jes Sorensenfcc60202014-06-09 15:16:53 +02001396 rtw_do_join_adhoc(adapter);
Larry Finger5e93f352014-03-28 21:37:38 -05001397 }
Larry Finger5e93f352014-03-28 21:37:38 -05001398 }
1399
1400 spin_unlock_bh(&pmlmepriv->lock);
Larry Finger5e93f352014-03-28 21:37:38 -05001401}
1402
Larry Finger5e93f352014-03-28 21:37:38 -05001403/*
Masanari Iida7c17d2d2014-07-22 23:42:24 +09001404* rtw23a_join_to_handler - Timeout/failure handler for CMD JoinBss
Larry Finger5e93f352014-03-28 21:37:38 -05001405* @adapter: pointer to _adapter structure
1406*/
1407void rtw23a_join_to_handler (unsigned long data)
1408{
1409 struct rtw_adapter *adapter = (struct rtw_adapter *)data;
Jes Sorensen8b3d9cd2014-05-31 18:05:09 +02001410 struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
Larry Finger5e93f352014-03-28 21:37:38 -05001411 int do_join_r;
1412
1413 DBG_8723A("%s, fw_state=%x\n", __func__, get_fwstate(pmlmepriv));
1414
Jes Sorensen8b3d9cd2014-05-31 18:05:09 +02001415 if (adapter->bDriverStopped || adapter->bSurpriseRemoved)
Larry Finger5e93f352014-03-28 21:37:38 -05001416 return;
1417
1418 spin_lock_bh(&pmlmepriv->lock);
1419
Jes Sorensen56828792014-04-15 19:44:46 +02001420 if (adapter->mlmepriv.to_roaming > 0) {
1421 /* join timeout caused by roaming */
Jes Sorensen480c8652014-04-15 19:44:45 +02001422 while (1) {
Larry Finger5e93f352014-03-28 21:37:38 -05001423 pmlmepriv->to_roaming--;
Jes Sorensen56828792014-04-15 19:44:46 +02001424 if (adapter->mlmepriv.to_roaming != 0) {
1425 /* try another */
Larry Finger5e93f352014-03-28 21:37:38 -05001426 DBG_8723A("%s try another roaming\n", __func__);
Jes Sorensene007b4c2014-06-09 15:17:00 +02001427 do_join_r = rtw_do_join(adapter);
Jes Sorensen480c8652014-04-15 19:44:45 +02001428 if (do_join_r != _SUCCESS) {
1429 DBG_8723A("%s roaming do_join return "
1430 "%d\n", __func__ , do_join_r);
Larry Finger5e93f352014-03-28 21:37:38 -05001431 continue;
1432 }
1433 break;
1434 } else {
Jes Sorensen480c8652014-04-15 19:44:45 +02001435 DBG_8723A("%s We've try roaming but fail\n",
1436 __func__);
Larry Finger5e93f352014-03-28 21:37:38 -05001437 rtw_indicate_disconnect23a(adapter);
1438 break;
1439 }
1440 }
1441 } else {
1442 rtw_indicate_disconnect23a(adapter);
1443 free_scanqueue(pmlmepriv);/* */
1444
Jes Sorensen480c8652014-04-15 19:44:45 +02001445 /* indicate disconnect for the case that join_timeout and
1446 check_fwstate != FW_LINKED */
Larry Finger5e93f352014-03-28 21:37:38 -05001447 rtw_cfg80211_indicate_disconnect(adapter);
1448 }
1449
1450 spin_unlock_bh(&pmlmepriv->lock);
1451
1452}
1453
1454/*
Masanari Iida7c17d2d2014-07-22 23:42:24 +09001455* rtw_scan_timeout_handler23a - Timeout/Failure handler for CMD SiteSurvey
Larry Finger5e93f352014-03-28 21:37:38 -05001456* @data: pointer to _adapter structure
1457*/
1458void rtw_scan_timeout_handler23a(unsigned long data)
1459{
1460 struct rtw_adapter *adapter = (struct rtw_adapter *)data;
Jes Sorensen8b3d9cd2014-05-31 18:05:09 +02001461 struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
Larry Finger5e93f352014-03-28 21:37:38 -05001462
Jes Sorensen9cd613c2014-05-09 15:04:03 +02001463 DBG_8723A("%s(%s): fw_state =%x\n", __func__, adapter->pnetdev->name,
Jes Sorensen480c8652014-04-15 19:44:45 +02001464 get_fwstate(pmlmepriv));
Larry Finger5e93f352014-03-28 21:37:38 -05001465
1466 spin_lock_bh(&pmlmepriv->lock);
1467
1468 _clr_fwstate_(pmlmepriv, _FW_UNDER_SURVEY);
1469
1470 spin_unlock_bh(&pmlmepriv->lock);
1471
Jes Sorensen810c8322014-04-09 23:21:00 +02001472 rtw_cfg80211_indicate_scan_done(wdev_to_priv(adapter->rtw_wdev), true);
Larry Finger5e93f352014-03-28 21:37:38 -05001473}
1474
Larry Finger5e93f352014-03-28 21:37:38 -05001475void rtw_dynamic_check_timer_handler(unsigned long data)
1476{
1477 struct rtw_adapter *adapter = (struct rtw_adapter *)data;
Larry Finger5e93f352014-03-28 21:37:38 -05001478
1479 if (adapter->hw_init_completed == false)
1480 goto out;
1481
Jes Sorensen480c8652014-04-15 19:44:45 +02001482 if (adapter->bDriverStopped == true ||
1483 adapter->bSurpriseRemoved == true)
Larry Finger5e93f352014-03-28 21:37:38 -05001484 goto out;
1485
1486 if (adapter->net_closed == true)
1487 goto out;
1488
1489 rtw_dynamic_chk_wk_cmd23a(adapter);
1490
Larry Finger5e93f352014-03-28 21:37:38 -05001491out:
1492 mod_timer(&adapter->mlmepriv.dynamic_chk_timer,
1493 jiffies + msecs_to_jiffies(2000));
1494}
1495
1496inline bool rtw_is_scan_deny(struct rtw_adapter *adapter)
1497{
1498 struct mlme_priv *mlmepriv = &adapter->mlmepriv;
Yeliz Taneroglu29ed9322014-10-09 01:22:14 +03001499
Larry Finger5e93f352014-03-28 21:37:38 -05001500 return (atomic_read(&mlmepriv->set_scan_deny) != 0) ? true : false;
1501}
1502
1503void rtw_clear_scan_deny(struct rtw_adapter *adapter)
1504{
1505 struct mlme_priv *mlmepriv = &adapter->mlmepriv;
Yeliz Taneroglu29ed9322014-10-09 01:22:14 +03001506
Larry Finger5e93f352014-03-28 21:37:38 -05001507 atomic_set(&mlmepriv->set_scan_deny, 0);
Larry Finger5e93f352014-03-28 21:37:38 -05001508}
1509
1510void rtw_set_scan_deny_timer_hdl(unsigned long data)
1511{
1512 struct rtw_adapter *adapter = (struct rtw_adapter *)data;
Yeliz Taneroglu29ed9322014-10-09 01:22:14 +03001513
Larry Finger5e93f352014-03-28 21:37:38 -05001514 rtw_clear_scan_deny(adapter);
1515}
1516
1517void rtw_set_scan_deny(struct rtw_adapter *adapter, u32 ms)
1518{
1519 struct mlme_priv *mlmepriv = &adapter->mlmepriv;
1520
Larry Finger5e93f352014-03-28 21:37:38 -05001521 atomic_set(&mlmepriv->set_scan_deny, 1);
1522 mod_timer(&mlmepriv->set_scan_deny_timer,
1523 jiffies + msecs_to_jiffies(ms));
Larry Finger5e93f352014-03-28 21:37:38 -05001524}
1525
1526#if defined(IEEE80211_SCAN_RESULT_EXPIRE)
Tina Ruchandanide1de2f2014-10-25 16:56:01 -07001527#define RTW_SCAN_RESULT_EXPIRE \
1528 ((IEEE80211_SCAN_RESULT_EXPIRE / (HZ*1000)) - 1000) /* 3000 -1000 */
Larry Finger5e93f352014-03-28 21:37:38 -05001529#else
1530#define RTW_SCAN_RESULT_EXPIRE 2000
1531#endif
1532
1533/*
Jes Sorensen480c8652014-04-15 19:44:45 +02001534* Select a new join candidate from the original @param candidate and
1535* @param competitor
Larry Finger5e93f352014-03-28 21:37:38 -05001536* @return true: candidate is updated
1537* @return false: candidate is not updated
1538*/
Jes Sorensen480c8652014-04-15 19:44:45 +02001539static int rtw_check_join_candidate(struct mlme_priv *pmlmepriv,
1540 struct wlan_network **candidate,
1541 struct wlan_network *competitor)
Larry Finger5e93f352014-03-28 21:37:38 -05001542{
1543 int updated = false;
Jes Sorensen480c8652014-04-15 19:44:45 +02001544 struct rtw_adapter *adapter;
1545
1546 adapter = container_of(pmlmepriv, struct rtw_adapter, mlmepriv);
Larry Finger5e93f352014-03-28 21:37:38 -05001547
1548 /* check bssid, if needed */
1549 if (pmlmepriv->assoc_by_bssid == true) {
1550 if (!ether_addr_equal(competitor->network.MacAddress,
1551 pmlmepriv->assoc_bssid))
1552 goto exit;
1553 }
1554
1555 /* check ssid, if needed */
Larry Fingerc17416e2014-03-28 21:37:42 -05001556 if (pmlmepriv->assoc_ssid.ssid_len) {
Larry Finger5e93f352014-03-28 21:37:38 -05001557 if (competitor->network.Ssid.ssid_len !=
1558 pmlmepriv->assoc_ssid.ssid_len ||
1559 memcmp(competitor->network.Ssid.ssid,
1560 pmlmepriv->assoc_ssid.ssid,
1561 pmlmepriv->assoc_ssid.ssid_len))
1562 goto exit;
1563 }
1564
Jes Sorensen480c8652014-04-15 19:44:45 +02001565 if (rtw_is_desired_network(adapter, competitor) == false)
Larry Finger5e93f352014-03-28 21:37:38 -05001566 goto exit;
1567
Jes Sorensen56828792014-04-15 19:44:46 +02001568 if (adapter->mlmepriv.to_roaming > 0) {
Larry Finger5e93f352014-03-28 21:37:38 -05001569 unsigned int passed;
1570
1571 passed = jiffies_to_msecs(jiffies - competitor->last_scanned);
1572 if (passed >= RTW_SCAN_RESULT_EXPIRE ||
1573 is_same_ess(&competitor->network,
1574 &pmlmepriv->cur_network.network) == false)
1575 goto exit;
1576 }
1577
Jes Sorensen480c8652014-04-15 19:44:45 +02001578 if (!*candidate ||
1579 (*candidate)->network.Rssi<competitor->network.Rssi) {
Larry Finger5e93f352014-03-28 21:37:38 -05001580 *candidate = competitor;
1581 updated = true;
1582 }
1583
1584 if (updated) {
Jes Sorensen480c8652014-04-15 19:44:45 +02001585 DBG_8723A("[by_bssid:%u][assoc_ssid:%s][to_roaming:%u] "
1586 "new candidate: %s("MAC_FMT") rssi:%d\n",
1587 pmlmepriv->assoc_by_bssid,
1588 pmlmepriv->assoc_ssid.ssid,
Jes Sorensen56828792014-04-15 19:44:46 +02001589 adapter->mlmepriv.to_roaming,
Jes Sorensen480c8652014-04-15 19:44:45 +02001590 (*candidate)->network.Ssid.ssid,
1591 MAC_ARG((*candidate)->network.MacAddress),
1592 (int)(*candidate)->network.Rssi);
Larry Finger5e93f352014-03-28 21:37:38 -05001593 }
1594
1595exit:
1596 return updated;
1597}
1598
1599/*
1600Calling context:
1601The caller of the sub-routine will be in critical section...
1602
1603The caller must hold the following spinlock
1604
1605pmlmepriv->lock
1606
1607*/
1608
Jes Sorensene007b4c2014-06-09 15:17:00 +02001609static int rtw_do_join(struct rtw_adapter *padapter)
1610{
1611 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1612 int ret;
1613
1614 pmlmepriv->cur_network.join_res = -2;
1615
1616 set_fwstate(pmlmepriv, _FW_UNDER_LINKING);
1617
1618 pmlmepriv->to_join = true;
1619
1620 ret = rtw_select_and_join_from_scanned_queue23a(pmlmepriv);
1621 if (ret == _SUCCESS) {
1622 pmlmepriv->to_join = false;
1623 } else {
1624 if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE)) {
1625 /* switch to ADHOC_MASTER */
1626 ret = rtw_do_join_adhoc(padapter);
1627 if (ret != _SUCCESS)
1628 goto exit;
1629 } else {
1630 /* can't associate ; reset under-linking */
1631 _clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING);
1632
1633 ret = _FAIL;
1634 pmlmepriv->to_join = false;
1635 }
1636 }
1637
1638exit:
1639 return ret;
1640}
1641
Jes Sorensen0e634a02014-06-09 15:16:49 +02001642static struct wlan_network *
1643rtw_select_candidate_from_queue(struct mlme_priv *pmlmepriv)
Larry Finger5e93f352014-03-28 21:37:38 -05001644{
Jes Sorensen0e634a02014-06-09 15:16:49 +02001645 struct wlan_network *pnetwork, *candidate = NULL;
Larry Finger5e93f352014-03-28 21:37:38 -05001646 struct rtw_queue *queue = &pmlmepriv->scanned_queue;
Jes Sorensen0e634a02014-06-09 15:16:49 +02001647 struct list_head *phead, *plist, *ptmp;
Larry Finger5e93f352014-03-28 21:37:38 -05001648
1649 spin_lock_bh(&pmlmepriv->scanned_queue.lock);
1650 phead = get_list_head(queue);
Larry Finger5e93f352014-03-28 21:37:38 -05001651
1652 list_for_each_safe(plist, ptmp, phead) {
1653 pnetwork = container_of(plist, struct wlan_network, list);
1654 if (!pnetwork) {
1655 RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_,
Jes Sorensen2febc8672014-06-09 15:16:47 +02001656 ("%s: return _FAIL:(pnetwork == NULL)\n",
Larry Finger5e93f352014-03-28 21:37:38 -05001657 __func__));
Larry Finger5e93f352014-03-28 21:37:38 -05001658 goto exit;
1659 }
1660
1661 rtw_check_join_candidate(pmlmepriv, &candidate, pnetwork);
1662 }
1663
Jes Sorensen0e634a02014-06-09 15:16:49 +02001664exit:
1665 spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
1666 return candidate;
1667}
1668
Jes Sorensenb66dad22014-06-09 15:16:50 +02001669
Jes Sorensenfcc60202014-06-09 15:16:53 +02001670int rtw_do_join_adhoc(struct rtw_adapter *adapter)
1671{
1672 struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
1673 struct wlan_bssid_ex *pdev_network;
1674 u8 *ibss;
1675 int ret;
1676
1677 pdev_network = &adapter->registrypriv.dev_network;
1678 ibss = adapter->registrypriv.dev_network.MacAddress;
1679
1680 _clr_fwstate_(pmlmepriv, _FW_UNDER_SURVEY);
1681
1682 RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_,
1683 ("switching to adhoc master\n"));
1684
1685 memcpy(&pdev_network->Ssid, &pmlmepriv->assoc_ssid,
1686 sizeof(struct cfg80211_ssid));
1687
1688 rtw_update_registrypriv_dev_network23a(adapter);
1689 rtw_generate_random_ibss23a(ibss);
1690
1691 pmlmepriv->fw_state = WIFI_ADHOC_MASTER_STATE;
1692
1693 ret = rtw_createbss_cmd23a(adapter);
1694 if (ret != _SUCCESS) {
1695 RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_,
1696 ("Error =>rtw_createbss_cmd23a status FAIL\n"));
1697 } else {
1698 pmlmepriv->to_join = false;
1699 }
1700
1701 return ret;
1702}
1703
Jes Sorensenb66dad22014-06-09 15:16:50 +02001704int rtw_do_join_network(struct rtw_adapter *adapter,
1705 struct wlan_network *candidate)
1706{
1707 int ret;
1708
1709 /* check for situation of _FW_LINKED */
1710 if (check_fwstate(&adapter->mlmepriv, _FW_LINKED)) {
1711 DBG_8723A("%s: _FW_LINKED while ask_for_joinbss!\n", __func__);
1712
1713 rtw_disassoc_cmd23a(adapter, 0, true);
1714 rtw_indicate_disconnect23a(adapter);
1715 rtw_free_assoc_resources23a(adapter, 0);
1716 }
1717 set_fwstate(&adapter->mlmepriv, _FW_UNDER_LINKING);
1718
1719 ret = rtw_joinbss_cmd23a(adapter, candidate);
1720
1721 if (ret == _SUCCESS)
1722 mod_timer(&adapter->mlmepriv.assoc_timer,
1723 jiffies + msecs_to_jiffies(MAX_JOIN_TIMEOUT));
1724
1725 return ret;
1726}
1727
Jes Sorensen0e634a02014-06-09 15:16:49 +02001728int rtw_select_and_join_from_scanned_queue23a(struct mlme_priv *pmlmepriv)
1729{
1730 struct rtw_adapter *adapter;
1731 struct wlan_network *candidate = NULL;
1732 int ret;
1733
1734 adapter = pmlmepriv->nic_hdl;
1735
1736 candidate = rtw_select_candidate_from_queue(pmlmepriv);
Larry Finger5e93f352014-03-28 21:37:38 -05001737 if (!candidate) {
1738 DBG_8723A("%s: return _FAIL(candidate == NULL)\n", __func__);
1739 ret = _FAIL;
1740 goto exit;
1741 } else {
1742 DBG_8723A("%s: candidate: %s("MAC_FMT", ch:%u)\n", __func__,
1743 candidate->network.Ssid.ssid,
1744 MAC_ARG(candidate->network.MacAddress),
Jes Sorensen37cb9822014-05-21 09:37:40 +02001745 candidate->network.DSConfig);
Larry Finger5e93f352014-03-28 21:37:38 -05001746 }
1747
Jes Sorensenb66dad22014-06-09 15:16:50 +02001748 ret = rtw_do_join_network(adapter, candidate);
Larry Finger5e93f352014-03-28 21:37:38 -05001749
1750exit:
Larry Finger5e93f352014-03-28 21:37:38 -05001751 return ret;
1752}
1753
Greg Donald8e3d1612014-10-02 18:28:41 -05001754int rtw_set_auth23a(struct rtw_adapter *adapter,
Jes Sorensen480c8652014-04-15 19:44:45 +02001755 struct security_priv *psecuritypriv)
Larry Finger5e93f352014-03-28 21:37:38 -05001756{
Greg Donald4e66cf02014-08-22 10:57:49 -05001757 struct cmd_obj *pcmd;
Larry Finger5e93f352014-03-28 21:37:38 -05001758 struct setauth_parm *psetauthparm;
1759 struct cmd_priv *pcmdpriv = &adapter->cmdpriv;
1760 int res = _SUCCESS;
1761
Sachin Kamatdb5767a2014-05-29 17:05:19 +05301762 pcmd = kzalloc(sizeof(struct cmd_obj), GFP_KERNEL);
Larry Finger5e93f352014-03-28 21:37:38 -05001763 if (!pcmd) {
1764 res = _FAIL; /* try again */
1765 goto exit;
1766 }
1767
Sachin Kamat47b0c982014-05-28 17:36:24 +05301768 psetauthparm = kzalloc(sizeof(struct setauth_parm), GFP_KERNEL);
Larry Finger5e93f352014-03-28 21:37:38 -05001769 if (!psetauthparm) {
1770 kfree(pcmd);
1771 res = _FAIL;
1772 goto exit;
1773 }
1774
1775 psetauthparm->mode = (unsigned char)psecuritypriv->dot11AuthAlgrthm;
1776
1777 pcmd->cmdcode = _SetAuth_CMD_;
1778 pcmd->parmbuf = (unsigned char *)psetauthparm;
1779 pcmd->cmdsz = (sizeof(struct setauth_parm));
1780 pcmd->rsp = NULL;
1781 pcmd->rspsz = 0;
1782
Greg Donaldc895a5d2014-09-16 18:37:41 -05001783 RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_,
Larry Finger5e93f352014-03-28 21:37:38 -05001784 ("after enqueue set_auth_cmd, auth_mode=%x\n",
1785 psecuritypriv->dot11AuthAlgrthm));
1786
1787 res = rtw_enqueue_cmd23a(pcmdpriv, pcmd);
1788
1789exit:
1790
1791 return res;
1792}
1793
1794int rtw_set_key23a(struct rtw_adapter *adapter,
Jes Sorensen480c8652014-04-15 19:44:45 +02001795 struct security_priv *psecuritypriv, int keyid, u8 set_tx)
Larry Finger5e93f352014-03-28 21:37:38 -05001796{
1797 u8 keylen;
1798 struct cmd_obj *pcmd;
1799 struct setkey_parm *psetkeyparm;
1800 struct cmd_priv *pcmdpriv = &adapter->cmdpriv;
1801 struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
1802 int res = _SUCCESS;
1803
Jes Sorensen4e489d92014-05-09 15:04:16 +02001804 if (keyid >= 4) {
1805 res = _FAIL;
1806 goto exit;
1807 }
1808
Sachin Kamat47b0c982014-05-28 17:36:24 +05301809 pcmd = kzalloc(sizeof(struct cmd_obj), GFP_KERNEL);
Larry Finger5e93f352014-03-28 21:37:38 -05001810 if (!pcmd) {
1811 res = _FAIL; /* try again */
1812 goto exit;
1813 }
Larry Fingerc17416e2014-03-28 21:37:42 -05001814 psetkeyparm = kzalloc(sizeof(struct setkey_parm), GFP_KERNEL);
Larry Finger5e93f352014-03-28 21:37:38 -05001815 if (!psetkeyparm) {
1816 kfree(pcmd);
1817 res = _FAIL;
1818 goto exit;
1819 }
1820
1821 if (psecuritypriv->dot11AuthAlgrthm == dot11AuthAlgrthm_8021X) {
1822 psetkeyparm->algorithm = (unsigned char)
1823 psecuritypriv->dot118021XGrpPrivacy;
1824 RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_,
Jes Sorensen480c8652014-04-15 19:44:45 +02001825 ("\n rtw_set_key23a: psetkeyparm->algorithm = "
1826 "(unsigned char)psecuritypriv->dot118021XGrpPrivacy "
1827 "=%d\n", psetkeyparm->algorithm));
Larry Finger5e93f352014-03-28 21:37:38 -05001828 } else {
1829 psetkeyparm->algorithm = (u8)psecuritypriv->dot11PrivacyAlgrthm;
1830 RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_,
1831 ("\n rtw_set_key23a: psetkeyparm->algorithm = (u8)"
1832 "psecuritypriv->dot11PrivacyAlgrthm =%d\n",
1833 psetkeyparm->algorithm));
1834 }
Jes Sorensen4e489d92014-05-09 15:04:16 +02001835 psetkeyparm->keyid = keyid;/* 0~3 */
Larry Finger5e93f352014-03-28 21:37:38 -05001836 psetkeyparm->set_tx = set_tx;
1837 if (is_wep_enc(psetkeyparm->algorithm))
Jes Sorensen4e489d92014-05-09 15:04:16 +02001838 pmlmepriv->key_mask |= BIT(psetkeyparm->keyid);
Larry Finger5e93f352014-03-28 21:37:38 -05001839
1840 DBG_8723A("==> rtw_set_key23a algorithm(%x), keyid(%x), key_mask(%x)\n",
1841 psetkeyparm->algorithm, psetkeyparm->keyid,
1842 pmlmepriv->key_mask);
1843 RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_,
1844 ("\n rtw_set_key23a: psetkeyparm->algorithm =%d psetkeyparm->"
1845 "keyid = (u8)keyid =%d\n", psetkeyparm->algorithm, keyid));
1846
1847 switch (psetkeyparm->algorithm) {
Jes Sorensen9e3d6df2014-05-21 09:37:34 +02001848 case WLAN_CIPHER_SUITE_WEP40:
Larry Finger5e93f352014-03-28 21:37:38 -05001849 keylen = 5;
1850 memcpy(&psetkeyparm->key[0],
Jes Sorensene0827902014-05-21 09:37:35 +02001851 &psecuritypriv->wep_key[keyid].key, keylen);
Larry Finger5e93f352014-03-28 21:37:38 -05001852 break;
Jes Sorensen9e3d6df2014-05-21 09:37:34 +02001853 case WLAN_CIPHER_SUITE_WEP104:
Larry Finger5e93f352014-03-28 21:37:38 -05001854 keylen = 13;
1855 memcpy(&psetkeyparm->key[0],
Jes Sorensene0827902014-05-21 09:37:35 +02001856 &psecuritypriv->wep_key[keyid].key, keylen);
Larry Finger5e93f352014-03-28 21:37:38 -05001857 break;
Jes Sorensen9e3d6df2014-05-21 09:37:34 +02001858 case WLAN_CIPHER_SUITE_TKIP:
Larry Finger5e93f352014-03-28 21:37:38 -05001859 keylen = 16;
1860 memcpy(&psetkeyparm->key,
1861 &psecuritypriv->dot118021XGrpKey[keyid], keylen);
1862 psetkeyparm->grpkey = 1;
1863 break;
Jes Sorensen9e3d6df2014-05-21 09:37:34 +02001864 case WLAN_CIPHER_SUITE_CCMP:
Larry Finger5e93f352014-03-28 21:37:38 -05001865 keylen = 16;
1866 memcpy(&psetkeyparm->key,
1867 &psecuritypriv->dot118021XGrpKey[keyid], keylen);
1868 psetkeyparm->grpkey = 1;
1869 break;
1870 default:
1871 RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_,
Jes Sorensen480c8652014-04-15 19:44:45 +02001872 ("\n rtw_set_key23a:psecuritypriv->dot11PrivacyAlgrthm"
1873 " = %x (must be 1 or 2 or 4 or 5)\n",
Larry Finger5e93f352014-03-28 21:37:38 -05001874 psecuritypriv->dot11PrivacyAlgrthm));
1875 res = _FAIL;
Larry Fingerc17416e2014-03-28 21:37:42 -05001876 kfree(pcmd);
1877 kfree(psetkeyparm);
Larry Finger5e93f352014-03-28 21:37:38 -05001878 goto exit;
1879 }
1880
1881 pcmd->cmdcode = _SetKey_CMD_;
1882 pcmd->parmbuf = (u8 *)psetkeyparm;
1883 pcmd->cmdsz = (sizeof(struct setkey_parm));
1884 pcmd->rsp = NULL;
1885 pcmd->rspsz = 0;
1886
Larry Finger5e93f352014-03-28 21:37:38 -05001887 /* sema_init(&pcmd->cmd_sem, 0); */
1888
1889 res = rtw_enqueue_cmd23a(pcmdpriv, pcmd);
1890
1891exit:
1892
1893 return res;
1894}
1895
1896/* adjust IEs for rtw_joinbss_cmd23a in WMM */
1897int rtw_restruct_wmm_ie23a(struct rtw_adapter *adapter, u8 *in_ie,
Jes Sorensen86184b92014-06-24 15:03:55 +02001898 u8 *out_ie, uint in_len, uint initial_out_len)
Larry Finger5e93f352014-03-28 21:37:38 -05001899{
Jes Sorensen86184b92014-06-24 15:03:55 +02001900 int ielength;
1901 const u8 *p;
Larry Finger5e93f352014-03-28 21:37:38 -05001902
Jes Sorensen86184b92014-06-24 15:03:55 +02001903 ielength = initial_out_len;
Larry Finger5e93f352014-03-28 21:37:38 -05001904
Jes Sorensen86184b92014-06-24 15:03:55 +02001905 p = cfg80211_find_vendor_ie(WLAN_OUI_MICROSOFT,
1906 WLAN_OUI_TYPE_MICROSOFT_WMM,
1907 in_ie, in_len);
Larry Finger5e93f352014-03-28 21:37:38 -05001908
Jes Sorensen86184b92014-06-24 15:03:55 +02001909 if (p && p[1]) {
1910 memcpy(out_ie + initial_out_len, p, 9);
Larry Finger5e93f352014-03-28 21:37:38 -05001911
Jes Sorensen86184b92014-06-24 15:03:55 +02001912 out_ie[initial_out_len + 1] = 7;
1913 out_ie[initial_out_len + 6] = 0;
1914 out_ie[initial_out_len + 8] = 0;
Larry Finger5e93f352014-03-28 21:37:38 -05001915
Jes Sorensen86184b92014-06-24 15:03:55 +02001916 ielength += 9;
Larry Finger5e93f352014-03-28 21:37:38 -05001917 }
1918
1919 return ielength;
1920}
1921
1922/* */
1923/* Ported from 8185: IsInPreAuthKeyList().
1924 (Renamed from SecIsInPreAuthKeyList(), 2006-10-13.) */
1925/* Added by Annie, 2006-05-07. */
1926/* */
1927/* Search by BSSID, */
1928/* Return Value: */
1929/* -1 :if there is no pre-auth key in the table */
1930/* >= 0 :if there is pre-auth key, and return the entry id */
1931/* */
1932/* */
1933
1934static int SecIsInPMKIDList(struct rtw_adapter *Adapter, u8 *bssid)
1935{
1936 struct security_priv *psecuritypriv = &Adapter->securitypriv;
1937 int i = 0;
1938
1939 do {
1940 if (psecuritypriv->PMKIDList[i].bUsed &&
1941 ether_addr_equal(psecuritypriv->PMKIDList[i].Bssid, bssid)) {
1942 break;
1943 } else {
1944 i++;
1945 /* continue; */
1946 }
Jes Sorensen480c8652014-04-15 19:44:45 +02001947 } while (i < NUM_PMKID_CACHE);
Larry Finger5e93f352014-03-28 21:37:38 -05001948
Jes Sorensen480c8652014-04-15 19:44:45 +02001949 if (i == NUM_PMKID_CACHE)
Larry Finger5e93f352014-03-28 21:37:38 -05001950 i = -1;/* Could not find. */
Jes Sorensen480c8652014-04-15 19:44:45 +02001951 else {
Larry Finger5e93f352014-03-28 21:37:38 -05001952 /* There is one Pre-Authentication Key for
1953 the specific BSSID. */
1954 }
1955
1956 return i;
1957}
1958
1959/* */
1960/* Check the RSN IE length */
1961/* If the RSN IE length <= 20, the RSN IE didn't include
1962 the PMKID information */
1963/* 0-11th element in the array are the fixed IE */
1964/* 12th element in the array is the IE */
1965/* 13th element in the array is the IE length */
1966/* */
1967
1968static int rtw_append_pmkid(struct rtw_adapter *Adapter, int iEntry,
1969 u8 *ie, uint ie_len)
1970{
1971 struct security_priv *psecuritypriv = &Adapter->securitypriv;
1972
Jes Sorensen98f979f2014-06-24 15:03:56 +02001973 if (ie[1] <= 20) {
Larry Finger5e93f352014-03-28 21:37:38 -05001974 /* The RSN IE didn't include the PMK ID,
1975 append the PMK information */
1976 ie[ie_len] = 1;
1977 ie_len++;
1978 ie[ie_len] = 0; /* PMKID count = 0x0100 */
1979 ie_len++;
1980 memcpy(&ie[ie_len],
1981 &psecuritypriv->PMKIDList[iEntry].PMKID, 16);
1982
1983 ie_len += 16;
Jes Sorensen98f979f2014-06-24 15:03:56 +02001984 ie[1] += 18;/* PMKID length = 2+16 */
Larry Finger5e93f352014-03-28 21:37:38 -05001985 }
1986 return ie_len;
1987}
Jes Sorensen814a1d92014-04-09 23:21:06 +02001988
Larry Finger5e93f352014-03-28 21:37:38 -05001989int rtw_restruct_sec_ie23a(struct rtw_adapter *adapter, u8 *in_ie, u8 *out_ie,
Jes Sorensen480c8652014-04-15 19:44:45 +02001990 uint in_len)
Larry Finger5e93f352014-03-28 21:37:38 -05001991{
1992 u8 authmode;
1993 uint ielength;
1994 int iEntry;
1995 struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
1996 struct security_priv *psecuritypriv = &adapter->securitypriv;
1997 uint ndisauthmode = psecuritypriv->ndisauthtype;
1998 uint ndissecuritytype = psecuritypriv->ndisencryptstatus;
1999
2000 RT_TRACE(_module_rtl871x_mlme_c_, _drv_notice_,
Jes Sorensen480c8652014-04-15 19:44:45 +02002001 ("+rtw_restruct_sec_ie23a: ndisauthmode=%d "
2002 "ndissecuritytype=%d\n", ndisauthmode, ndissecuritytype));
Larry Finger5e93f352014-03-28 21:37:38 -05002003
Jes Sorensen1de65cc2014-06-24 15:03:30 +02002004 ielength = 0;
Jes Sorensen480c8652014-04-15 19:44:45 +02002005 if (ndisauthmode == Ndis802_11AuthModeWPA ||
2006 ndisauthmode == Ndis802_11AuthModeWPAPSK)
Jes Sorensen9300c942014-04-15 19:43:21 +02002007 authmode = WLAN_EID_VENDOR_SPECIFIC;
Jes Sorensen480c8652014-04-15 19:44:45 +02002008 if (ndisauthmode == Ndis802_11AuthModeWPA2 ||
2009 ndisauthmode == Ndis802_11AuthModeWPA2PSK)
Jes Sorensena131aac2014-06-21 16:50:15 +02002010 authmode = WLAN_EID_RSN;
Larry Finger5e93f352014-03-28 21:37:38 -05002011
2012 if (check_fwstate(pmlmepriv, WIFI_UNDER_WPS)) {
2013 memcpy(out_ie + ielength, psecuritypriv->wps_ie,
2014 psecuritypriv->wps_ie_len);
2015
2016 ielength += psecuritypriv->wps_ie_len;
Jes Sorensen480c8652014-04-15 19:44:45 +02002017 } else if (authmode == WLAN_EID_VENDOR_SPECIFIC ||
Jes Sorensena131aac2014-06-21 16:50:15 +02002018 authmode == WLAN_EID_RSN) {
Larry Finger5e93f352014-03-28 21:37:38 -05002019 /* copy RSN or SSN */
2020 memcpy(&out_ie[ielength], &psecuritypriv->supplicant_ie[0],
2021 psecuritypriv->supplicant_ie[1] + 2);
2022 ielength += psecuritypriv->supplicant_ie[1] + 2;
Larry Finger5e93f352014-03-28 21:37:38 -05002023 }
2024
2025 iEntry = SecIsInPMKIDList(adapter, pmlmepriv->assoc_bssid);
Jes Sorensen480c8652014-04-15 19:44:45 +02002026 if (iEntry < 0)
Larry Finger5e93f352014-03-28 21:37:38 -05002027 return ielength;
Jes Sorensen480c8652014-04-15 19:44:45 +02002028 else {
Jes Sorensena131aac2014-06-21 16:50:15 +02002029 if (authmode == WLAN_EID_RSN)
Jes Sorensen480c8652014-04-15 19:44:45 +02002030 ielength = rtw_append_pmkid(adapter, iEntry,
2031 out_ie, ielength);
Larry Finger5e93f352014-03-28 21:37:38 -05002032 }
2033
2034 return ielength;
2035}
2036
Greg Donald4e66cf02014-08-22 10:57:49 -05002037void rtw_init_registrypriv_dev_network23a(struct rtw_adapter *adapter)
Larry Finger5e93f352014-03-28 21:37:38 -05002038{
Greg Donald4e66cf02014-08-22 10:57:49 -05002039 struct registry_priv *pregistrypriv = &adapter->registrypriv;
2040 struct eeprom_priv *peepriv = &adapter->eeprompriv;
Larry Finger5e93f352014-03-28 21:37:38 -05002041 struct wlan_bssid_ex *pdev_network = &pregistrypriv->dev_network;
2042 u8 *myhwaddr = myid(peepriv);
2043
2044 ether_addr_copy(pdev_network->MacAddress, myhwaddr);
2045
2046 memcpy(&pdev_network->Ssid, &pregistrypriv->ssid,
2047 sizeof(struct cfg80211_ssid));
2048
Jes Sorensen143ced22014-06-19 11:37:22 +02002049 pdev_network->beacon_interval = 100;
Larry Finger5e93f352014-03-28 21:37:38 -05002050}
2051
Greg Donald4e66cf02014-08-22 10:57:49 -05002052void rtw_update_registrypriv_dev_network23a(struct rtw_adapter *adapter)
Larry Finger5e93f352014-03-28 21:37:38 -05002053{
2054 int sz = 0;
Greg Donald4e66cf02014-08-22 10:57:49 -05002055 struct registry_priv *pregistrypriv = &adapter->registrypriv;
Larry Finger5e93f352014-03-28 21:37:38 -05002056 struct wlan_bssid_ex *pdev_network = &pregistrypriv->dev_network;
2057 struct security_priv *psecuritypriv = &adapter->securitypriv;
2058 struct wlan_network *cur_network = &adapter->mlmepriv.cur_network;
2059 /* struct xmit_priv *pxmitpriv = &adapter->xmitpriv; */
2060
2061 pdev_network->Privacy =
2062 (psecuritypriv->dot11PrivacyAlgrthm > 0 ? 1 : 0);
2063
2064 pdev_network->Rssi = 0;
2065
Jes Sorensen37cb9822014-05-21 09:37:40 +02002066 pdev_network->DSConfig = pregistrypriv->channel;
Larry Finger5e93f352014-03-28 21:37:38 -05002067 RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_,
Jes Sorensen37cb9822014-05-21 09:37:40 +02002068 ("pregistrypriv->channel =%d, pdev_network->DSConfig = 0x%x\n",
2069 pregistrypriv->channel, pdev_network->DSConfig));
Larry Finger5e93f352014-03-28 21:37:38 -05002070
Jes Sorensenefc71442014-05-21 09:37:26 +02002071 if (cur_network->network.ifmode == NL80211_IFTYPE_ADHOC)
Jes Sorensen37cb9822014-05-21 09:37:40 +02002072 pdev_network->ATIMWindow = 0;
Larry Finger5e93f352014-03-28 21:37:38 -05002073
Jes Sorensenefc71442014-05-21 09:37:26 +02002074 pdev_network->ifmode = cur_network->network.ifmode;
Larry Finger5e93f352014-03-28 21:37:38 -05002075
2076 /* 1. Supported rates */
2077 /* 2. IE */
2078
2079 sz = rtw_generate_ie23a(pregistrypriv);
2080
2081 pdev_network->IELength = sz;
2082
2083 pdev_network->Length =
Jes Sorensen52017952014-04-26 18:55:09 +02002084 get_wlan_bssid_ex_sz(pdev_network);
Larry Finger5e93f352014-03-28 21:37:38 -05002085
2086 /* notes: translate IELength & Length after assign the
2087 Length to cmdsz in createbss_cmd(); */
2088 /* pdev_network->IELength = cpu_to_le32(sz); */
Larry Finger5e93f352014-03-28 21:37:38 -05002089}
2090
Masanari Iida7c17d2d2014-07-22 23:42:24 +09002091/* the function is at passive_level */
Larry Finger5e93f352014-03-28 21:37:38 -05002092void rtw_joinbss_reset23a(struct rtw_adapter *padapter)
2093{
2094 u8 threshold;
2095 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
2096 struct ht_priv *phtpriv = &pmlmepriv->htpriv;
2097
2098 /* todo: if you want to do something io/reg/hw setting
2099 before join_bss, please add code here */
2100
2101 pmlmepriv->num_FortyMHzIntolerant = 0;
2102
2103 pmlmepriv->num_sta_no_ht = 0;
2104
2105 phtpriv->ampdu_enable = false;/* reset to disabled */
2106
2107 /* TH = 1 => means that invalidate usb rx aggregation */
2108 /* TH = 0 => means that validate usb rx aggregation, use init value. */
2109 if (phtpriv->ht_option) {
2110 if (padapter->registrypriv.wifi_spec == 1)
2111 threshold = 1;
2112 else
2113 threshold = 0;
Jes Sorensen1e7b6eb2014-04-09 23:20:36 +02002114 } else
Larry Finger5e93f352014-03-28 21:37:38 -05002115 threshold = 1;
Jes Sorensen1e7b6eb2014-04-09 23:20:36 +02002116
2117 rtl8723a_set_rxdma_agg_pg_th(padapter, threshold);
Larry Finger5e93f352014-03-28 21:37:38 -05002118}
2119
Masanari Iida7c17d2d2014-07-22 23:42:24 +09002120/* the function is >= passive_level */
Jes Sorensen6f765c22014-06-09 15:16:06 +02002121bool rtw_restructure_ht_ie23a(struct rtw_adapter *padapter, u8 *in_ie,
2122 u8 *out_ie, uint in_len, uint *pout_len)
Larry Finger5e93f352014-03-28 21:37:38 -05002123{
Jes Sorensen7c2f97b2014-04-15 19:43:37 +02002124 u32 out_len;
Larry Finger5e93f352014-03-28 21:37:38 -05002125 int max_rx_ampdu_factor;
Jes Sorensen7c2f97b2014-04-15 19:43:37 +02002126 unsigned char *pframe;
2127 const u8 *p;
Larry Finger5e93f352014-03-28 21:37:38 -05002128 struct ieee80211_ht_cap ht_capie;
Jes Sorensenc9324c82014-06-09 15:16:05 +02002129 u8 WMM_IE[7] = {0x00, 0x50, 0xf2, 0x02, 0x00, 0x01, 0x00};
Larry Finger5e93f352014-03-28 21:37:38 -05002130 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
Larry Finger5e93f352014-03-28 21:37:38 -05002131 struct ht_priv *phtpriv = &pmlmepriv->htpriv;
2132
2133 phtpriv->ht_option = false;
2134
Jes Sorensen1de65cc2014-06-24 15:03:30 +02002135 p = cfg80211_find_ie(WLAN_EID_HT_CAPABILITY, in_ie, in_len);
Larry Finger5e93f352014-03-28 21:37:38 -05002136
Jes Sorensen7c2f97b2014-04-15 19:43:37 +02002137 if (p && p[1] > 0) {
Larry Finger5e93f352014-03-28 21:37:38 -05002138 u32 rx_packet_offset, max_recvbuf_sz;
Yeliz Taneroglu29ed9322014-10-09 01:22:14 +03002139
Jes Sorensenbd8ad4a2014-05-09 15:03:21 +02002140 if (pmlmepriv->qos_option == 0) {
Larry Finger5e93f352014-03-28 21:37:38 -05002141 out_len = *pout_len;
2142 pframe = rtw_set_ie23a(out_ie + out_len,
Jes Sorensenc9324c82014-06-09 15:16:05 +02002143 WLAN_EID_VENDOR_SPECIFIC,
2144 sizeof(WMM_IE), WMM_IE,
2145 pout_len);
Larry Finger5e93f352014-03-28 21:37:38 -05002146
Jes Sorensenbd8ad4a2014-05-09 15:03:21 +02002147 pmlmepriv->qos_option = 1;
Larry Finger5e93f352014-03-28 21:37:38 -05002148 }
2149
2150 out_len = *pout_len;
2151
2152 memset(&ht_capie, 0, sizeof(struct ieee80211_ht_cap));
2153
Kinka Huangce6bed62014-11-20 00:27:02 +08002154 ht_capie.cap_info = cpu_to_le16(IEEE80211_HT_CAP_SUP_WIDTH_20_40 |
Larry Finger5e93f352014-03-28 21:37:38 -05002155 IEEE80211_HT_CAP_SGI_20 | IEEE80211_HT_CAP_SGI_40 |
Kinka Huangce6bed62014-11-20 00:27:02 +08002156 IEEE80211_HT_CAP_TX_STBC | IEEE80211_HT_CAP_DSSSCCK40);
Larry Finger5e93f352014-03-28 21:37:38 -05002157
Jes Sorensen39f1a8e2014-05-16 10:04:20 +02002158 GetHalDefVar8192CUsb(padapter, HAL_DEF_RX_PACKET_OFFSET,
2159 &rx_packet_offset);
2160 GetHalDefVar8192CUsb(padapter, HAL_DEF_MAX_RECVBUF_SZ,
2161 &max_recvbuf_sz);
Larry Finger5e93f352014-03-28 21:37:38 -05002162
Jes Sorensen39f1a8e2014-05-16 10:04:20 +02002163 GetHalDefVar8192CUsb(padapter, HW_VAR_MAX_RX_AMPDU_FACTOR,
2164 &max_rx_ampdu_factor);
Larry Finger5e93f352014-03-28 21:37:38 -05002165 ht_capie.ampdu_params_info = max_rx_ampdu_factor & 0x03;
2166
Jes Sorensen9e3d6df2014-05-21 09:37:34 +02002167 if (padapter->securitypriv.dot11PrivacyAlgrthm ==
2168 WLAN_CIPHER_SUITE_CCMP)
Larry Finger5e93f352014-03-28 21:37:38 -05002169 ht_capie.ampdu_params_info |=
2170 (IEEE80211_HT_AMPDU_PARM_DENSITY& (0x07 << 2));
2171 else
2172 ht_capie.ampdu_params_info |=
2173 (IEEE80211_HT_AMPDU_PARM_DENSITY & 0x00);
2174
Jes Sorensena7eab382014-04-15 19:43:25 +02002175 pframe = rtw_set_ie23a(out_ie + out_len, WLAN_EID_HT_CAPABILITY,
Larry Finger5e93f352014-03-28 21:37:38 -05002176 sizeof(struct ieee80211_ht_cap),
Greg Donald7e6646d2014-09-06 19:42:03 -05002177 (unsigned char *)&ht_capie, pout_len);
Larry Finger5e93f352014-03-28 21:37:38 -05002178
2179 phtpriv->ht_option = true;
2180
Jes Sorensen1de65cc2014-06-24 15:03:30 +02002181 p = cfg80211_find_ie(WLAN_EID_HT_OPERATION, in_ie, in_len);
Jes Sorensen6594c962014-05-31 18:05:12 +02002182 if (p && (p[1] == sizeof(struct ieee80211_ht_operation))) {
Larry Finger5e93f352014-03-28 21:37:38 -05002183 out_len = *pout_len;
Jes Sorensena7eab382014-04-15 19:43:25 +02002184 pframe = rtw_set_ie23a(out_ie + out_len,
2185 WLAN_EID_HT_OPERATION,
Jes Sorensen7c2f97b2014-04-15 19:43:37 +02002186 p[1], p + 2 , pout_len);
Larry Finger5e93f352014-03-28 21:37:38 -05002187 }
2188 }
2189
2190 return phtpriv->ht_option;
2191}
2192
Masanari Iida7c17d2d2014-07-22 23:42:24 +09002193/* the function is > passive_level (in critical_section) */
Larry Finger5e93f352014-03-28 21:37:38 -05002194void rtw_update_ht_cap23a(struct rtw_adapter *padapter, u8 *pie, uint ie_len)
2195{
Jes Sorensen2403ea62014-04-15 19:43:38 +02002196 u8 max_ampdu_sz;
2197 const u8 *p;
Larry Finger5e93f352014-03-28 21:37:38 -05002198 struct ieee80211_ht_cap *pht_capie;
Jes Sorensen6594c962014-05-31 18:05:12 +02002199 struct ieee80211_ht_operation *pht_addtinfo;
Jes Sorensen2403ea62014-04-15 19:43:38 +02002200 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
2201 struct ht_priv *phtpriv = &pmlmepriv->htpriv;
Larry Finger5e93f352014-03-28 21:37:38 -05002202 struct registry_priv *pregistrypriv = &padapter->registrypriv;
Jes Sorensen2403ea62014-04-15 19:43:38 +02002203 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
Larry Finger5e93f352014-03-28 21:37:38 -05002204 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
2205
2206 if (!phtpriv->ht_option)
2207 return;
2208
2209 if ((!pmlmeinfo->HT_info_enable) || (!pmlmeinfo->HT_caps_enable))
2210 return;
2211
2212 DBG_8723A("+rtw_update_ht_cap23a()\n");
2213
2214 /* maybe needs check if ap supports rx ampdu. */
Jes Sorensen47e5d2f2014-06-09 15:16:08 +02002215 if (!phtpriv->ampdu_enable && pregistrypriv->ampdu_enable == 1) {
Larry Finger5e93f352014-03-28 21:37:38 -05002216 if (pregistrypriv->wifi_spec == 1)
2217 phtpriv->ampdu_enable = false;
2218 else
2219 phtpriv->ampdu_enable = true;
Jes Sorensen2403ea62014-04-15 19:43:38 +02002220 } else if (pregistrypriv->ampdu_enable == 2)
Larry Finger5e93f352014-03-28 21:37:38 -05002221 phtpriv->ampdu_enable = true;
Larry Finger5e93f352014-03-28 21:37:38 -05002222
2223 /* check Max Rx A-MPDU Size */
Jes Sorensen2403ea62014-04-15 19:43:38 +02002224 p = cfg80211_find_ie(WLAN_EID_HT_CAPABILITY, pie, ie_len);
Larry Finger5e93f352014-03-28 21:37:38 -05002225
Jes Sorensen2403ea62014-04-15 19:43:38 +02002226 if (p && p[1] > 0) {
2227 pht_capie = (struct ieee80211_ht_cap *)(p + 2);
2228 max_ampdu_sz = pht_capie->ampdu_params_info &
2229 IEEE80211_HT_AMPDU_PARM_FACTOR;
2230 /* max_ampdu_sz (kbytes); */
2231 max_ampdu_sz = 1 << (max_ampdu_sz + 3);
2232
Larry Finger5e93f352014-03-28 21:37:38 -05002233 phtpriv->rx_ampdu_maxlen = max_ampdu_sz;
Larry Finger5e93f352014-03-28 21:37:38 -05002234 }
2235
Jes Sorensen2403ea62014-04-15 19:43:38 +02002236 p = cfg80211_find_ie(WLAN_EID_HT_OPERATION, pie, ie_len);
2237 if (p && p[1] > 0) {
Jes Sorensen6594c962014-05-31 18:05:12 +02002238 pht_addtinfo = (struct ieee80211_ht_operation *)(p + 2);
Larry Finger5e93f352014-03-28 21:37:38 -05002239 /* todo: */
2240 }
2241
2242 /* update cur_bwmode & cur_ch_offset */
Jes Sorensen2403ea62014-04-15 19:43:38 +02002243 if (pregistrypriv->cbw40_enable &&
Jes Sorensen65be27d2014-05-31 18:05:11 +02002244 pmlmeinfo->ht_cap.cap_info &
2245 cpu_to_le16(IEEE80211_HT_CAP_SUP_WIDTH_20_40) &&
Jes Sorensen4dc5f8b2014-05-31 18:05:13 +02002246 pmlmeinfo->HT_info.ht_param & IEEE80211_HT_PARAM_CHAN_WIDTH_ANY) {
Larry Finger5e93f352014-03-28 21:37:38 -05002247 int i;
Jes Sorensenc2370e82014-04-09 23:20:53 +02002248 u8 rf_type;
Larry Finger5e93f352014-03-28 21:37:38 -05002249
Jes Sorensenc2370e82014-04-09 23:20:53 +02002250 rf_type = rtl8723a_get_rf_type(padapter);
Larry Finger5e93f352014-03-28 21:37:38 -05002251
2252 /* update the MCS rates */
Jes Sorensen198e95d2014-05-31 18:05:10 +02002253 for (i = 0; i < IEEE80211_HT_MCS_MASK_LEN; i++) {
Jes Sorensen480c8652014-04-15 19:44:45 +02002254 if (rf_type == RF_1T1R || rf_type == RF_1T2R)
Jes Sorensen65be27d2014-05-31 18:05:11 +02002255 pmlmeinfo->ht_cap.mcs.rx_mask[i] &=
2256 MCS_rate_1R23A[i];
Larry Finger5e93f352014-03-28 21:37:38 -05002257 else
Jes Sorensen65be27d2014-05-31 18:05:11 +02002258 pmlmeinfo->ht_cap.mcs.rx_mask[i] &=
2259 MCS_rate_2R23A[i];
Larry Finger5e93f352014-03-28 21:37:38 -05002260 }
Masanari Iida7c17d2d2014-07-22 23:42:24 +09002261 /* switch to the 40M Hz mode according to the AP */
Larry Finger5e93f352014-03-28 21:37:38 -05002262 pmlmeext->cur_bwmode = HT_CHANNEL_WIDTH_40;
Jes Sorensen4dc5f8b2014-05-31 18:05:13 +02002263 switch (pmlmeinfo->HT_info.ht_param &
Jes Sorensenb2775412014-06-03 23:41:22 +02002264 IEEE80211_HT_PARAM_CHA_SEC_OFFSET) {
Jes Sorensen4dc5f8b2014-05-31 18:05:13 +02002265 case IEEE80211_HT_PARAM_CHA_SEC_ABOVE:
Jes Sorensenb54e8802014-04-09 23:20:52 +02002266 pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_LOWER;
2267 break;
Larry Finger5e93f352014-03-28 21:37:38 -05002268
Jes Sorensen4dc5f8b2014-05-31 18:05:13 +02002269 case IEEE80211_HT_PARAM_CHA_SEC_BELOW:
Jes Sorensenb54e8802014-04-09 23:20:52 +02002270 pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_UPPER;
2271 break;
Larry Finger5e93f352014-03-28 21:37:38 -05002272
Jes Sorensenb54e8802014-04-09 23:20:52 +02002273 default:
2274 pmlmeext->cur_ch_offset =
2275 HAL_PRIME_CHNL_OFFSET_DONT_CARE;
2276 break;
Larry Finger5e93f352014-03-28 21:37:38 -05002277 }
2278 }
2279
2280 /* */
2281 /* Config SM Power Save setting */
2282 /* */
Jes Sorensen65be27d2014-05-31 18:05:11 +02002283 pmlmeinfo->SM_PS =
2284 (le16_to_cpu(pmlmeinfo->ht_cap.cap_info) &
2285 IEEE80211_HT_CAP_SM_PS) >> IEEE80211_HT_CAP_SM_PS_SHIFT;
Larry Finger5e93f352014-03-28 21:37:38 -05002286 if (pmlmeinfo->SM_PS == WLAN_HT_CAP_SM_PS_STATIC)
2287 DBG_8723A("%s(): WLAN_HT_CAP_SM_PS_STATIC\n", __func__);
2288
2289 /* */
2290 /* Config current HT Protection mode. */
2291 /* */
Jes Sorensen4dc5f8b2014-05-31 18:05:13 +02002292 pmlmeinfo->HT_protection =
2293 le16_to_cpu(pmlmeinfo->HT_info.operation_mode) &
2294 IEEE80211_HT_OP_MODE_PROTECTION;
Larry Finger5e93f352014-03-28 21:37:38 -05002295}
2296
Jes Sorensen480c8652014-04-15 19:44:45 +02002297void rtw_issue_addbareq_cmd23a(struct rtw_adapter *padapter,
2298 struct xmit_frame *pxmitframe)
Larry Finger5e93f352014-03-28 21:37:38 -05002299{
2300 u8 issued;
2301 int priority;
Jes Sorensen480c8652014-04-15 19:44:45 +02002302 struct sta_info *psta;
Larry Finger5e93f352014-03-28 21:37:38 -05002303 struct ht_priv *phtpriv;
2304 struct pkt_attrib *pattrib = &pxmitframe->attrib;
2305 s32 bmcst = is_multicast_ether_addr(pattrib->ra);
2306
Jes Sorensen480c8652014-04-15 19:44:45 +02002307 if (bmcst || padapter->mlmepriv.LinkDetectInfo.NumTxOkInPeriod < 100)
Larry Finger5e93f352014-03-28 21:37:38 -05002308 return;
2309
2310 priority = pattrib->priority;
2311
2312 if (pattrib->psta)
2313 psta = pattrib->psta;
Jes Sorensen480c8652014-04-15 19:44:45 +02002314 else {
Larry Finger5e93f352014-03-28 21:37:38 -05002315 DBG_8723A("%s, call rtw_get_stainfo23a()\n", __func__);
2316 psta = rtw_get_stainfo23a(&padapter->stapriv, pattrib->ra);
2317 }
2318
Jes Sorensen480c8652014-04-15 19:44:45 +02002319 if (!psta) {
Larry Finger5e93f352014-03-28 21:37:38 -05002320 DBG_8723A("%s, psta == NUL\n", __func__);
2321 return;
2322 }
2323
Jes Sorensen480c8652014-04-15 19:44:45 +02002324 if (!(psta->state &_FW_LINKED)) {
2325 DBG_8723A("%s, psta->state(0x%x) != _FW_LINKED\n",
2326 __func__, psta->state);
Larry Finger5e93f352014-03-28 21:37:38 -05002327 return;
2328 }
2329
2330 phtpriv = &psta->htpriv;
2331
Jes Sorensen47e5d2f2014-06-09 15:16:08 +02002332 if (phtpriv->ht_option && phtpriv->ampdu_enable) {
Larry Finger5e93f352014-03-28 21:37:38 -05002333 issued = (phtpriv->agg_enable_bitmap>>priority)&0x1;
2334 issued |= (phtpriv->candidate_tid_bitmap>>priority)&0x1;
2335
Jes Sorensen480c8652014-04-15 19:44:45 +02002336 if (issued == 0) {
2337 DBG_8723A("rtw_issue_addbareq_cmd23a, p =%d\n",
2338 priority);
Jes Sorensen561fb402014-05-09 15:04:20 +02002339 psta->htpriv.candidate_tid_bitmap |= BIT(priority);
Jes Sorensen480c8652014-04-15 19:44:45 +02002340 rtw_addbareq_cmd23a(padapter, (u8) priority,
2341 pattrib->ra);
Larry Finger5e93f352014-03-28 21:37:38 -05002342 }
2343 }
2344}
2345
Larry Finger5e93f352014-03-28 21:37:38 -05002346int rtw_linked_check(struct rtw_adapter *padapter)
2347{
Jes Sorensen56828792014-04-15 19:44:46 +02002348 if (check_fwstate(&padapter->mlmepriv, WIFI_AP_STATE) ||
2349 check_fwstate(&padapter->mlmepriv,
2350 WIFI_ADHOC_STATE|WIFI_ADHOC_MASTER_STATE)) {
Larry Finger5e93f352014-03-28 21:37:38 -05002351 if (padapter->stapriv.asoc_sta_count > 2)
2352 return true;
2353 } else { /* Station mode */
Jes Sorensen56828792014-04-15 19:44:46 +02002354 if (check_fwstate(&padapter->mlmepriv, _FW_LINKED))
Larry Finger5e93f352014-03-28 21:37:38 -05002355 return true;
2356 }
2357 return false;
2358}