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