Merge tag 'linux-kselftest-3.19-rc1' of git://git.kernel.org/pub/scm/linux/kernel...
[cascardo/linux.git] / drivers / staging / rtl8723au / core / rtw_mlme.c
1 /******************************************************************************
2  *
3  * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
4  *
5  * This program is free software; you can redistribute it and/or modify it
6  * under the terms of version 2 of the GNU General Public License as
7  * published by the Free Software Foundation.
8  *
9  * This program is distributed in the hope that it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11  * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12  * more details.
13  *
14  ******************************************************************************/
15 #define _RTW_MLME_C_
16
17 #include <osdep_service.h>
18 #include <drv_types.h>
19 #include <recv_osdep.h>
20 #include <xmit_osdep.h>
21 #include <hal_intf.h>
22 #include <mlme_osdep.h>
23 #include <sta_info.h>
24 #include <linux/ieee80211.h>
25 #include <wifi.h>
26 #include <wlan_bssdef.h>
27 #include <rtw_sreset.h>
28
29 static struct wlan_network *
30 rtw_select_candidate_from_queue(struct mlme_priv *pmlmepriv);
31 static int rtw_do_join(struct rtw_adapter *padapter);
32
33 static void rtw_init_mlme_timer(struct rtw_adapter *padapter)
34 {
35         struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
36
37         setup_timer(&pmlmepriv->assoc_timer, rtw23a_join_to_handler,
38                     (unsigned long)padapter);
39
40         setup_timer(&pmlmepriv->scan_to_timer, rtw_scan_timeout_handler23a,
41                     (unsigned long)padapter);
42
43         setup_timer(&pmlmepriv->dynamic_chk_timer,
44                     rtw_dynamic_check_timer_handler, (unsigned long)padapter);
45
46         setup_timer(&pmlmepriv->set_scan_deny_timer,
47                     rtw_set_scan_deny_timer_hdl, (unsigned long)padapter);
48 }
49
50 int rtw_init_mlme_priv23a(struct rtw_adapter *padapter)
51 {
52         struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
53
54         pmlmepriv->nic_hdl = padapter;
55
56         pmlmepriv->fw_state = 0;
57         pmlmepriv->cur_network.network.ifmode = NL80211_IFTYPE_UNSPECIFIED;
58         /*  1: active, 0: pasive. Maybe someday we should rename this
59             varable to "active_mode" (Jeff) */
60         pmlmepriv->scan_mode = SCAN_ACTIVE;
61
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
67         rtw_clear_scan_deny(padapter);
68
69         rtw_init_mlme_timer(padapter);
70         return _SUCCESS;
71 }
72
73 #ifdef CONFIG_8723AU_AP_MODE
74 static void rtw_free_mlme_ie_data(u8 **ppie, u32 *plen)
75 {
76         if (*ppie) {
77                 kfree(*ppie);
78                 *plen = 0;
79                 *ppie = NULL;
80         }
81 }
82 #endif
83
84 void rtw23a_free_mlme_priv_ie_data(struct mlme_priv *pmlmepriv)
85 {
86 #ifdef CONFIG_8723AU_AP_MODE
87         kfree(pmlmepriv->assoc_req);
88         kfree(pmlmepriv->assoc_rsp);
89         rtw_free_mlme_ie_data(&pmlmepriv->wps_probe_req_ie,
90                               &pmlmepriv->wps_probe_req_ie_len);
91 #endif
92 }
93
94 void rtw_free_mlme_priv23a(struct mlme_priv *pmlmepriv)
95 {
96         RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_,
97                  ("rtw_free_mlme_priv23a\n"));
98
99         rtw23a_free_mlme_priv_ie_data(pmlmepriv);
100 }
101
102 struct wlan_network *rtw_alloc_network(struct mlme_priv *pmlmepriv, gfp_t gfp)
103 {
104         struct wlan_network *pnetwork;
105
106         pnetwork = kzalloc(sizeof(struct wlan_network), gfp);
107         if (pnetwork) {
108                 INIT_LIST_HEAD(&pnetwork->list);
109                 pnetwork->network_type = 0;
110                 pnetwork->fixed = false;
111                 pnetwork->last_scanned = jiffies;
112                 pnetwork->join_res = 0;
113         }
114
115         return pnetwork;
116 }
117
118 static void _rtw_free_network23a(struct mlme_priv *pmlmepriv,
119                                  struct wlan_network *pnetwork)
120 {
121         if (!pnetwork)
122                 return;
123
124         if (pnetwork->fixed == true)
125                 return;
126
127         list_del_init(&pnetwork->list);
128
129         kfree(pnetwork);
130 }
131
132 /*
133  return the wlan_network with the matching addr
134
135  Shall be called under atomic context... to avoid possible racing condition...
136 */
137 struct wlan_network *
138 rtw_find_network23a(struct rtw_queue *scanned_queue, u8 *addr)
139 {
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;
160         }
161
162         if (plist == phead)
163                 pnetwork = NULL;
164
165         /* spin_unlock_bh(&scanned_queue->lock); */
166
167 exit:
168
169         return pnetwork;
170 }
171
172 void rtw_free_network_queue23a(struct rtw_adapter *padapter)
173 {
174         struct list_head *phead, *plist, *ptmp;
175         struct wlan_network *pnetwork;
176         struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
177         struct rtw_queue *scanned_queue = &pmlmepriv->scanned_queue;
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
186                 _rtw_free_network23a(pmlmepriv, pnetwork);
187         }
188
189         spin_unlock_bh(&scanned_queue->lock);
190 }
191
192 int rtw_if_up23a(struct rtw_adapter *padapter)
193 {
194         int res;
195
196         if (padapter->bDriverStopped || padapter->bSurpriseRemoved ||
197             !check_fwstate(&padapter->mlmepriv, _FW_LINKED)) {
198                 RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_,
199                          ("rtw_if_up23a:bDriverStopped(%d) OR "
200                           "bSurpriseRemoved(%d)", padapter->bDriverStopped,
201                           padapter->bSurpriseRemoved));
202                 res = false;
203         } else
204                 res =  true;
205
206         return res;
207 }
208
209 void rtw_generate_random_ibss23a(u8 *pibss)
210 {
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;
216         pibss[3] = curtime & 0xff;/* p[0]; */
217         pibss[4] = (curtime >> 8) & 0xff;/* p[1]; */
218         pibss[5] = (curtime >> 16) & 0xff;/* p[2]; */
219 }
220
221 void 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
228 static 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) {
251                         do_join_r = rtw_do_join(padapter);
252                         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
273 void 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
283 static void rtw_free_network_nolock(struct mlme_priv *pmlmepriv,
284                                     struct wlan_network *pnetwork)
285 {
286         _rtw_free_network23a(pmlmepriv, pnetwork);
287 }
288
289 bool rtw_is_same_ibss23a(struct rtw_adapter *adapter,
290                          struct wlan_network *pnetwork)
291 {
292         int ret;
293         struct security_priv *psecuritypriv = &adapter->securitypriv;
294
295         if (psecuritypriv->dot11PrivacyAlgrthm != 0 &&
296             pnetwork->network.Privacy == 0)
297                 ret = false;
298         else if (psecuritypriv->dot11PrivacyAlgrthm == 0 &&
299                  pnetwork->network.Privacy == 1)
300                 ret = false;
301         else
302                 ret = true;
303
304         return ret;
305 }
306
307 inline int is_same_ess(struct wlan_bssid_ex *a, struct wlan_bssid_ex *b);
308 inline int is_same_ess(struct wlan_bssid_ex *a, struct wlan_bssid_ex *b)
309 {
310         return (a->Ssid.ssid_len == b->Ssid.ssid_len) &&
311                 !memcmp(a->Ssid.ssid, b->Ssid.ssid, a->Ssid.ssid_len);
312 }
313
314 int is_same_network23a(struct wlan_bssid_ex *src, struct wlan_bssid_ex *dst)
315 {
316         u16 s_cap, d_cap;
317
318         s_cap = src->capability;
319         d_cap = dst->capability;
320
321         return ((src->Ssid.ssid_len == dst->Ssid.ssid_len) &&
322                 /*      (src->DSConfig == dst->DSConfig) && */
323                 ether_addr_equal(src->MacAddress, dst->MacAddress) &&
324                 !memcmp(src->Ssid.ssid, dst->Ssid.ssid, src->Ssid.ssid_len) &&
325                 (s_cap & WLAN_CAPABILITY_IBSS) ==
326                 (d_cap & WLAN_CAPABILITY_IBSS) &&
327                 (s_cap & WLAN_CAPABILITY_ESS) == (d_cap & WLAN_CAPABILITY_ESS));
328 }
329
330 struct wlan_network *
331 rtw_get_oldest_wlan_network23a(struct rtw_queue *scanned_queue)
332 {
333         struct list_head *plist, *phead;
334         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
352 void update_network23a(struct wlan_bssid_ex *dst, struct wlan_bssid_ex *src,
353                        struct rtw_adapter *padapter, bool update_ie)
354 {
355         u8 ss_ori = dst->SignalStrength;
356         u8 sq_ori = dst->SignalQuality;
357         long rssi_ori = dst->Rssi;
358
359         u8 ss_smp = src->SignalStrength;
360         u8 sq_smp = src->SignalQuality;
361         long rssi_smp = src->Rssi;
362
363         u8 ss_final;
364         u8 sq_final;
365         long rssi_final;
366
367         DBG_8723A("%s %s(%pM, ch%u) ss_ori:%3u, sq_ori:%3u, rssi_ori:%3ld, "
368                   "ss_smp:%3u, sq_smp:%3u, rssi_smp:%3ld\n",
369                   __func__, src->Ssid.ssid, src->MacAddress,
370                   src->DSConfig, ss_ori, sq_ori, rssi_ori,
371                   ss_smp, sq_smp, rssi_smp
372         );
373
374         /* The rule below is 1/5 for sample value, 4/5 for history value */
375         if (check_fwstate(&padapter->mlmepriv, _FW_LINKED) &&
376             is_same_network23a(&padapter->mlmepriv.cur_network.network, src)) {
377                 /* Take the recvpriv's value for the connected AP*/
378                 ss_final = padapter->recvpriv.signal_strength;
379                 sq_final = padapter->recvpriv.signal_qual;
380                 /* the rssi value here is undecorated, and will be
381                    used for antenna diversity */
382                 if (sq_smp != 101) /* from the right channel */
383                         rssi_final = (src->Rssi+dst->Rssi*4)/5;
384                 else
385                         rssi_final = rssi_ori;
386         } else {
387                 if (sq_smp != 101) { /* from the right channel */
388                         ss_final = ((u32)src->SignalStrength +
389                                     (u32)dst->SignalStrength * 4) / 5;
390                         sq_final = ((u32)src->SignalQuality +
391                                     (u32)dst->SignalQuality * 4) / 5;
392                         rssi_final = src->Rssi+dst->Rssi * 4 / 5;
393                 } else {
394                         /* bss info not receiving from the right channel, use
395                            the original RX signal infos */
396                         ss_final = dst->SignalStrength;
397                         sq_final = dst->SignalQuality;
398                         rssi_final = dst->Rssi;
399                 }
400
401         }
402
403         if (update_ie)
404                 memcpy(dst, src, get_wlan_bssid_ex_sz(src));
405
406         dst->SignalStrength = ss_final;
407         dst->SignalQuality = sq_final;
408         dst->Rssi = rssi_final;
409
410         DBG_8723A("%s %s(%pM), SignalStrength:%u, SignalQuality:%u, "
411                   "RawRSSI:%ld\n",  __func__, dst->Ssid.ssid, dst->MacAddress,
412                   dst->SignalStrength, dst->SignalQuality, dst->Rssi);
413 }
414
415 static void update_current_network(struct rtw_adapter *adapter,
416                                    struct wlan_bssid_ex *pnetwork)
417 {
418         struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
419
420         if (check_fwstate(pmlmepriv, _FW_LINKED) &&
421             is_same_network23a(&pmlmepriv->cur_network.network, pnetwork)) {
422                 update_network23a(&pmlmepriv->cur_network.network,
423                                   pnetwork, adapter, true);
424
425                 rtw_update_protection23a(adapter,
426                                          pmlmepriv->cur_network.network.IEs,
427                                          pmlmepriv->cur_network.network.IELength);
428         }
429 }
430
431 /*
432
433 Caller must hold pmlmepriv->lock first.
434
435 */
436 static void rtw_update_scanned_network(struct rtw_adapter *adapter,
437                                        struct wlan_bssid_ex *target)
438 {
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) {
465                 pnetwork = rtw_alloc_network(pmlmepriv, GFP_ATOMIC);
466                 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;
485                 pnetwork->join_res = 0;
486
487                 /* bss info not receiving from the right channel */
488                 if (pnetwork->network.SignalQuality == 101)
489                         pnetwork->network.SignalQuality = 0;
490         } 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. */
503                 if (pnetwork->network.IELength > target->IELength &&
504                     target->reserved == 1)
505                         update_ie = false;
506
507                 update_network23a(&pnetwork->network, target, adapter,
508                                   update_ie);
509         }
510
511 exit:
512         spin_unlock_bh(&queue->lock);
513 }
514
515 static void rtw_add_network(struct rtw_adapter *adapter,
516                             struct wlan_bssid_ex *pnetwork)
517 {
518         update_current_network(adapter, pnetwork);
519         rtw_update_scanned_network(adapter, pnetwork);
520 }
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 */
528 static int rtw_is_desired_network(struct rtw_adapter *adapter,
529                                   struct wlan_network *pnetwork)
530 {
531         struct security_priv *psecuritypriv = &adapter->securitypriv;
532         struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
533         u32 desired_encmode;
534         u32 privacy;
535         int bselected = true;
536
537         desired_encmode = psecuritypriv->ndisencryptstatus;
538         privacy = pnetwork->network.Privacy;
539
540         if (check_fwstate(pmlmepriv, WIFI_UNDER_WPS)) {
541                 if (cfg80211_find_vendor_ie(WLAN_OUI_MICROSOFT,
542                                             WLAN_OUI_TYPE_MICROSOFT_WPA,
543                                             pnetwork->network.IEs,
544                                             pnetwork->network.IELength))
545                         return true;
546                 else
547                         return false;
548         }
549         if (adapter->registrypriv.wifi_spec == 1) {
550                 /* for  correct flow of 8021X  to do.... */
551                 if (desired_encmode == Ndis802_11EncryptionDisabled &&
552                     privacy != 0)
553                         bselected = false;
554         }
555
556         if (desired_encmode != Ndis802_11EncryptionDisabled && privacy == 0) {
557                 DBG_8723A("desired_encmode: %d, privacy: %d\n",
558                           desired_encmode, privacy);
559                 bselected = false;
560         }
561
562         if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE)) {
563                 if (pnetwork->network.ifmode !=
564                     pmlmepriv->cur_network.network.ifmode)
565                         bselected = false;
566         }
567
568         return bselected;
569 }
570
571 /* TODO: Perry : For Power Management */
572 void rtw_atimdone_event_callback23a(struct rtw_adapter *adapter, const u8 *pbuf)
573 {
574         RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_,
575                  ("receive atimdone_evet\n"));
576 }
577
578 void rtw_survey_event_cb23a(struct rtw_adapter *adapter, const u8 *pbuf)
579 {
580         u32 len;
581         struct wlan_bssid_ex *pnetwork;
582         struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
583         struct survey_event *survey = (struct survey_event *)pbuf;
584
585         pnetwork = survey->bss;
586
587         RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_,
588                  ("rtw_survey_event_cb23a, ssid=%s\n", pnetwork->Ssid.ssid));
589
590         len = get_wlan_bssid_ex_sz(pnetwork);
591         if (len > (sizeof(struct wlan_bssid_ex))) {
592                 RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_,
593                          ("\n ****rtw_survey_event_cb23a: return a wrong "
594                           "bss ***\n"));
595                 return;
596         }
597
598         spin_lock_bh(&pmlmepriv->lock);
599
600         /*  update IBSS_network 's timestamp */
601         if (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE)) {
602                 /* RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_,
603                    "rtw_survey_event_cb23a : WIFI_ADHOC_MASTER_STATE\n\n"); */
604                 if (ether_addr_equal(pmlmepriv->cur_network.network.MacAddress,
605                                      pnetwork->MacAddress)) {
606                         struct wlan_network *ibss_wlan;
607
608                         pmlmepriv->cur_network.network.beacon_interval =
609                                 pnetwork->beacon_interval;
610                         pmlmepriv->cur_network.network.capability =
611                                 pnetwork->capability;
612                         pmlmepriv->cur_network.network.tsf = pnetwork->tsf;
613                         spin_lock_bh(&pmlmepriv->scanned_queue.lock);
614                         ibss_wlan = rtw_find_network23a(
615                                 &pmlmepriv->scanned_queue,
616                                 pnetwork->MacAddress);
617                         if (ibss_wlan) {
618                                 pmlmepriv->cur_network.network.beacon_interval =
619                                         ibss_wlan->network.beacon_interval;
620                                 pmlmepriv->cur_network.network.capability =
621                                         ibss_wlan->network.capability;
622                                 pmlmepriv->cur_network.network.tsf =
623                                         ibss_wlan->network.tsf;
624                                 spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
625                                 goto exit;
626                         }
627                         spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
628                 }
629         }
630
631         /*  lock pmlmepriv->lock when you accessing network_q */
632         if (!check_fwstate(pmlmepriv, _FW_UNDER_LINKING)) {
633                 if (pnetwork->Ssid.ssid[0] == 0)
634                         pnetwork->Ssid.ssid_len = 0;
635
636                 rtw_add_network(adapter, pnetwork);
637         }
638
639 exit:
640
641         spin_unlock_bh(&pmlmepriv->lock);
642
643         kfree(survey->bss);
644         survey->bss = NULL;
645 }
646
647 void
648 rtw_surveydone_event_callback23a(struct rtw_adapter *adapter, const u8 *pbuf)
649 {
650         struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
651         struct mlme_ext_priv *pmlmeext = &adapter->mlmeextpriv;
652         int ret;
653
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
662         RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_,
663                  ("rtw_surveydone_event_callback23a: fw_state:%x\n\n",
664                   get_fwstate(pmlmepriv)));
665
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 {
671                 RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_,
672                          ("nic status =%x, survey done event comes too late!\n",
673                           get_fwstate(pmlmepriv)));
674         }
675
676         rtw_set_signal_stat_timer(&adapter->recvpriv);
677
678         if (pmlmepriv->to_join == true) {
679                 set_fwstate(pmlmepriv, _FW_UNDER_LINKING);
680                 if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE)) {
681                         ret = rtw_select_and_join_from_scanned_queue23a(
682                                 pmlmepriv);
683                         if (ret != _SUCCESS)
684                                 rtw_do_join_adhoc(adapter);
685                 } else {
686                         pmlmepriv->to_join = false;
687                         ret = rtw_select_and_join_from_scanned_queue23a(
688                                 pmlmepriv);
689                         if (ret != _SUCCESS) {
690                                 DBG_8723A("try_to_join, but select scanning "
691                                           "queue fail, to_roaming:%d\n",
692                                           adapter->mlmepriv.to_roaming);
693                                 if (adapter->mlmepriv.to_roaming) {
694                                         if (--pmlmepriv->to_roaming == 0 ||
695                                             rtw_sitesurvey_cmd23a(
696                                                     adapter,
697                                                     &pmlmepriv->assoc_ssid, 1,
698                                                     NULL, 0) != _SUCCESS) {
699                                                 rtw_set_roaming(adapter, 0);
700                                                 rtw_free_assoc_resources23a(
701                                                         adapter, 1);
702                                                 rtw_indicate_disconnect23a(
703                                                         adapter);
704                                         } else
705                                                 pmlmepriv->to_join = true;
706                                 }
707                                 _clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING);
708                         }
709                 }
710         }
711
712         spin_unlock_bh(&pmlmepriv->lock);
713
714         rtw_os_xmit_schedule23a(adapter);
715
716         if (pmlmeext->sitesurvey_res.bss_cnt == 0)
717                 rtw_sreset_reset(adapter);
718
719         rtw_cfg80211_surveydone_event_callback(adapter);
720 }
721
722 static void free_scanqueue(struct mlme_priv *pmlmepriv)
723 {
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) {
734                 pnetwork = container_of(plist, struct wlan_network, list);
735                 pnetwork->fixed = false;
736                 _rtw_free_network23a(pmlmepriv, pnetwork);
737         }
738
739         spin_unlock_bh(&scan_queue->lock);
740 }
741
742 /*
743  *rtw_free_assoc_resources23a: the caller has to lock pmlmepriv->lock
744  */
745 void rtw_free_assoc_resources23a(struct rtw_adapter *adapter,
746                                  int lock_scanned_queue)
747 {
748         struct wlan_network *pwlan;
749         struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
750         struct sta_priv *pstapriv = &adapter->stapriv;
751         struct wlan_network *tgt_network = &pmlmepriv->cur_network;
752         struct sta_info *psta;
753
754         RT_TRACE(_module_rtl871x_mlme_c_, _drv_notice_,
755                  ("+rtw_free_assoc_resources23a\n"));
756         RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_,
757                  ("tgt_network->network.MacAddress="MAC_FMT" ssid=%s\n",
758                   MAC_ARG(tgt_network->network.MacAddress),
759                   tgt_network->network.Ssid.ssid));
760
761         if (check_fwstate(pmlmepriv, WIFI_STATION_STATE|WIFI_AP_STATE)) {
762                 psta = rtw_get_stainfo23a(&adapter->stapriv,
763                                           tgt_network->network.MacAddress);
764
765                 spin_lock_bh(&pstapriv->sta_hash_lock);
766                 rtw_free_stainfo23a(adapter,  psta);
767                 spin_unlock_bh(&pstapriv->sta_hash_lock);
768         }
769
770         if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE |
771                           WIFI_ADHOC_MASTER_STATE|WIFI_AP_STATE)) {
772                 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
782         if (lock_scanned_queue)
783                 spin_lock_bh(&pmlmepriv->scanned_queue.lock);
784
785         pwlan = rtw_find_network23a(&pmlmepriv->scanned_queue,
786                                     tgt_network->network.MacAddress);
787         if (pwlan)
788                 pwlan->fixed = false;
789         else
790                 RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_,
791                          ("rtw_free_assoc_resources23a : pwlan== NULL\n"));
792
793         if (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) &&
794             adapter->stapriv.asoc_sta_count == 1)
795                 rtw_free_network_nolock(pmlmepriv, pwlan);
796
797         if (lock_scanned_queue)
798                 spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
799
800         pmlmepriv->key_mask = 0;
801 }
802
803 /*
804 *rtw_indicate_connect23a: the caller has to lock pmlmepriv->lock
805 */
806 void rtw_indicate_connect23a(struct rtw_adapter *padapter)
807 {
808         struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
809
810         RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_,
811                  ("+rtw_indicate_connect23a\n"));
812
813         pmlmepriv->to_join = false;
814
815         if (!check_fwstate(&padapter->mlmepriv, _FW_LINKED)) {
816                 set_fwstate(pmlmepriv, _FW_LINKED);
817
818                 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);
824         }
825
826         rtw_set_roaming(padapter, 0);
827
828         rtw_set_scan_deny(padapter, 3000);
829
830         RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_,
831                  ("-rtw_indicate_connect23a: fw_state=0x%08x\n",
832                   get_fwstate(pmlmepriv)));
833 }
834
835 /*
836  *rtw_indicate_disconnect23a: the caller has to lock pmlmepriv->lock
837  */
838 void rtw_indicate_disconnect23a(struct rtw_adapter *padapter)
839 {
840         struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
841
842         RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_,
843                  ("+rtw_indicate_disconnect23a\n"));
844
845         _clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING|WIFI_UNDER_WPS);
846
847         /* DBG_8723A("clear wps when %s\n", __func__); */
848
849         if (padapter->mlmepriv.to_roaming > 0)
850                 _clr_fwstate_(pmlmepriv, _FW_LINKED);
851
852         if (check_fwstate(&padapter->mlmepriv, _FW_LINKED) ||
853             padapter->mlmepriv.to_roaming <= 0) {
854                 rtw_os_indicate_disconnect23a(padapter);
855
856                 /* set ips_deny_time to avoid enter IPS before LPS leave */
857                 padapter->pwrctrlpriv.ips_deny_time =
858                         jiffies + msecs_to_jiffies(3000);
859
860                 _clr_fwstate_(pmlmepriv, _FW_LINKED);
861
862                 rtw_clear_scan_deny(padapter);
863         }
864
865         rtw_lps_ctrl_wk_cmd23a(padapter, LPS_CTRL_DISCONNECT, 1);
866 }
867
868 void 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) {
878                 if (adapter->bDriverStopped || adapter->bSurpriseRemoved)
879                         break;
880
881                 DBG_8723A("%s(%s): fw_state = _FW_UNDER_SURVEY!\n",
882                           __func__, adapter->pnetdev->name);
883                 msleep(20);
884         }
885
886         if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY)) {
887                 if (!adapter->bDriverStopped && !adapter->bSurpriseRemoved)
888                         DBG_8723A("%s(%s): waiting for scan_abort time out!\n",
889                                   __func__, adapter->pnetdev->name);
890                 rtw_cfg80211_indicate_scan_done(wdev_to_priv(adapter->rtw_wdev),
891                                                 true);
892         }
893         pmlmeext->scan_abort = false;
894 }
895
896 static struct sta_info *
897 rtw_joinbss_update_stainfo(struct rtw_adapter *padapter,
898                            struct wlan_network *pnetwork)
899 {
900         int i;
901         struct sta_info *bmc_sta, *psta;
902         struct recv_reorder_ctrl *preorder_ctrl;
903         struct sta_priv *pstapriv = &padapter->stapriv;
904
905         psta = rtw_get_stainfo23a(pstapriv, pnetwork->network.MacAddress);
906         if (!psta)
907                 psta = rtw_alloc_stainfo23a(pstapriv,
908                                             pnetwork->network.MacAddress,
909                                             GFP_ATOMIC);
910
911         if (psta) { /* update ptarget_sta */
912                 DBG_8723A("%s\n", __func__);
913
914                 psta->aid  = pnetwork->join_res;
915                 psta->mac_id = 0;
916
917                 /* sta mode */
918                 rtl8723a_SetHalODMVar(padapter, HAL_ODM_STA_INFO, psta, true);
919
920                 /* security related */
921                 if (padapter->securitypriv.dot11AuthAlgrthm ==
922                     dot11AuthAlgrthm_8021X) {
923                         padapter->securitypriv.binstallGrpkey = 0;
924                         padapter->securitypriv.busetkipkey = 0;
925
926                         psta->ieee8021x_blocked = true;
927                         psta->dot118021XPrivacy =
928                                 padapter->securitypriv.dot11PrivacyAlgrthm;
929
930                         memset(&psta->dot118021x_UncstKey, 0,
931                                sizeof (union Keytype));
932
933                         memset(&psta->dot11tkiprxmickey, 0,
934                                sizeof (union Keytype));
935                         memset(&psta->dot11tkiptxmickey, 0,
936                                sizeof (union Keytype));
937
938                         memset(&psta->dot11txpn, 0, sizeof (union pn48));
939                         memset(&psta->dot11rxpn, 0, sizeof (union pn48));
940                 }
941
942                 /*      Commented by Albert 2012/07/21 */
943                 /*      When doing the WPS, the wps_ie_len won't equal to 0 */
944                 /*      And the Wi-Fi driver shouldn't allow the data packet
945                         to be transmitted. */
946                 if (padapter->securitypriv.wps_ie_len != 0) {
947                         psta->ieee8021x_blocked = true;
948                         padapter->securitypriv.wps_ie_len = 0;
949                 }
950
951                 /* for A-MPDU Rx reordering buffer control for bmc_sta &
952                  * sta_info */
953                 /* if A-MPDU Rx is enabled, resetting
954                    rx_ordering_ctrl wstart_b(indicate_seq) to default
955                    value = 0xffff */
956                 /* todo: check if AP can send A-MPDU packets */
957                 for (i = 0; i < 16 ; i++) {
958                         /* preorder_ctrl = &precvpriv->recvreorder_ctrl[i]; */
959                         preorder_ctrl = &psta->recvreorder_ctrl[i];
960                         preorder_ctrl->enable = false;
961                         preorder_ctrl->indicate_seq = 0xffff;
962                         preorder_ctrl->wend_b = 0xffff;
963                         /* max_ampdu_sz; ex. 32(kbytes) -> wsize_b = 32 */
964                         preorder_ctrl->wsize_b = 64;
965                 }
966
967                 bmc_sta = rtw_get_bcmc_stainfo23a(padapter);
968                 if (bmc_sta) {
969                         for (i = 0; i < 16 ; i++) {
970                                 preorder_ctrl = &bmc_sta->recvreorder_ctrl[i];
971                                 preorder_ctrl->enable = false;
972                                 preorder_ctrl->indicate_seq = 0xffff;
973                                 preorder_ctrl->wend_b = 0xffff;
974                                 /* max_ampdu_sz; ex. 32(kbytes) ->
975                                    wsize_b = 32 */
976                                 preorder_ctrl->wsize_b = 64;
977                         }
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 */
990 static void
991 rtw_joinbss_update_network23a(struct rtw_adapter *padapter,
992                               struct wlan_network *ptarget_wlan,
993                               struct wlan_network  *pnetwork)
994 {
995         struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
996         struct wlan_network *cur_network = &pmlmepriv->cur_network;
997
998         DBG_8723A("%s\n", __func__);
999
1000         RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_,
1001                  ("\nfw_state:%x, BSSID:"MAC_FMT"\n", get_fwstate(pmlmepriv),
1002                   MAC_ARG(pnetwork->network.MacAddress)));
1003
1004         /*  why not use ptarget_wlan?? */
1005         memcpy(&cur_network->network, &pnetwork->network,
1006                pnetwork->network.Length);
1007         /*  some IEs in pnetwork is wrong, so we should use ptarget_wlan IEs */
1008         cur_network->network.IELength = ptarget_wlan->network.IELength;
1009         memcpy(&cur_network->network.IEs[0], &ptarget_wlan->network.IEs[0],
1010                MAX_IE_SZ);
1011
1012         cur_network->network.capability = ptarget_wlan->network.capability;
1013         cur_network->network.beacon_interval =
1014                 ptarget_wlan->network.beacon_interval;
1015         cur_network->network.tsf = ptarget_wlan->network.tsf;
1016
1017         rtw_set_signal_stat_timer(&padapter->recvpriv);
1018         padapter->recvpriv.signal_strength =
1019                 ptarget_wlan->network.SignalStrength;
1020         padapter->recvpriv.signal_qual = ptarget_wlan->network.SignalQuality;
1021         /*
1022          * the ptarget_wlan->network.Rssi is raw data, we use
1023          * ptarget_wlan->network.SignalStrength instead (has scaled)
1024          */
1025         DBG_8723A("%s signal_strength:%3u, signal_qual:%3u\n",
1026                   __func__, padapter->recvpriv.signal_strength,
1027                   padapter->recvpriv.signal_qual);
1028         rtw_set_signal_stat_timer(&padapter->recvpriv);
1029
1030         /* update fw_state will clr _FW_UNDER_LINKING here indirectly */
1031         switch (pnetwork->network.ifmode) {
1032         case NL80211_IFTYPE_P2P_CLIENT:
1033         case NL80211_IFTYPE_STATION:
1034                 if (pmlmepriv->fw_state & WIFI_UNDER_WPS)
1035                         pmlmepriv->fw_state = WIFI_STATION_STATE|WIFI_UNDER_WPS;
1036                 else
1037                         pmlmepriv->fw_state = WIFI_STATION_STATE;
1038                 break;
1039         case NL80211_IFTYPE_ADHOC:
1040                 pmlmepriv->fw_state = WIFI_ADHOC_STATE;
1041                 break;
1042         default:
1043                 pmlmepriv->fw_state = WIFI_NULL_STATE;
1044                 RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_,
1045                          ("Invalid network_mode\n"));
1046                 break;
1047         }
1048
1049         rtw_update_protection23a(padapter, cur_network->network.IEs,
1050                                  cur_network->network.IELength);
1051
1052         rtw_update_ht_cap23a(padapter, cur_network->network.IEs,
1053                              cur_network->network.IELength);
1054 }
1055
1056 /*
1057  * Notes:
1058  * the function could be > passive_level (the same context as Rx tasklet)
1059  * pnetwork : returns from rtw23a_joinbss_event_cb
1060  * ptarget_wlan: found from scanned_queue
1061  * if join_res > 0, for (fw_state==WIFI_STATION_STATE),
1062  * we check if  "ptarget_sta" & "ptarget_wlan" exist.
1063  * if join_res > 0, for (fw_state==WIFI_ADHOC_STATE),
1064  * we only check if "ptarget_wlan" exist.
1065  * if join_res > 0, update "cur_network->network" from "pnetwork->network"
1066  * if (ptarget_wlan !=NULL).
1067  */
1068
1069 void rtw_joinbss_event_prehandle23a(struct rtw_adapter *adapter, u8 *pbuf)
1070 {
1071         struct sta_info *ptarget_sta, *pcur_sta;
1072         struct sta_priv *pstapriv = &adapter->stapriv;
1073         struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
1074         struct wlan_network *pnetwork = (struct wlan_network *)pbuf;
1075         struct wlan_network *cur_network = &pmlmepriv->cur_network;
1076         struct wlan_network *pcur_wlan, *ptarget_wlan = NULL;
1077         bool the_same_macaddr;
1078
1079         RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_,
1080                  ("joinbss event call back received with res=%d\n",
1081                   pnetwork->join_res));
1082
1083         if (pmlmepriv->assoc_ssid.ssid_len == 0) {
1084                 RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_,
1085                          ("@@@@@   joinbss event call back  for Any SSid\n"));
1086         } else {
1087                 RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_,
1088                          ("@@@@@   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);
1099         if (pnetwork->network.Length > sizeof(struct wlan_bssid_ex)) {
1100                 RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_,
1101                          ("\n\n ***joinbss_evt_callback return a wrong bss "
1102                           "***\n\n"));
1103                 return;
1104         }
1105
1106         spin_lock_bh(&pmlmepriv->lock);
1107
1108         RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_,
1109                  ("\n rtw23a_joinbss_event_cb !! _enter_critical\n"));
1110
1111         if (pnetwork->join_res > 0) {
1112                 spin_lock_bh(&pmlmepriv->scanned_queue.lock);
1113                 if (check_fwstate(pmlmepriv, _FW_UNDER_LINKING)) {
1114                         /* s1. find ptarget_wlan */
1115                         if (check_fwstate(pmlmepriv, _FW_LINKED)) {
1116                                 if (the_same_macaddr) {
1117                                         ptarget_wlan = rtw_find_network23a(&pmlmepriv->scanned_queue, cur_network->network.MacAddress);
1118                                 } else {
1119                                         pcur_wlan = rtw_find_network23a(&pmlmepriv->scanned_queue, cur_network->network.MacAddress);
1120                                         if (pcur_wlan)
1121                                                 pcur_wlan->fixed = false;
1122
1123                                         pcur_sta = rtw_get_stainfo23a(pstapriv, cur_network->network.MacAddress);
1124                                         if (pcur_sta) {
1125                                                 spin_lock_bh(&pstapriv->sta_hash_lock);
1126                                                 rtw_free_stainfo23a(adapter,
1127                                                                     pcur_sta);
1128                                                 spin_unlock_bh(&pstapriv->sta_hash_lock);
1129                                         }
1130
1131                                         ptarget_wlan = rtw_find_network23a(&pmlmepriv->scanned_queue, pnetwork->network.MacAddress);
1132                                         if (check_fwstate(pmlmepriv,
1133                                                           WIFI_STATION_STATE)) {
1134                                                 if (ptarget_wlan)
1135                                                         ptarget_wlan->fixed =
1136                                                                 true;
1137                                         }
1138                                 }
1139
1140                         } 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;
1148                                 }
1149                         }
1150
1151                         /* s2. update cur_network */
1152                         if (ptarget_wlan)
1153                                 rtw_joinbss_update_network23a(adapter,
1154                                                               ptarget_wlan,
1155                                                               pnetwork);
1156                         else {
1157                                 RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_,
1158                                          ("Can't find ptarget_wlan when "
1159                                           "joinbss_event callback\n"));
1160                                 spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
1161                                 goto ignore_joinbss_callback;
1162                         }
1163
1164                         /* s3. find ptarget_sta & update ptarget_sta after
1165                            update cur_network only for station mode */
1166                         if (check_fwstate(pmlmepriv, WIFI_STATION_STATE)) {
1167                                 ptarget_sta = rtw_joinbss_update_stainfo(
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"));
1174                                         spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
1175                                         goto ignore_joinbss_callback;
1176                                 }
1177                         }
1178
1179                         /* s4. indicate connect */
1180                         if (check_fwstate(pmlmepriv, WIFI_STATION_STATE))
1181                                 rtw_indicate_connect23a(adapter);
1182                         else {
1183                                 /* adhoc mode will rtw_indicate_connect23a
1184                                    when rtw_stassoc_event_callback23a */
1185                                 RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_,
1186                                          ("adhoc mode, fw_state:%x",
1187                                           get_fwstate(pmlmepriv)));
1188                         }
1189
1190                         /* s5. Cancle assoc_timer */
1191                         del_timer_sync(&pmlmepriv->assoc_timer);
1192
1193                         RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_,
1194                                  ("Cancle assoc_timer\n"));
1195                 } 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);
1203         } else if (pnetwork->join_res == -4) {
1204                 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
1210                 if (check_fwstate(pmlmepriv, _FW_UNDER_LINKING)) {
1211                         RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_,
1212                                  ("fail! clear _FW_UNDER_LINKING ^^^fw_state="
1213                                   "%x\n", get_fwstate(pmlmepriv)));
1214                         _clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING);
1215                 }
1216         } 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
1223 ignore_joinbss_callback:
1224
1225         spin_unlock_bh(&pmlmepriv->lock);
1226 }
1227
1228 void rtw23a_joinbss_event_cb(struct rtw_adapter *adapter, const u8 *pbuf)
1229 {
1230         struct wlan_network *pnetwork = (struct wlan_network *)pbuf;
1231
1232         mlmeext_joinbss_event_callback23a(adapter, pnetwork->join_res);
1233
1234         rtw_os_xmit_schedule23a(adapter);
1235 }
1236
1237 void rtw_stassoc_event_callback23a(struct rtw_adapter *adapter, const u8 *pbuf)
1238 {
1239         struct sta_info *psta;
1240         struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
1241         struct stassoc_event *pstassoc = (struct stassoc_event *)pbuf;
1242         struct wlan_network *cur_network = &pmlmepriv->cur_network;
1243         struct wlan_network *ptarget_wlan;
1244
1245         if (rtw_access_ctrl23a(adapter, pstassoc->macaddr) == false)
1246                 return;
1247
1248 #ifdef CONFIG_8723AU_AP_MODE
1249         if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) {
1250                 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);
1255                 }
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 */
1263                 RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_,
1264                          ("Error: rtw_stassoc_event_callback23a: sta has "
1265                           "been in sta_hash_queue\n"));
1266                 /* between drv has received this event before and
1267                    fw have not yet to set key to CAM_ENTRY) */
1268                 return;
1269         }
1270
1271         psta = rtw_alloc_stainfo23a(&adapter->stapriv, pstassoc->macaddr,
1272                 GFP_KERNEL);
1273         if (!psta) {
1274                 RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_,
1275                          ("Can't alloc sta_info when "
1276                           "rtw_stassoc_event_callback23a\n"));
1277                 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; */
1284         DBG_8723A("%s\n", __func__);
1285         /* for ad-hoc mode */
1286         rtl8723a_SetHalODMVar(adapter, HAL_ODM_STA_INFO, psta, true);
1287
1288         if (adapter->securitypriv.dot11AuthAlgrthm == dot11AuthAlgrthm_8021X)
1289                 psta->dot118021XPrivacy =
1290                         adapter->securitypriv.dot11PrivacyAlgrthm;
1291
1292         psta->ieee8021x_blocked = false;
1293
1294         spin_lock_bh(&pmlmepriv->lock);
1295
1296         if (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) ||
1297             check_fwstate(pmlmepriv, WIFI_ADHOC_STATE)) {
1298                 if (adapter->stapriv.asoc_sta_count == 2) {
1299                         spin_lock_bh(&pmlmepriv->scanned_queue.lock);
1300                         ptarget_wlan =
1301                                 rtw_find_network23a(&pmlmepriv->scanned_queue,
1302                                                     cur_network->network.MacAddress);
1303                         if (ptarget_wlan)
1304                                 ptarget_wlan->fixed = true;
1305                         spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
1306                         /*  a sta + bc/mc_stainfo (not Ibss_stainfo) */
1307                         rtw_indicate_connect23a(adapter);
1308                 }
1309         }
1310
1311         spin_unlock_bh(&pmlmepriv->lock);
1312
1313         mlmeext_sta_add_event_callback23a(adapter, psta);
1314 }
1315
1316 void rtw_stadel_event_callback23a(struct rtw_adapter *adapter, const u8 *pbuf)
1317 {
1318         int mac_id;
1319         struct sta_info *psta;
1320         struct wlan_network *pwlan;
1321         struct wlan_bssid_ex *pdev_network;
1322         struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
1323         struct stadel_event *pstadel = (struct stadel_event *)pbuf;
1324         struct sta_priv *pstapriv = &adapter->stapriv;
1325         struct wlan_network *tgt_network = &pmlmepriv->cur_network;
1326
1327         psta = rtw_get_stainfo23a(&adapter->stapriv, pstadel->macaddr);
1328         if (psta)
1329                 mac_id = psta->mac_id;
1330         else
1331                 mac_id = pstadel->mac_id;
1332
1333         DBG_8723A("%s(mac_id=%d)=" MAC_FMT "\n", __func__, mac_id,
1334                   MAC_ARG(pstadel->macaddr));
1335
1336         if (check_fwstate(pmlmepriv, WIFI_AP_STATE))
1337                 return;
1338
1339         mlmeext_sta_del_event_callback23a(adapter);
1340
1341         spin_lock_bh(&pmlmepriv->lock);
1342
1343         if (check_fwstate(pmlmepriv, WIFI_STATION_STATE)) {
1344                 if (adapter->mlmepriv.to_roaming > 0) {
1345                         /* this stadel_event is caused by roaming,
1346                            decrease to_roaming */
1347                         pmlmepriv->to_roaming--;
1348                 } else if (adapter->mlmepriv.to_roaming == 0)
1349                         rtw_set_roaming(adapter, adapter->registrypriv.max_roaming_times);
1350                 if (*((u16 *)pstadel->rsvd) != WLAN_REASON_EXPIRATION_CHK)
1351                         rtw_set_roaming(adapter, 0); /* don't roam */
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 */
1359                 pwlan = rtw_find_network23a(&pmlmepriv->scanned_queue,
1360                                             tgt_network->network.MacAddress);
1361                 if (pwlan) {
1362                         pwlan->fixed = false;
1363                         rtw_free_network_nolock(pmlmepriv, pwlan);
1364                 }
1365                 spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
1366
1367                 _rtw_roaming(adapter, tgt_network);
1368         }
1369
1370         if (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) ||
1371             check_fwstate(pmlmepriv, WIFI_ADHOC_STATE)) {
1372
1373                 spin_lock_bh(&pstapriv->sta_hash_lock);
1374                 rtw_free_stainfo23a(adapter,  psta);
1375                 spin_unlock_bh(&pstapriv->sta_hash_lock);
1376
1377                 /* a sta + bc/mc_stainfo (not Ibss_stainfo) */
1378                 if (adapter->stapriv.asoc_sta_count == 1) {
1379                         spin_lock_bh(&pmlmepriv->scanned_queue.lock);
1380                         /* free old ibss network */
1381                         /* pwlan = rtw_find_network23a(
1382                            &pmlmepriv->scanned_queue, pstadel->macaddr); */
1383                         pwlan = rtw_find_network23a(&pmlmepriv->scanned_queue,
1384                                                     tgt_network->network.MacAddress);
1385                         if (pwlan) {
1386                                 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;
1392
1393                         memcpy(pdev_network, &tgt_network->network,
1394                                get_wlan_bssid_ex_sz(&tgt_network->network));
1395
1396                         rtw_do_join_adhoc(adapter);
1397                 }
1398         }
1399
1400         spin_unlock_bh(&pmlmepriv->lock);
1401 }
1402
1403 /*
1404 * rtw23a_join_to_handler - Timeout/failure handler for CMD JoinBss
1405 * @adapter: pointer to _adapter structure
1406 */
1407 void rtw23a_join_to_handler (unsigned long data)
1408 {
1409         struct rtw_adapter *adapter = (struct rtw_adapter *)data;
1410         struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
1411         int do_join_r;
1412
1413         DBG_8723A("%s, fw_state=%x\n", __func__, get_fwstate(pmlmepriv));
1414
1415         if (adapter->bDriverStopped || adapter->bSurpriseRemoved)
1416                 return;
1417
1418         spin_lock_bh(&pmlmepriv->lock);
1419
1420         if (adapter->mlmepriv.to_roaming > 0) {
1421                 /* join timeout caused by roaming */
1422                 while (1) {
1423                         pmlmepriv->to_roaming--;
1424                         if (adapter->mlmepriv.to_roaming != 0) {
1425                                 /* try another */
1426                                 DBG_8723A("%s try another roaming\n", __func__);
1427                                 do_join_r = rtw_do_join(adapter);
1428                                 if (do_join_r != _SUCCESS) {
1429                                         DBG_8723A("%s roaming do_join return "
1430                                                   "%d\n", __func__ , do_join_r);
1431                                         continue;
1432                                 }
1433                                 break;
1434                         } else {
1435                                 DBG_8723A("%s We've try roaming but fail\n",
1436                                           __func__);
1437                                 rtw_indicate_disconnect23a(adapter);
1438                                 break;
1439                         }
1440                 }
1441         } else {
1442                 rtw_indicate_disconnect23a(adapter);
1443                 free_scanqueue(pmlmepriv);/*  */
1444
1445                 /* indicate disconnect for the case that join_timeout and
1446                    check_fwstate != FW_LINKED */
1447                 rtw_cfg80211_indicate_disconnect(adapter);
1448         }
1449
1450         spin_unlock_bh(&pmlmepriv->lock);
1451
1452 }
1453
1454 /*
1455 * rtw_scan_timeout_handler23a - Timeout/Failure handler for CMD SiteSurvey
1456 * @data: pointer to _adapter structure
1457 */
1458 void rtw_scan_timeout_handler23a(unsigned long data)
1459 {
1460         struct rtw_adapter *adapter = (struct rtw_adapter *)data;
1461         struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
1462
1463         DBG_8723A("%s(%s): fw_state =%x\n", __func__, adapter->pnetdev->name,
1464                   get_fwstate(pmlmepriv));
1465
1466         spin_lock_bh(&pmlmepriv->lock);
1467
1468         _clr_fwstate_(pmlmepriv, _FW_UNDER_SURVEY);
1469
1470         spin_unlock_bh(&pmlmepriv->lock);
1471
1472         rtw_cfg80211_indicate_scan_done(wdev_to_priv(adapter->rtw_wdev), true);
1473 }
1474
1475 void rtw_dynamic_check_timer_handler(unsigned long data)
1476 {
1477         struct rtw_adapter *adapter = (struct rtw_adapter *)data;
1478
1479         if (adapter->hw_init_completed == false)
1480                 goto out;
1481
1482         if (adapter->bDriverStopped == true ||
1483             adapter->bSurpriseRemoved == true)
1484                 goto out;
1485
1486         if (adapter->net_closed == true)
1487                 goto out;
1488
1489         rtw_dynamic_chk_wk_cmd23a(adapter);
1490
1491 out:
1492         mod_timer(&adapter->mlmepriv.dynamic_chk_timer,
1493                   jiffies + msecs_to_jiffies(2000));
1494 }
1495
1496 inline bool rtw_is_scan_deny(struct rtw_adapter *adapter)
1497 {
1498         struct mlme_priv *mlmepriv = &adapter->mlmepriv;
1499
1500         return (atomic_read(&mlmepriv->set_scan_deny) != 0) ? true : false;
1501 }
1502
1503 void rtw_clear_scan_deny(struct rtw_adapter *adapter)
1504 {
1505         struct mlme_priv *mlmepriv = &adapter->mlmepriv;
1506
1507         atomic_set(&mlmepriv->set_scan_deny, 0);
1508 }
1509
1510 void rtw_set_scan_deny_timer_hdl(unsigned long data)
1511 {
1512         struct rtw_adapter *adapter = (struct rtw_adapter *)data;
1513
1514         rtw_clear_scan_deny(adapter);
1515 }
1516
1517 void rtw_set_scan_deny(struct rtw_adapter *adapter, u32 ms)
1518 {
1519         struct mlme_priv *mlmepriv = &adapter->mlmepriv;
1520
1521         atomic_set(&mlmepriv->set_scan_deny, 1);
1522         mod_timer(&mlmepriv->set_scan_deny_timer,
1523                   jiffies + msecs_to_jiffies(ms));
1524 }
1525
1526 #if defined(IEEE80211_SCAN_RESULT_EXPIRE)
1527 #define RTW_SCAN_RESULT_EXPIRE  \
1528         ((IEEE80211_SCAN_RESULT_EXPIRE / (HZ*1000)) - 1000) /* 3000 -1000 */
1529 #else
1530 #define RTW_SCAN_RESULT_EXPIRE 2000
1531 #endif
1532
1533 /*
1534 * Select a new join candidate from the original @param candidate and
1535 *     @param competitor
1536 * @return true: candidate is updated
1537 * @return false: candidate is not updated
1538 */
1539 static int rtw_check_join_candidate(struct mlme_priv *pmlmepriv,
1540                                     struct wlan_network **candidate,
1541                                     struct wlan_network *competitor)
1542 {
1543         int updated = false;
1544         struct rtw_adapter *adapter;
1545
1546         adapter = container_of(pmlmepriv, struct rtw_adapter, mlmepriv);
1547
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 */
1556         if (pmlmepriv->assoc_ssid.ssid_len) {
1557                 if (competitor->network.Ssid.ssid_len !=
1558                     pmlmepriv->assoc_ssid.ssid_len ||
1559                     memcmp(competitor->network.Ssid.ssid,
1560                            pmlmepriv->assoc_ssid.ssid,
1561                            pmlmepriv->assoc_ssid.ssid_len))
1562                         goto exit;
1563         }
1564
1565         if (rtw_is_desired_network(adapter, competitor) == false)
1566                 goto exit;
1567
1568         if (adapter->mlmepriv.to_roaming > 0) {
1569                 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
1578         if (!*candidate ||
1579             (*candidate)->network.Rssi<competitor->network.Rssi) {
1580                 *candidate = competitor;
1581                 updated = true;
1582         }
1583
1584         if (updated) {
1585                 DBG_8723A("[by_bssid:%u][assoc_ssid:%s][to_roaming:%u] "
1586                           "new candidate: %s("MAC_FMT") rssi:%d\n",
1587                           pmlmepriv->assoc_by_bssid,
1588                           pmlmepriv->assoc_ssid.ssid,
1589                           adapter->mlmepriv.to_roaming,
1590                           (*candidate)->network.Ssid.ssid,
1591                           MAC_ARG((*candidate)->network.MacAddress),
1592                           (int)(*candidate)->network.Rssi);
1593         }
1594
1595 exit:
1596         return updated;
1597 }
1598
1599 /*
1600 Calling context:
1601 The caller of the sub-routine will be in critical section...
1602
1603 The caller must hold the following spinlock
1604
1605 pmlmepriv->lock
1606
1607 */
1608
1609 static 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
1638 exit:
1639         return ret;
1640 }
1641
1642 static struct wlan_network *
1643 rtw_select_candidate_from_queue(struct mlme_priv *pmlmepriv)
1644 {
1645         struct wlan_network *pnetwork, *candidate = NULL;
1646         struct rtw_queue *queue = &pmlmepriv->scanned_queue;
1647         struct list_head *phead, *plist, *ptmp;
1648
1649         spin_lock_bh(&pmlmepriv->scanned_queue.lock);
1650         phead = get_list_head(queue);
1651
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_,
1656                                  ("%s: return _FAIL:(pnetwork == NULL)\n",
1657                                   __func__));
1658                         goto exit;
1659                 }
1660
1661                 rtw_check_join_candidate(pmlmepriv, &candidate, pnetwork);
1662         }
1663
1664 exit:
1665         spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
1666         return candidate;
1667 }
1668
1669
1670 int 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
1704 int 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
1728 int 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);
1737         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),
1745                           candidate->network.DSConfig);
1746         }
1747
1748         ret = rtw_do_join_network(adapter, candidate);
1749
1750 exit:
1751         return ret;
1752 }
1753
1754 int rtw_set_auth23a(struct rtw_adapter *adapter,
1755                     struct security_priv *psecuritypriv)
1756 {
1757         struct cmd_obj *pcmd;
1758         struct setauth_parm *psetauthparm;
1759         struct cmd_priv *pcmdpriv = &adapter->cmdpriv;
1760         int res = _SUCCESS;
1761
1762         pcmd = kzalloc(sizeof(struct cmd_obj), GFP_KERNEL);
1763         if (!pcmd) {
1764                 res = _FAIL;  /* try again */
1765                 goto exit;
1766         }
1767
1768         psetauthparm = kzalloc(sizeof(struct setauth_parm), GFP_KERNEL);
1769         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
1783         RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_,
1784                  ("after enqueue set_auth_cmd, auth_mode=%x\n",
1785                   psecuritypriv->dot11AuthAlgrthm));
1786
1787         res = rtw_enqueue_cmd23a(pcmdpriv, pcmd);
1788
1789 exit:
1790
1791         return res;
1792 }
1793
1794 int rtw_set_key23a(struct rtw_adapter *adapter,
1795                    struct security_priv *psecuritypriv, int keyid, u8 set_tx)
1796 {
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
1804         if (keyid >= 4) {
1805                 res = _FAIL;
1806                 goto exit;
1807         }
1808
1809         pcmd = kzalloc(sizeof(struct cmd_obj), GFP_KERNEL);
1810         if (!pcmd) {
1811                 res = _FAIL;  /* try again */
1812                 goto exit;
1813         }
1814         psetkeyparm = kzalloc(sizeof(struct setkey_parm), GFP_KERNEL);
1815         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_,
1825                          ("\n rtw_set_key23a: psetkeyparm->algorithm = "
1826                           "(unsigned char)psecuritypriv->dot118021XGrpPrivacy "
1827                           "=%d\n", psetkeyparm->algorithm));
1828         } 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         }
1835         psetkeyparm->keyid = keyid;/* 0~3 */
1836         psetkeyparm->set_tx = set_tx;
1837         if (is_wep_enc(psetkeyparm->algorithm))
1838                 pmlmepriv->key_mask |= BIT(psetkeyparm->keyid);
1839
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) {
1848         case WLAN_CIPHER_SUITE_WEP40:
1849                 keylen = 5;
1850                 memcpy(&psetkeyparm->key[0],
1851                        &psecuritypriv->wep_key[keyid].key, keylen);
1852                 break;
1853         case WLAN_CIPHER_SUITE_WEP104:
1854                 keylen = 13;
1855                 memcpy(&psetkeyparm->key[0],
1856                        &psecuritypriv->wep_key[keyid].key, keylen);
1857                 break;
1858         case WLAN_CIPHER_SUITE_TKIP:
1859                 keylen = 16;
1860                 memcpy(&psetkeyparm->key,
1861                        &psecuritypriv->dot118021XGrpKey[keyid], keylen);
1862                 psetkeyparm->grpkey = 1;
1863                 break;
1864         case WLAN_CIPHER_SUITE_CCMP:
1865                 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_,
1872                          ("\n rtw_set_key23a:psecuritypriv->dot11PrivacyAlgrthm"
1873                           " = %x (must be 1 or 2 or 4 or 5)\n",
1874                           psecuritypriv->dot11PrivacyAlgrthm));
1875                 res = _FAIL;
1876                 kfree(pcmd);
1877                 kfree(psetkeyparm);
1878                 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
1887         /* sema_init(&pcmd->cmd_sem, 0); */
1888
1889         res = rtw_enqueue_cmd23a(pcmdpriv, pcmd);
1890
1891 exit:
1892
1893         return res;
1894 }
1895
1896 /* adjust IEs for rtw_joinbss_cmd23a in WMM */
1897 int rtw_restruct_wmm_ie23a(struct rtw_adapter *adapter, u8 *in_ie,
1898                            u8 *out_ie, uint in_len, uint initial_out_len)
1899 {
1900         int ielength;
1901         const u8 *p;
1902
1903         ielength = initial_out_len;
1904
1905         p = cfg80211_find_vendor_ie(WLAN_OUI_MICROSOFT,
1906                                     WLAN_OUI_TYPE_MICROSOFT_WMM,
1907                                     in_ie, in_len);
1908
1909         if (p && p[1]) {
1910                 memcpy(out_ie + initial_out_len, p, 9);
1911
1912                 out_ie[initial_out_len + 1] = 7;
1913                 out_ie[initial_out_len + 6] = 0;
1914                 out_ie[initial_out_len + 8] = 0;
1915
1916                 ielength += 9;
1917         }
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
1934 static 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                 }
1947         } while (i < NUM_PMKID_CACHE);
1948
1949         if (i == NUM_PMKID_CACHE)
1950                 i = -1;/*  Could not find. */
1951         else {
1952                 /*  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
1968 static 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
1973         if (ie[1] <= 20) {
1974                 /*  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;
1984                         ie[1] += 18;/* PMKID length = 2+16 */
1985         }
1986         return ie_len;
1987 }
1988
1989 int rtw_restruct_sec_ie23a(struct rtw_adapter *adapter, u8 *in_ie, u8 *out_ie,
1990                            uint in_len)
1991 {
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_,
2001                  ("+rtw_restruct_sec_ie23a: ndisauthmode=%d "
2002                   "ndissecuritytype=%d\n", ndisauthmode, ndissecuritytype));
2003
2004         ielength = 0;
2005         if (ndisauthmode == Ndis802_11AuthModeWPA ||
2006             ndisauthmode == Ndis802_11AuthModeWPAPSK)
2007                 authmode = WLAN_EID_VENDOR_SPECIFIC;
2008         if (ndisauthmode == Ndis802_11AuthModeWPA2 ||
2009             ndisauthmode == Ndis802_11AuthModeWPA2PSK)
2010                 authmode = WLAN_EID_RSN;
2011
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;
2017         } else if (authmode == WLAN_EID_VENDOR_SPECIFIC ||
2018                    authmode == WLAN_EID_RSN) {
2019                 /* copy RSN or SSN */
2020                 memcpy(&out_ie[ielength], &psecuritypriv->supplicant_ie[0],
2021                        psecuritypriv->supplicant_ie[1] + 2);
2022                 ielength += psecuritypriv->supplicant_ie[1] + 2;
2023         }
2024
2025         iEntry = SecIsInPMKIDList(adapter, pmlmepriv->assoc_bssid);
2026         if (iEntry < 0)
2027                 return ielength;
2028         else {
2029                 if (authmode == WLAN_EID_RSN)
2030                         ielength = rtw_append_pmkid(adapter, iEntry,
2031                                                     out_ie, ielength);
2032         }
2033
2034         return ielength;
2035 }
2036
2037 void rtw_init_registrypriv_dev_network23a(struct rtw_adapter *adapter)
2038 {
2039         struct registry_priv *pregistrypriv = &adapter->registrypriv;
2040         struct eeprom_priv *peepriv = &adapter->eeprompriv;
2041         struct wlan_bssid_ex    *pdev_network = &pregistrypriv->dev_network;
2042         u8 *myhwaddr = myid(peepriv);
2043
2044         ether_addr_copy(pdev_network->MacAddress, myhwaddr);
2045
2046         memcpy(&pdev_network->Ssid, &pregistrypriv->ssid,
2047                sizeof(struct cfg80211_ssid));
2048
2049         pdev_network->beacon_interval = 100;
2050 }
2051
2052 void rtw_update_registrypriv_dev_network23a(struct rtw_adapter *adapter)
2053 {
2054         int sz = 0;
2055         struct registry_priv *pregistrypriv = &adapter->registrypriv;
2056         struct wlan_bssid_ex *pdev_network = &pregistrypriv->dev_network;
2057         struct security_priv *psecuritypriv = &adapter->securitypriv;
2058         struct wlan_network *cur_network = &adapter->mlmepriv.cur_network;
2059         /* struct       xmit_priv       *pxmitpriv = &adapter->xmitpriv; */
2060
2061         pdev_network->Privacy =
2062                 (psecuritypriv->dot11PrivacyAlgrthm > 0 ? 1 : 0);
2063
2064         pdev_network->Rssi = 0;
2065
2066         pdev_network->DSConfig = pregistrypriv->channel;
2067         RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_,
2068                  ("pregistrypriv->channel =%d, pdev_network->DSConfig = 0x%x\n",
2069                   pregistrypriv->channel, pdev_network->DSConfig));
2070
2071         if (cur_network->network.ifmode == NL80211_IFTYPE_ADHOC)
2072                 pdev_network->ATIMWindow = 0;
2073
2074         pdev_network->ifmode = cur_network->network.ifmode;
2075
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 =
2084                 get_wlan_bssid_ex_sz(pdev_network);
2085
2086         /* notes: translate IELength & Length after assign the
2087            Length to cmdsz in createbss_cmd(); */
2088         /* pdev_network->IELength = cpu_to_le32(sz); */
2089 }
2090
2091 /* the function is at passive_level */
2092 void 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;
2114         } else
2115                 threshold = 1;
2116
2117         rtl8723a_set_rxdma_agg_pg_th(padapter, threshold);
2118 }
2119
2120 /* the function is >= passive_level */
2121 bool rtw_restructure_ht_ie23a(struct rtw_adapter *padapter, u8 *in_ie,
2122                               u8 *out_ie, uint in_len, uint *pout_len)
2123 {
2124         u32 out_len;
2125         int max_rx_ampdu_factor;
2126         unsigned char *pframe;
2127         const u8 *p;
2128         struct ieee80211_ht_cap ht_capie;
2129         u8 WMM_IE[7] = {0x00, 0x50, 0xf2, 0x02, 0x00, 0x01, 0x00};
2130         struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
2131         struct ht_priv *phtpriv = &pmlmepriv->htpriv;
2132
2133         phtpriv->ht_option = false;
2134
2135         p = cfg80211_find_ie(WLAN_EID_HT_CAPABILITY, in_ie, in_len);
2136
2137         if (p && p[1] > 0) {
2138                 u32 rx_packet_offset, max_recvbuf_sz;
2139
2140                 if (pmlmepriv->qos_option == 0) {
2141                         out_len = *pout_len;
2142                         pframe = rtw_set_ie23a(out_ie + out_len,
2143                                                WLAN_EID_VENDOR_SPECIFIC,
2144                                                sizeof(WMM_IE), WMM_IE,
2145                                                pout_len);
2146
2147                         pmlmepriv->qos_option = 1;
2148                 }
2149
2150                 out_len = *pout_len;
2151
2152                 memset(&ht_capie, 0, sizeof(struct ieee80211_ht_cap));
2153
2154                 ht_capie.cap_info = cpu_to_le16(IEEE80211_HT_CAP_SUP_WIDTH_20_40 |
2155                         IEEE80211_HT_CAP_SGI_20 | IEEE80211_HT_CAP_SGI_40 |
2156                         IEEE80211_HT_CAP_TX_STBC | IEEE80211_HT_CAP_DSSSCCK40);
2157
2158                 GetHalDefVar8192CUsb(padapter, HAL_DEF_RX_PACKET_OFFSET,
2159                                      &rx_packet_offset);
2160                 GetHalDefVar8192CUsb(padapter, HAL_DEF_MAX_RECVBUF_SZ,
2161                                      &max_recvbuf_sz);
2162
2163                 GetHalDefVar8192CUsb(padapter, HW_VAR_MAX_RX_AMPDU_FACTOR,
2164                                      &max_rx_ampdu_factor);
2165                 ht_capie.ampdu_params_info = max_rx_ampdu_factor & 0x03;
2166
2167                 if (padapter->securitypriv.dot11PrivacyAlgrthm ==
2168                     WLAN_CIPHER_SUITE_CCMP)
2169                         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
2175                 pframe = rtw_set_ie23a(out_ie + out_len, WLAN_EID_HT_CAPABILITY,
2176                                     sizeof(struct ieee80211_ht_cap),
2177                                     (unsigned char *)&ht_capie, pout_len);
2178
2179                 phtpriv->ht_option = true;
2180
2181                 p = cfg80211_find_ie(WLAN_EID_HT_OPERATION, in_ie, in_len);
2182                 if (p && (p[1] == sizeof(struct ieee80211_ht_operation))) {
2183                         out_len = *pout_len;
2184                         pframe = rtw_set_ie23a(out_ie + out_len,
2185                                                WLAN_EID_HT_OPERATION,
2186                                                p[1], p + 2 , pout_len);
2187                 }
2188         }
2189
2190         return phtpriv->ht_option;
2191 }
2192
2193 /* the function is > passive_level (in critical_section) */
2194 void rtw_update_ht_cap23a(struct rtw_adapter *padapter, u8 *pie, uint ie_len)
2195 {
2196         u8 max_ampdu_sz;
2197         const u8 *p;
2198         struct ieee80211_ht_cap *pht_capie;
2199         struct ieee80211_ht_operation *pht_addtinfo;
2200         struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
2201         struct ht_priv *phtpriv = &pmlmepriv->htpriv;
2202         struct registry_priv *pregistrypriv = &padapter->registrypriv;
2203         struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
2204         struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
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. */
2215         if (!phtpriv->ampdu_enable && pregistrypriv->ampdu_enable == 1) {
2216                 if (pregistrypriv->wifi_spec == 1)
2217                         phtpriv->ampdu_enable = false;
2218                 else
2219                         phtpriv->ampdu_enable = true;
2220         } else if (pregistrypriv->ampdu_enable == 2)
2221                 phtpriv->ampdu_enable = true;
2222
2223         /* check Max Rx A-MPDU Size */
2224         p = cfg80211_find_ie(WLAN_EID_HT_CAPABILITY, pie, ie_len);
2225
2226         if (p && p[1] > 0) {
2227                 pht_capie = (struct ieee80211_ht_cap *)(p + 2);
2228                 max_ampdu_sz = pht_capie->ampdu_params_info &
2229                         IEEE80211_HT_AMPDU_PARM_FACTOR;
2230                 /*  max_ampdu_sz (kbytes); */
2231                 max_ampdu_sz = 1 << (max_ampdu_sz + 3);
2232
2233                 phtpriv->rx_ampdu_maxlen = max_ampdu_sz;
2234         }
2235
2236         p = cfg80211_find_ie(WLAN_EID_HT_OPERATION, pie, ie_len);
2237         if (p && p[1] > 0) {
2238                 pht_addtinfo = (struct ieee80211_ht_operation *)(p + 2);
2239                 /* todo: */
2240         }
2241
2242         /* update cur_bwmode & cur_ch_offset */
2243         if (pregistrypriv->cbw40_enable &&
2244             pmlmeinfo->ht_cap.cap_info &
2245             cpu_to_le16(IEEE80211_HT_CAP_SUP_WIDTH_20_40) &&
2246             pmlmeinfo->HT_info.ht_param & IEEE80211_HT_PARAM_CHAN_WIDTH_ANY) {
2247                 int i;
2248                 u8 rf_type;
2249
2250                 rf_type = rtl8723a_get_rf_type(padapter);
2251
2252                 /* update the MCS rates */
2253                 for (i = 0; i < IEEE80211_HT_MCS_MASK_LEN; i++) {
2254                         if (rf_type == RF_1T1R || rf_type == RF_1T2R)
2255                                 pmlmeinfo->ht_cap.mcs.rx_mask[i] &=
2256                                         MCS_rate_1R23A[i];
2257                         else
2258                                 pmlmeinfo->ht_cap.mcs.rx_mask[i] &=
2259                                         MCS_rate_2R23A[i];
2260                 }
2261                 /* switch to the 40M Hz mode according to the AP */
2262                 pmlmeext->cur_bwmode = HT_CHANNEL_WIDTH_40;
2263                 switch (pmlmeinfo->HT_info.ht_param &
2264                         IEEE80211_HT_PARAM_CHA_SEC_OFFSET) {
2265                 case IEEE80211_HT_PARAM_CHA_SEC_ABOVE:
2266                         pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_LOWER;
2267                         break;
2268
2269                 case IEEE80211_HT_PARAM_CHA_SEC_BELOW:
2270                         pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_UPPER;
2271                         break;
2272
2273                 default:
2274                         pmlmeext->cur_ch_offset =
2275                                 HAL_PRIME_CHNL_OFFSET_DONT_CARE;
2276                         break;
2277                 }
2278         }
2279
2280         /*  */
2281         /*  Config SM Power Save setting */
2282         /*  */
2283         pmlmeinfo->SM_PS =
2284                 (le16_to_cpu(pmlmeinfo->ht_cap.cap_info) &
2285                  IEEE80211_HT_CAP_SM_PS) >> IEEE80211_HT_CAP_SM_PS_SHIFT;
2286         if (pmlmeinfo->SM_PS == WLAN_HT_CAP_SM_PS_STATIC)
2287                 DBG_8723A("%s(): WLAN_HT_CAP_SM_PS_STATIC\n", __func__);
2288
2289         /*  */
2290         /*  Config current HT Protection mode. */
2291         /*  */
2292         pmlmeinfo->HT_protection =
2293                 le16_to_cpu(pmlmeinfo->HT_info.operation_mode) &
2294                 IEEE80211_HT_OP_MODE_PROTECTION;
2295 }
2296
2297 void rtw_issue_addbareq_cmd23a(struct rtw_adapter *padapter,
2298                                struct xmit_frame *pxmitframe)
2299 {
2300         u8 issued;
2301         int priority;
2302         struct sta_info *psta;
2303         struct ht_priv  *phtpriv;
2304         struct pkt_attrib *pattrib = &pxmitframe->attrib;
2305         s32 bmcst = is_multicast_ether_addr(pattrib->ra);
2306
2307         if (bmcst || padapter->mlmepriv.LinkDetectInfo.NumTxOkInPeriod < 100)
2308                 return;
2309
2310         priority = pattrib->priority;
2311
2312         if (pattrib->psta)
2313                 psta = pattrib->psta;
2314         else {
2315                 DBG_8723A("%s, call rtw_get_stainfo23a()\n", __func__);
2316                 psta = rtw_get_stainfo23a(&padapter->stapriv, pattrib->ra);
2317         }
2318
2319         if (!psta) {
2320                 DBG_8723A("%s, psta == NUL\n", __func__);
2321                 return;
2322         }
2323
2324         if (!(psta->state &_FW_LINKED)) {
2325                 DBG_8723A("%s, psta->state(0x%x) != _FW_LINKED\n",
2326                           __func__, psta->state);
2327                 return;
2328         }
2329
2330         phtpriv = &psta->htpriv;
2331
2332         if (phtpriv->ht_option && phtpriv->ampdu_enable) {
2333                 issued = (phtpriv->agg_enable_bitmap>>priority)&0x1;
2334                 issued |= (phtpriv->candidate_tid_bitmap>>priority)&0x1;
2335
2336                 if (issued == 0) {
2337                         DBG_8723A("rtw_issue_addbareq_cmd23a, p =%d\n",
2338                                   priority);
2339                         psta->htpriv.candidate_tid_bitmap |= BIT(priority);
2340                         rtw_addbareq_cmd23a(padapter, (u8) priority,
2341                                             pattrib->ra);
2342                 }
2343         }
2344 }
2345
2346 int rtw_linked_check(struct rtw_adapter *padapter)
2347 {
2348         if (check_fwstate(&padapter->mlmepriv, WIFI_AP_STATE) ||
2349             check_fwstate(&padapter->mlmepriv,
2350                           WIFI_ADHOC_STATE|WIFI_ADHOC_MASTER_STATE)) {
2351                 if (padapter->stapriv.asoc_sta_count > 2)
2352                         return true;
2353         } else {        /* Station mode */
2354                 if (check_fwstate(&padapter->mlmepriv, _FW_LINKED))
2355                         return true;
2356         }
2357         return false;
2358 }