GNU Linux-libre 5.19-rc6-gnu
[releases.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.InfrastructureMode)
435                         bselected = false;
436         }
437         return bselected;
438 }
439
440 /* TODO: Perry : For Power Management */
441 void r8712_atimdone_event_callback(struct _adapter *adapter, u8 *pbuf)
442 {
443 }
444
445 void r8712_survey_event_callback(struct _adapter *adapter, u8 *pbuf)
446 {
447         unsigned long flags;
448         u32 len;
449         struct wlan_bssid_ex *pnetwork;
450         struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
451
452         pnetwork = (struct wlan_bssid_ex *)pbuf;
453 #ifdef __BIG_ENDIAN
454         /* endian_convert */
455         pnetwork->Length = le32_to_cpu(pnetwork->Length);
456         pnetwork->Ssid.SsidLength = le32_to_cpu(pnetwork->Ssid.SsidLength);
457         pnetwork->Privacy = le32_to_cpu(pnetwork->Privacy);
458         pnetwork->Rssi = le32_to_cpu(pnetwork->Rssi);
459         pnetwork->NetworkTypeInUse = le32_to_cpu(pnetwork->NetworkTypeInUse);
460         pnetwork->Configuration.ATIMWindow =
461                  le32_to_cpu(pnetwork->Configuration.ATIMWindow);
462         pnetwork->Configuration.BeaconPeriod =
463                  le32_to_cpu(pnetwork->Configuration.BeaconPeriod);
464         pnetwork->Configuration.DSConfig =
465                  le32_to_cpu(pnetwork->Configuration.DSConfig);
466         pnetwork->Configuration.FHConfig.DwellTime =
467                  le32_to_cpu(pnetwork->Configuration.FHConfig.DwellTime);
468         pnetwork->Configuration.FHConfig.HopPattern =
469                  le32_to_cpu(pnetwork->Configuration.FHConfig.HopPattern);
470         pnetwork->Configuration.FHConfig.HopSet =
471                  le32_to_cpu(pnetwork->Configuration.FHConfig.HopSet);
472         pnetwork->Configuration.FHConfig.Length =
473                  le32_to_cpu(pnetwork->Configuration.FHConfig.Length);
474         pnetwork->Configuration.Length =
475                  le32_to_cpu(pnetwork->Configuration.Length);
476         pnetwork->InfrastructureMode =
477                  le32_to_cpu(pnetwork->InfrastructureMode);
478         pnetwork->IELength = le32_to_cpu(pnetwork->IELength);
479 #endif
480         len = r8712_get_wlan_bssid_ex_sz(pnetwork);
481         if (len > sizeof(struct wlan_bssid_ex))
482                 return;
483         spin_lock_irqsave(&pmlmepriv->lock2, flags);
484         /* update IBSS_network 's timestamp */
485         if (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE)) {
486                 if (!memcmp(&(pmlmepriv->cur_network.network.MacAddress),
487                     pnetwork->MacAddress, ETH_ALEN)) {
488                         struct wlan_network *ibss_wlan = NULL;
489
490                         memcpy(pmlmepriv->cur_network.network.IEs,
491                                 pnetwork->IEs, 8);
492                         ibss_wlan = r8712_find_network(
493                                                 &pmlmepriv->scanned_queue,
494                                                 pnetwork->MacAddress);
495                         if (ibss_wlan) {
496                                 memcpy(ibss_wlan->network.IEs,
497                                         pnetwork->IEs, 8);
498                                 goto exit;
499                         }
500                 }
501         }
502         /* lock pmlmepriv->lock when you accessing network_q */
503         if (!check_fwstate(pmlmepriv, _FW_UNDER_LINKING)) {
504                 if (pnetwork->Ssid.Ssid[0] != 0) {
505                         rtl8711_add_network(adapter, pnetwork);
506                 } else {
507                         pnetwork->Ssid.SsidLength = 8;
508                         memcpy(pnetwork->Ssid.Ssid, "<hidden>", 8);
509                         rtl8711_add_network(adapter, pnetwork);
510                 }
511         }
512 exit:
513         spin_unlock_irqrestore(&pmlmepriv->lock2, flags);
514 }
515
516 void r8712_surveydone_event_callback(struct _adapter *adapter, u8 *pbuf)
517 {
518         unsigned long irqL;
519         struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
520
521         spin_lock_irqsave(&pmlmepriv->lock, irqL);
522
523         if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY)) {
524                 del_timer(&pmlmepriv->scan_to_timer);
525
526                 _clr_fwstate_(pmlmepriv, _FW_UNDER_SURVEY);
527         }
528
529         if (pmlmepriv->to_join) {
530                 if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE)) {
531                         if (!check_fwstate(pmlmepriv, _FW_LINKED)) {
532                                 set_fwstate(pmlmepriv, _FW_UNDER_LINKING);
533
534                                 if (!r8712_select_and_join_from_scan(pmlmepriv)) {
535                                         mod_timer(&pmlmepriv->assoc_timer, jiffies +
536                                                   msecs_to_jiffies(MAX_JOIN_TIMEOUT));
537                                 } else {
538                                         struct wlan_bssid_ex *pdev_network =
539                                           &(adapter->registrypriv.dev_network);
540                                         u8 *pibss =
541                                                  adapter->registrypriv.dev_network.MacAddress;
542                                         pmlmepriv->fw_state ^= _FW_UNDER_SURVEY;
543                                         memcpy(&pdev_network->Ssid,
544                                                 &pmlmepriv->assoc_ssid,
545                                                 sizeof(struct
546                                                          ndis_802_11_ssid));
547                                         r8712_update_registrypriv_dev_network
548                                                 (adapter);
549                                         r8712_generate_random_ibss(pibss);
550                                         pmlmepriv->fw_state =
551                                                  WIFI_ADHOC_MASTER_STATE;
552                                         pmlmepriv->to_join = false;
553                                 }
554                         }
555                 } else {
556                         pmlmepriv->to_join = false;
557                         set_fwstate(pmlmepriv, _FW_UNDER_LINKING);
558                         if (!r8712_select_and_join_from_scan(pmlmepriv))
559                                 mod_timer(&pmlmepriv->assoc_timer, jiffies +
560                                           msecs_to_jiffies(MAX_JOIN_TIMEOUT));
561                         else
562                                 _clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING);
563                 }
564         }
565         spin_unlock_irqrestore(&pmlmepriv->lock, irqL);
566 }
567
568 /*
569  *r8712_free_assoc_resources: the caller has to lock pmlmepriv->lock
570  */
571 void r8712_free_assoc_resources(struct _adapter *adapter)
572 {
573         unsigned long irqL;
574         struct wlan_network *pwlan = NULL;
575         struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
576         struct sta_priv *pstapriv = &adapter->stapriv;
577         struct wlan_network *tgt_network = &pmlmepriv->cur_network;
578
579         pwlan = r8712_find_network(&pmlmepriv->scanned_queue,
580                                    tgt_network->network.MacAddress);
581
582         if (check_fwstate(pmlmepriv, WIFI_STATION_STATE | WIFI_AP_STATE)) {
583                 struct sta_info *psta;
584
585                 psta = r8712_get_stainfo(&adapter->stapriv,
586                                          tgt_network->network.MacAddress);
587
588                 spin_lock_irqsave(&pstapriv->sta_hash_lock, irqL);
589                 r8712_free_stainfo(adapter,  psta);
590                 spin_unlock_irqrestore(&pstapriv->sta_hash_lock, irqL);
591         }
592
593         if (check_fwstate(pmlmepriv,
594             WIFI_ADHOC_STATE | WIFI_ADHOC_MASTER_STATE | WIFI_AP_STATE))
595                 r8712_free_all_stainfo(adapter);
596         if (pwlan)
597                 pwlan->fixed = false;
598
599         if (((check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE)) &&
600              (adapter->stapriv.asoc_sta_count == 1)))
601                 free_network_nolock(pmlmepriv, pwlan);
602 }
603
604 /*
605  * r8712_indicate_connect: the caller has to lock pmlmepriv->lock
606  */
607 void r8712_indicate_connect(struct _adapter *padapter)
608 {
609         struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
610
611         pmlmepriv->to_join = false;
612         set_fwstate(pmlmepriv, _FW_LINKED);
613         padapter->ledpriv.LedControlHandler(padapter, LED_CTL_LINK);
614         r8712_os_indicate_connect(padapter);
615         if (padapter->registrypriv.power_mgnt > PS_MODE_ACTIVE)
616                 mod_timer(&pmlmepriv->dhcp_timer,
617                           jiffies + msecs_to_jiffies(60000));
618 }
619
620 /*
621  * r8712_ind_disconnect: the caller has to lock pmlmepriv->lock
622  */
623 void r8712_ind_disconnect(struct _adapter *padapter)
624 {
625         struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
626
627         if (check_fwstate(pmlmepriv, _FW_LINKED)) {
628                 _clr_fwstate_(pmlmepriv, _FW_LINKED);
629                 padapter->ledpriv.LedControlHandler(padapter, LED_CTL_NO_LINK);
630                 r8712_os_indicate_disconnect(padapter);
631         }
632         if (padapter->pwrctrlpriv.pwr_mode !=
633             padapter->registrypriv.power_mgnt) {
634                 del_timer(&pmlmepriv->dhcp_timer);
635                 r8712_set_ps_mode(padapter, padapter->registrypriv.power_mgnt,
636                                   padapter->registrypriv.smart_ps);
637         }
638 }
639
640 /*Notes:
641  *pnetwork : returns from r8712_joinbss_event_callback
642  *ptarget_wlan: found from scanned_queue
643  *if join_res > 0, for (fw_state==WIFI_STATION_STATE), we check if
644  *  "ptarget_sta" & "ptarget_wlan" exist.
645  *if join_res > 0, for (fw_state==WIFI_ADHOC_STATE), we only check
646  * if "ptarget_wlan" exist.
647  *if join_res > 0, update "cur_network->network" from
648  * "pnetwork->network" if (ptarget_wlan !=NULL).
649  */
650 void r8712_joinbss_event_callback(struct _adapter *adapter, u8 *pbuf)
651 {
652         unsigned long irqL = 0, irqL2;
653         struct sta_info *ptarget_sta = NULL, *pcur_sta = NULL;
654         struct sta_priv *pstapriv = &adapter->stapriv;
655         struct mlme_priv        *pmlmepriv = &adapter->mlmepriv;
656         struct wlan_network     *cur_network = &pmlmepriv->cur_network;
657         struct wlan_network     *pcur_wlan = NULL, *ptarget_wlan = NULL;
658         unsigned int            the_same_macaddr = false;
659         struct wlan_network *pnetwork;
660
661         if (sizeof(struct list_head) == 4 * sizeof(u32)) {
662                 pnetwork = kmalloc(sizeof(struct wlan_network), GFP_ATOMIC);
663                 if (!pnetwork)
664                         return;
665                 memcpy((u8 *)pnetwork + 16, (u8 *)pbuf + 8,
666                        sizeof(struct wlan_network) - 16);
667         } else {
668                 pnetwork = (struct wlan_network *)pbuf;
669         }
670
671 #ifdef __BIG_ENDIAN
672         /* endian_convert */
673         pnetwork->join_res = le32_to_cpu(pnetwork->join_res);
674         pnetwork->network_type = le32_to_cpu(pnetwork->network_type);
675         pnetwork->network.Length = le32_to_cpu(pnetwork->network.Length);
676         pnetwork->network.Ssid.SsidLength =
677                  le32_to_cpu(pnetwork->network.Ssid.SsidLength);
678         pnetwork->network.Privacy = le32_to_cpu(pnetwork->network.Privacy);
679         pnetwork->network.Rssi = le32_to_cpu(pnetwork->network.Rssi);
680         pnetwork->network.NetworkTypeInUse =
681                  le32_to_cpu(pnetwork->network.NetworkTypeInUse);
682         pnetwork->network.Configuration.ATIMWindow =
683                  le32_to_cpu(pnetwork->network.Configuration.ATIMWindow);
684         pnetwork->network.Configuration.BeaconPeriod =
685                  le32_to_cpu(pnetwork->network.Configuration.BeaconPeriod);
686         pnetwork->network.Configuration.DSConfig =
687                  le32_to_cpu(pnetwork->network.Configuration.DSConfig);
688         pnetwork->network.Configuration.FHConfig.DwellTime =
689                  le32_to_cpu(pnetwork->network.Configuration.FHConfig.DwellTime);
690         pnetwork->network.Configuration.FHConfig.HopPattern =
691                  le32_to_cpu(pnetwork->network.Configuration.FHConfig.HopPattern);
692         pnetwork->network.Configuration.FHConfig.HopSet =
693                  le32_to_cpu(pnetwork->network.Configuration.FHConfig.HopSet);
694         pnetwork->network.Configuration.FHConfig.Length =
695                  le32_to_cpu(pnetwork->network.Configuration.FHConfig.Length);
696         pnetwork->network.Configuration.Length =
697                  le32_to_cpu(pnetwork->network.Configuration.Length);
698         pnetwork->network.InfrastructureMode =
699                  le32_to_cpu(pnetwork->network.InfrastructureMode);
700         pnetwork->network.IELength = le32_to_cpu(pnetwork->network.IELength);
701 #endif
702
703         the_same_macaddr = !memcmp(pnetwork->network.MacAddress,
704                                    cur_network->network.MacAddress, ETH_ALEN);
705         pnetwork->network.Length =
706                  r8712_get_wlan_bssid_ex_sz(&pnetwork->network);
707         spin_lock_irqsave(&pmlmepriv->lock, irqL);
708         if (pnetwork->network.Length > sizeof(struct wlan_bssid_ex))
709                 goto ignore_joinbss_callback;
710         if (pnetwork->join_res > 0) {
711                 if (check_fwstate(pmlmepriv, _FW_UNDER_LINKING)) {
712                         /*s1. find ptarget_wlan*/
713                         if (check_fwstate(pmlmepriv, _FW_LINKED)) {
714                                 if (the_same_macaddr) {
715                                         ptarget_wlan =
716                                             r8712_find_network(&pmlmepriv->scanned_queue,
717                                             cur_network->network.MacAddress);
718                                 } else {
719                                         pcur_wlan =
720                                              r8712_find_network(&pmlmepriv->scanned_queue,
721                                              cur_network->network.MacAddress);
722                                         if (pcur_wlan)
723                                                 pcur_wlan->fixed = false;
724
725                                         pcur_sta = r8712_get_stainfo(pstapriv,
726                                              cur_network->network.MacAddress);
727                                         spin_lock_irqsave(&pstapriv->sta_hash_lock, irqL2);
728                                         r8712_free_stainfo(adapter, pcur_sta);
729                                         spin_unlock_irqrestore(&(pstapriv->sta_hash_lock), irqL2);
730
731                                         ptarget_wlan =
732                                                  r8712_find_network(&pmlmepriv->scanned_queue,
733                                                  pnetwork->network.MacAddress);
734                                         if (ptarget_wlan)
735                                                 ptarget_wlan->fixed = true;
736                                 }
737                         } else {
738                                 ptarget_wlan = r8712_find_network(&pmlmepriv->scanned_queue,
739                                                 pnetwork->network.MacAddress);
740                                 if (ptarget_wlan)
741                                         ptarget_wlan->fixed = true;
742                         }
743
744                         if (!ptarget_wlan) {
745                                 if (check_fwstate(pmlmepriv,
746                                         _FW_UNDER_LINKING))
747                                         pmlmepriv->fw_state ^=
748                                                  _FW_UNDER_LINKING;
749                                 goto ignore_joinbss_callback;
750                         }
751
752                         /*s2. find ptarget_sta & update ptarget_sta*/
753                         if (check_fwstate(pmlmepriv, WIFI_STATION_STATE)) {
754                                 if (the_same_macaddr) {
755                                         ptarget_sta =
756                                                  r8712_get_stainfo(pstapriv,
757                                                  pnetwork->network.MacAddress);
758                                         if (!ptarget_sta)
759                                                 ptarget_sta =
760                                                  r8712_alloc_stainfo(pstapriv,
761                                                  pnetwork->network.MacAddress);
762                                 } else {
763                                         ptarget_sta =
764                                                  r8712_alloc_stainfo(pstapriv,
765                                                  pnetwork->network.MacAddress);
766                                 }
767                                 if (ptarget_sta) /*update ptarget_sta*/ {
768                                         ptarget_sta->aid = pnetwork->join_res;
769                                         ptarget_sta->qos_option = 1;
770                                         ptarget_sta->mac_id = 5;
771                                         if (adapter->securitypriv.AuthAlgrthm == 2) {
772                                                 adapter->securitypriv.binstallGrpkey = false;
773                                                 adapter->securitypriv.busetkipkey = false;
774                                                 adapter->securitypriv.bgrpkey_handshake = false;
775                                                 ptarget_sta->ieee8021x_blocked = true;
776                                                 ptarget_sta->XPrivacy = adapter->
777                                                 securitypriv.PrivacyAlgrthm;
778                                                 memset((u8 *)&ptarget_sta->x_UncstKey,
779                                                          0,
780                                                          sizeof(union Keytype));
781                                                 memset((u8 *)&ptarget_sta->tkiprxmickey,
782                                                          0,
783                                                          sizeof(union Keytype));
784                                                 memset((u8 *)&ptarget_sta->tkiptxmickey,
785                                                          0,
786                                                          sizeof(union Keytype));
787                                                 memset((u8 *)&ptarget_sta->txpn, 0,
788                                                          sizeof(union pn48));
789                                                 memset((u8 *)&ptarget_sta->rxpn, 0,
790                                                          sizeof(union pn48));
791                                         }
792                                 } else {
793                                         if (check_fwstate(pmlmepriv,
794                                             _FW_UNDER_LINKING))
795                                                 pmlmepriv->fw_state ^=
796                                                          _FW_UNDER_LINKING;
797                                         goto ignore_joinbss_callback;
798                                 }
799                         }
800
801                         /*s3. update cur_network & indicate connect*/
802                         memcpy(&cur_network->network, &pnetwork->network,
803                                 pnetwork->network.Length);
804                         cur_network->aid = pnetwork->join_res;
805                         /*update fw_state will clr _FW_UNDER_LINKING*/
806                         switch (pnetwork->network.InfrastructureMode) {
807                         case Ndis802_11Infrastructure:
808                                 pmlmepriv->fw_state = WIFI_STATION_STATE;
809                                 break;
810                         case Ndis802_11IBSS:
811                                 pmlmepriv->fw_state = WIFI_ADHOC_STATE;
812                                 break;
813                         default:
814                                 pmlmepriv->fw_state = WIFI_NULL_STATE;
815                                 break;
816                         }
817                         r8712_update_protection(adapter,
818                                           (cur_network->network.IEs) +
819                                           sizeof(struct NDIS_802_11_FIXED_IEs),
820                                           (cur_network->network.IELength));
821                         /*TODO: update HT_Capability*/
822                         update_ht_cap(adapter, cur_network->network.IEs,
823                                       cur_network->network.IELength);
824                         /*indicate connect*/
825                         if (check_fwstate(pmlmepriv, WIFI_STATION_STATE))
826                                 r8712_indicate_connect(adapter);
827                         del_timer(&pmlmepriv->assoc_timer);
828                 } else {
829                         goto ignore_joinbss_callback;
830                 }
831         } else {
832                 if (check_fwstate(pmlmepriv, _FW_UNDER_LINKING)) {
833                         mod_timer(&pmlmepriv->assoc_timer,
834                                   jiffies + msecs_to_jiffies(1));
835                         _clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING);
836                 }
837         }
838 ignore_joinbss_callback:
839         spin_unlock_irqrestore(&pmlmepriv->lock, irqL);
840         if (sizeof(struct list_head) == 4 * sizeof(u32))
841                 kfree(pnetwork);
842 }
843
844 void r8712_stassoc_event_callback(struct _adapter *adapter, u8 *pbuf)
845 {
846         unsigned long irqL;
847         struct sta_info *psta;
848         struct mlme_priv *pmlmepriv = &(adapter->mlmepriv);
849         struct stassoc_event *pstassoc  = (struct stassoc_event *)pbuf;
850
851         /* to do: */
852         if (!r8712_access_ctrl(&adapter->acl_list, pstassoc->macaddr))
853                 return;
854         psta = r8712_get_stainfo(&adapter->stapriv, pstassoc->macaddr);
855         if (psta) {
856                 /*the sta have been in sta_info_queue => do nothing
857                  *(between drv has received this event before and
858                  * fw have not yet to set key to CAM_ENTRY)
859                  */
860                 return;
861         }
862
863         psta = r8712_alloc_stainfo(&adapter->stapriv, pstassoc->macaddr);
864         if (!psta)
865                 return;
866         /* to do : init sta_info variable */
867         psta->qos_option = 0;
868         psta->mac_id = le32_to_cpu(pstassoc->cam_id);
869         /* psta->aid = (uint)pstassoc->cam_id; */
870
871         if (adapter->securitypriv.AuthAlgrthm == 2)
872                 psta->XPrivacy = adapter->securitypriv.PrivacyAlgrthm;
873         psta->ieee8021x_blocked = false;
874         spin_lock_irqsave(&pmlmepriv->lock, irqL);
875         if (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) ||
876             check_fwstate(pmlmepriv, WIFI_ADHOC_STATE)) {
877                 if (adapter->stapriv.asoc_sta_count == 2) {
878                         /* a sta + bc/mc_stainfo (not Ibss_stainfo) */
879                         r8712_indicate_connect(adapter);
880                 }
881         }
882         spin_unlock_irqrestore(&pmlmepriv->lock, irqL);
883 }
884
885 void r8712_stadel_event_callback(struct _adapter *adapter, u8 *pbuf)
886 {
887         unsigned long irqL, irqL2;
888         struct sta_info *psta;
889         struct wlan_network *pwlan = NULL;
890         struct wlan_bssid_ex *pdev_network = NULL;
891         u8 *pibss = NULL;
892         struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
893         struct stadel_event *pstadel = (struct stadel_event *)pbuf;
894         struct sta_priv *pstapriv = &adapter->stapriv;
895         struct wlan_network *tgt_network = &pmlmepriv->cur_network;
896
897         spin_lock_irqsave(&pmlmepriv->lock, irqL2);
898         if (check_fwstate(pmlmepriv, WIFI_STATION_STATE)) {
899                 r8712_ind_disconnect(adapter);
900                 r8712_free_assoc_resources(adapter);
901         }
902         if (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE |
903             WIFI_ADHOC_STATE)) {
904                 psta = r8712_get_stainfo(&adapter->stapriv, pstadel->macaddr);
905                 spin_lock_irqsave(&pstapriv->sta_hash_lock, irqL);
906                 r8712_free_stainfo(adapter, psta);
907                 spin_unlock_irqrestore(&pstapriv->sta_hash_lock, irqL);
908                 if (adapter->stapriv.asoc_sta_count == 1) {
909                         /*a sta + bc/mc_stainfo (not Ibss_stainfo) */
910                         pwlan = r8712_find_network(&pmlmepriv->scanned_queue,
911                                 tgt_network->network.MacAddress);
912                         if (pwlan) {
913                                 pwlan->fixed = false;
914                                 free_network_nolock(pmlmepriv, pwlan);
915                         }
916                         /*re-create ibss*/
917                         pdev_network = &(adapter->registrypriv.dev_network);
918                         pibss = adapter->registrypriv.dev_network.MacAddress;
919                         memcpy(pdev_network, &tgt_network->network,
920                                 r8712_get_wlan_bssid_ex_sz(&tgt_network->network));
921                         memcpy(&pdev_network->Ssid,
922                                 &pmlmepriv->assoc_ssid,
923                                 sizeof(struct ndis_802_11_ssid));
924                         r8712_update_registrypriv_dev_network(adapter);
925                         r8712_generate_random_ibss(pibss);
926                         if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE)) {
927                                 _clr_fwstate_(pmlmepriv, WIFI_ADHOC_STATE);
928                                 set_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE);
929                         }
930                 }
931         }
932         spin_unlock_irqrestore(&pmlmepriv->lock, irqL2);
933 }
934
935 void r8712_cpwm_event_callback(struct _adapter *adapter, u8 *pbuf)
936 {
937         struct reportpwrstate_parm *preportpwrstate =
938                          (struct reportpwrstate_parm *)pbuf;
939
940         preportpwrstate->state |= (u8)(adapter->pwrctrlpriv.cpwm_tog + 0x80);
941         r8712_cpwm_int_hdl(adapter, preportpwrstate);
942 }
943
944 /*      When the Netgear 3500 AP is with WPA2PSK-AES mode, it will send
945  *       the ADDBA req frame with start seq control = 0 to wifi client after
946  *       the WPA handshake and the seqence number of following data packet
947  *      will be 0. In this case, the Rx reorder sequence is not longer than 0
948  *       and the WiFi client will drop the data with seq number 0.
949  *      So, the 8712 firmware has to inform driver with receiving the
950  *       ADDBA-Req frame so that the driver can reset the
951  *      sequence value of Rx reorder control.
952  */
953 void r8712_got_addbareq_event_callback(struct _adapter *adapter, u8 *pbuf)
954 {
955         struct  ADDBA_Req_Report_parm *pAddbareq_pram =
956                          (struct ADDBA_Req_Report_parm *)pbuf;
957         struct  sta_info *psta;
958         struct  sta_priv *pstapriv = &adapter->stapriv;
959         struct  recv_reorder_ctrl *precvreorder_ctrl = NULL;
960
961         psta = r8712_get_stainfo(pstapriv, pAddbareq_pram->MacAddress);
962         if (psta) {
963                 precvreorder_ctrl =
964                          &psta->recvreorder_ctrl[pAddbareq_pram->tid];
965                 /* set the indicate_seq to 0xffff so that the rx reorder
966                  * can store any following data packet.
967                  */
968                 precvreorder_ctrl->indicate_seq = 0xffff;
969         }
970 }
971
972 void r8712_wpspbc_event_callback(struct _adapter *adapter, u8 *pbuf)
973 {
974         if (!adapter->securitypriv.wps_hw_pbc_pressed)
975                 adapter->securitypriv.wps_hw_pbc_pressed = true;
976 }
977
978 void _r8712_sitesurvey_ctrl_handler(struct _adapter *adapter)
979 {
980         struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
981         struct sitesurvey_ctrl  *psitesurveyctrl = &pmlmepriv->sitesurveyctrl;
982         struct registry_priv    *pregistrypriv = &adapter->registrypriv;
983         u64 current_tx_pkts;
984         uint current_rx_pkts;
985
986         current_tx_pkts = (adapter->xmitpriv.tx_pkts) -
987                           (psitesurveyctrl->last_tx_pkts);
988         current_rx_pkts = (adapter->recvpriv.rx_pkts) -
989                           (psitesurveyctrl->last_rx_pkts);
990         psitesurveyctrl->last_tx_pkts = adapter->xmitpriv.tx_pkts;
991         psitesurveyctrl->last_rx_pkts = adapter->recvpriv.rx_pkts;
992         if ((current_tx_pkts > pregistrypriv->busy_thresh) ||
993             (current_rx_pkts > pregistrypriv->busy_thresh))
994                 psitesurveyctrl->traffic_busy = true;
995         else
996                 psitesurveyctrl->traffic_busy = false;
997 }
998
999 void _r8712_join_timeout_handler(struct _adapter *adapter)
1000 {
1001         unsigned long irqL;
1002         struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
1003
1004         if (adapter->driver_stopped || adapter->surprise_removed)
1005                 return;
1006         spin_lock_irqsave(&pmlmepriv->lock, irqL);
1007         _clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING);
1008         pmlmepriv->to_join = false;
1009         if (check_fwstate(pmlmepriv, _FW_LINKED)) {
1010                 r8712_os_indicate_disconnect(adapter);
1011                 _clr_fwstate_(pmlmepriv, _FW_LINKED);
1012         }
1013         if (adapter->pwrctrlpriv.pwr_mode != adapter->registrypriv.power_mgnt) {
1014                 r8712_set_ps_mode(adapter, adapter->registrypriv.power_mgnt,
1015                                   adapter->registrypriv.smart_ps);
1016         }
1017         spin_unlock_irqrestore(&pmlmepriv->lock, irqL);
1018 }
1019
1020 void r8712_scan_timeout_handler (struct _adapter *adapter)
1021 {
1022         unsigned long irqL;
1023         struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
1024
1025         spin_lock_irqsave(&pmlmepriv->lock, irqL);
1026         _clr_fwstate_(pmlmepriv, _FW_UNDER_SURVEY);
1027         pmlmepriv->to_join = false;     /* scan fail, so clear to_join flag */
1028         spin_unlock_irqrestore(&pmlmepriv->lock, irqL);
1029 }
1030
1031 void _r8712_dhcp_timeout_handler (struct _adapter *adapter)
1032 {
1033         if (adapter->driver_stopped || adapter->surprise_removed)
1034                 return;
1035         if (adapter->pwrctrlpriv.pwr_mode != adapter->registrypriv.power_mgnt)
1036                 r8712_set_ps_mode(adapter, adapter->registrypriv.power_mgnt,
1037                             adapter->registrypriv.smart_ps);
1038 }
1039
1040 int r8712_select_and_join_from_scan(struct mlme_priv *pmlmepriv)
1041 {
1042         struct list_head *phead;
1043         unsigned char *dst_ssid, *src_ssid;
1044         struct _adapter *adapter;
1045         struct  __queue *queue = NULL;
1046         struct wlan_network *pnetwork = NULL;
1047         struct wlan_network *pnetwork_max_rssi = NULL;
1048
1049         adapter = (struct _adapter *)pmlmepriv->nic_hdl;
1050         queue = &pmlmepriv->scanned_queue;
1051         phead = &queue->queue;
1052         pmlmepriv->pscanned = phead->next;
1053         while (1) {
1054                 if (end_of_queue_search(phead, pmlmepriv->pscanned)) {
1055                         if (pmlmepriv->assoc_by_rssi && pnetwork_max_rssi) {
1056                                 pnetwork = pnetwork_max_rssi;
1057                                 goto ask_for_joinbss;
1058                         }
1059                         return -EINVAL;
1060                 }
1061                 pnetwork = container_of(pmlmepriv->pscanned,
1062                                         struct wlan_network, list);
1063                 pmlmepriv->pscanned = pmlmepriv->pscanned->next;
1064                 if (pmlmepriv->assoc_by_bssid) {
1065                         dst_ssid = pnetwork->network.MacAddress;
1066                         src_ssid = pmlmepriv->assoc_bssid;
1067                         if (!memcmp(dst_ssid, src_ssid, ETH_ALEN)) {
1068                                 if (check_fwstate(pmlmepriv, _FW_LINKED)) {
1069                                         if (is_same_network(&pmlmepriv->cur_network.network,
1070                                             &pnetwork->network)) {
1071                                                 _clr_fwstate_(pmlmepriv,
1072                                                         _FW_UNDER_LINKING);
1073                                                 /*r8712_indicate_connect again*/
1074                                                 r8712_indicate_connect(adapter);
1075                                                 return 2;
1076                                         }
1077                                         r8712_disassoc_cmd(adapter);
1078                                         r8712_ind_disconnect(adapter);
1079                                         r8712_free_assoc_resources(adapter);
1080                                 }
1081                                 goto ask_for_joinbss;
1082                         }
1083                 } else if (pmlmepriv->assoc_ssid.SsidLength == 0) {
1084                         goto ask_for_joinbss;
1085                 }
1086                 dst_ssid = pnetwork->network.Ssid.Ssid;
1087                 src_ssid = pmlmepriv->assoc_ssid.Ssid;
1088                 if ((pnetwork->network.Ssid.SsidLength ==
1089                     pmlmepriv->assoc_ssid.SsidLength) &&
1090                     (!memcmp(dst_ssid, src_ssid,
1091                      pmlmepriv->assoc_ssid.SsidLength))) {
1092                         if (pmlmepriv->assoc_by_rssi) {
1093                                 /* if the ssid is the same, select the bss
1094                                  * which has the max rssi
1095                                  */
1096                                 if (pnetwork_max_rssi) {
1097                                         if (pnetwork->network.Rssi >
1098                                             pnetwork_max_rssi->network.Rssi)
1099                                                 pnetwork_max_rssi = pnetwork;
1100                                 } else {
1101                                         pnetwork_max_rssi = pnetwork;
1102                                 }
1103                         } else if (is_desired_network(adapter, pnetwork)) {
1104                                 if (check_fwstate(pmlmepriv, _FW_LINKED)) {
1105                                         r8712_disassoc_cmd(adapter);
1106                                         r8712_free_assoc_resources(adapter);
1107                                 }
1108                                 goto ask_for_joinbss;
1109                         }
1110                 }
1111         }
1112
1113 ask_for_joinbss:
1114         return r8712_joinbss_cmd(adapter, pnetwork);
1115 }
1116
1117 int r8712_set_auth(struct _adapter *adapter,
1118                    struct security_priv *psecuritypriv)
1119 {
1120         struct cmd_priv *pcmdpriv = &adapter->cmdpriv;
1121         struct cmd_obj *pcmd;
1122         struct setauth_parm *psetauthparm;
1123
1124         pcmd = kmalloc(sizeof(*pcmd), GFP_ATOMIC);
1125         if (!pcmd)
1126                 return -ENOMEM;
1127
1128         psetauthparm = kzalloc(sizeof(*psetauthparm), GFP_ATOMIC);
1129         if (!psetauthparm) {
1130                 kfree(pcmd);
1131                 return -ENOMEM;
1132         }
1133         psetauthparm->mode = (u8)psecuritypriv->AuthAlgrthm;
1134         pcmd->cmdcode = _SetAuth_CMD_;
1135         pcmd->parmbuf = (unsigned char *)psetauthparm;
1136         pcmd->cmdsz = sizeof(struct setauth_parm);
1137         pcmd->rsp = NULL;
1138         pcmd->rspsz = 0;
1139         INIT_LIST_HEAD(&pcmd->list);
1140         r8712_enqueue_cmd(pcmdpriv, pcmd);
1141         return 0;
1142 }
1143
1144 int r8712_set_key(struct _adapter *adapter,
1145                   struct security_priv *psecuritypriv,
1146                   sint keyid)
1147 {
1148         struct cmd_priv *pcmdpriv = &adapter->cmdpriv;
1149         struct cmd_obj *pcmd;
1150         struct setkey_parm *psetkeyparm;
1151         u8 keylen;
1152         int ret;
1153
1154         pcmd = kmalloc(sizeof(*pcmd), GFP_ATOMIC);
1155         if (!pcmd)
1156                 return -ENOMEM;
1157         psetkeyparm = kzalloc(sizeof(*psetkeyparm), GFP_ATOMIC);
1158         if (!psetkeyparm) {
1159                 ret = -ENOMEM;
1160                 goto err_free_cmd;
1161         }
1162         if (psecuritypriv->AuthAlgrthm == 2) { /* 802.1X */
1163                 psetkeyparm->algorithm =
1164                          (u8)psecuritypriv->XGrpPrivacy;
1165         } else { /* WEP */
1166                 psetkeyparm->algorithm =
1167                          (u8)psecuritypriv->PrivacyAlgrthm;
1168         }
1169         psetkeyparm->keyid = (u8)keyid;
1170
1171         switch (psetkeyparm->algorithm) {
1172         case _WEP40_:
1173                 keylen = 5;
1174                 memcpy(psetkeyparm->key,
1175                         psecuritypriv->DefKey[keyid].skey, keylen);
1176                 break;
1177         case _WEP104_:
1178                 keylen = 13;
1179                 memcpy(psetkeyparm->key,
1180                         psecuritypriv->DefKey[keyid].skey, keylen);
1181                 break;
1182         case _TKIP_:
1183                 if (keyid < 1 || keyid > 2) {
1184                         ret = -EINVAL;
1185                         goto err_free_parm;
1186                 }
1187                 keylen = 16;
1188                 memcpy(psetkeyparm->key,
1189                         &psecuritypriv->XGrpKey[keyid - 1], keylen);
1190                 psetkeyparm->grpkey = 1;
1191                 break;
1192         case _AES_:
1193                 if (keyid < 1 || keyid > 2) {
1194                         ret = -EINVAL;
1195                         goto err_free_parm;
1196                 }
1197                 keylen = 16;
1198                 memcpy(psetkeyparm->key,
1199                         &psecuritypriv->XGrpKey[keyid - 1], keylen);
1200                 psetkeyparm->grpkey = 1;
1201                 break;
1202         default:
1203                 ret = -EINVAL;
1204                 goto err_free_parm;
1205         }
1206         pcmd->cmdcode = _SetKey_CMD_;
1207         pcmd->parmbuf = (u8 *)psetkeyparm;
1208         pcmd->cmdsz =  (sizeof(struct setkey_parm));
1209         pcmd->rsp = NULL;
1210         pcmd->rspsz = 0;
1211         INIT_LIST_HEAD(&pcmd->list);
1212         r8712_enqueue_cmd(pcmdpriv, pcmd);
1213         return 0;
1214
1215 err_free_parm:
1216         kfree(psetkeyparm);
1217 err_free_cmd:
1218         kfree(pcmd);
1219         return ret;
1220 }
1221
1222 /* adjust IEs for r8712_joinbss_cmd in WMM */
1223 int r8712_restruct_wmm_ie(struct _adapter *adapter, u8 *in_ie, u8 *out_ie,
1224                     uint in_len, uint initial_out_len)
1225 {
1226         unsigned int ielength = 0;
1227         unsigned int i, j;
1228
1229         i = 12; /* after the fixed IE */
1230         while (i < in_len) {
1231                 ielength = initial_out_len;
1232                 if (in_ie[i] == 0xDD && in_ie[i + 2] == 0x00 &&
1233                     in_ie[i + 3] == 0x50 && in_ie[i + 4] == 0xF2 &&
1234                     in_ie[i + 5] == 0x02 && i + 5 < in_len) {
1235                         /*WMM element ID and OUI*/
1236                         for (j = i; j < i + 9; j++) {
1237                                 out_ie[ielength] = in_ie[j];
1238                                 ielength++;
1239                         }
1240                         out_ie[initial_out_len + 1] = 0x07;
1241                         out_ie[initial_out_len + 6] = 0x00;
1242                         out_ie[initial_out_len + 8] = 0x00;
1243                         break;
1244                 }
1245                 i += (in_ie[i + 1] + 2); /* to the next IE element */
1246         }
1247         return ielength;
1248 }
1249
1250 /*
1251  * Ported from 8185: IsInPreAuthKeyList().
1252  *
1253  * Search by BSSID,
1254  * Return Value:
1255  *      -1              :if there is no pre-auth key in the  table
1256  *      >=0             :if there is pre-auth key, and   return the entry id
1257  */
1258 static int SecIsInPMKIDList(struct _adapter *Adapter, u8 *bssid)
1259 {
1260         struct security_priv *p = &Adapter->securitypriv;
1261         int i;
1262
1263         for (i = 0; i < NUM_PMKID_CACHE; i++)
1264                 if (p->PMKIDList[i].bUsed && !memcmp(p->PMKIDList[i].Bssid, bssid, ETH_ALEN))
1265                         return i;
1266         return -1;
1267 }
1268
1269 sint r8712_restruct_sec_ie(struct _adapter *adapter, u8 *in_ie,
1270                      u8 *out_ie, uint in_len)
1271 {
1272         u8 authmode = 0, match;
1273         u8 sec_ie[IW_CUSTOM_MAX], uncst_oui[4], bkup_ie[255];
1274         u8 wpa_oui[4] = {0x0, 0x50, 0xf2, 0x01};
1275         uint ielength, cnt, remove_cnt;
1276         int iEntry;
1277         struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
1278         struct security_priv *psecuritypriv = &adapter->securitypriv;
1279         uint ndisauthmode = psecuritypriv->ndisauthtype;
1280         uint ndissecuritytype = psecuritypriv->ndisencryptstatus;
1281
1282         if ((ndisauthmode == Ndis802_11AuthModeWPA) ||
1283             (ndisauthmode == Ndis802_11AuthModeWPAPSK)) {
1284                 authmode = _WPA_IE_ID_;
1285                 uncst_oui[0] = 0x0;
1286                 uncst_oui[1] = 0x50;
1287                 uncst_oui[2] = 0xf2;
1288         }
1289         if ((ndisauthmode == Ndis802_11AuthModeWPA2) ||
1290             (ndisauthmode == Ndis802_11AuthModeWPA2PSK)) {
1291                 authmode = _WPA2_IE_ID_;
1292                 uncst_oui[0] = 0x0;
1293                 uncst_oui[1] = 0x0f;
1294                 uncst_oui[2] = 0xac;
1295         }
1296         switch (ndissecuritytype) {
1297         case Ndis802_11Encryption1Enabled:
1298         case Ndis802_11Encryption1KeyAbsent:
1299                 uncst_oui[3] = 0x1;
1300                 break;
1301         case Ndis802_11Encryption2Enabled:
1302         case Ndis802_11Encryption2KeyAbsent:
1303                 uncst_oui[3] = 0x2;
1304                 break;
1305         case Ndis802_11Encryption3Enabled:
1306         case Ndis802_11Encryption3KeyAbsent:
1307                 uncst_oui[3] = 0x4;
1308                 break;
1309         default:
1310                 break;
1311         }
1312         /*Search required WPA or WPA2 IE and copy to sec_ie[] */
1313         cnt = 12;
1314         match = false;
1315         while (cnt < in_len) {
1316                 if (in_ie[cnt] == authmode) {
1317                         if ((authmode == _WPA_IE_ID_) &&
1318                             (!memcmp(&in_ie[cnt + 2], &wpa_oui[0], 4))) {
1319                                 memcpy(&sec_ie[0], &in_ie[cnt],
1320                                         in_ie[cnt + 1] + 2);
1321                                 match = true;
1322                                 break;
1323                         }
1324                         if (authmode == _WPA2_IE_ID_) {
1325                                 memcpy(&sec_ie[0], &in_ie[cnt],
1326                                         in_ie[cnt + 1] + 2);
1327                                 match = true;
1328                                 break;
1329                         }
1330                         if (((authmode == _WPA_IE_ID_) &&
1331                              (!memcmp(&in_ie[cnt + 2], &wpa_oui[0], 4))) ||
1332                              (authmode == _WPA2_IE_ID_))
1333                                 memcpy(&bkup_ie[0], &in_ie[cnt],
1334                                         in_ie[cnt + 1] + 2);
1335                 }
1336                 cnt += in_ie[cnt + 1] + 2; /*get next*/
1337         }
1338         /*restruct WPA IE or WPA2 IE in sec_ie[] */
1339         if (match) {
1340                 if (sec_ie[0] == _WPA_IE_ID_) {
1341                         /* parsing SSN IE to select required encryption
1342                          * algorithm, and set the bc/mc encryption algorithm
1343                          */
1344                         while (true) {
1345                                 /*check wpa_oui tag*/
1346                                 if (memcmp(&sec_ie[2], &wpa_oui[0], 4)) {
1347                                         match = false;
1348                                         break;
1349                                 }
1350                                 if ((sec_ie[6] != 0x01) || (sec_ie[7] != 0x0)) {
1351                                         /*IE Ver error*/
1352                                         match = false;
1353                                         break;
1354                                 }
1355                                 if (!memcmp(&sec_ie[8], &wpa_oui[0], 3)) {
1356                                         /* get bc/mc encryption type (group
1357                                          * key type)
1358                                          */
1359                                         switch (sec_ie[11]) {
1360                                         case 0x0: /*none*/
1361                                                 psecuritypriv->XGrpPrivacy =
1362                                                                 _NO_PRIVACY_;
1363                                                 break;
1364                                         case 0x1: /*WEP_40*/
1365                                                 psecuritypriv->XGrpPrivacy =
1366                                                                 _WEP40_;
1367                                                 break;
1368                                         case 0x2: /*TKIP*/
1369                                                 psecuritypriv->XGrpPrivacy =
1370                                                                 _TKIP_;
1371                                                 break;
1372                                         case 0x3: /*AESCCMP*/
1373                                         case 0x4:
1374                                                 psecuritypriv->XGrpPrivacy =
1375                                                                 _AES_;
1376                                                 break;
1377                                         case 0x5: /*WEP_104*/
1378                                                 psecuritypriv->XGrpPrivacy =
1379                                                                 _WEP104_;
1380                                                 break;
1381                                         }
1382                                 } else {
1383                                         match = false;
1384                                         break;
1385                                 }
1386                                 if (sec_ie[12] == 0x01) {
1387                                         /*check the unicast encryption type*/
1388                                         if (memcmp(&sec_ie[14],
1389                                             &uncst_oui[0], 4)) {
1390                                                 match = false;
1391                                                 break;
1392
1393                                         } /*else the uncst_oui is match*/
1394                                 } else { /*mixed mode, unicast_enc_type > 1*/
1395                                         /*select the uncst_oui and remove
1396                                          * the other uncst_oui
1397                                          */
1398                                         cnt = sec_ie[12];
1399                                         remove_cnt = (cnt - 1) * 4;
1400                                         sec_ie[12] = 0x01;
1401                                         memcpy(&sec_ie[14], &uncst_oui[0], 4);
1402                                         /*remove the other unicast suit*/
1403                                         memcpy(&sec_ie[18],
1404                                                 &sec_ie[18 + remove_cnt],
1405                                                 sec_ie[1] - 18 + 2 -
1406                                                 remove_cnt);
1407                                         sec_ie[1] = sec_ie[1] - remove_cnt;
1408                                 }
1409                                 break;
1410                         }
1411                 }
1412                 if (authmode == _WPA2_IE_ID_) {
1413                         /* parsing RSN IE to select required encryption
1414                          * algorithm, and set the bc/mc encryption algorithm
1415                          */
1416                         while (true) {
1417                                 if ((sec_ie[2] != 0x01) || (sec_ie[3] != 0x0)) {
1418                                         /*IE Ver error*/
1419                                         match = false;
1420                                         break;
1421                                 }
1422                                 if (!memcmp(&sec_ie[4], &uncst_oui[0], 3)) {
1423                                         /*get bc/mc encryption type*/
1424                                         switch (sec_ie[7]) {
1425                                         case 0x1: /*WEP_40*/
1426                                                 psecuritypriv->XGrpPrivacy =
1427                                                                 _WEP40_;
1428                                                 break;
1429                                         case 0x2: /*TKIP*/
1430                                                 psecuritypriv->XGrpPrivacy =
1431                                                                 _TKIP_;
1432                                                 break;
1433                                         case 0x4: /*AESWRAP*/
1434                                                 psecuritypriv->XGrpPrivacy =
1435                                                                 _AES_;
1436                                                 break;
1437                                         case 0x5: /*WEP_104*/
1438                                                 psecuritypriv->XGrpPrivacy =
1439                                                                 _WEP104_;
1440                                                 break;
1441                                         default: /*one*/
1442                                                 psecuritypriv->XGrpPrivacy =
1443                                                                 _NO_PRIVACY_;
1444                                                 break;
1445                                         }
1446                                 } else {
1447                                         match = false;
1448                                         break;
1449                                 }
1450                                 if (sec_ie[8] == 0x01) {
1451                                         /*check the unicast encryption type*/
1452                                         if (memcmp(&sec_ie[10],
1453                                                      &uncst_oui[0], 4)) {
1454                                                 match = false;
1455                                                 break;
1456                                         } /*else the uncst_oui is match*/
1457                                 } else { /*mixed mode, unicast_enc_type > 1*/
1458                                         /*select the uncst_oui and remove the
1459                                          * other uncst_oui
1460                                          */
1461                                         cnt = sec_ie[8];
1462                                         remove_cnt = (cnt - 1) * 4;
1463                                         sec_ie[8] = 0x01;
1464                                         memcpy(&sec_ie[10], &uncst_oui[0], 4);
1465                                         /*remove the other unicast suit*/
1466                                         memcpy(&sec_ie[14],
1467                                                 &sec_ie[14 + remove_cnt],
1468                                                 (sec_ie[1] - 14 + 2 -
1469                                                 remove_cnt));
1470                                         sec_ie[1] = sec_ie[1] - remove_cnt;
1471                                 }
1472                                 break;
1473                         }
1474                 }
1475         }
1476         if ((authmode == _WPA_IE_ID_) || (authmode == _WPA2_IE_ID_)) {
1477                 /*copy fixed ie*/
1478                 memcpy(out_ie, in_ie, 12);
1479                 ielength = 12;
1480                 /*copy RSN or SSN*/
1481                 if (match) {
1482                         memcpy(&out_ie[ielength], &sec_ie[0], sec_ie[1] + 2);
1483                         ielength += sec_ie[1] + 2;
1484                         if (authmode == _WPA2_IE_ID_) {
1485                                 /*the Pre-Authentication bit should be zero*/
1486                                 out_ie[ielength - 1] = 0;
1487                                 out_ie[ielength - 2] = 0;
1488                         }
1489                         r8712_report_sec_ie(adapter, authmode, sec_ie);
1490                 }
1491         } else {
1492                 /*copy fixed ie only*/
1493                 memcpy(out_ie, in_ie, 12);
1494                 ielength = 12;
1495                 if (psecuritypriv->wps_phase) {
1496                         memcpy(out_ie + ielength, psecuritypriv->wps_ie,
1497                                psecuritypriv->wps_ie_len);
1498                         ielength += psecuritypriv->wps_ie_len;
1499                 }
1500         }
1501         iEntry = SecIsInPMKIDList(adapter, pmlmepriv->assoc_bssid);
1502         if (iEntry < 0)
1503                 return ielength;
1504         if (authmode == _WPA2_IE_ID_) {
1505                 out_ie[ielength] = 1;
1506                 ielength++;
1507                 out_ie[ielength] = 0;   /*PMKID count = 0x0100*/
1508                 ielength++;
1509                 memcpy(&out_ie[ielength],
1510                         &psecuritypriv->PMKIDList[iEntry].PMKID, 16);
1511                 ielength += 16;
1512                 out_ie[13] += 18;/*PMKID length = 2+16*/
1513         }
1514         return ielength;
1515 }
1516
1517 void r8712_init_registrypriv_dev_network(struct _adapter *adapter)
1518 {
1519         struct registry_priv *pregistrypriv = &adapter->registrypriv;
1520         struct eeprom_priv *peepriv = &adapter->eeprompriv;
1521         struct wlan_bssid_ex *pdev_network = &pregistrypriv->dev_network;
1522         u8 *myhwaddr = myid(peepriv);
1523
1524         memcpy(pdev_network->MacAddress, myhwaddr, ETH_ALEN);
1525         memcpy(&pdev_network->Ssid, &pregistrypriv->ssid,
1526                 sizeof(struct ndis_802_11_ssid));
1527         pdev_network->Configuration.Length =
1528                          sizeof(struct NDIS_802_11_CONFIGURATION);
1529         pdev_network->Configuration.BeaconPeriod = 100;
1530         pdev_network->Configuration.FHConfig.Length = 0;
1531         pdev_network->Configuration.FHConfig.HopPattern = 0;
1532         pdev_network->Configuration.FHConfig.HopSet = 0;
1533         pdev_network->Configuration.FHConfig.DwellTime = 0;
1534 }
1535
1536 void r8712_update_registrypriv_dev_network(struct _adapter *adapter)
1537 {
1538         int sz = 0;
1539         struct registry_priv    *pregistrypriv = &adapter->registrypriv;
1540         struct wlan_bssid_ex    *pdev_network = &pregistrypriv->dev_network;
1541         struct security_priv    *psecuritypriv = &adapter->securitypriv;
1542         struct wlan_network     *cur_network = &adapter->mlmepriv.cur_network;
1543
1544         pdev_network->Privacy = cpu_to_le32(psecuritypriv->PrivacyAlgrthm
1545                                             > 0 ? 1 : 0); /* adhoc no 802.1x */
1546         pdev_network->Rssi = 0;
1547         switch (pregistrypriv->wireless_mode) {
1548         case WIRELESS_11B:
1549                 pdev_network->NetworkTypeInUse = Ndis802_11DS;
1550                 break;
1551         case WIRELESS_11G:
1552         case WIRELESS_11BG:
1553                 pdev_network->NetworkTypeInUse = Ndis802_11OFDM24;
1554                 break;
1555         case WIRELESS_11A:
1556                 pdev_network->NetworkTypeInUse = Ndis802_11OFDM5;
1557                 break;
1558         default:
1559                 /* TODO */
1560                 break;
1561         }
1562         pdev_network->Configuration.DSConfig = pregistrypriv->channel;
1563         if (cur_network->network.InfrastructureMode == Ndis802_11IBSS)
1564                 pdev_network->Configuration.ATIMWindow = 3;
1565         pdev_network->InfrastructureMode = cur_network->network.InfrastructureMode;
1566         /* 1. Supported rates
1567          * 2. IE
1568          */
1569         sz = r8712_generate_ie(pregistrypriv);
1570         pdev_network->IELength = sz;
1571         pdev_network->Length = r8712_get_wlan_bssid_ex_sz(pdev_network);
1572 }
1573
1574 /*the function is at passive_level*/
1575 void r8712_joinbss_reset(struct _adapter *padapter)
1576 {
1577         int i;
1578         struct mlme_priv        *pmlmepriv = &padapter->mlmepriv;
1579         struct ht_priv          *phtpriv = &pmlmepriv->htpriv;
1580
1581         /* todo: if you want to do something io/reg/hw setting before join_bss,
1582          * please add code here
1583          */
1584         phtpriv->ampdu_enable = false;/*reset to disabled*/
1585         for (i = 0; i < 16; i++)
1586                 phtpriv->baddbareq_issued[i] = false;/*reset it*/
1587         if (phtpriv->ht_option) {
1588                 /* validate  usb rx aggregation */
1589                 r8712_write8(padapter, 0x102500D9, 48);/*TH = 48 pages, 6k*/
1590         } else {
1591                 /* invalidate  usb rx aggregation */
1592                 /* TH=1 => means that invalidate usb rx aggregation */
1593                 r8712_write8(padapter, 0x102500D9, 1);
1594         }
1595 }
1596
1597 /*the function is >= passive_level*/
1598 unsigned int r8712_restructure_ht_ie(struct _adapter *padapter, u8 *in_ie,
1599                                      u8 *out_ie, uint in_len, uint *pout_len)
1600 {
1601         u32 ielen, out_len;
1602         unsigned char *p;
1603         struct ieee80211_ht_cap ht_capie;
1604         unsigned char WMM_IE[] = {0x00, 0x50, 0xf2, 0x02, 0x00, 0x01, 0x00};
1605         struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1606         struct qos_priv *pqospriv = &pmlmepriv->qospriv;
1607         struct ht_priv *phtpriv = &pmlmepriv->htpriv;
1608
1609         phtpriv->ht_option = 0;
1610         p = r8712_get_ie(in_ie + 12, WLAN_EID_HT_CAPABILITY, &ielen, in_len - 12);
1611         if (p && (ielen > 0)) {
1612                 if (pqospriv->qos_option == 0) {
1613                         out_len = *pout_len;
1614                         r8712_set_ie(out_ie + out_len, WLAN_EID_VENDOR_SPECIFIC,
1615                                      _WMM_IE_Length_, WMM_IE, pout_len);
1616                         pqospriv->qos_option = 1;
1617                 }
1618                 out_len = *pout_len;
1619                 memset(&ht_capie, 0, sizeof(struct ieee80211_ht_cap));
1620                 ht_capie.cap_info = cpu_to_le16(IEEE80211_HT_CAP_SUP_WIDTH_20_40 |
1621                                     IEEE80211_HT_CAP_SGI_20 |
1622                                     IEEE80211_HT_CAP_SGI_40 |
1623                                     IEEE80211_HT_CAP_TX_STBC |
1624                                     IEEE80211_HT_CAP_MAX_AMSDU |
1625                                     IEEE80211_HT_CAP_DSSSCCK40);
1626                 ht_capie.ampdu_params_info = (IEEE80211_HT_AMPDU_PARM_FACTOR &
1627                                 0x03) | (IEEE80211_HT_AMPDU_PARM_DENSITY & 0x00);
1628                 r8712_set_ie(out_ie + out_len, WLAN_EID_HT_CAPABILITY,
1629                              sizeof(struct ieee80211_ht_cap),
1630                              (unsigned char *)&ht_capie, pout_len);
1631                 phtpriv->ht_option = 1;
1632         }
1633         return phtpriv->ht_option;
1634 }
1635
1636 /* the function is > passive_level (in critical_section) */
1637 static void update_ht_cap(struct _adapter *padapter, u8 *pie, uint ie_len)
1638 {
1639         u8 *p, max_ampdu_sz;
1640         int i;
1641         uint len;
1642         struct sta_info *bmc_sta, *psta;
1643         struct ieee80211_ht_cap *pht_capie;
1644         struct recv_reorder_ctrl *preorder_ctrl;
1645         struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1646         struct ht_priv *phtpriv = &pmlmepriv->htpriv;
1647         struct registry_priv *pregistrypriv = &padapter->registrypriv;
1648         struct wlan_network *pcur_network = &(pmlmepriv->cur_network);
1649
1650         if (!phtpriv->ht_option)
1651                 return;
1652         /* maybe needs check if ap supports rx ampdu. */
1653         if (!phtpriv->ampdu_enable &&
1654             (pregistrypriv->ampdu_enable == 1))
1655                 phtpriv->ampdu_enable = true;
1656         /*check Max Rx A-MPDU Size*/
1657         len = 0;
1658         p = r8712_get_ie(pie + sizeof(struct NDIS_802_11_FIXED_IEs),
1659                                 WLAN_EID_HT_CAPABILITY,
1660                                 &len, ie_len -
1661                                 sizeof(struct NDIS_802_11_FIXED_IEs));
1662         if (p && len > 0) {
1663                 pht_capie = (struct ieee80211_ht_cap *)(p + 2);
1664                 max_ampdu_sz = (pht_capie->ampdu_params_info &
1665                                 IEEE80211_HT_AMPDU_PARM_FACTOR);
1666                 /* max_ampdu_sz (kbytes); */
1667                 max_ampdu_sz = 1 << (max_ampdu_sz + 3);
1668                 phtpriv->rx_ampdu_maxlen = max_ampdu_sz;
1669         }
1670         /* for A-MPDU Rx reordering buffer control for bmc_sta & sta_info
1671          * if A-MPDU Rx is enabled, resetting rx_ordering_ctrl
1672          * wstart_b(indicate_seq) to default value=0xffff
1673          * todo: check if AP can send A-MPDU packets
1674          */
1675         bmc_sta = r8712_get_bcmc_stainfo(padapter);
1676         if (bmc_sta) {
1677                 for (i = 0; i < 16; i++) {
1678                         preorder_ctrl = &bmc_sta->recvreorder_ctrl[i];
1679                         preorder_ctrl->indicate_seq = 0xffff;
1680                         preorder_ctrl->wend_b = 0xffff;
1681                 }
1682         }
1683         psta = r8712_get_stainfo(&padapter->stapriv,
1684                                  pcur_network->network.MacAddress);
1685         if (psta) {
1686                 for (i = 0; i < 16; i++) {
1687                         preorder_ctrl = &psta->recvreorder_ctrl[i];
1688                         preorder_ctrl->indicate_seq = 0xffff;
1689                         preorder_ctrl->wend_b = 0xffff;
1690                 }
1691         }
1692         len = 0;
1693         p = r8712_get_ie(pie + sizeof(struct NDIS_802_11_FIXED_IEs),
1694                    WLAN_EID_HT_OPERATION, &len,
1695                    ie_len - sizeof(struct NDIS_802_11_FIXED_IEs));
1696 }
1697
1698 void r8712_issue_addbareq_cmd(struct _adapter *padapter, int priority)
1699 {
1700         struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1701         struct ht_priv   *phtpriv = &pmlmepriv->htpriv;
1702
1703         if ((phtpriv->ht_option == 1) && (phtpriv->ampdu_enable)) {
1704                 if (!phtpriv->baddbareq_issued[priority]) {
1705                         r8712_addbareq_cmd(padapter, (u8)priority);
1706                         phtpriv->baddbareq_issued[priority] = true;
1707                 }
1708         }
1709 }