GNU Linux-libre 6.9.1-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 =
777                                                         adapter->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,
788                                                         0,
789                                                         sizeof(union pn48));
790                                                 memset((u8 *)&ptarget_sta->rxpn,
791                                                         0,
792                                                         sizeof(union pn48));
793                                         }
794                                 } else {
795                                         if (check_fwstate(pmlmepriv, _FW_UNDER_LINKING))
796                                                 pmlmepriv->fw_state ^=
797                                                         _FW_UNDER_LINKING;
798                                         goto ignore_joinbss_callback;
799                                 }
800                         }
801
802                         /*s3. update cur_network & indicate connect*/
803                         memcpy(&cur_network->network, &pnetwork->network,
804                                 pnetwork->network.Length);
805                         cur_network->aid = pnetwork->join_res;
806                         /*update fw_state will clr _FW_UNDER_LINKING*/
807                         switch (pnetwork->network.InfrastructureMode) {
808                         case Ndis802_11Infrastructure:
809                                 pmlmepriv->fw_state = WIFI_STATION_STATE;
810                                 break;
811                         case Ndis802_11IBSS:
812                                 pmlmepriv->fw_state = WIFI_ADHOC_STATE;
813                                 break;
814                         default:
815                                 pmlmepriv->fw_state = WIFI_NULL_STATE;
816                                 break;
817                         }
818                         r8712_update_protection(adapter,
819                                 (cur_network->network.IEs) +
820                                 sizeof(struct NDIS_802_11_FIXED_IEs),
821                                 (cur_network->network.IELength));
822                         /*TODO: update HT_Capability*/
823                         update_ht_cap(adapter, cur_network->network.IEs,
824                                 cur_network->network.IELength);
825                         /*indicate connect*/
826                         if (check_fwstate(pmlmepriv, WIFI_STATION_STATE))
827                                 r8712_indicate_connect(adapter);
828                         del_timer(&pmlmepriv->assoc_timer);
829                 } else {
830                         goto ignore_joinbss_callback;
831                 }
832         } else {
833                 if (check_fwstate(pmlmepriv, _FW_UNDER_LINKING)) {
834                         mod_timer(&pmlmepriv->assoc_timer,
835                                 jiffies + msecs_to_jiffies(1));
836                         _clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING);
837                 }
838         }
839 ignore_joinbss_callback:
840         spin_unlock_irqrestore(&pmlmepriv->lock, irqL);
841         if (sizeof(struct list_head) == 4 * sizeof(u32))
842                 kfree(pnetwork);
843 }
844
845 void r8712_stassoc_event_callback(struct _adapter *adapter, u8 *pbuf)
846 {
847         unsigned long irqL;
848         struct sta_info *psta;
849         struct mlme_priv *pmlmepriv = &(adapter->mlmepriv);
850         struct stassoc_event *pstassoc  = (struct stassoc_event *)pbuf;
851
852         /* to do: */
853         if (!r8712_access_ctrl(&adapter->acl_list, pstassoc->macaddr))
854                 return;
855         psta = r8712_get_stainfo(&adapter->stapriv, pstassoc->macaddr);
856         if (psta) {
857                 /*the sta have been in sta_info_queue => do nothing
858                  *(between drv has received this event before and
859                  * fw have not yet to set key to CAM_ENTRY)
860                  */
861                 return;
862         }
863
864         psta = r8712_alloc_stainfo(&adapter->stapriv, pstassoc->macaddr);
865         if (!psta)
866                 return;
867         /* to do : init sta_info variable */
868         psta->qos_option = 0;
869         psta->mac_id = le32_to_cpu(pstassoc->cam_id);
870         /* psta->aid = (uint)pstassoc->cam_id; */
871
872         if (adapter->securitypriv.AuthAlgrthm == 2)
873                 psta->XPrivacy = adapter->securitypriv.PrivacyAlgrthm;
874         psta->ieee8021x_blocked = false;
875         spin_lock_irqsave(&pmlmepriv->lock, irqL);
876         if (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) ||
877             check_fwstate(pmlmepriv, WIFI_ADHOC_STATE)) {
878                 if (adapter->stapriv.asoc_sta_count == 2) {
879                         /* a sta + bc/mc_stainfo (not Ibss_stainfo) */
880                         r8712_indicate_connect(adapter);
881                 }
882         }
883         spin_unlock_irqrestore(&pmlmepriv->lock, irqL);
884 }
885
886 void r8712_stadel_event_callback(struct _adapter *adapter, u8 *pbuf)
887 {
888         unsigned long irqL, irqL2;
889         struct sta_info *psta;
890         struct wlan_network *pwlan = NULL;
891         struct wlan_bssid_ex *pdev_network = NULL;
892         u8 *pibss = NULL;
893         struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
894         struct stadel_event *pstadel = (struct stadel_event *)pbuf;
895         struct sta_priv *pstapriv = &adapter->stapriv;
896         struct wlan_network *tgt_network = &pmlmepriv->cur_network;
897
898         spin_lock_irqsave(&pmlmepriv->lock, irqL2);
899         if (check_fwstate(pmlmepriv, WIFI_STATION_STATE)) {
900                 r8712_ind_disconnect(adapter);
901                 r8712_free_assoc_resources(adapter);
902         }
903         if (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE |
904             WIFI_ADHOC_STATE)) {
905                 psta = r8712_get_stainfo(&adapter->stapriv, pstadel->macaddr);
906                 spin_lock_irqsave(&pstapriv->sta_hash_lock, irqL);
907                 r8712_free_stainfo(adapter, psta);
908                 spin_unlock_irqrestore(&pstapriv->sta_hash_lock, irqL);
909                 if (adapter->stapriv.asoc_sta_count == 1) {
910                         /*a sta + bc/mc_stainfo (not Ibss_stainfo) */
911                         pwlan = r8712_find_network(&pmlmepriv->scanned_queue,
912                                 tgt_network->network.MacAddress);
913                         if (pwlan) {
914                                 pwlan->fixed = false;
915                                 free_network_nolock(pmlmepriv, pwlan);
916                         }
917                         /*re-create ibss*/
918                         pdev_network = &(adapter->registrypriv.dev_network);
919                         pibss = adapter->registrypriv.dev_network.MacAddress;
920                         memcpy(pdev_network, &tgt_network->network,
921                                 r8712_get_wlan_bssid_ex_sz(&tgt_network->network));
922                         memcpy(&pdev_network->Ssid,
923                                 &pmlmepriv->assoc_ssid,
924                                 sizeof(struct ndis_802_11_ssid));
925                         r8712_update_registrypriv_dev_network(adapter);
926                         r8712_generate_random_ibss(pibss);
927                         if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE)) {
928                                 _clr_fwstate_(pmlmepriv, WIFI_ADHOC_STATE);
929                                 set_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE);
930                         }
931                 }
932         }
933         spin_unlock_irqrestore(&pmlmepriv->lock, irqL2);
934 }
935
936 void r8712_cpwm_event_callback(struct _adapter *adapter, u8 *pbuf)
937 {
938         struct reportpwrstate_parm *preportpwrstate =
939                          (struct reportpwrstate_parm *)pbuf;
940
941         preportpwrstate->state |= (u8)(adapter->pwrctrlpriv.cpwm_tog + 0x80);
942         r8712_cpwm_int_hdl(adapter, preportpwrstate);
943 }
944
945 /*      When the Netgear 3500 AP is with WPA2PSK-AES mode, it will send
946  *       the ADDBA req frame with start seq control = 0 to wifi client after
947  *       the WPA handshake and the seqence number of following data packet
948  *      will be 0. In this case, the Rx reorder sequence is not longer than 0
949  *       and the WiFi client will drop the data with seq number 0.
950  *      So, the 8712 firmware has to inform driver with receiving the
951  *       ADDBA-Req frame so that the driver can reset the
952  *      sequence value of Rx reorder control.
953  */
954 void r8712_got_addbareq_event_callback(struct _adapter *adapter, u8 *pbuf)
955 {
956         struct  ADDBA_Req_Report_parm *pAddbareq_pram =
957                          (struct ADDBA_Req_Report_parm *)pbuf;
958         struct  sta_info *psta;
959         struct  sta_priv *pstapriv = &adapter->stapriv;
960         struct  recv_reorder_ctrl *precvreorder_ctrl = NULL;
961
962         psta = r8712_get_stainfo(pstapriv, pAddbareq_pram->MacAddress);
963         if (psta) {
964                 precvreorder_ctrl =
965                          &psta->recvreorder_ctrl[pAddbareq_pram->tid];
966                 /* set the indicate_seq to 0xffff so that the rx reorder
967                  * can store any following data packet.
968                  */
969                 precvreorder_ctrl->indicate_seq = 0xffff;
970         }
971 }
972
973 void r8712_wpspbc_event_callback(struct _adapter *adapter, u8 *pbuf)
974 {
975         if (!adapter->securitypriv.wps_hw_pbc_pressed)
976                 adapter->securitypriv.wps_hw_pbc_pressed = true;
977 }
978
979 void _r8712_sitesurvey_ctrl_handler(struct _adapter *adapter)
980 {
981         struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
982         struct sitesurvey_ctrl  *psitesurveyctrl = &pmlmepriv->sitesurveyctrl;
983         struct registry_priv    *pregistrypriv = &adapter->registrypriv;
984         u64 current_tx_pkts;
985         uint current_rx_pkts;
986
987         current_tx_pkts = (adapter->xmitpriv.tx_pkts) -
988                           (psitesurveyctrl->last_tx_pkts);
989         current_rx_pkts = (adapter->recvpriv.rx_pkts) -
990                           (psitesurveyctrl->last_rx_pkts);
991         psitesurveyctrl->last_tx_pkts = adapter->xmitpriv.tx_pkts;
992         psitesurveyctrl->last_rx_pkts = adapter->recvpriv.rx_pkts;
993         if ((current_tx_pkts > pregistrypriv->busy_thresh) ||
994             (current_rx_pkts > pregistrypriv->busy_thresh))
995                 psitesurveyctrl->traffic_busy = true;
996         else
997                 psitesurveyctrl->traffic_busy = false;
998 }
999
1000 void _r8712_join_timeout_handler(struct _adapter *adapter)
1001 {
1002         unsigned long irqL;
1003         struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
1004
1005         if (adapter->driver_stopped || adapter->surprise_removed)
1006                 return;
1007         spin_lock_irqsave(&pmlmepriv->lock, irqL);
1008         _clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING);
1009         pmlmepriv->to_join = false;
1010         if (check_fwstate(pmlmepriv, _FW_LINKED)) {
1011                 r8712_os_indicate_disconnect(adapter);
1012                 _clr_fwstate_(pmlmepriv, _FW_LINKED);
1013         }
1014         if (adapter->pwrctrlpriv.pwr_mode != adapter->registrypriv.power_mgnt) {
1015                 r8712_set_ps_mode(adapter, adapter->registrypriv.power_mgnt,
1016                                   adapter->registrypriv.smart_ps);
1017         }
1018         spin_unlock_irqrestore(&pmlmepriv->lock, irqL);
1019 }
1020
1021 void r8712_scan_timeout_handler (struct _adapter *adapter)
1022 {
1023         unsigned long irqL;
1024         struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
1025
1026         spin_lock_irqsave(&pmlmepriv->lock, irqL);
1027         _clr_fwstate_(pmlmepriv, _FW_UNDER_SURVEY);
1028         pmlmepriv->to_join = false;     /* scan fail, so clear to_join flag */
1029         spin_unlock_irqrestore(&pmlmepriv->lock, irqL);
1030 }
1031
1032 void _r8712_dhcp_timeout_handler (struct _adapter *adapter)
1033 {
1034         if (adapter->driver_stopped || adapter->surprise_removed)
1035                 return;
1036         if (adapter->pwrctrlpriv.pwr_mode != adapter->registrypriv.power_mgnt)
1037                 r8712_set_ps_mode(adapter, adapter->registrypriv.power_mgnt,
1038                             adapter->registrypriv.smart_ps);
1039 }
1040
1041 int r8712_select_and_join_from_scan(struct mlme_priv *pmlmepriv)
1042 {
1043         struct list_head *phead;
1044         unsigned char *dst_ssid, *src_ssid;
1045         struct _adapter *adapter;
1046         struct  __queue *queue = NULL;
1047         struct wlan_network *pnetwork = NULL;
1048         struct wlan_network *pnetwork_max_rssi = NULL;
1049
1050         adapter = (struct _adapter *)pmlmepriv->nic_hdl;
1051         queue = &pmlmepriv->scanned_queue;
1052         phead = &queue->queue;
1053         pmlmepriv->pscanned = phead->next;
1054         while (1) {
1055                 if (end_of_queue_search(phead, pmlmepriv->pscanned)) {
1056                         if (pmlmepriv->assoc_by_rssi && pnetwork_max_rssi) {
1057                                 pnetwork = pnetwork_max_rssi;
1058                                 goto ask_for_joinbss;
1059                         }
1060                         return -EINVAL;
1061                 }
1062                 pnetwork = container_of(pmlmepriv->pscanned,
1063                                         struct wlan_network, list);
1064                 pmlmepriv->pscanned = pmlmepriv->pscanned->next;
1065                 if (pmlmepriv->assoc_by_bssid) {
1066                         dst_ssid = pnetwork->network.MacAddress;
1067                         src_ssid = pmlmepriv->assoc_bssid;
1068                         if (!memcmp(dst_ssid, src_ssid, ETH_ALEN)) {
1069                                 if (check_fwstate(pmlmepriv, _FW_LINKED)) {
1070                                         if (is_same_network(&pmlmepriv->cur_network.network,
1071                                             &pnetwork->network)) {
1072                                                 _clr_fwstate_(pmlmepriv,
1073                                                         _FW_UNDER_LINKING);
1074                                                 /*r8712_indicate_connect again*/
1075                                                 r8712_indicate_connect(adapter);
1076                                                 return 2;
1077                                         }
1078                                         r8712_disassoc_cmd(adapter);
1079                                         r8712_ind_disconnect(adapter);
1080                                         r8712_free_assoc_resources(adapter);
1081                                 }
1082                                 goto ask_for_joinbss;
1083                         }
1084                 } else if (pmlmepriv->assoc_ssid.SsidLength == 0) {
1085                         goto ask_for_joinbss;
1086                 }
1087                 dst_ssid = pnetwork->network.Ssid.Ssid;
1088                 src_ssid = pmlmepriv->assoc_ssid.Ssid;
1089                 if ((pnetwork->network.Ssid.SsidLength ==
1090                     pmlmepriv->assoc_ssid.SsidLength) &&
1091                     (!memcmp(dst_ssid, src_ssid,
1092                      pmlmepriv->assoc_ssid.SsidLength))) {
1093                         if (pmlmepriv->assoc_by_rssi) {
1094                                 /* if the ssid is the same, select the bss
1095                                  * which has the max rssi
1096                                  */
1097                                 if (pnetwork_max_rssi) {
1098                                         if (pnetwork->network.Rssi >
1099                                             pnetwork_max_rssi->network.Rssi)
1100                                                 pnetwork_max_rssi = pnetwork;
1101                                 } else {
1102                                         pnetwork_max_rssi = pnetwork;
1103                                 }
1104                         } else if (is_desired_network(adapter, pnetwork)) {
1105                                 if (check_fwstate(pmlmepriv, _FW_LINKED)) {
1106                                         r8712_disassoc_cmd(adapter);
1107                                         r8712_free_assoc_resources(adapter);
1108                                 }
1109                                 goto ask_for_joinbss;
1110                         }
1111                 }
1112         }
1113
1114 ask_for_joinbss:
1115         return r8712_joinbss_cmd(adapter, pnetwork);
1116 }
1117
1118 int r8712_set_auth(struct _adapter *adapter,
1119                    struct security_priv *psecuritypriv)
1120 {
1121         struct cmd_priv *pcmdpriv = &adapter->cmdpriv;
1122         struct cmd_obj *pcmd;
1123         struct setauth_parm *psetauthparm;
1124
1125         pcmd = kmalloc(sizeof(*pcmd), GFP_ATOMIC);
1126         if (!pcmd)
1127                 return -ENOMEM;
1128
1129         psetauthparm = kzalloc(sizeof(*psetauthparm), GFP_ATOMIC);
1130         if (!psetauthparm) {
1131                 kfree(pcmd);
1132                 return -ENOMEM;
1133         }
1134         psetauthparm->mode = (u8)psecuritypriv->AuthAlgrthm;
1135         pcmd->cmdcode = _SetAuth_CMD_;
1136         pcmd->parmbuf = (unsigned char *)psetauthparm;
1137         pcmd->cmdsz = sizeof(struct setauth_parm);
1138         pcmd->rsp = NULL;
1139         pcmd->rspsz = 0;
1140         INIT_LIST_HEAD(&pcmd->list);
1141         r8712_enqueue_cmd(pcmdpriv, pcmd);
1142         return 0;
1143 }
1144
1145 int r8712_set_key(struct _adapter *adapter,
1146                   struct security_priv *psecuritypriv,
1147                   sint keyid)
1148 {
1149         struct cmd_priv *pcmdpriv = &adapter->cmdpriv;
1150         struct cmd_obj *pcmd;
1151         struct setkey_parm *psetkeyparm;
1152         u8 keylen;
1153         int ret;
1154
1155         pcmd = kmalloc(sizeof(*pcmd), GFP_ATOMIC);
1156         if (!pcmd)
1157                 return -ENOMEM;
1158         psetkeyparm = kzalloc(sizeof(*psetkeyparm), GFP_ATOMIC);
1159         if (!psetkeyparm) {
1160                 ret = -ENOMEM;
1161                 goto err_free_cmd;
1162         }
1163         if (psecuritypriv->AuthAlgrthm == 2) { /* 802.1X */
1164                 psetkeyparm->algorithm =
1165                          (u8)psecuritypriv->XGrpPrivacy;
1166         } else { /* WEP */
1167                 psetkeyparm->algorithm =
1168                          (u8)psecuritypriv->PrivacyAlgrthm;
1169         }
1170         psetkeyparm->keyid = (u8)keyid;
1171
1172         switch (psetkeyparm->algorithm) {
1173         case _WEP40_:
1174                 keylen = 5;
1175                 memcpy(psetkeyparm->key,
1176                         psecuritypriv->DefKey[keyid].skey, keylen);
1177                 break;
1178         case _WEP104_:
1179                 keylen = 13;
1180                 memcpy(psetkeyparm->key,
1181                         psecuritypriv->DefKey[keyid].skey, keylen);
1182                 break;
1183         case _TKIP_:
1184                 if (keyid < 1 || keyid > 2) {
1185                         ret = -EINVAL;
1186                         goto err_free_parm;
1187                 }
1188                 keylen = 16;
1189                 memcpy(psetkeyparm->key,
1190                         &psecuritypriv->XGrpKey[keyid - 1], keylen);
1191                 psetkeyparm->grpkey = 1;
1192                 break;
1193         case _AES_:
1194                 if (keyid < 1 || keyid > 2) {
1195                         ret = -EINVAL;
1196                         goto err_free_parm;
1197                 }
1198                 keylen = 16;
1199                 memcpy(psetkeyparm->key,
1200                         &psecuritypriv->XGrpKey[keyid - 1], keylen);
1201                 psetkeyparm->grpkey = 1;
1202                 break;
1203         default:
1204                 ret = -EINVAL;
1205                 goto err_free_parm;
1206         }
1207         pcmd->cmdcode = _SetKey_CMD_;
1208         pcmd->parmbuf = (u8 *)psetkeyparm;
1209         pcmd->cmdsz =  (sizeof(struct setkey_parm));
1210         pcmd->rsp = NULL;
1211         pcmd->rspsz = 0;
1212         INIT_LIST_HEAD(&pcmd->list);
1213         r8712_enqueue_cmd(pcmdpriv, pcmd);
1214         return 0;
1215
1216 err_free_parm:
1217         kfree(psetkeyparm);
1218 err_free_cmd:
1219         kfree(pcmd);
1220         return ret;
1221 }
1222
1223 /* adjust IEs for r8712_joinbss_cmd in WMM */
1224 int r8712_restruct_wmm_ie(struct _adapter *adapter, u8 *in_ie, u8 *out_ie,
1225                     uint in_len, uint initial_out_len)
1226 {
1227         unsigned int ielength = 0;
1228         unsigned int i, j;
1229
1230         i = 12; /* after the fixed IE */
1231         while (i < in_len) {
1232                 ielength = initial_out_len;
1233                 if (in_ie[i] == 0xDD && in_ie[i + 2] == 0x00 &&
1234                     in_ie[i + 3] == 0x50 && in_ie[i + 4] == 0xF2 &&
1235                     in_ie[i + 5] == 0x02 && i + 5 < in_len) {
1236                         /*WMM element ID and OUI*/
1237                         for (j = i; j < i + 9; j++) {
1238                                 out_ie[ielength] = in_ie[j];
1239                                 ielength++;
1240                         }
1241                         out_ie[initial_out_len + 1] = 0x07;
1242                         out_ie[initial_out_len + 6] = 0x00;
1243                         out_ie[initial_out_len + 8] = 0x00;
1244                         break;
1245                 }
1246                 i += (in_ie[i + 1] + 2); /* to the next IE element */
1247         }
1248         return ielength;
1249 }
1250
1251 /*
1252  * Ported from 8185: IsInPreAuthKeyList().
1253  *
1254  * Search by BSSID,
1255  * Return Value:
1256  *      -1              :if there is no pre-auth key in the  table
1257  *      >=0             :if there is pre-auth key, and   return the entry id
1258  */
1259 static int SecIsInPMKIDList(struct _adapter *Adapter, u8 *bssid)
1260 {
1261         struct security_priv *p = &Adapter->securitypriv;
1262         int i;
1263
1264         for (i = 0; i < NUM_PMKID_CACHE; i++)
1265                 if (p->PMKIDList[i].bUsed && !memcmp(p->PMKIDList[i].Bssid, bssid, ETH_ALEN))
1266                         return i;
1267         return -1;
1268 }
1269
1270 sint r8712_restruct_sec_ie(struct _adapter *adapter, u8 *in_ie,
1271                      u8 *out_ie, uint in_len)
1272 {
1273         u8 authmode = 0, match;
1274         u8 sec_ie[IW_CUSTOM_MAX], uncst_oui[4], bkup_ie[255];
1275         u8 wpa_oui[4] = {0x0, 0x50, 0xf2, 0x01};
1276         uint ielength, cnt, remove_cnt;
1277         int iEntry;
1278         struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
1279         struct security_priv *psecuritypriv = &adapter->securitypriv;
1280         uint ndisauthmode = psecuritypriv->ndisauthtype;
1281         uint ndissecuritytype = psecuritypriv->ndisencryptstatus;
1282
1283         if ((ndisauthmode == Ndis802_11AuthModeWPA) ||
1284             (ndisauthmode == Ndis802_11AuthModeWPAPSK)) {
1285                 authmode = _WPA_IE_ID_;
1286                 uncst_oui[0] = 0x0;
1287                 uncst_oui[1] = 0x50;
1288                 uncst_oui[2] = 0xf2;
1289         }
1290         if ((ndisauthmode == Ndis802_11AuthModeWPA2) ||
1291             (ndisauthmode == Ndis802_11AuthModeWPA2PSK)) {
1292                 authmode = _WPA2_IE_ID_;
1293                 uncst_oui[0] = 0x0;
1294                 uncst_oui[1] = 0x0f;
1295                 uncst_oui[2] = 0xac;
1296         }
1297         switch (ndissecuritytype) {
1298         case Ndis802_11Encryption1Enabled:
1299         case Ndis802_11Encryption1KeyAbsent:
1300                 uncst_oui[3] = 0x1;
1301                 break;
1302         case Ndis802_11Encryption2Enabled:
1303         case Ndis802_11Encryption2KeyAbsent:
1304                 uncst_oui[3] = 0x2;
1305                 break;
1306         case Ndis802_11Encryption3Enabled:
1307         case Ndis802_11Encryption3KeyAbsent:
1308                 uncst_oui[3] = 0x4;
1309                 break;
1310         default:
1311                 break;
1312         }
1313         /*Search required WPA or WPA2 IE and copy to sec_ie[] */
1314         cnt = 12;
1315         match = false;
1316         while (cnt < in_len) {
1317                 if (in_ie[cnt] == authmode) {
1318                         if ((authmode == _WPA_IE_ID_) &&
1319                             (!memcmp(&in_ie[cnt + 2], &wpa_oui[0], 4))) {
1320                                 memcpy(&sec_ie[0], &in_ie[cnt],
1321                                         in_ie[cnt + 1] + 2);
1322                                 match = true;
1323                                 break;
1324                         }
1325                         if (authmode == _WPA2_IE_ID_) {
1326                                 memcpy(&sec_ie[0], &in_ie[cnt],
1327                                         in_ie[cnt + 1] + 2);
1328                                 match = true;
1329                                 break;
1330                         }
1331                         if (((authmode == _WPA_IE_ID_) &&
1332                              (!memcmp(&in_ie[cnt + 2], &wpa_oui[0], 4))) ||
1333                              (authmode == _WPA2_IE_ID_))
1334                                 memcpy(&bkup_ie[0], &in_ie[cnt],
1335                                         in_ie[cnt + 1] + 2);
1336                 }
1337                 cnt += in_ie[cnt + 1] + 2; /*get next*/
1338         }
1339         /*restruct WPA IE or WPA2 IE in sec_ie[] */
1340         if (match) {
1341                 if (sec_ie[0] == _WPA_IE_ID_) {
1342                         /* parsing SSN IE to select required encryption
1343                          * algorithm, and set the bc/mc encryption algorithm
1344                          */
1345                         while (true) {
1346                                 /*check wpa_oui tag*/
1347                                 if (memcmp(&sec_ie[2], &wpa_oui[0], 4)) {
1348                                         match = false;
1349                                         break;
1350                                 }
1351                                 if ((sec_ie[6] != 0x01) || (sec_ie[7] != 0x0)) {
1352                                         /*IE Ver error*/
1353                                         match = false;
1354                                         break;
1355                                 }
1356                                 if (!memcmp(&sec_ie[8], &wpa_oui[0], 3)) {
1357                                         /* get bc/mc encryption type (group
1358                                          * key type)
1359                                          */
1360                                         switch (sec_ie[11]) {
1361                                         case 0x0: /*none*/
1362                                                 psecuritypriv->XGrpPrivacy =
1363                                                                 _NO_PRIVACY_;
1364                                                 break;
1365                                         case 0x1: /*WEP_40*/
1366                                                 psecuritypriv->XGrpPrivacy =
1367                                                                 _WEP40_;
1368                                                 break;
1369                                         case 0x2: /*TKIP*/
1370                                                 psecuritypriv->XGrpPrivacy =
1371                                                                 _TKIP_;
1372                                                 break;
1373                                         case 0x3: /*AESCCMP*/
1374                                         case 0x4:
1375                                                 psecuritypriv->XGrpPrivacy =
1376                                                                 _AES_;
1377                                                 break;
1378                                         case 0x5: /*WEP_104*/
1379                                                 psecuritypriv->XGrpPrivacy =
1380                                                                 _WEP104_;
1381                                                 break;
1382                                         }
1383                                 } else {
1384                                         match = false;
1385                                         break;
1386                                 }
1387                                 if (sec_ie[12] == 0x01) {
1388                                         /*check the unicast encryption type*/
1389                                         if (memcmp(&sec_ie[14],
1390                                             &uncst_oui[0], 4)) {
1391                                                 match = false;
1392                                                 break;
1393
1394                                         } /*else the uncst_oui is match*/
1395                                 } else { /*mixed mode, unicast_enc_type > 1*/
1396                                         /*select the uncst_oui and remove
1397                                          * the other uncst_oui
1398                                          */
1399                                         cnt = sec_ie[12];
1400                                         remove_cnt = (cnt - 1) * 4;
1401                                         sec_ie[12] = 0x01;
1402                                         memcpy(&sec_ie[14], &uncst_oui[0], 4);
1403                                         /*remove the other unicast suit*/
1404                                         memcpy(&sec_ie[18],
1405                                                 &sec_ie[18 + remove_cnt],
1406                                                 sec_ie[1] - 18 + 2 -
1407                                                 remove_cnt);
1408                                         sec_ie[1] = sec_ie[1] - remove_cnt;
1409                                 }
1410                                 break;
1411                         }
1412                 }
1413                 if (authmode == _WPA2_IE_ID_) {
1414                         /* parsing RSN IE to select required encryption
1415                          * algorithm, and set the bc/mc encryption algorithm
1416                          */
1417                         while (true) {
1418                                 if ((sec_ie[2] != 0x01) || (sec_ie[3] != 0x0)) {
1419                                         /*IE Ver error*/
1420                                         match = false;
1421                                         break;
1422                                 }
1423                                 if (!memcmp(&sec_ie[4], &uncst_oui[0], 3)) {
1424                                         /*get bc/mc encryption type*/
1425                                         switch (sec_ie[7]) {
1426                                         case 0x1: /*WEP_40*/
1427                                                 psecuritypriv->XGrpPrivacy =
1428                                                                 _WEP40_;
1429                                                 break;
1430                                         case 0x2: /*TKIP*/
1431                                                 psecuritypriv->XGrpPrivacy =
1432                                                                 _TKIP_;
1433                                                 break;
1434                                         case 0x4: /*AESWRAP*/
1435                                                 psecuritypriv->XGrpPrivacy =
1436                                                                 _AES_;
1437                                                 break;
1438                                         case 0x5: /*WEP_104*/
1439                                                 psecuritypriv->XGrpPrivacy =
1440                                                                 _WEP104_;
1441                                                 break;
1442                                         default: /*one*/
1443                                                 psecuritypriv->XGrpPrivacy =
1444                                                                 _NO_PRIVACY_;
1445                                                 break;
1446                                         }
1447                                 } else {
1448                                         match = false;
1449                                         break;
1450                                 }
1451                                 if (sec_ie[8] == 0x01) {
1452                                         /*check the unicast encryption type*/
1453                                         if (memcmp(&sec_ie[10],
1454                                                      &uncst_oui[0], 4)) {
1455                                                 match = false;
1456                                                 break;
1457                                         } /*else the uncst_oui is match*/
1458                                 } else { /*mixed mode, unicast_enc_type > 1*/
1459                                         /*select the uncst_oui and remove the
1460                                          * other uncst_oui
1461                                          */
1462                                         cnt = sec_ie[8];
1463                                         remove_cnt = (cnt - 1) * 4;
1464                                         sec_ie[8] = 0x01;
1465                                         memcpy(&sec_ie[10], &uncst_oui[0], 4);
1466                                         /*remove the other unicast suit*/
1467                                         memcpy(&sec_ie[14],
1468                                                 &sec_ie[14 + remove_cnt],
1469                                                 (sec_ie[1] - 14 + 2 -
1470                                                 remove_cnt));
1471                                         sec_ie[1] = sec_ie[1] - remove_cnt;
1472                                 }
1473                                 break;
1474                         }
1475                 }
1476         }
1477         if ((authmode == _WPA_IE_ID_) || (authmode == _WPA2_IE_ID_)) {
1478                 /*copy fixed ie*/
1479                 memcpy(out_ie, in_ie, 12);
1480                 ielength = 12;
1481                 /*copy RSN or SSN*/
1482                 if (match) {
1483                         memcpy(&out_ie[ielength], &sec_ie[0], sec_ie[1] + 2);
1484                         ielength += sec_ie[1] + 2;
1485                         if (authmode == _WPA2_IE_ID_) {
1486                                 /*the Pre-Authentication bit should be zero*/
1487                                 out_ie[ielength - 1] = 0;
1488                                 out_ie[ielength - 2] = 0;
1489                         }
1490                         r8712_report_sec_ie(adapter, authmode, sec_ie);
1491                 }
1492         } else {
1493                 /*copy fixed ie only*/
1494                 memcpy(out_ie, in_ie, 12);
1495                 ielength = 12;
1496                 if (psecuritypriv->wps_phase) {
1497                         memcpy(out_ie + ielength, psecuritypriv->wps_ie,
1498                                psecuritypriv->wps_ie_len);
1499                         ielength += psecuritypriv->wps_ie_len;
1500                 }
1501         }
1502         iEntry = SecIsInPMKIDList(adapter, pmlmepriv->assoc_bssid);
1503         if (iEntry < 0)
1504                 return ielength;
1505         if (authmode == _WPA2_IE_ID_) {
1506                 out_ie[ielength] = 1;
1507                 ielength++;
1508                 out_ie[ielength] = 0;   /*PMKID count = 0x0100*/
1509                 ielength++;
1510                 memcpy(&out_ie[ielength],
1511                         &psecuritypriv->PMKIDList[iEntry].PMKID, 16);
1512                 ielength += 16;
1513                 out_ie[13] += 18;/*PMKID length = 2+16*/
1514         }
1515         return ielength;
1516 }
1517
1518 void r8712_init_registrypriv_dev_network(struct _adapter *adapter)
1519 {
1520         struct registry_priv *pregistrypriv = &adapter->registrypriv;
1521         struct eeprom_priv *peepriv = &adapter->eeprompriv;
1522         struct wlan_bssid_ex *pdev_network = &pregistrypriv->dev_network;
1523         u8 *myhwaddr = myid(peepriv);
1524
1525         memcpy(pdev_network->MacAddress, myhwaddr, ETH_ALEN);
1526         memcpy(&pdev_network->Ssid, &pregistrypriv->ssid,
1527                 sizeof(struct ndis_802_11_ssid));
1528         pdev_network->Configuration.Length =
1529                          sizeof(struct NDIS_802_11_CONFIGURATION);
1530         pdev_network->Configuration.BeaconPeriod = 100;
1531         pdev_network->Configuration.FHConfig.Length = 0;
1532         pdev_network->Configuration.FHConfig.HopPattern = 0;
1533         pdev_network->Configuration.FHConfig.HopSet = 0;
1534         pdev_network->Configuration.FHConfig.DwellTime = 0;
1535 }
1536
1537 void r8712_update_registrypriv_dev_network(struct _adapter *adapter)
1538 {
1539         int sz = 0;
1540         struct registry_priv    *pregistrypriv = &adapter->registrypriv;
1541         struct wlan_bssid_ex    *pdev_network = &pregistrypriv->dev_network;
1542         struct security_priv    *psecuritypriv = &adapter->securitypriv;
1543         struct wlan_network     *cur_network = &adapter->mlmepriv.cur_network;
1544
1545         pdev_network->Privacy = cpu_to_le32(psecuritypriv->PrivacyAlgrthm
1546                                             > 0 ? 1 : 0); /* adhoc no 802.1x */
1547         pdev_network->Rssi = 0;
1548         switch (pregistrypriv->wireless_mode) {
1549         case WIRELESS_11B:
1550                 pdev_network->NetworkTypeInUse = Ndis802_11DS;
1551                 break;
1552         case WIRELESS_11G:
1553         case WIRELESS_11BG:
1554                 pdev_network->NetworkTypeInUse = Ndis802_11OFDM24;
1555                 break;
1556         case WIRELESS_11A:
1557                 pdev_network->NetworkTypeInUse = Ndis802_11OFDM5;
1558                 break;
1559         default:
1560                 /* TODO */
1561                 break;
1562         }
1563         pdev_network->Configuration.DSConfig = pregistrypriv->channel;
1564         if (cur_network->network.InfrastructureMode == Ndis802_11IBSS)
1565                 pdev_network->Configuration.ATIMWindow = 3;
1566         pdev_network->InfrastructureMode = cur_network->network.InfrastructureMode;
1567         /* 1. Supported rates
1568          * 2. IE
1569          */
1570         sz = r8712_generate_ie(pregistrypriv);
1571         pdev_network->IELength = sz;
1572         pdev_network->Length = r8712_get_wlan_bssid_ex_sz(pdev_network);
1573 }
1574
1575 /*the function is at passive_level*/
1576 void r8712_joinbss_reset(struct _adapter *padapter)
1577 {
1578         int i;
1579         struct mlme_priv        *pmlmepriv = &padapter->mlmepriv;
1580         struct ht_priv          *phtpriv = &pmlmepriv->htpriv;
1581
1582         /* todo: if you want to do something io/reg/hw setting before join_bss,
1583          * please add code here
1584          */
1585         phtpriv->ampdu_enable = false;/*reset to disabled*/
1586         for (i = 0; i < 16; i++)
1587                 phtpriv->baddbareq_issued[i] = false;/*reset it*/
1588         if (phtpriv->ht_option) {
1589                 /* validate  usb rx aggregation */
1590                 r8712_write8(padapter, 0x102500D9, 48);/*TH = 48 pages, 6k*/
1591         } else {
1592                 /* invalidate  usb rx aggregation */
1593                 /* TH=1 => means that invalidate usb rx aggregation */
1594                 r8712_write8(padapter, 0x102500D9, 1);
1595         }
1596 }
1597
1598 /*the function is >= passive_level*/
1599 unsigned int r8712_restructure_ht_ie(struct _adapter *padapter, u8 *in_ie,
1600                                      u8 *out_ie, uint in_len, uint *pout_len)
1601 {
1602         u32 ielen, out_len;
1603         unsigned char *p;
1604         struct ieee80211_ht_cap ht_capie;
1605         unsigned char WMM_IE[] = {0x00, 0x50, 0xf2, 0x02, 0x00, 0x01, 0x00};
1606         struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1607         struct qos_priv *pqospriv = &pmlmepriv->qospriv;
1608         struct ht_priv *phtpriv = &pmlmepriv->htpriv;
1609
1610         phtpriv->ht_option = 0;
1611         p = r8712_get_ie(in_ie + 12, WLAN_EID_HT_CAPABILITY, &ielen, in_len - 12);
1612         if (p && (ielen > 0)) {
1613                 if (pqospriv->qos_option == 0) {
1614                         out_len = *pout_len;
1615                         r8712_set_ie(out_ie + out_len, WLAN_EID_VENDOR_SPECIFIC,
1616                                      _WMM_IE_Length_, WMM_IE, pout_len);
1617                         pqospriv->qos_option = 1;
1618                 }
1619                 out_len = *pout_len;
1620                 memset(&ht_capie, 0, sizeof(struct ieee80211_ht_cap));
1621                 ht_capie.cap_info = cpu_to_le16(IEEE80211_HT_CAP_SUP_WIDTH_20_40 |
1622                                     IEEE80211_HT_CAP_SGI_20 |
1623                                     IEEE80211_HT_CAP_SGI_40 |
1624                                     IEEE80211_HT_CAP_TX_STBC |
1625                                     IEEE80211_HT_CAP_MAX_AMSDU |
1626                                     IEEE80211_HT_CAP_DSSSCCK40);
1627                 ht_capie.ampdu_params_info = (IEEE80211_HT_AMPDU_PARM_FACTOR &
1628                                 0x03) | (IEEE80211_HT_AMPDU_PARM_DENSITY & 0x00);
1629                 r8712_set_ie(out_ie + out_len, WLAN_EID_HT_CAPABILITY,
1630                              sizeof(struct ieee80211_ht_cap),
1631                              (unsigned char *)&ht_capie, pout_len);
1632                 phtpriv->ht_option = 1;
1633         }
1634         return phtpriv->ht_option;
1635 }
1636
1637 /* the function is > passive_level (in critical_section) */
1638 static void update_ht_cap(struct _adapter *padapter, u8 *pie, uint ie_len)
1639 {
1640         u8 *p, max_ampdu_sz;
1641         int i;
1642         uint len;
1643         struct sta_info *bmc_sta, *psta;
1644         struct ieee80211_ht_cap *pht_capie;
1645         struct recv_reorder_ctrl *preorder_ctrl;
1646         struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1647         struct ht_priv *phtpriv = &pmlmepriv->htpriv;
1648         struct registry_priv *pregistrypriv = &padapter->registrypriv;
1649         struct wlan_network *pcur_network = &(pmlmepriv->cur_network);
1650
1651         if (!phtpriv->ht_option)
1652                 return;
1653         /* maybe needs check if ap supports rx ampdu. */
1654         if (!phtpriv->ampdu_enable &&
1655             (pregistrypriv->ampdu_enable == 1))
1656                 phtpriv->ampdu_enable = true;
1657         /*check Max Rx A-MPDU Size*/
1658         len = 0;
1659         p = r8712_get_ie(pie + sizeof(struct NDIS_802_11_FIXED_IEs),
1660                                 WLAN_EID_HT_CAPABILITY,
1661                                 &len, ie_len -
1662                                 sizeof(struct NDIS_802_11_FIXED_IEs));
1663         if (p && len > 0) {
1664                 pht_capie = (struct ieee80211_ht_cap *)(p + 2);
1665                 max_ampdu_sz = (pht_capie->ampdu_params_info &
1666                                 IEEE80211_HT_AMPDU_PARM_FACTOR);
1667                 /* max_ampdu_sz (kbytes); */
1668                 max_ampdu_sz = 1 << (max_ampdu_sz + 3);
1669                 phtpriv->rx_ampdu_maxlen = max_ampdu_sz;
1670         }
1671         /* for A-MPDU Rx reordering buffer control for bmc_sta & sta_info
1672          * if A-MPDU Rx is enabled, resetting rx_ordering_ctrl
1673          * wstart_b(indicate_seq) to default value=0xffff
1674          * todo: check if AP can send A-MPDU packets
1675          */
1676         bmc_sta = r8712_get_bcmc_stainfo(padapter);
1677         if (bmc_sta) {
1678                 for (i = 0; i < 16; i++) {
1679                         preorder_ctrl = &bmc_sta->recvreorder_ctrl[i];
1680                         preorder_ctrl->indicate_seq = 0xffff;
1681                         preorder_ctrl->wend_b = 0xffff;
1682                 }
1683         }
1684         psta = r8712_get_stainfo(&padapter->stapriv,
1685                                  pcur_network->network.MacAddress);
1686         if (psta) {
1687                 for (i = 0; i < 16; i++) {
1688                         preorder_ctrl = &psta->recvreorder_ctrl[i];
1689                         preorder_ctrl->indicate_seq = 0xffff;
1690                         preorder_ctrl->wend_b = 0xffff;
1691                 }
1692         }
1693         len = 0;
1694         p = r8712_get_ie(pie + sizeof(struct NDIS_802_11_FIXED_IEs),
1695                    WLAN_EID_HT_OPERATION, &len,
1696                    ie_len - sizeof(struct NDIS_802_11_FIXED_IEs));
1697 }
1698
1699 void r8712_issue_addbareq_cmd(struct _adapter *padapter, int priority)
1700 {
1701         struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1702         struct ht_priv   *phtpriv = &pmlmepriv->htpriv;
1703
1704         if ((phtpriv->ht_option == 1) && (phtpriv->ampdu_enable)) {
1705                 if (!phtpriv->baddbareq_issued[priority]) {
1706                         r8712_addbareq_cmd(padapter, (u8)priority);
1707                         phtpriv->baddbareq_issued[priority] = true;
1708                 }
1709         }
1710 }