Merge tag 'xtensa-20210902' of git://github.com/jcmvbkbc/linux-xtensa
[linux-2.6-microblaze.git] / drivers / staging / rtl8712 / rtl871x_mlme.c
1 // SPDX-License-Identifier: GPL-2.0
2 /******************************************************************************
3  * rtl871x_mlme.c
4  *
5  * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
6  * Linux device driver for RTL8192SU
7  *
8  * Modifications for inclusion into the Linux staging tree are
9  * Copyright(c) 2010 Larry Finger. All rights reserved.
10  *
11  * Contact information:
12  * WLAN FAE <wlanfae@realtek.com>
13  * Larry Finger <Larry.Finger@lwfinger.net>
14  *
15  ******************************************************************************/
16
17 #define _RTL871X_MLME_C_
18
19 #include <linux/etherdevice.h>
20
21 #include "osdep_service.h"
22 #include "drv_types.h"
23 #include "recv_osdep.h"
24 #include "xmit_osdep.h"
25 #include "mlme_osdep.h"
26 #include "sta_info.h"
27 #include "wifi.h"
28 #include "wlan_bssdef.h"
29
30 static void update_ht_cap(struct _adapter *padapter, u8 *pie, uint ie_len);
31
32 int r8712_init_mlme_priv(struct _adapter *padapter)
33 {
34         sint    i;
35         u8      *pbuf;
36         struct wlan_network     *pnetwork;
37         struct  mlme_priv *pmlmepriv = &padapter->mlmepriv;
38
39         memset((u8 *)pmlmepriv, 0, sizeof(struct mlme_priv));
40         pmlmepriv->nic_hdl = (u8 *)padapter;
41         pmlmepriv->pscanned = NULL;
42         pmlmepriv->fw_state = 0;
43         pmlmepriv->cur_network.network.InfrastructureMode =
44                                  Ndis802_11AutoUnknown;
45         /* Maybe someday we should rename this variable to "active_mode"(Jeff)*/
46         pmlmepriv->passive_mode = 1; /* 1: active, 0: passive. */
47         spin_lock_init(&(pmlmepriv->lock));
48         spin_lock_init(&(pmlmepriv->lock2));
49         _init_queue(&(pmlmepriv->free_bss_pool));
50         _init_queue(&(pmlmepriv->scanned_queue));
51         set_scanned_network_val(pmlmepriv, 0);
52         memset(&pmlmepriv->assoc_ssid, 0, sizeof(struct ndis_802_11_ssid));
53         pbuf = kmalloc_array(MAX_BSS_CNT, sizeof(struct wlan_network),
54                              GFP_ATOMIC);
55         if (!pbuf)
56                 return -ENOMEM;
57         pmlmepriv->free_bss_buf = pbuf;
58         pnetwork = (struct wlan_network *)pbuf;
59         for (i = 0; i < MAX_BSS_CNT; i++) {
60                 INIT_LIST_HEAD(&(pnetwork->list));
61                 list_add_tail(&(pnetwork->list),
62                                  &(pmlmepriv->free_bss_pool.queue));
63                 pnetwork++;
64         }
65         pmlmepriv->sitesurveyctrl.last_rx_pkts = 0;
66         pmlmepriv->sitesurveyctrl.last_tx_pkts = 0;
67         pmlmepriv->sitesurveyctrl.traffic_busy = false;
68         /* allocate DMA-able/Non-Page memory for cmd_buf and rsp_buf */
69         r8712_init_mlme_timer(padapter);
70         return 0;
71 }
72
73 struct wlan_network *_r8712_alloc_network(struct mlme_priv *pmlmepriv)
74 {
75         unsigned long irqL;
76         struct wlan_network *pnetwork;
77         struct  __queue *free_queue = &pmlmepriv->free_bss_pool;
78
79         spin_lock_irqsave(&free_queue->lock, irqL);
80         pnetwork = list_first_entry_or_null(&free_queue->queue,
81                                             struct wlan_network, list);
82         if (pnetwork) {
83                 list_del_init(&pnetwork->list);
84                 pnetwork->last_scanned = jiffies;
85                 pmlmepriv->num_of_scanned++;
86         }
87         spin_unlock_irqrestore(&free_queue->lock, irqL);
88         return pnetwork;
89 }
90
91 static void _free_network(struct mlme_priv *pmlmepriv,
92                           struct wlan_network *pnetwork)
93 {
94         u32 curr_time, delta_time;
95         unsigned long irqL;
96         struct  __queue *free_queue = &(pmlmepriv->free_bss_pool);
97
98         if (!pnetwork)
99                 return;
100         if (pnetwork->fixed)
101                 return;
102         curr_time = jiffies;
103         delta_time = (curr_time - (u32)pnetwork->last_scanned) / HZ;
104         if (delta_time < SCANQUEUE_LIFETIME)
105                 return;
106         spin_lock_irqsave(&free_queue->lock, irqL);
107         list_del_init(&pnetwork->list);
108         list_add_tail(&pnetwork->list, &free_queue->queue);
109         pmlmepriv->num_of_scanned--;
110         spin_unlock_irqrestore(&free_queue->lock, irqL);
111 }
112
113 static void free_network_nolock(struct mlme_priv *pmlmepriv,
114                           struct wlan_network *pnetwork)
115 {
116         struct  __queue *free_queue = &pmlmepriv->free_bss_pool;
117
118         if (!pnetwork)
119                 return;
120         if (pnetwork->fixed)
121                 return;
122         list_del_init(&pnetwork->list);
123         list_add_tail(&pnetwork->list, &free_queue->queue);
124         pmlmepriv->num_of_scanned--;
125 }
126
127 /* return the wlan_network with the matching addr
128  * Shall be called under atomic context...
129  * to avoid possible racing condition...
130  */
131 static struct wlan_network *r8712_find_network(struct  __queue *scanned_queue,
132                                                u8 *addr)
133 {
134         unsigned long irqL;
135         struct list_head *phead, *plist;
136         struct wlan_network *pnetwork = NULL;
137
138         if (is_zero_ether_addr(addr))
139                 return NULL;
140         spin_lock_irqsave(&scanned_queue->lock, irqL);
141         phead = &scanned_queue->queue;
142         list_for_each(plist, phead) {
143                 pnetwork = list_entry(plist, struct wlan_network, list);
144                 if (!memcmp(addr, pnetwork->network.MacAddress, ETH_ALEN))
145                         break;
146         }
147         if (plist == phead)
148                 pnetwork = NULL;
149         spin_unlock_irqrestore(&scanned_queue->lock, irqL);
150         return pnetwork;
151 }
152
153 void r8712_free_network_queue(struct _adapter *padapter)
154 {
155         unsigned long irqL;
156         struct list_head *phead, *plist;
157         struct wlan_network *pnetwork;
158         struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
159         struct  __queue *scanned_queue = &pmlmepriv->scanned_queue;
160
161         spin_lock_irqsave(&scanned_queue->lock, irqL);
162         phead = &scanned_queue->queue;
163         plist = phead->next;
164         while (!end_of_queue_search(phead, plist)) {
165                 pnetwork = container_of(plist, struct wlan_network, list);
166                 plist = plist->next;
167                 _free_network(pmlmepriv, pnetwork);
168         }
169         spin_unlock_irqrestore(&scanned_queue->lock, irqL);
170 }
171
172 sint r8712_if_up(struct _adapter *padapter)
173 {
174         sint res;
175
176         if (padapter->driver_stopped || padapter->surprise_removed ||
177             !check_fwstate(&padapter->mlmepriv, _FW_LINKED)) {
178                 res = false;
179         } else {
180                 res = true;
181         }
182         return res;
183 }
184
185 void r8712_generate_random_ibss(u8 *pibss)
186 {
187         u32 curtime = jiffies;
188
189         pibss[0] = 0x02; /*in ad-hoc mode bit1 must set to 1 */
190         pibss[1] = 0x11;
191         pibss[2] = 0x87;
192         pibss[3] = (u8)(curtime & 0xff);
193         pibss[4] = (u8)((curtime >> 8) & 0xff);
194         pibss[5] = (u8)((curtime >> 16) & 0xff);
195 }
196
197 uint r8712_get_wlan_bssid_ex_sz(struct wlan_bssid_ex *bss)
198 {
199         return sizeof(*bss) + bss->IELength - MAX_IE_SZ;
200 }
201
202 u8 *r8712_get_capability_from_ie(u8 *ie)
203 {
204         return ie + 8 + 2;
205 }
206
207 void r8712_free_mlme_priv(struct mlme_priv *pmlmepriv)
208 {
209         kfree(pmlmepriv->free_bss_buf);
210 }
211
212 static struct   wlan_network *alloc_network(struct mlme_priv *pmlmepriv)
213 {
214         return _r8712_alloc_network(pmlmepriv);
215 }
216
217 int r8712_is_same_ibss(struct _adapter *adapter, struct wlan_network *pnetwork)
218 {
219         int ret = true;
220         struct security_priv *psecuritypriv = &adapter->securitypriv;
221
222         if ((psecuritypriv->PrivacyAlgrthm != _NO_PRIVACY_) &&
223                     (pnetwork->network.Privacy == cpu_to_le32(0)))
224                 ret = false;
225         else if ((psecuritypriv->PrivacyAlgrthm == _NO_PRIVACY_) &&
226                  (pnetwork->network.Privacy == cpu_to_le32(1)))
227                 ret = false;
228         else
229                 ret = true;
230         return ret;
231
232 }
233
234 static int is_same_network(struct wlan_bssid_ex *src,
235                            struct wlan_bssid_ex *dst)
236 {
237         u16 s_cap, d_cap;
238
239         memcpy((u8 *)&s_cap, r8712_get_capability_from_ie(src->IEs), 2);
240         memcpy((u8 *)&d_cap, r8712_get_capability_from_ie(dst->IEs), 2);
241         return (src->Ssid.SsidLength == dst->Ssid.SsidLength) &&
242                         (src->Configuration.DSConfig ==
243                         dst->Configuration.DSConfig) &&
244                         ((!memcmp(src->MacAddress, dst->MacAddress,
245                         ETH_ALEN))) &&
246                         ((!memcmp(src->Ssid.Ssid,
247                           dst->Ssid.Ssid,
248                           src->Ssid.SsidLength))) &&
249                         ((s_cap & WLAN_CAPABILITY_IBSS) ==
250                         (d_cap & WLAN_CAPABILITY_IBSS)) &&
251                         ((s_cap & WLAN_CAPABILITY_ESS) ==
252                         (d_cap & WLAN_CAPABILITY_ESS));
253
254 }
255
256 struct  wlan_network *r8712_get_oldest_wlan_network(
257                                 struct  __queue *scanned_queue)
258 {
259         struct list_head *plist, *phead;
260         struct  wlan_network    *pwlan = NULL;
261         struct  wlan_network    *oldest = NULL;
262
263         phead = &scanned_queue->queue;
264         plist = phead->next;
265         while (1) {
266                 if (end_of_queue_search(phead, plist))
267                         break;
268                 pwlan = container_of(plist, struct wlan_network, list);
269                 if (!pwlan->fixed) {
270                         if (!oldest ||
271                             time_after((unsigned long)oldest->last_scanned,
272                                        (unsigned long)pwlan->last_scanned))
273                                 oldest = pwlan;
274                 }
275                 plist = plist->next;
276         }
277         return oldest;
278 }
279
280 static void update_network(struct wlan_bssid_ex *dst,
281                            struct wlan_bssid_ex *src,
282                            struct _adapter *padapter)
283 {
284         u32 last_evm = 0, tmpVal;
285         struct smooth_rssi_data *sqd = &padapter->recvpriv.signal_qual_data;
286
287         if (check_fwstate(&padapter->mlmepriv, _FW_LINKED) &&
288             is_same_network(&(padapter->mlmepriv.cur_network.network), src)) {
289                 if (padapter->recvpriv.signal_qual_data.total_num++ >=
290                     PHY_LINKQUALITY_SLID_WIN_MAX) {
291                         padapter->recvpriv.signal_qual_data.total_num =
292                                    PHY_LINKQUALITY_SLID_WIN_MAX;
293                         last_evm = sqd->elements[sqd->index];
294                         padapter->recvpriv.signal_qual_data.total_val -=
295                                  last_evm;
296                 }
297                 padapter->recvpriv.signal_qual_data.total_val += src->Rssi;
298
299                 sqd->elements[sqd->index++] = src->Rssi;
300                 if (padapter->recvpriv.signal_qual_data.index >=
301                     PHY_LINKQUALITY_SLID_WIN_MAX)
302                         padapter->recvpriv.signal_qual_data.index = 0;
303                 /* <1> Showed on UI for user, in percentage. */
304                 tmpVal = padapter->recvpriv.signal_qual_data.total_val /
305                          padapter->recvpriv.signal_qual_data.total_num;
306                 padapter->recvpriv.signal = (u8)tmpVal;
307
308                 src->Rssi = padapter->recvpriv.signal;
309         } else {
310                 src->Rssi = (src->Rssi + dst->Rssi) / 2;
311         }
312         memcpy((u8 *)dst, (u8 *)src, r8712_get_wlan_bssid_ex_sz(src));
313 }
314
315 static void update_current_network(struct _adapter *adapter,
316                                    struct wlan_bssid_ex *pnetwork)
317 {
318         struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
319
320         if (is_same_network(&(pmlmepriv->cur_network.network), pnetwork)) {
321                 update_network(&(pmlmepriv->cur_network.network),
322                                pnetwork, adapter);
323                 r8712_update_protection(adapter,
324                                (pmlmepriv->cur_network.network.IEs) +
325                                sizeof(struct NDIS_802_11_FIXED_IEs),
326                                pmlmepriv->cur_network.network.IELength);
327         }
328 }
329
330 /* Caller must hold pmlmepriv->lock first */
331 static void update_scanned_network(struct _adapter *adapter,
332                             struct wlan_bssid_ex *target)
333 {
334         struct list_head *plist, *phead;
335
336         u32 bssid_ex_sz;
337         struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
338         struct  __queue *queue = &pmlmepriv->scanned_queue;
339         struct wlan_network *pnetwork = NULL;
340         struct wlan_network *oldest = NULL;
341
342         phead = &queue->queue;
343         plist = phead->next;
344
345         while (1) {
346                 if (end_of_queue_search(phead, plist))
347                         break;
348
349                 pnetwork = container_of(plist, struct wlan_network, list);
350                 if (is_same_network(&pnetwork->network, target))
351                         break;
352                 if ((oldest == ((struct wlan_network *)0)) ||
353                     time_after((unsigned long)oldest->last_scanned,
354                                 (unsigned long)pnetwork->last_scanned))
355                         oldest = pnetwork;
356
357                 plist = plist->next;
358         }
359
360         /* If we didn't find a match, then get a new network slot to initialize
361          * with this beacon's information
362          */
363         if (end_of_queue_search(phead, plist)) {
364                 if (list_empty(&pmlmepriv->free_bss_pool.queue)) {
365                         /* If there are no more slots, expire the oldest */
366                         pnetwork = oldest;
367                         target->Rssi = (pnetwork->network.Rssi +
368                                         target->Rssi) / 2;
369                         memcpy(&pnetwork->network, target,
370                                 r8712_get_wlan_bssid_ex_sz(target));
371                         pnetwork->last_scanned = jiffies;
372                 } else {
373                         /* Otherwise just pull from the free list */
374                         /* update scan_time */
375                         pnetwork = alloc_network(pmlmepriv);
376                         if (!pnetwork)
377                                 return;
378                         bssid_ex_sz = r8712_get_wlan_bssid_ex_sz(target);
379                         target->Length = bssid_ex_sz;
380                         memcpy(&pnetwork->network, target, bssid_ex_sz);
381                         list_add_tail(&pnetwork->list, &queue->queue);
382                 }
383         } else {
384                 /* we have an entry and we are going to update it. But
385                  * this entry may be already expired. In this case we
386                  * do the same as we found a new net and call the new_net
387                  * handler
388                  */
389                 update_network(&pnetwork->network, target, adapter);
390                 pnetwork->last_scanned = jiffies;
391         }
392 }
393
394 static void rtl8711_add_network(struct _adapter *adapter,
395                          struct wlan_bssid_ex *pnetwork)
396 {
397         unsigned long irqL;
398         struct mlme_priv *pmlmepriv = &(((struct _adapter *)adapter)->mlmepriv);
399         struct  __queue *queue = &pmlmepriv->scanned_queue;
400
401         spin_lock_irqsave(&queue->lock, irqL);
402         update_current_network(adapter, pnetwork);
403         update_scanned_network(adapter, pnetwork);
404         spin_unlock_irqrestore(&queue->lock, irqL);
405 }
406
407 /*select the desired network based on the capability of the (i)bss.
408  * check items:         (1) security
409  *                      (2) network_type
410  *                      (3) WMM
411  *                      (4) HT
412  *                      (5) others
413  */
414 static int is_desired_network(struct _adapter *adapter,
415                                 struct wlan_network *pnetwork)
416 {
417         u8 wps_ie[512];
418         uint wps_ielen;
419         int bselected = true;
420         struct  security_priv *psecuritypriv = &adapter->securitypriv;
421
422         if (psecuritypriv->wps_phase) {
423                 if (r8712_get_wps_ie(pnetwork->network.IEs,
424                     pnetwork->network.IELength, wps_ie,
425                     &wps_ielen))
426                         return true;
427                 return false;
428         }
429         if ((psecuritypriv->PrivacyAlgrthm != _NO_PRIVACY_) &&
430                     (pnetwork->network.Privacy == 0))
431                 bselected = false;
432         if (check_fwstate(&adapter->mlmepriv, WIFI_ADHOC_STATE)) {
433                 if (pnetwork->network.InfrastructureMode !=
434                         adapter->mlmepriv.cur_network.network.
435                         InfrastructureMode)
436                         bselected = false;
437         }
438         return bselected;
439 }
440
441 /* TODO: Perry : For Power Management */
442 void r8712_atimdone_event_callback(struct _adapter *adapter, u8 *pbuf)
443 {
444 }
445
446 void r8712_survey_event_callback(struct _adapter *adapter, u8 *pbuf)
447 {
448         unsigned long flags;
449         u32 len;
450         struct wlan_bssid_ex *pnetwork;
451         struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
452
453         pnetwork = (struct wlan_bssid_ex *)pbuf;
454 #ifdef __BIG_ENDIAN
455         /* endian_convert */
456         pnetwork->Length = le32_to_cpu(pnetwork->Length);
457         pnetwork->Ssid.SsidLength = le32_to_cpu(pnetwork->Ssid.SsidLength);
458         pnetwork->Privacy = le32_to_cpu(pnetwork->Privacy);
459         pnetwork->Rssi = le32_to_cpu(pnetwork->Rssi);
460         pnetwork->NetworkTypeInUse = le32_to_cpu(pnetwork->NetworkTypeInUse);
461         pnetwork->Configuration.ATIMWindow =
462                  le32_to_cpu(pnetwork->Configuration.ATIMWindow);
463         pnetwork->Configuration.BeaconPeriod =
464                  le32_to_cpu(pnetwork->Configuration.BeaconPeriod);
465         pnetwork->Configuration.DSConfig =
466                  le32_to_cpu(pnetwork->Configuration.DSConfig);
467         pnetwork->Configuration.FHConfig.DwellTime =
468                  le32_to_cpu(pnetwork->Configuration.FHConfig.DwellTime);
469         pnetwork->Configuration.FHConfig.HopPattern =
470                  le32_to_cpu(pnetwork->Configuration.FHConfig.HopPattern);
471         pnetwork->Configuration.FHConfig.HopSet =
472                  le32_to_cpu(pnetwork->Configuration.FHConfig.HopSet);
473         pnetwork->Configuration.FHConfig.Length =
474                  le32_to_cpu(pnetwork->Configuration.FHConfig.Length);
475         pnetwork->Configuration.Length =
476                  le32_to_cpu(pnetwork->Configuration.Length);
477         pnetwork->InfrastructureMode =
478                  le32_to_cpu(pnetwork->InfrastructureMode);
479         pnetwork->IELength = le32_to_cpu(pnetwork->IELength);
480 #endif
481         len = r8712_get_wlan_bssid_ex_sz(pnetwork);
482         if (len > sizeof(struct wlan_bssid_ex))
483                 return;
484         spin_lock_irqsave(&pmlmepriv->lock2, flags);
485         /* update IBSS_network 's timestamp */
486         if (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE)) {
487                 if (!memcmp(&(pmlmepriv->cur_network.network.MacAddress),
488                     pnetwork->MacAddress, ETH_ALEN)) {
489                         struct wlan_network *ibss_wlan = NULL;
490
491                         memcpy(pmlmepriv->cur_network.network.IEs,
492                                 pnetwork->IEs, 8);
493                         ibss_wlan = r8712_find_network(
494                                                 &pmlmepriv->scanned_queue,
495                                                 pnetwork->MacAddress);
496                         if (ibss_wlan) {
497                                 memcpy(ibss_wlan->network.IEs,
498                                         pnetwork->IEs, 8);
499                                 goto exit;
500                         }
501                 }
502         }
503         /* lock pmlmepriv->lock when you accessing network_q */
504         if (!check_fwstate(pmlmepriv, _FW_UNDER_LINKING)) {
505                 if (pnetwork->Ssid.Ssid[0] != 0) {
506                         rtl8711_add_network(adapter, pnetwork);
507                 } else {
508                         pnetwork->Ssid.SsidLength = 8;
509                         memcpy(pnetwork->Ssid.Ssid, "<hidden>", 8);
510                         rtl8711_add_network(adapter, pnetwork);
511                 }
512         }
513 exit:
514         spin_unlock_irqrestore(&pmlmepriv->lock2, flags);
515 }
516
517 void r8712_surveydone_event_callback(struct _adapter *adapter, u8 *pbuf)
518 {
519         unsigned long irqL;
520         struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
521
522         spin_lock_irqsave(&pmlmepriv->lock, irqL);
523
524         if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY)) {
525                 del_timer(&pmlmepriv->scan_to_timer);
526
527                 _clr_fwstate_(pmlmepriv, _FW_UNDER_SURVEY);
528         }
529
530         if (pmlmepriv->to_join) {
531                 if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE)) {
532                         if (!check_fwstate(pmlmepriv, _FW_LINKED)) {
533                                 set_fwstate(pmlmepriv, _FW_UNDER_LINKING);
534
535                                 if (!r8712_select_and_join_from_scan(pmlmepriv)) {
536                                         mod_timer(&pmlmepriv->assoc_timer, jiffies +
537                                                   msecs_to_jiffies(MAX_JOIN_TIMEOUT));
538                                 } else {
539                                         struct wlan_bssid_ex *pdev_network =
540                                           &(adapter->registrypriv.dev_network);
541                                         u8 *pibss =
542                                                  adapter->registrypriv.
543                                                         dev_network.MacAddress;
544                                         pmlmepriv->fw_state ^= _FW_UNDER_SURVEY;
545                                         memcpy(&pdev_network->Ssid,
546                                                 &pmlmepriv->assoc_ssid,
547                                                 sizeof(struct
548                                                          ndis_802_11_ssid));
549                                         r8712_update_registrypriv_dev_network
550                                                 (adapter);
551                                         r8712_generate_random_ibss(pibss);
552                                         pmlmepriv->fw_state =
553                                                  WIFI_ADHOC_MASTER_STATE;
554                                         pmlmepriv->to_join = false;
555                                 }
556                         }
557                 } else {
558                         pmlmepriv->to_join = false;
559                         set_fwstate(pmlmepriv, _FW_UNDER_LINKING);
560                         if (!r8712_select_and_join_from_scan(pmlmepriv))
561                                 mod_timer(&pmlmepriv->assoc_timer, jiffies +
562                                           msecs_to_jiffies(MAX_JOIN_TIMEOUT));
563                         else
564                                 _clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING);
565                 }
566         }
567         spin_unlock_irqrestore(&pmlmepriv->lock, irqL);
568 }
569
570 /*
571  *r8712_free_assoc_resources: the caller has to lock pmlmepriv->lock
572  */
573 void r8712_free_assoc_resources(struct _adapter *adapter)
574 {
575         unsigned long irqL;
576         struct wlan_network *pwlan = NULL;
577         struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
578         struct sta_priv *pstapriv = &adapter->stapriv;
579         struct wlan_network *tgt_network = &pmlmepriv->cur_network;
580
581         pwlan = r8712_find_network(&pmlmepriv->scanned_queue,
582                                    tgt_network->network.MacAddress);
583
584         if (check_fwstate(pmlmepriv, WIFI_STATION_STATE | WIFI_AP_STATE)) {
585                 struct sta_info *psta;
586
587                 psta = r8712_get_stainfo(&adapter->stapriv,
588                                          tgt_network->network.MacAddress);
589
590                 spin_lock_irqsave(&pstapriv->sta_hash_lock, irqL);
591                 r8712_free_stainfo(adapter,  psta);
592                 spin_unlock_irqrestore(&pstapriv->sta_hash_lock, irqL);
593         }
594
595         if (check_fwstate(pmlmepriv,
596             WIFI_ADHOC_STATE | WIFI_ADHOC_MASTER_STATE | WIFI_AP_STATE))
597                 r8712_free_all_stainfo(adapter);
598         if (pwlan)
599                 pwlan->fixed = false;
600
601         if (((check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE)) &&
602              (adapter->stapriv.asoc_sta_count == 1)))
603                 free_network_nolock(pmlmepriv, pwlan);
604 }
605
606 /*
607  * r8712_indicate_connect: the caller has to lock pmlmepriv->lock
608  */
609 void r8712_indicate_connect(struct _adapter *padapter)
610 {
611         struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
612
613         pmlmepriv->to_join = false;
614         set_fwstate(pmlmepriv, _FW_LINKED);
615         padapter->ledpriv.LedControlHandler(padapter, LED_CTL_LINK);
616         r8712_os_indicate_connect(padapter);
617         if (padapter->registrypriv.power_mgnt > PS_MODE_ACTIVE)
618                 mod_timer(&pmlmepriv->dhcp_timer,
619                           jiffies + msecs_to_jiffies(60000));
620 }
621
622 /*
623  * r8712_ind_disconnect: the caller has to lock pmlmepriv->lock
624  */
625 void r8712_ind_disconnect(struct _adapter *padapter)
626 {
627         struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
628
629         if (check_fwstate(pmlmepriv, _FW_LINKED)) {
630                 _clr_fwstate_(pmlmepriv, _FW_LINKED);
631                 padapter->ledpriv.LedControlHandler(padapter, LED_CTL_NO_LINK);
632                 r8712_os_indicate_disconnect(padapter);
633         }
634         if (padapter->pwrctrlpriv.pwr_mode !=
635             padapter->registrypriv.power_mgnt) {
636                 del_timer(&pmlmepriv->dhcp_timer);
637                 r8712_set_ps_mode(padapter, padapter->registrypriv.power_mgnt,
638                                   padapter->registrypriv.smart_ps);
639         }
640 }
641
642 /*Notes:
643  *pnetwork : returns from r8712_joinbss_event_callback
644  *ptarget_wlan: found from scanned_queue
645  *if join_res > 0, for (fw_state==WIFI_STATION_STATE), we check if
646  *  "ptarget_sta" & "ptarget_wlan" exist.
647  *if join_res > 0, for (fw_state==WIFI_ADHOC_STATE), we only check
648  * if "ptarget_wlan" exist.
649  *if join_res > 0, update "cur_network->network" from
650  * "pnetwork->network" if (ptarget_wlan !=NULL).
651  */
652 void r8712_joinbss_event_callback(struct _adapter *adapter, u8 *pbuf)
653 {
654         unsigned long irqL = 0, irqL2;
655         struct sta_info *ptarget_sta = NULL, *pcur_sta = NULL;
656         struct sta_priv *pstapriv = &adapter->stapriv;
657         struct mlme_priv        *pmlmepriv = &adapter->mlmepriv;
658         struct wlan_network     *cur_network = &pmlmepriv->cur_network;
659         struct wlan_network     *pcur_wlan = NULL, *ptarget_wlan = NULL;
660         unsigned int            the_same_macaddr = false;
661         struct wlan_network *pnetwork;
662
663         if (sizeof(struct list_head) == 4 * sizeof(u32)) {
664                 pnetwork = kmalloc(sizeof(struct wlan_network), GFP_ATOMIC);
665                 if (!pnetwork)
666                         return;
667                 memcpy((u8 *)pnetwork + 16, (u8 *)pbuf + 8,
668                        sizeof(struct wlan_network) - 16);
669         } else {
670                 pnetwork = (struct wlan_network *)pbuf;
671         }
672
673 #ifdef __BIG_ENDIAN
674         /* endian_convert */
675         pnetwork->join_res = le32_to_cpu(pnetwork->join_res);
676         pnetwork->network_type = le32_to_cpu(pnetwork->network_type);
677         pnetwork->network.Length = le32_to_cpu(pnetwork->network.Length);
678         pnetwork->network.Ssid.SsidLength =
679                  le32_to_cpu(pnetwork->network.Ssid.SsidLength);
680         pnetwork->network.Privacy = le32_to_cpu(pnetwork->network.Privacy);
681         pnetwork->network.Rssi = le32_to_cpu(pnetwork->network.Rssi);
682         pnetwork->network.NetworkTypeInUse =
683                  le32_to_cpu(pnetwork->network.NetworkTypeInUse);
684         pnetwork->network.Configuration.ATIMWindow =
685                  le32_to_cpu(pnetwork->network.Configuration.ATIMWindow);
686         pnetwork->network.Configuration.BeaconPeriod =
687                  le32_to_cpu(pnetwork->network.Configuration.BeaconPeriod);
688         pnetwork->network.Configuration.DSConfig =
689                  le32_to_cpu(pnetwork->network.Configuration.DSConfig);
690         pnetwork->network.Configuration.FHConfig.DwellTime =
691                  le32_to_cpu(pnetwork->network.Configuration.FHConfig.
692                              DwellTime);
693         pnetwork->network.Configuration.FHConfig.HopPattern =
694                  le32_to_cpu(pnetwork->network.Configuration.
695                              FHConfig.HopPattern);
696         pnetwork->network.Configuration.FHConfig.HopSet =
697                  le32_to_cpu(pnetwork->network.Configuration.FHConfig.HopSet);
698         pnetwork->network.Configuration.FHConfig.Length =
699                  le32_to_cpu(pnetwork->network.Configuration.FHConfig.Length);
700         pnetwork->network.Configuration.Length =
701                  le32_to_cpu(pnetwork->network.Configuration.Length);
702         pnetwork->network.InfrastructureMode =
703                  le32_to_cpu(pnetwork->network.InfrastructureMode);
704         pnetwork->network.IELength = le32_to_cpu(pnetwork->network.IELength);
705 #endif
706
707         the_same_macaddr = !memcmp(pnetwork->network.MacAddress,
708                                    cur_network->network.MacAddress, ETH_ALEN);
709         pnetwork->network.Length =
710                  r8712_get_wlan_bssid_ex_sz(&pnetwork->network);
711         spin_lock_irqsave(&pmlmepriv->lock, irqL);
712         if (pnetwork->network.Length > sizeof(struct wlan_bssid_ex))
713                 goto ignore_joinbss_callback;
714         if (pnetwork->join_res > 0) {
715                 if (check_fwstate(pmlmepriv, _FW_UNDER_LINKING)) {
716                         /*s1. find ptarget_wlan*/
717                         if (check_fwstate(pmlmepriv, _FW_LINKED)) {
718                                 if (the_same_macaddr) {
719                                         ptarget_wlan =
720                                             r8712_find_network(&pmlmepriv->
721                                             scanned_queue,
722                                             cur_network->network.MacAddress);
723                                 } else {
724                                         pcur_wlan =
725                                              r8712_find_network(&pmlmepriv->
726                                              scanned_queue,
727                                              cur_network->network.MacAddress);
728                                         if (pcur_wlan)
729                                                 pcur_wlan->fixed = false;
730
731                                         pcur_sta = r8712_get_stainfo(pstapriv,
732                                              cur_network->network.MacAddress);
733                                         spin_lock_irqsave(&pstapriv->
734                                                 sta_hash_lock, irqL2);
735                                         r8712_free_stainfo(adapter, pcur_sta);
736                                         spin_unlock_irqrestore(&(pstapriv->
737                                                 sta_hash_lock), irqL2);
738
739                                         ptarget_wlan =
740                                                  r8712_find_network(&pmlmepriv->
741                                                  scanned_queue,
742                                                  pnetwork->network.
743                                                  MacAddress);
744                                         if (ptarget_wlan)
745                                                 ptarget_wlan->fixed = true;
746                                 }
747                         } else {
748                                 ptarget_wlan = r8712_find_network(&pmlmepriv->
749                                                 scanned_queue,
750                                                 pnetwork->network.MacAddress);
751                                 if (ptarget_wlan)
752                                         ptarget_wlan->fixed = true;
753                         }
754
755                         if (!ptarget_wlan) {
756                                 if (check_fwstate(pmlmepriv,
757                                         _FW_UNDER_LINKING))
758                                         pmlmepriv->fw_state ^=
759                                                  _FW_UNDER_LINKING;
760                                 goto ignore_joinbss_callback;
761                         }
762
763                         /*s2. find ptarget_sta & update ptarget_sta*/
764                         if (check_fwstate(pmlmepriv, WIFI_STATION_STATE)) {
765                                 if (the_same_macaddr) {
766                                         ptarget_sta =
767                                                  r8712_get_stainfo(pstapriv,
768                                                  pnetwork->network.MacAddress);
769                                         if (!ptarget_sta)
770                                                 ptarget_sta =
771                                                  r8712_alloc_stainfo(pstapriv,
772                                                  pnetwork->network.MacAddress);
773                                 } else {
774                                         ptarget_sta =
775                                                  r8712_alloc_stainfo(pstapriv,
776                                                  pnetwork->network.MacAddress);
777                                 }
778                                 if (ptarget_sta) /*update ptarget_sta*/ {
779                                         ptarget_sta->aid = pnetwork->join_res;
780                                         ptarget_sta->qos_option = 1;
781                                         ptarget_sta->mac_id = 5;
782                                         if (adapter->securitypriv.
783                                             AuthAlgrthm == 2) {
784                                                 adapter->securitypriv.
785                                                         binstallGrpkey =
786                                                          false;
787                                                 adapter->securitypriv.
788                                                         busetkipkey =
789                                                          false;
790                                                 adapter->securitypriv.
791                                                         bgrpkey_handshake =
792                                                          false;
793                                                 ptarget_sta->ieee8021x_blocked
794                                                          = true;
795                                                 ptarget_sta->XPrivacy =
796                                                          adapter->securitypriv.
797                                                          PrivacyAlgrthm;
798                                                 memset((u8 *)&ptarget_sta->
799                                                          x_UncstKey,
800                                                          0,
801                                                          sizeof(union Keytype));
802                                                 memset((u8 *)&ptarget_sta->
803                                                          tkiprxmickey,
804                                                          0,
805                                                          sizeof(union Keytype));
806                                                 memset((u8 *)&ptarget_sta->
807                                                          tkiptxmickey,
808                                                          0,
809                                                          sizeof(union Keytype));
810                                                 memset((u8 *)&ptarget_sta->
811                                                          txpn, 0,
812                                                          sizeof(union pn48));
813                                                 memset((u8 *)&ptarget_sta->
814                                                          rxpn, 0,
815                                                          sizeof(union pn48));
816                                         }
817                                 } else {
818                                         if (check_fwstate(pmlmepriv,
819                                             _FW_UNDER_LINKING))
820                                                 pmlmepriv->fw_state ^=
821                                                          _FW_UNDER_LINKING;
822                                         goto ignore_joinbss_callback;
823                                 }
824                         }
825
826                         /*s3. update cur_network & indicate connect*/
827                         memcpy(&cur_network->network, &pnetwork->network,
828                                 pnetwork->network.Length);
829                         cur_network->aid = pnetwork->join_res;
830                         /*update fw_state will clr _FW_UNDER_LINKING*/
831                         switch (pnetwork->network.InfrastructureMode) {
832                         case Ndis802_11Infrastructure:
833                                 pmlmepriv->fw_state = WIFI_STATION_STATE;
834                                 break;
835                         case Ndis802_11IBSS:
836                                 pmlmepriv->fw_state = WIFI_ADHOC_STATE;
837                                 break;
838                         default:
839                                 pmlmepriv->fw_state = WIFI_NULL_STATE;
840                                 break;
841                         }
842                         r8712_update_protection(adapter,
843                                           (cur_network->network.IEs) +
844                                           sizeof(struct NDIS_802_11_FIXED_IEs),
845                                           (cur_network->network.IELength));
846                         /*TODO: update HT_Capability*/
847                         update_ht_cap(adapter, cur_network->network.IEs,
848                                       cur_network->network.IELength);
849                         /*indicate connect*/
850                         if (check_fwstate(pmlmepriv, WIFI_STATION_STATE))
851                                 r8712_indicate_connect(adapter);
852                         del_timer(&pmlmepriv->assoc_timer);
853                 } else {
854                         goto ignore_joinbss_callback;
855                 }
856         } else {
857                 if (check_fwstate(pmlmepriv, _FW_UNDER_LINKING)) {
858                         mod_timer(&pmlmepriv->assoc_timer,
859                                   jiffies + msecs_to_jiffies(1));
860                         _clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING);
861                 }
862         }
863 ignore_joinbss_callback:
864         spin_unlock_irqrestore(&pmlmepriv->lock, irqL);
865         if (sizeof(struct list_head) == 4 * sizeof(u32))
866                 kfree(pnetwork);
867 }
868
869 void r8712_stassoc_event_callback(struct _adapter *adapter, u8 *pbuf)
870 {
871         unsigned long irqL;
872         struct sta_info *psta;
873         struct mlme_priv *pmlmepriv = &(adapter->mlmepriv);
874         struct stassoc_event *pstassoc  = (struct stassoc_event *)pbuf;
875
876         /* to do: */
877         if (!r8712_access_ctrl(&adapter->acl_list, pstassoc->macaddr))
878                 return;
879         psta = r8712_get_stainfo(&adapter->stapriv, pstassoc->macaddr);
880         if (psta) {
881                 /*the sta have been in sta_info_queue => do nothing
882                  *(between drv has received this event before and
883                  * fw have not yet to set key to CAM_ENTRY)
884                  */
885                 return;
886         }
887
888         psta = r8712_alloc_stainfo(&adapter->stapriv, pstassoc->macaddr);
889         if (!psta)
890                 return;
891         /* to do : init sta_info variable */
892         psta->qos_option = 0;
893         psta->mac_id = le32_to_cpu(pstassoc->cam_id);
894         /* psta->aid = (uint)pstassoc->cam_id; */
895
896         if (adapter->securitypriv.AuthAlgrthm == 2)
897                 psta->XPrivacy = adapter->securitypriv.PrivacyAlgrthm;
898         psta->ieee8021x_blocked = false;
899         spin_lock_irqsave(&pmlmepriv->lock, irqL);
900         if (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) ||
901             check_fwstate(pmlmepriv, WIFI_ADHOC_STATE)) {
902                 if (adapter->stapriv.asoc_sta_count == 2) {
903                         /* a sta + bc/mc_stainfo (not Ibss_stainfo) */
904                         r8712_indicate_connect(adapter);
905                 }
906         }
907         spin_unlock_irqrestore(&pmlmepriv->lock, irqL);
908 }
909
910 void r8712_stadel_event_callback(struct _adapter *adapter, u8 *pbuf)
911 {
912         unsigned long irqL, irqL2;
913         struct sta_info *psta;
914         struct wlan_network *pwlan = NULL;
915         struct wlan_bssid_ex *pdev_network = NULL;
916         u8 *pibss = NULL;
917         struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
918         struct stadel_event *pstadel = (struct stadel_event *)pbuf;
919         struct sta_priv *pstapriv = &adapter->stapriv;
920         struct wlan_network *tgt_network = &pmlmepriv->cur_network;
921
922         spin_lock_irqsave(&pmlmepriv->lock, irqL2);
923         if (check_fwstate(pmlmepriv, WIFI_STATION_STATE)) {
924                 r8712_ind_disconnect(adapter);
925                 r8712_free_assoc_resources(adapter);
926         }
927         if (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE |
928             WIFI_ADHOC_STATE)) {
929                 psta = r8712_get_stainfo(&adapter->stapriv, pstadel->macaddr);
930                 spin_lock_irqsave(&pstapriv->sta_hash_lock, irqL);
931                 r8712_free_stainfo(adapter, psta);
932                 spin_unlock_irqrestore(&pstapriv->sta_hash_lock, irqL);
933                 if (adapter->stapriv.asoc_sta_count == 1) {
934                         /*a sta + bc/mc_stainfo (not Ibss_stainfo) */
935                         pwlan = r8712_find_network(&pmlmepriv->scanned_queue,
936                                 tgt_network->network.MacAddress);
937                         if (pwlan) {
938                                 pwlan->fixed = false;
939                                 free_network_nolock(pmlmepriv, pwlan);
940                         }
941                         /*re-create ibss*/
942                         pdev_network = &(adapter->registrypriv.dev_network);
943                         pibss = adapter->registrypriv.dev_network.MacAddress;
944                         memcpy(pdev_network, &tgt_network->network,
945                                 r8712_get_wlan_bssid_ex_sz(&tgt_network->
946                                                         network));
947                         memcpy(&pdev_network->Ssid,
948                                 &pmlmepriv->assoc_ssid,
949                                 sizeof(struct ndis_802_11_ssid));
950                         r8712_update_registrypriv_dev_network(adapter);
951                         r8712_generate_random_ibss(pibss);
952                         if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE)) {
953                                 _clr_fwstate_(pmlmepriv, WIFI_ADHOC_STATE);
954                                 set_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE);
955                         }
956                 }
957         }
958         spin_unlock_irqrestore(&pmlmepriv->lock, irqL2);
959 }
960
961 void r8712_cpwm_event_callback(struct _adapter *adapter, u8 *pbuf)
962 {
963         struct reportpwrstate_parm *preportpwrstate =
964                          (struct reportpwrstate_parm *)pbuf;
965
966         preportpwrstate->state |= (u8)(adapter->pwrctrlpriv.cpwm_tog + 0x80);
967         r8712_cpwm_int_hdl(adapter, preportpwrstate);
968 }
969
970 /*      When the Netgear 3500 AP is with WPA2PSK-AES mode, it will send
971  *       the ADDBA req frame with start seq control = 0 to wifi client after
972  *       the WPA handshake and the seqence number of following data packet
973  *      will be 0. In this case, the Rx reorder sequence is not longer than 0
974  *       and the WiFi client will drop the data with seq number 0.
975  *      So, the 8712 firmware has to inform driver with receiving the
976  *       ADDBA-Req frame so that the driver can reset the
977  *      sequence value of Rx reorder control.
978  */
979 void r8712_got_addbareq_event_callback(struct _adapter *adapter, u8 *pbuf)
980 {
981         struct  ADDBA_Req_Report_parm *pAddbareq_pram =
982                          (struct ADDBA_Req_Report_parm *)pbuf;
983         struct  sta_info *psta;
984         struct  sta_priv *pstapriv = &adapter->stapriv;
985         struct  recv_reorder_ctrl *precvreorder_ctrl = NULL;
986
987         psta = r8712_get_stainfo(pstapriv, pAddbareq_pram->MacAddress);
988         if (psta) {
989                 precvreorder_ctrl =
990                          &psta->recvreorder_ctrl[pAddbareq_pram->tid];
991                 /* set the indicate_seq to 0xffff so that the rx reorder
992                  * can store any following data packet.
993                  */
994                 precvreorder_ctrl->indicate_seq = 0xffff;
995         }
996 }
997
998 void r8712_wpspbc_event_callback(struct _adapter *adapter, u8 *pbuf)
999 {
1000         if (!adapter->securitypriv.wps_hw_pbc_pressed)
1001                 adapter->securitypriv.wps_hw_pbc_pressed = true;
1002 }
1003
1004 void _r8712_sitesurvey_ctrl_handler(struct _adapter *adapter)
1005 {
1006         struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
1007         struct sitesurvey_ctrl  *psitesurveyctrl = &pmlmepriv->sitesurveyctrl;
1008         struct registry_priv    *pregistrypriv = &adapter->registrypriv;
1009         u64 current_tx_pkts;
1010         uint current_rx_pkts;
1011
1012         current_tx_pkts = (adapter->xmitpriv.tx_pkts) -
1013                           (psitesurveyctrl->last_tx_pkts);
1014         current_rx_pkts = (adapter->recvpriv.rx_pkts) -
1015                           (psitesurveyctrl->last_rx_pkts);
1016         psitesurveyctrl->last_tx_pkts = adapter->xmitpriv.tx_pkts;
1017         psitesurveyctrl->last_rx_pkts = adapter->recvpriv.rx_pkts;
1018         if ((current_tx_pkts > pregistrypriv->busy_thresh) ||
1019             (current_rx_pkts > pregistrypriv->busy_thresh))
1020                 psitesurveyctrl->traffic_busy = true;
1021         else
1022                 psitesurveyctrl->traffic_busy = false;
1023 }
1024
1025 void _r8712_join_timeout_handler(struct _adapter *adapter)
1026 {
1027         unsigned long irqL;
1028         struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
1029
1030         if (adapter->driver_stopped || adapter->surprise_removed)
1031                 return;
1032         spin_lock_irqsave(&pmlmepriv->lock, irqL);
1033         _clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING);
1034         pmlmepriv->to_join = false;
1035         if (check_fwstate(pmlmepriv, _FW_LINKED)) {
1036                 r8712_os_indicate_disconnect(adapter);
1037                 _clr_fwstate_(pmlmepriv, _FW_LINKED);
1038         }
1039         if (adapter->pwrctrlpriv.pwr_mode != adapter->registrypriv.power_mgnt) {
1040                 r8712_set_ps_mode(adapter, adapter->registrypriv.power_mgnt,
1041                                   adapter->registrypriv.smart_ps);
1042         }
1043         spin_unlock_irqrestore(&pmlmepriv->lock, irqL);
1044 }
1045
1046 void r8712_scan_timeout_handler (struct _adapter *adapter)
1047 {
1048         unsigned long irqL;
1049         struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
1050
1051         spin_lock_irqsave(&pmlmepriv->lock, irqL);
1052         _clr_fwstate_(pmlmepriv, _FW_UNDER_SURVEY);
1053         pmlmepriv->to_join = false;     /* scan fail, so clear to_join flag */
1054         spin_unlock_irqrestore(&pmlmepriv->lock, irqL);
1055 }
1056
1057 void _r8712_dhcp_timeout_handler (struct _adapter *adapter)
1058 {
1059         if (adapter->driver_stopped || adapter->surprise_removed)
1060                 return;
1061         if (adapter->pwrctrlpriv.pwr_mode != adapter->registrypriv.power_mgnt)
1062                 r8712_set_ps_mode(adapter, adapter->registrypriv.power_mgnt,
1063                             adapter->registrypriv.smart_ps);
1064 }
1065
1066 int r8712_select_and_join_from_scan(struct mlme_priv *pmlmepriv)
1067 {
1068         struct list_head *phead;
1069         unsigned char *dst_ssid, *src_ssid;
1070         struct _adapter *adapter;
1071         struct  __queue *queue = NULL;
1072         struct wlan_network *pnetwork = NULL;
1073         struct wlan_network *pnetwork_max_rssi = NULL;
1074
1075         adapter = (struct _adapter *)pmlmepriv->nic_hdl;
1076         queue = &pmlmepriv->scanned_queue;
1077         phead = &queue->queue;
1078         pmlmepriv->pscanned = phead->next;
1079         while (1) {
1080                 if (end_of_queue_search(phead, pmlmepriv->pscanned)) {
1081                         if (pmlmepriv->assoc_by_rssi && pnetwork_max_rssi) {
1082                                 pnetwork = pnetwork_max_rssi;
1083                                 goto ask_for_joinbss;
1084                         }
1085                         return -EINVAL;
1086                 }
1087                 pnetwork = container_of(pmlmepriv->pscanned,
1088                                         struct wlan_network, list);
1089                 pmlmepriv->pscanned = pmlmepriv->pscanned->next;
1090                 if (pmlmepriv->assoc_by_bssid) {
1091                         dst_ssid = pnetwork->network.MacAddress;
1092                         src_ssid = pmlmepriv->assoc_bssid;
1093                         if (!memcmp(dst_ssid, src_ssid, ETH_ALEN)) {
1094                                 if (check_fwstate(pmlmepriv, _FW_LINKED)) {
1095                                         if (is_same_network(&pmlmepriv->
1096                                             cur_network.network,
1097                                             &pnetwork->network)) {
1098                                                 _clr_fwstate_(pmlmepriv,
1099                                                         _FW_UNDER_LINKING);
1100                                                 /*r8712_indicate_connect again*/
1101                                                 r8712_indicate_connect(adapter);
1102                                                 return 2;
1103                                         }
1104                                         r8712_disassoc_cmd(adapter);
1105                                         r8712_ind_disconnect(adapter);
1106                                         r8712_free_assoc_resources(adapter);
1107                                 }
1108                                 goto ask_for_joinbss;
1109                         }
1110                 } else if (pmlmepriv->assoc_ssid.SsidLength == 0) {
1111                         goto ask_for_joinbss;
1112                 }
1113                 dst_ssid = pnetwork->network.Ssid.Ssid;
1114                 src_ssid = pmlmepriv->assoc_ssid.Ssid;
1115                 if ((pnetwork->network.Ssid.SsidLength ==
1116                     pmlmepriv->assoc_ssid.SsidLength) &&
1117                     (!memcmp(dst_ssid, src_ssid,
1118                      pmlmepriv->assoc_ssid.SsidLength))) {
1119                         if (pmlmepriv->assoc_by_rssi) {
1120                                 /* if the ssid is the same, select the bss
1121                                  * which has the max rssi
1122                                  */
1123                                 if (pnetwork_max_rssi) {
1124                                         if (pnetwork->network.Rssi >
1125                                             pnetwork_max_rssi->network.Rssi)
1126                                                 pnetwork_max_rssi = pnetwork;
1127                                 } else {
1128                                         pnetwork_max_rssi = pnetwork;
1129                                 }
1130                         } else if (is_desired_network(adapter, pnetwork)) {
1131                                 if (check_fwstate(pmlmepriv, _FW_LINKED)) {
1132                                         r8712_disassoc_cmd(adapter);
1133                                         r8712_free_assoc_resources(adapter);
1134                                 }
1135                                 goto ask_for_joinbss;
1136                         }
1137                 }
1138         }
1139
1140 ask_for_joinbss:
1141         return r8712_joinbss_cmd(adapter, pnetwork);
1142 }
1143
1144 int r8712_set_auth(struct _adapter *adapter,
1145                    struct security_priv *psecuritypriv)
1146 {
1147         struct cmd_priv *pcmdpriv = &adapter->cmdpriv;
1148         struct cmd_obj *pcmd;
1149         struct setauth_parm *psetauthparm;
1150
1151         pcmd = kmalloc(sizeof(*pcmd), GFP_ATOMIC);
1152         if (!pcmd)
1153                 return -ENOMEM;
1154
1155         psetauthparm = kzalloc(sizeof(*psetauthparm), GFP_ATOMIC);
1156         if (!psetauthparm) {
1157                 kfree(pcmd);
1158                 return -ENOMEM;
1159         }
1160         psetauthparm->mode = (u8)psecuritypriv->AuthAlgrthm;
1161         pcmd->cmdcode = _SetAuth_CMD_;
1162         pcmd->parmbuf = (unsigned char *)psetauthparm;
1163         pcmd->cmdsz = sizeof(struct setauth_parm);
1164         pcmd->rsp = NULL;
1165         pcmd->rspsz = 0;
1166         INIT_LIST_HEAD(&pcmd->list);
1167         r8712_enqueue_cmd(pcmdpriv, pcmd);
1168         return 0;
1169 }
1170
1171 int r8712_set_key(struct _adapter *adapter,
1172                   struct security_priv *psecuritypriv,
1173                   sint keyid)
1174 {
1175         struct cmd_priv *pcmdpriv = &adapter->cmdpriv;
1176         struct cmd_obj *pcmd;
1177         struct setkey_parm *psetkeyparm;
1178         u8 keylen;
1179         int ret;
1180
1181         pcmd = kmalloc(sizeof(*pcmd), GFP_ATOMIC);
1182         if (!pcmd)
1183                 return -ENOMEM;
1184         psetkeyparm = kzalloc(sizeof(*psetkeyparm), GFP_ATOMIC);
1185         if (!psetkeyparm) {
1186                 ret = -ENOMEM;
1187                 goto err_free_cmd;
1188         }
1189         if (psecuritypriv->AuthAlgrthm == 2) { /* 802.1X */
1190                 psetkeyparm->algorithm =
1191                          (u8)psecuritypriv->XGrpPrivacy;
1192         } else { /* WEP */
1193                 psetkeyparm->algorithm =
1194                          (u8)psecuritypriv->PrivacyAlgrthm;
1195         }
1196         psetkeyparm->keyid = (u8)keyid;
1197
1198         switch (psetkeyparm->algorithm) {
1199         case _WEP40_:
1200                 keylen = 5;
1201                 memcpy(psetkeyparm->key,
1202                         psecuritypriv->DefKey[keyid].skey, keylen);
1203                 break;
1204         case _WEP104_:
1205                 keylen = 13;
1206                 memcpy(psetkeyparm->key,
1207                         psecuritypriv->DefKey[keyid].skey, keylen);
1208                 break;
1209         case _TKIP_:
1210                 if (keyid < 1 || keyid > 2) {
1211                         ret = -EINVAL;
1212                         goto err_free_parm;
1213                 }
1214                 keylen = 16;
1215                 memcpy(psetkeyparm->key,
1216                         &psecuritypriv->XGrpKey[keyid - 1], keylen);
1217                 psetkeyparm->grpkey = 1;
1218                 break;
1219         case _AES_:
1220                 if (keyid < 1 || keyid > 2) {
1221                         ret = -EINVAL;
1222                         goto err_free_parm;
1223                 }
1224                 keylen = 16;
1225                 memcpy(psetkeyparm->key,
1226                         &psecuritypriv->XGrpKey[keyid - 1], keylen);
1227                 psetkeyparm->grpkey = 1;
1228                 break;
1229         default:
1230                 ret = -EINVAL;
1231                 goto err_free_parm;
1232         }
1233         pcmd->cmdcode = _SetKey_CMD_;
1234         pcmd->parmbuf = (u8 *)psetkeyparm;
1235         pcmd->cmdsz =  (sizeof(struct setkey_parm));
1236         pcmd->rsp = NULL;
1237         pcmd->rspsz = 0;
1238         INIT_LIST_HEAD(&pcmd->list);
1239         r8712_enqueue_cmd(pcmdpriv, pcmd);
1240         return 0;
1241
1242 err_free_parm:
1243         kfree(psetkeyparm);
1244 err_free_cmd:
1245         kfree(pcmd);
1246         return ret;
1247 }
1248
1249 /* adjust IEs for r8712_joinbss_cmd in WMM */
1250 int r8712_restruct_wmm_ie(struct _adapter *adapter, u8 *in_ie, u8 *out_ie,
1251                     uint in_len, uint initial_out_len)
1252 {
1253         unsigned int ielength = 0;
1254         unsigned int i, j;
1255
1256         i = 12; /* after the fixed IE */
1257         while (i < in_len) {
1258                 ielength = initial_out_len;
1259                 if (in_ie[i] == 0xDD && in_ie[i + 2] == 0x00 &&
1260                     in_ie[i + 3] == 0x50 && in_ie[i + 4] == 0xF2 &&
1261                     in_ie[i + 5] == 0x02 && i + 5 < in_len) {
1262                         /*WMM element ID and OUI*/
1263                         for (j = i; j < i + 9; j++) {
1264                                 out_ie[ielength] = in_ie[j];
1265                                 ielength++;
1266                         }
1267                         out_ie[initial_out_len + 1] = 0x07;
1268                         out_ie[initial_out_len + 6] = 0x00;
1269                         out_ie[initial_out_len + 8] = 0x00;
1270                         break;
1271                 }
1272                 i += (in_ie[i + 1] + 2); /* to the next IE element */
1273         }
1274         return ielength;
1275 }
1276
1277 /*
1278  * Ported from 8185: IsInPreAuthKeyList().
1279  *
1280  * Search by BSSID,
1281  * Return Value:
1282  *      -1              :if there is no pre-auth key in the  table
1283  *      >=0             :if there is pre-auth key, and   return the entry id
1284  */
1285 static int SecIsInPMKIDList(struct _adapter *Adapter, u8 *bssid)
1286 {
1287         struct security_priv *psecuritypriv = &Adapter->securitypriv;
1288         int i = 0;
1289
1290         do {
1291                 if (psecuritypriv->PMKIDList[i].bUsed &&
1292                    (!memcmp(psecuritypriv->PMKIDList[i].Bssid,
1293                             bssid, ETH_ALEN)))
1294                         break;
1295                 i++;
1296
1297         } while (i < NUM_PMKID_CACHE);
1298
1299         if (i == NUM_PMKID_CACHE) {
1300                 i = -1; /* Could not find. */
1301         } else {
1302                 ; /* There is one Pre-Authentication Key for the
1303                    * specific BSSID.
1304                    */
1305         }
1306         return i;
1307 }
1308
1309 sint r8712_restruct_sec_ie(struct _adapter *adapter, u8 *in_ie,
1310                      u8 *out_ie, uint in_len)
1311 {
1312         u8 authmode = 0, match;
1313         u8 sec_ie[IW_CUSTOM_MAX], uncst_oui[4], bkup_ie[255];
1314         u8 wpa_oui[4] = {0x0, 0x50, 0xf2, 0x01};
1315         uint ielength, cnt, remove_cnt;
1316         int iEntry;
1317         struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
1318         struct security_priv *psecuritypriv = &adapter->securitypriv;
1319         uint ndisauthmode = psecuritypriv->ndisauthtype;
1320         uint ndissecuritytype = psecuritypriv->ndisencryptstatus;
1321
1322         if ((ndisauthmode == Ndis802_11AuthModeWPA) ||
1323             (ndisauthmode == Ndis802_11AuthModeWPAPSK)) {
1324                 authmode = _WPA_IE_ID_;
1325                 uncst_oui[0] = 0x0;
1326                 uncst_oui[1] = 0x50;
1327                 uncst_oui[2] = 0xf2;
1328         }
1329         if ((ndisauthmode == Ndis802_11AuthModeWPA2) ||
1330             (ndisauthmode == Ndis802_11AuthModeWPA2PSK)) {
1331                 authmode = _WPA2_IE_ID_;
1332                 uncst_oui[0] = 0x0;
1333                 uncst_oui[1] = 0x0f;
1334                 uncst_oui[2] = 0xac;
1335         }
1336         switch (ndissecuritytype) {
1337         case Ndis802_11Encryption1Enabled:
1338         case Ndis802_11Encryption1KeyAbsent:
1339                 uncst_oui[3] = 0x1;
1340                 break;
1341         case Ndis802_11Encryption2Enabled:
1342         case Ndis802_11Encryption2KeyAbsent:
1343                 uncst_oui[3] = 0x2;
1344                 break;
1345         case Ndis802_11Encryption3Enabled:
1346         case Ndis802_11Encryption3KeyAbsent:
1347                 uncst_oui[3] = 0x4;
1348                 break;
1349         default:
1350                 break;
1351         }
1352         /*Search required WPA or WPA2 IE and copy to sec_ie[] */
1353         cnt = 12;
1354         match = false;
1355         while (cnt < in_len) {
1356                 if (in_ie[cnt] == authmode) {
1357                         if ((authmode == _WPA_IE_ID_) &&
1358                             (!memcmp(&in_ie[cnt + 2], &wpa_oui[0], 4))) {
1359                                 memcpy(&sec_ie[0], &in_ie[cnt],
1360                                         in_ie[cnt + 1] + 2);
1361                                 match = true;
1362                                 break;
1363                         }
1364                         if (authmode == _WPA2_IE_ID_) {
1365                                 memcpy(&sec_ie[0], &in_ie[cnt],
1366                                         in_ie[cnt + 1] + 2);
1367                                 match = true;
1368                                 break;
1369                         }
1370                         if (((authmode == _WPA_IE_ID_) &&
1371                              (!memcmp(&in_ie[cnt + 2], &wpa_oui[0], 4))) ||
1372                              (authmode == _WPA2_IE_ID_))
1373                                 memcpy(&bkup_ie[0], &in_ie[cnt],
1374                                         in_ie[cnt + 1] + 2);
1375                 }
1376                 cnt += in_ie[cnt + 1] + 2; /*get next*/
1377         }
1378         /*restruct WPA IE or WPA2 IE in sec_ie[] */
1379         if (match) {
1380                 if (sec_ie[0] == _WPA_IE_ID_) {
1381                         /* parsing SSN IE to select required encryption
1382                          * algorithm, and set the bc/mc encryption algorithm
1383                          */
1384                         while (true) {
1385                                 /*check wpa_oui tag*/
1386                                 if (memcmp(&sec_ie[2], &wpa_oui[0], 4)) {
1387                                         match = false;
1388                                         break;
1389                                 }
1390                                 if ((sec_ie[6] != 0x01) || (sec_ie[7] != 0x0)) {
1391                                         /*IE Ver error*/
1392                                         match = false;
1393                                         break;
1394                                 }
1395                                 if (!memcmp(&sec_ie[8], &wpa_oui[0], 3)) {
1396                                         /* get bc/mc encryption type (group
1397                                          * key type)
1398                                          */
1399                                         switch (sec_ie[11]) {
1400                                         case 0x0: /*none*/
1401                                                 psecuritypriv->XGrpPrivacy =
1402                                                                 _NO_PRIVACY_;
1403                                                 break;
1404                                         case 0x1: /*WEP_40*/
1405                                                 psecuritypriv->XGrpPrivacy =
1406                                                                 _WEP40_;
1407                                                 break;
1408                                         case 0x2: /*TKIP*/
1409                                                 psecuritypriv->XGrpPrivacy =
1410                                                                 _TKIP_;
1411                                                 break;
1412                                         case 0x3: /*AESCCMP*/
1413                                         case 0x4:
1414                                                 psecuritypriv->XGrpPrivacy =
1415                                                                 _AES_;
1416                                                 break;
1417                                         case 0x5: /*WEP_104*/
1418                                                 psecuritypriv->XGrpPrivacy =
1419                                                                 _WEP104_;
1420                                                 break;
1421                                         }
1422                                 } else {
1423                                         match = false;
1424                                         break;
1425                                 }
1426                                 if (sec_ie[12] == 0x01) {
1427                                         /*check the unicast encryption type*/
1428                                         if (memcmp(&sec_ie[14],
1429                                             &uncst_oui[0], 4)) {
1430                                                 match = false;
1431                                                 break;
1432
1433                                         } /*else the uncst_oui is match*/
1434                                 } else { /*mixed mode, unicast_enc_type > 1*/
1435                                         /*select the uncst_oui and remove
1436                                          * the other uncst_oui
1437                                          */
1438                                         cnt = sec_ie[12];
1439                                         remove_cnt = (cnt - 1) * 4;
1440                                         sec_ie[12] = 0x01;
1441                                         memcpy(&sec_ie[14], &uncst_oui[0], 4);
1442                                         /*remove the other unicast suit*/
1443                                         memcpy(&sec_ie[18],
1444                                                 &sec_ie[18 + remove_cnt],
1445                                                 sec_ie[1] - 18 + 2 -
1446                                                 remove_cnt);
1447                                         sec_ie[1] = sec_ie[1] - remove_cnt;
1448                                 }
1449                                 break;
1450                         }
1451                 }
1452                 if (authmode == _WPA2_IE_ID_) {
1453                         /* parsing RSN IE to select required encryption
1454                          * algorithm, and set the bc/mc encryption algorithm
1455                          */
1456                         while (true) {
1457                                 if ((sec_ie[2] != 0x01) || (sec_ie[3] != 0x0)) {
1458                                         /*IE Ver error*/
1459                                         match = false;
1460                                         break;
1461                                 }
1462                                 if (!memcmp(&sec_ie[4], &uncst_oui[0], 3)) {
1463                                         /*get bc/mc encryption type*/
1464                                         switch (sec_ie[7]) {
1465                                         case 0x1: /*WEP_40*/
1466                                                 psecuritypriv->XGrpPrivacy =
1467                                                                 _WEP40_;
1468                                                 break;
1469                                         case 0x2: /*TKIP*/
1470                                                 psecuritypriv->XGrpPrivacy =
1471                                                                 _TKIP_;
1472                                                 break;
1473                                         case 0x4: /*AESWRAP*/
1474                                                 psecuritypriv->XGrpPrivacy =
1475                                                                 _AES_;
1476                                                 break;
1477                                         case 0x5: /*WEP_104*/
1478                                                 psecuritypriv->XGrpPrivacy =
1479                                                                 _WEP104_;
1480                                                 break;
1481                                         default: /*one*/
1482                                                 psecuritypriv->XGrpPrivacy =
1483                                                                 _NO_PRIVACY_;
1484                                                 break;
1485                                         }
1486                                 } else {
1487                                         match = false;
1488                                         break;
1489                                 }
1490                                 if (sec_ie[8] == 0x01) {
1491                                         /*check the unicast encryption type*/
1492                                         if (memcmp(&sec_ie[10],
1493                                                      &uncst_oui[0], 4)) {
1494                                                 match = false;
1495                                                 break;
1496                                         } /*else the uncst_oui is match*/
1497                                 } else { /*mixed mode, unicast_enc_type > 1*/
1498                                         /*select the uncst_oui and remove the
1499                                          * other uncst_oui
1500                                          */
1501                                         cnt = sec_ie[8];
1502                                         remove_cnt = (cnt - 1) * 4;
1503                                         sec_ie[8] = 0x01;
1504                                         memcpy(&sec_ie[10], &uncst_oui[0], 4);
1505                                         /*remove the other unicast suit*/
1506                                         memcpy(&sec_ie[14],
1507                                                 &sec_ie[14 + remove_cnt],
1508                                                 (sec_ie[1] - 14 + 2 -
1509                                                 remove_cnt));
1510                                         sec_ie[1] = sec_ie[1] - remove_cnt;
1511                                 }
1512                                 break;
1513                         }
1514                 }
1515         }
1516         if ((authmode == _WPA_IE_ID_) || (authmode == _WPA2_IE_ID_)) {
1517                 /*copy fixed ie*/
1518                 memcpy(out_ie, in_ie, 12);
1519                 ielength = 12;
1520                 /*copy RSN or SSN*/
1521                 if (match) {
1522                         memcpy(&out_ie[ielength], &sec_ie[0], sec_ie[1] + 2);
1523                         ielength += sec_ie[1] + 2;
1524                         if (authmode == _WPA2_IE_ID_) {
1525                                 /*the Pre-Authentication bit should be zero*/
1526                                 out_ie[ielength - 1] = 0;
1527                                 out_ie[ielength - 2] = 0;
1528                         }
1529                         r8712_report_sec_ie(adapter, authmode, sec_ie);
1530                 }
1531         } else {
1532                 /*copy fixed ie only*/
1533                 memcpy(out_ie, in_ie, 12);
1534                 ielength = 12;
1535                 if (psecuritypriv->wps_phase) {
1536                         memcpy(out_ie + ielength, psecuritypriv->wps_ie,
1537                                psecuritypriv->wps_ie_len);
1538                         ielength += psecuritypriv->wps_ie_len;
1539                 }
1540         }
1541         iEntry = SecIsInPMKIDList(adapter, pmlmepriv->assoc_bssid);
1542         if (iEntry < 0)
1543                 return ielength;
1544         if (authmode == _WPA2_IE_ID_) {
1545                 out_ie[ielength] = 1;
1546                 ielength++;
1547                 out_ie[ielength] = 0;   /*PMKID count = 0x0100*/
1548                 ielength++;
1549                 memcpy(&out_ie[ielength],
1550                         &psecuritypriv->PMKIDList[iEntry].PMKID, 16);
1551                 ielength += 16;
1552                 out_ie[13] += 18;/*PMKID length = 2+16*/
1553         }
1554         return ielength;
1555 }
1556
1557 void r8712_init_registrypriv_dev_network(struct _adapter *adapter)
1558 {
1559         struct registry_priv *pregistrypriv = &adapter->registrypriv;
1560         struct eeprom_priv *peepriv = &adapter->eeprompriv;
1561         struct wlan_bssid_ex *pdev_network = &pregistrypriv->dev_network;
1562         u8 *myhwaddr = myid(peepriv);
1563
1564         memcpy(pdev_network->MacAddress, myhwaddr, ETH_ALEN);
1565         memcpy(&pdev_network->Ssid, &pregistrypriv->ssid,
1566                 sizeof(struct ndis_802_11_ssid));
1567         pdev_network->Configuration.Length =
1568                          sizeof(struct NDIS_802_11_CONFIGURATION);
1569         pdev_network->Configuration.BeaconPeriod = 100;
1570         pdev_network->Configuration.FHConfig.Length = 0;
1571         pdev_network->Configuration.FHConfig.HopPattern = 0;
1572         pdev_network->Configuration.FHConfig.HopSet = 0;
1573         pdev_network->Configuration.FHConfig.DwellTime = 0;
1574 }
1575
1576 void r8712_update_registrypriv_dev_network(struct _adapter *adapter)
1577 {
1578         int sz = 0;
1579         struct registry_priv    *pregistrypriv = &adapter->registrypriv;
1580         struct wlan_bssid_ex    *pdev_network = &pregistrypriv->dev_network;
1581         struct security_priv    *psecuritypriv = &adapter->securitypriv;
1582         struct wlan_network     *cur_network = &adapter->mlmepriv.cur_network;
1583
1584         pdev_network->Privacy = cpu_to_le32(psecuritypriv->PrivacyAlgrthm
1585                                             > 0 ? 1 : 0); /* adhoc no 802.1x */
1586         pdev_network->Rssi = 0;
1587         switch (pregistrypriv->wireless_mode) {
1588         case WIRELESS_11B:
1589                 pdev_network->NetworkTypeInUse = Ndis802_11DS;
1590                 break;
1591         case WIRELESS_11G:
1592         case WIRELESS_11BG:
1593                 pdev_network->NetworkTypeInUse = Ndis802_11OFDM24;
1594                 break;
1595         case WIRELESS_11A:
1596                 pdev_network->NetworkTypeInUse = Ndis802_11OFDM5;
1597                 break;
1598         default:
1599                 /* TODO */
1600                 break;
1601         }
1602         pdev_network->Configuration.DSConfig = pregistrypriv->channel;
1603         if (cur_network->network.InfrastructureMode == Ndis802_11IBSS)
1604                 pdev_network->Configuration.ATIMWindow = 3;
1605         pdev_network->InfrastructureMode = cur_network->network.InfrastructureMode;
1606         /* 1. Supported rates
1607          * 2. IE
1608          */
1609         sz = r8712_generate_ie(pregistrypriv);
1610         pdev_network->IELength = sz;
1611         pdev_network->Length = r8712_get_wlan_bssid_ex_sz(pdev_network);
1612 }
1613
1614 /*the function is at passive_level*/
1615 void r8712_joinbss_reset(struct _adapter *padapter)
1616 {
1617         int i;
1618         struct mlme_priv        *pmlmepriv = &padapter->mlmepriv;
1619         struct ht_priv          *phtpriv = &pmlmepriv->htpriv;
1620
1621         /* todo: if you want to do something io/reg/hw setting before join_bss,
1622          * please add code here
1623          */
1624         phtpriv->ampdu_enable = false;/*reset to disabled*/
1625         for (i = 0; i < 16; i++)
1626                 phtpriv->baddbareq_issued[i] = false;/*reset it*/
1627         if (phtpriv->ht_option) {
1628                 /* validate  usb rx aggregation */
1629                 r8712_write8(padapter, 0x102500D9, 48);/*TH = 48 pages, 6k*/
1630         } else {
1631                 /* invalidate  usb rx aggregation */
1632                 /* TH=1 => means that invalidate usb rx aggregation */
1633                 r8712_write8(padapter, 0x102500D9, 1);
1634         }
1635 }
1636
1637 /*the function is >= passive_level*/
1638 unsigned int r8712_restructure_ht_ie(struct _adapter *padapter, u8 *in_ie,
1639                                      u8 *out_ie, uint in_len, uint *pout_len)
1640 {
1641         u32 ielen, out_len;
1642         unsigned char *p;
1643         struct ieee80211_ht_cap ht_capie;
1644         unsigned char WMM_IE[] = {0x00, 0x50, 0xf2, 0x02, 0x00, 0x01, 0x00};
1645         struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1646         struct qos_priv *pqospriv = &pmlmepriv->qospriv;
1647         struct ht_priv *phtpriv = &pmlmepriv->htpriv;
1648
1649         phtpriv->ht_option = 0;
1650         p = r8712_get_ie(in_ie + 12, WLAN_EID_HT_CAPABILITY, &ielen, in_len - 12);
1651         if (p && (ielen > 0)) {
1652                 if (pqospriv->qos_option == 0) {
1653                         out_len = *pout_len;
1654                         r8712_set_ie(out_ie + out_len, WLAN_EID_VENDOR_SPECIFIC,
1655                                      _WMM_IE_Length_, WMM_IE, pout_len);
1656                         pqospriv->qos_option = 1;
1657                 }
1658                 out_len = *pout_len;
1659                 memset(&ht_capie, 0, sizeof(struct ieee80211_ht_cap));
1660                 ht_capie.cap_info = cpu_to_le16(IEEE80211_HT_CAP_SUP_WIDTH_20_40 |
1661                                     IEEE80211_HT_CAP_SGI_20 |
1662                                     IEEE80211_HT_CAP_SGI_40 |
1663                                     IEEE80211_HT_CAP_TX_STBC |
1664                                     IEEE80211_HT_CAP_MAX_AMSDU |
1665                                     IEEE80211_HT_CAP_DSSSCCK40);
1666                 ht_capie.ampdu_params_info = (IEEE80211_HT_AMPDU_PARM_FACTOR &
1667                                 0x03) | (IEEE80211_HT_AMPDU_PARM_DENSITY & 0x00);
1668                 r8712_set_ie(out_ie + out_len, WLAN_EID_HT_CAPABILITY,
1669                              sizeof(struct ieee80211_ht_cap),
1670                              (unsigned char *)&ht_capie, pout_len);
1671                 phtpriv->ht_option = 1;
1672         }
1673         return phtpriv->ht_option;
1674 }
1675
1676 /* the function is > passive_level (in critical_section) */
1677 static void update_ht_cap(struct _adapter *padapter, u8 *pie, uint ie_len)
1678 {
1679         u8 *p, max_ampdu_sz;
1680         int i;
1681         uint len;
1682         struct sta_info *bmc_sta, *psta;
1683         struct ieee80211_ht_cap *pht_capie;
1684         struct recv_reorder_ctrl *preorder_ctrl;
1685         struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1686         struct ht_priv *phtpriv = &pmlmepriv->htpriv;
1687         struct registry_priv *pregistrypriv = &padapter->registrypriv;
1688         struct wlan_network *pcur_network = &(pmlmepriv->cur_network);
1689
1690         if (!phtpriv->ht_option)
1691                 return;
1692         /* maybe needs check if ap supports rx ampdu. */
1693         if (!phtpriv->ampdu_enable &&
1694             (pregistrypriv->ampdu_enable == 1))
1695                 phtpriv->ampdu_enable = true;
1696         /*check Max Rx A-MPDU Size*/
1697         len = 0;
1698         p = r8712_get_ie(pie + sizeof(struct NDIS_802_11_FIXED_IEs),
1699                                 WLAN_EID_HT_CAPABILITY,
1700                                 &len, ie_len -
1701                                 sizeof(struct NDIS_802_11_FIXED_IEs));
1702         if (p && len > 0) {
1703                 pht_capie = (struct ieee80211_ht_cap *)(p + 2);
1704                 max_ampdu_sz = (pht_capie->ampdu_params_info &
1705                                 IEEE80211_HT_AMPDU_PARM_FACTOR);
1706                 /* max_ampdu_sz (kbytes); */
1707                 max_ampdu_sz = 1 << (max_ampdu_sz + 3);
1708                 phtpriv->rx_ampdu_maxlen = max_ampdu_sz;
1709         }
1710         /* for A-MPDU Rx reordering buffer control for bmc_sta & sta_info
1711          * if A-MPDU Rx is enabled, resetting rx_ordering_ctrl
1712          * wstart_b(indicate_seq) to default value=0xffff
1713          * todo: check if AP can send A-MPDU packets
1714          */
1715         bmc_sta = r8712_get_bcmc_stainfo(padapter);
1716         if (bmc_sta) {
1717                 for (i = 0; i < 16; i++) {
1718                         preorder_ctrl = &bmc_sta->recvreorder_ctrl[i];
1719                         preorder_ctrl->indicate_seq = 0xffff;
1720                         preorder_ctrl->wend_b = 0xffff;
1721                 }
1722         }
1723         psta = r8712_get_stainfo(&padapter->stapriv,
1724                                  pcur_network->network.MacAddress);
1725         if (psta) {
1726                 for (i = 0; i < 16; i++) {
1727                         preorder_ctrl = &psta->recvreorder_ctrl[i];
1728                         preorder_ctrl->indicate_seq = 0xffff;
1729                         preorder_ctrl->wend_b = 0xffff;
1730                 }
1731         }
1732         len = 0;
1733         p = r8712_get_ie(pie + sizeof(struct NDIS_802_11_FIXED_IEs),
1734                    WLAN_EID_HT_OPERATION, &len,
1735                    ie_len - sizeof(struct NDIS_802_11_FIXED_IEs));
1736 }
1737
1738 void r8712_issue_addbareq_cmd(struct _adapter *padapter, int priority)
1739 {
1740         struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1741         struct ht_priv   *phtpriv = &pmlmepriv->htpriv;
1742
1743         if ((phtpriv->ht_option == 1) && (phtpriv->ampdu_enable)) {
1744                 if (!phtpriv->baddbareq_issued[priority]) {
1745                         r8712_addbareq_cmd(padapter, (u8)priority);
1746                         phtpriv->baddbareq_issued[priority] = true;
1747                 }
1748         }
1749 }