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