]> git.karo-electronics.de Git - karo-tx-linux.git/blob - drivers/staging/rtl8188eu/core/rtw_mlme_ext.c
a0b8f665fa2f5546f23b584abb9248c1ba35d652
[karo-tx-linux.git] / drivers / staging / rtl8188eu / core / rtw_mlme_ext.c
1 /******************************************************************************
2  *
3  * Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved.
4  *
5  * This program is free software; you can redistribute it and/or modify it
6  * under the terms of version 2 of the GNU General Public License as
7  * published by the Free Software Foundation.
8  *
9  * This program is distributed in the hope that it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11  * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12  * more details.
13  *
14  * You should have received a copy of the GNU General Public License along with
15  * this program; if not, write to the Free Software Foundation, Inc.,
16  * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
17  *
18  *
19  ******************************************************************************/
20 #define _RTW_MLME_EXT_C_
21
22 #include <linux/ieee80211.h>
23
24 #include <osdep_service.h>
25 #include <drv_types.h>
26 #include <wifi.h>
27 #include <rtw_mlme_ext.h>
28 #include <wlan_bssdef.h>
29 #include <mlme_osdep.h>
30 #include <recv_osdep.h>
31
32 static u8 null_addr[ETH_ALEN] = {0, 0, 0, 0, 0, 0};
33
34 /**************************************************
35 OUI definitions for the vendor specific IE
36 ***************************************************/
37 unsigned char   RTW_WPA_OUI[] = {0x00, 0x50, 0xf2, 0x01};
38 unsigned char WMM_OUI[] = {0x00, 0x50, 0xf2, 0x02};
39 unsigned char   WPS_OUI[] = {0x00, 0x50, 0xf2, 0x04};
40 unsigned char   P2P_OUI[] = {0x50, 0x6F, 0x9A, 0x09};
41 unsigned char   WFD_OUI[] = {0x50, 0x6F, 0x9A, 0x0A};
42
43 unsigned char   WMM_INFO_OUI[] = {0x00, 0x50, 0xf2, 0x02, 0x00, 0x01};
44 unsigned char   WMM_PARA_OUI[] = {0x00, 0x50, 0xf2, 0x02, 0x01, 0x01};
45
46 unsigned char WPA_TKIP_CIPHER[4] = {0x00, 0x50, 0xf2, 0x02};
47 unsigned char RSN_TKIP_CIPHER[4] = {0x00, 0x0f, 0xac, 0x02};
48
49 extern unsigned char REALTEK_96B_IE[];
50
51 /********************************************************
52 MCS rate definitions
53 *********************************************************/
54 unsigned char   MCS_rate_2R[16] = {0xff, 0xff, 0x0, 0x0, 0x01, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0};
55 unsigned char   MCS_rate_1R[16] = {0xff, 0x00, 0x0, 0x0, 0x01, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0};
56
57 /********************************************************
58 ChannelPlan definitions
59 *********************************************************/
60 static struct rt_channel_plan_2g RTW_ChannelPlan2G[RT_CHANNEL_DOMAIN_2G_MAX] = {
61         {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13}, 13},              /*  0x00, RT_CHANNEL_DOMAIN_2G_WORLD , Passive scan CH 12, 13 */
62         {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13}, 13},              /*  0x01, RT_CHANNEL_DOMAIN_2G_ETSI1 */
63         {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}, 11},                      /*  0x02, RT_CHANNEL_DOMAIN_2G_FCC1 */
64         {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14}, 14},  /*  0x03, RT_CHANNEL_DOMAIN_2G_MIKK1 */
65         {{10, 11, 12, 13}, 4},                                  /*  0x04, RT_CHANNEL_DOMAIN_2G_ETSI2 */
66         {{}, 0},                                                                        /*  0x05, RT_CHANNEL_DOMAIN_2G_NULL */
67 };
68
69 static struct rt_channel_plan_map       RTW_ChannelPlanMap[RT_CHANNEL_DOMAIN_MAX] = {
70         /*  0x00 ~ 0x1F , Old Define ===== */
71         {0x02}, /* 0x00, RT_CHANNEL_DOMAIN_FCC */
72         {0x02}, /* 0x01, RT_CHANNEL_DOMAIN_IC */
73         {0x01}, /* 0x02, RT_CHANNEL_DOMAIN_ETSI */
74         {0x01}, /* 0x03, RT_CHANNEL_DOMAIN_SPAIN */
75         {0x01}, /* 0x04, RT_CHANNEL_DOMAIN_FRANCE */
76         {0x03}, /* 0x05, RT_CHANNEL_DOMAIN_MKK */
77         {0x03}, /* 0x06, RT_CHANNEL_DOMAIN_MKK1 */
78         {0x01}, /* 0x07, RT_CHANNEL_DOMAIN_ISRAEL */
79         {0x03}, /* 0x08, RT_CHANNEL_DOMAIN_TELEC */
80         {0x03}, /* 0x09, RT_CHANNEL_DOMAIN_GLOBAL_DOAMIN */
81         {0x00}, /* 0x0A, RT_CHANNEL_DOMAIN_WORLD_WIDE_13 */
82         {0x02}, /* 0x0B, RT_CHANNEL_DOMAIN_TAIWAN */
83         {0x01}, /* 0x0C, RT_CHANNEL_DOMAIN_CHINA */
84         {0x02}, /* 0x0D, RT_CHANNEL_DOMAIN_SINGAPORE_INDIA_MEXICO */
85         {0x02}, /* 0x0E, RT_CHANNEL_DOMAIN_KOREA */
86         {0x02}, /* 0x0F, RT_CHANNEL_DOMAIN_TURKEY */
87         {0x01}, /* 0x10, RT_CHANNEL_DOMAIN_JAPAN */
88         {0x02}, /* 0x11, RT_CHANNEL_DOMAIN_FCC_NO_DFS */
89         {0x01}, /* 0x12, RT_CHANNEL_DOMAIN_JAPAN_NO_DFS */
90         {0x00}, /* 0x13, RT_CHANNEL_DOMAIN_WORLD_WIDE_5G */
91         {0x02}, /* 0x14, RT_CHANNEL_DOMAIN_TAIWAN_NO_DFS */
92         {0x00}, /* 0x15, RT_CHANNEL_DOMAIN_ETSI_NO_DFS */
93         {0x00}, /* 0x16, RT_CHANNEL_DOMAIN_KOREA_NO_DFS */
94         {0x03}, /* 0x17, RT_CHANNEL_DOMAIN_JAPAN_NO_DFS */
95         {0x05}, /* 0x18, RT_CHANNEL_DOMAIN_PAKISTAN_NO_DFS */
96         {0x02}, /* 0x19, RT_CHANNEL_DOMAIN_TAIWAN2_NO_DFS */
97         {0x00}, /* 0x1A, */
98         {0x00}, /* 0x1B, */
99         {0x00}, /* 0x1C, */
100         {0x00}, /* 0x1D, */
101         {0x00}, /* 0x1E, */
102         {0x05}, /* 0x1F, RT_CHANNEL_DOMAIN_WORLD_WIDE_ONLY_5G */
103         /*  0x20 ~ 0x7F , New Define ===== */
104         {0x00}, /* 0x20, RT_CHANNEL_DOMAIN_WORLD_NULL */
105         {0x01}, /* 0x21, RT_CHANNEL_DOMAIN_ETSI1_NULL */
106         {0x02}, /* 0x22, RT_CHANNEL_DOMAIN_FCC1_NULL */
107         {0x03}, /* 0x23, RT_CHANNEL_DOMAIN_MKK1_NULL */
108         {0x04}, /* 0x24, RT_CHANNEL_DOMAIN_ETSI2_NULL */
109         {0x02}, /* 0x25, RT_CHANNEL_DOMAIN_FCC1_FCC1 */
110         {0x00}, /* 0x26, RT_CHANNEL_DOMAIN_WORLD_ETSI1 */
111         {0x03}, /* 0x27, RT_CHANNEL_DOMAIN_MKK1_MKK1 */
112         {0x00}, /* 0x28, RT_CHANNEL_DOMAIN_WORLD_KCC1 */
113         {0x00}, /* 0x29, RT_CHANNEL_DOMAIN_WORLD_FCC2 */
114         {0x00}, /* 0x2A, */
115         {0x00}, /* 0x2B, */
116         {0x00}, /* 0x2C, */
117         {0x00}, /* 0x2D, */
118         {0x00}, /* 0x2E, */
119         {0x00}, /* 0x2F, */
120         {0x00}, /* 0x30, RT_CHANNEL_DOMAIN_WORLD_FCC3 */
121         {0x00}, /* 0x31, RT_CHANNEL_DOMAIN_WORLD_FCC4 */
122         {0x00}, /* 0x32, RT_CHANNEL_DOMAIN_WORLD_FCC5 */
123         {0x00}, /* 0x33, RT_CHANNEL_DOMAIN_WORLD_FCC6 */
124         {0x02}, /* 0x34, RT_CHANNEL_DOMAIN_FCC1_FCC7 */
125         {0x00}, /* 0x35, RT_CHANNEL_DOMAIN_WORLD_ETSI2 */
126         {0x00}, /* 0x36, RT_CHANNEL_DOMAIN_WORLD_ETSI3 */
127         {0x03}, /* 0x37, RT_CHANNEL_DOMAIN_MKK1_MKK2 */
128         {0x03}, /* 0x38, RT_CHANNEL_DOMAIN_MKK1_MKK3 */
129         {0x02}, /* 0x39, RT_CHANNEL_DOMAIN_FCC1_NCC1 */
130         {0x00}, /* 0x3A, */
131         {0x00}, /* 0x3B, */
132         {0x00}, /* 0x3C, */
133         {0x00}, /* 0x3D, */
134         {0x00}, /* 0x3E, */
135         {0x00}, /* 0x3F, */
136         {0x02}, /* 0x40, RT_CHANNEL_DOMAIN_FCC1_NCC2 */
137         {0x03}, /* 0x41, RT_CHANNEL_DOMAIN_GLOBAL_DOAMIN_2G */
138 };
139
140 static struct rt_channel_plan_map RTW_CHANNEL_PLAN_MAP_REALTEK_DEFINE = {0x03}; /* use the combination for max channel numbers */
141
142 /*
143  * Search the @param channel_num in given @param channel_set
144  * @ch_set: the given channel set
145  * @ch: the given channel number
146  *
147  * return the index of channel_num in channel_set, -1 if not found
148  */
149 int rtw_ch_set_search_ch(struct rt_channel_info *ch_set, const u32 ch)
150 {
151         int i;
152         for (i = 0; ch_set[i].ChannelNum != 0; i++) {
153                 if (ch == ch_set[i].ChannelNum)
154                         break;
155         }
156
157         if (i >= ch_set[i].ChannelNum)
158                 return -1;
159         return i;
160 }
161
162 struct xmit_frame *alloc_mgtxmitframe(struct xmit_priv *pxmitpriv)
163 {
164         struct xmit_frame                       *pmgntframe;
165         struct xmit_buf                         *pxmitbuf;
166
167         pmgntframe = rtw_alloc_xmitframe(pxmitpriv);
168         if (pmgntframe == NULL) {
169                 DBG_88E("%s, alloc xmitframe fail\n", __func__);
170                 return NULL;
171         }
172
173         pxmitbuf = rtw_alloc_xmitbuf_ext(pxmitpriv);
174         if (pxmitbuf == NULL) {
175                 DBG_88E("%s, alloc xmitbuf fail\n", __func__);
176                 rtw_free_xmitframe(pxmitpriv, pmgntframe);
177                 return NULL;
178         }
179         pmgntframe->frame_tag = MGNT_FRAMETAG;
180         pmgntframe->pxmitbuf = pxmitbuf;
181         pmgntframe->buf_addr = pxmitbuf->pbuf;
182         pxmitbuf->priv_data = pmgntframe;
183         return pmgntframe;
184 }
185
186 /****************************************************************************
187
188 Following are some TX functions for WiFi MLME
189
190 *****************************************************************************/
191
192 void update_mgnt_tx_rate(struct adapter *padapter, u8 rate)
193 {
194         struct mlme_ext_priv    *pmlmeext = &(padapter->mlmeextpriv);
195
196         pmlmeext->tx_rate = rate;
197         DBG_88E("%s(): rate = %x\n", __func__, rate);
198 }
199
200 void update_mgntframe_attrib(struct adapter *padapter, struct pkt_attrib *pattrib)
201 {
202         struct mlme_ext_priv    *pmlmeext = &(padapter->mlmeextpriv);
203
204         memset((u8 *)(pattrib), 0, sizeof(struct pkt_attrib));
205
206         pattrib->hdrlen = 24;
207         pattrib->nr_frags = 1;
208         pattrib->priority = 7;
209         pattrib->mac_id = 0;
210         pattrib->qsel = 0x12;
211
212         pattrib->pktlen = 0;
213
214         if (pmlmeext->cur_wireless_mode & WIRELESS_11B)
215                 pattrib->raid = 6;/* b mode */
216         else
217                 pattrib->raid = 5;/* a/g mode */
218
219         pattrib->encrypt = _NO_PRIVACY_;
220         pattrib->bswenc = false;
221
222         pattrib->qos_en = false;
223         pattrib->ht_en = false;
224         pattrib->bwmode = HT_CHANNEL_WIDTH_20;
225         pattrib->ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
226         pattrib->sgi = false;
227
228         pattrib->seqnum = pmlmeext->mgnt_seq;
229
230         pattrib->retry_ctrl = true;
231 }
232
233 static void dump_mgntframe(struct adapter *padapter,
234                            struct xmit_frame *pmgntframe)
235 {
236         if (padapter->bSurpriseRemoved || padapter->bDriverStopped)
237                 return;
238
239         rtw_hal_mgnt_xmit(padapter, pmgntframe);
240 }
241
242 static s32 dump_mgntframe_and_wait(struct adapter *padapter,
243                                    struct xmit_frame *pmgntframe,
244                                    int timeout_ms)
245 {
246         s32 ret = _FAIL;
247         struct xmit_buf *pxmitbuf = pmgntframe->pxmitbuf;
248         struct submit_ctx sctx;
249
250         if (padapter->bSurpriseRemoved || padapter->bDriverStopped)
251                 return ret;
252
253         rtw_sctx_init(&sctx, timeout_ms);
254         pxmitbuf->sctx = &sctx;
255
256         ret = rtw_hal_mgnt_xmit(padapter, pmgntframe);
257
258         if (ret == _SUCCESS)
259                 ret = rtw_sctx_wait(&sctx);
260
261         return ret;
262 }
263
264 static s32 dump_mgntframe_and_wait_ack(struct adapter *padapter,
265                                        struct xmit_frame *pmgntframe)
266 {
267         s32 ret = _FAIL;
268         u32 timeout_ms = 500;/*   500ms */
269         struct xmit_priv        *pxmitpriv = &padapter->xmitpriv;
270
271         if (padapter->bSurpriseRemoved || padapter->bDriverStopped)
272                 return -1;
273
274         _enter_critical_mutex(&pxmitpriv->ack_tx_mutex, NULL);
275         pxmitpriv->ack_tx = true;
276
277         pmgntframe->ack_report = 1;
278         if (rtw_hal_mgnt_xmit(padapter, pmgntframe) == _SUCCESS) {
279                 ret = rtw_ack_tx_wait(pxmitpriv, timeout_ms);
280         }
281
282         pxmitpriv->ack_tx = false;
283         mutex_unlock(&pxmitpriv->ack_tx_mutex);
284
285          return ret;
286 }
287
288 static int update_hidden_ssid(u8 *ies, u32 ies_len, u8 hidden_ssid_mode)
289 {
290         u8 *ssid_ie;
291         int ssid_len_ori;
292         int len_diff = 0;
293
294         ssid_ie = rtw_get_ie(ies,  WLAN_EID_SSID, &ssid_len_ori, ies_len);
295
296         if (ssid_ie && ssid_len_ori > 0) {
297                 switch (hidden_ssid_mode) {
298                 case 1: {
299                         u8 *next_ie = ssid_ie + 2 + ssid_len_ori;
300                         u32 remain_len = 0;
301
302                         remain_len = ies_len - (next_ie - ies);
303
304                         ssid_ie[1] = 0;
305                         memcpy(ssid_ie+2, next_ie, remain_len);
306                         len_diff -= ssid_len_ori;
307
308                         break;
309                 }
310                 case 2:
311                         memset(&ssid_ie[2], 0, ssid_len_ori);
312                         break;
313                 default:
314                         break;
315                 }
316         }
317
318         return len_diff;
319 }
320
321 static void issue_beacon(struct adapter *padapter, int timeout_ms)
322 {
323         struct xmit_frame       *pmgntframe;
324         struct pkt_attrib       *pattrib;
325         unsigned char   *pframe;
326         struct rtw_ieee80211_hdr *pwlanhdr;
327         __le16 *fctrl;
328         unsigned int    rate_len;
329         struct xmit_priv        *pxmitpriv = &(padapter->xmitpriv);
330         struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
331         struct mlme_ext_priv    *pmlmeext = &(padapter->mlmeextpriv);
332         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
333         struct wlan_bssid_ex            *cur_network = &(pmlmeinfo->network);
334         u8      bc_addr[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
335
336         pmgntframe = alloc_mgtxmitframe(pxmitpriv);
337         if (pmgntframe == NULL) {
338                 DBG_88E("%s, alloc mgnt frame fail\n", __func__);
339                 return;
340         }
341 #if defined(CONFIG_88EU_AP_MODE)
342         spin_lock_bh(&pmlmepriv->bcn_update_lock);
343 #endif /* if defined (CONFIG_88EU_AP_MODE) */
344
345         /* update attribute */
346         pattrib = &pmgntframe->attrib;
347         update_mgntframe_attrib(padapter, pattrib);
348         pattrib->qsel = 0x10;
349
350         memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
351
352         pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
353         pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
354
355
356         fctrl = &(pwlanhdr->frame_ctl);
357         *(fctrl) = 0;
358
359         memcpy(pwlanhdr->addr1, bc_addr, ETH_ALEN);
360         memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN);
361         memcpy(pwlanhdr->addr3, cur_network->MacAddress, ETH_ALEN);
362
363         SetSeqNum(pwlanhdr, 0/*pmlmeext->mgnt_seq*/);
364         /* pmlmeext->mgnt_seq++; */
365         SetFrameSubType(pframe, WIFI_BEACON);
366
367         pframe += sizeof(struct rtw_ieee80211_hdr_3addr);
368         pattrib->pktlen = sizeof(struct rtw_ieee80211_hdr_3addr);
369
370         if ((pmlmeinfo->state&0x03) == WIFI_FW_AP_STATE) {
371                 int len_diff;
372                 u8 *wps_ie;
373                 uint wps_ielen;
374                 u8 sr = 0;
375                 memcpy(pframe, cur_network->IEs, cur_network->IELength);
376                 len_diff = update_hidden_ssid(
377                         pframe+_BEACON_IE_OFFSET_
378                         , cur_network->IELength-_BEACON_IE_OFFSET_
379                         , pmlmeinfo->hidden_ssid_mode
380                         );
381                 pframe += (cur_network->IELength+len_diff);
382                 pattrib->pktlen += (cur_network->IELength+len_diff);
383                 wps_ie = rtw_get_wps_ie(pmgntframe->buf_addr+TXDESC_OFFSET+sizeof(struct rtw_ieee80211_hdr_3addr)+_BEACON_IE_OFFSET_,
384                         pattrib->pktlen-sizeof(struct rtw_ieee80211_hdr_3addr)-_BEACON_IE_OFFSET_, NULL, &wps_ielen);
385                 if (wps_ie && wps_ielen > 0)
386                         rtw_get_wps_attr_content(wps_ie,  wps_ielen, WPS_ATTR_SELECTED_REGISTRAR, (u8 *)(&sr), NULL);
387                 if (sr != 0)
388                         set_fwstate(pmlmepriv, WIFI_UNDER_WPS);
389                 else
390                         _clr_fwstate_(pmlmepriv, WIFI_UNDER_WPS);
391
392                 goto _issue_bcn;
393         }
394
395         /* below for ad-hoc mode */
396
397         /* timestamp will be inserted by hardware */
398         pframe += 8;
399         pattrib->pktlen += 8;
400
401         /*  beacon interval: 2 bytes */
402
403         memcpy(pframe, (unsigned char *)(rtw_get_beacon_interval_from_ie(cur_network->IEs)), 2);
404
405         pframe += 2;
406         pattrib->pktlen += 2;
407
408         /*  capability info: 2 bytes */
409
410         memcpy(pframe, (unsigned char *)(rtw_get_capability_from_ie(cur_network->IEs)), 2);
411
412         pframe += 2;
413         pattrib->pktlen += 2;
414
415         /*  SSID */
416         pframe = rtw_set_ie(pframe, _SSID_IE_, cur_network->Ssid.SsidLength, cur_network->Ssid.Ssid, &pattrib->pktlen);
417
418         /*  supported rates... */
419         rate_len = rtw_get_rateset_len(cur_network->SupportedRates);
420         pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_, ((rate_len > 8) ? 8 : rate_len), cur_network->SupportedRates, &pattrib->pktlen);
421
422         /*  DS parameter set */
423         pframe = rtw_set_ie(pframe, _DSSET_IE_, 1, (unsigned char *)&(cur_network->Configuration.DSConfig), &pattrib->pktlen);
424
425         {
426                 u8 erpinfo = 0;
427                 u32 ATIMWindow;
428                 /*  IBSS Parameter Set... */
429                 ATIMWindow = 0;
430                 pframe = rtw_set_ie(pframe, _IBSS_PARA_IE_, 2, (unsigned char *)(&ATIMWindow), &pattrib->pktlen);
431
432                 /* ERP IE */
433                 pframe = rtw_set_ie(pframe, _ERPINFO_IE_, 1, &erpinfo, &pattrib->pktlen);
434         }
435
436         /*  EXTERNDED SUPPORTED RATE */
437         if (rate_len > 8)
438                 pframe = rtw_set_ie(pframe, _EXT_SUPPORTEDRATES_IE_, (rate_len - 8), (cur_network->SupportedRates + 8), &pattrib->pktlen);
439         /* todo:HT for adhoc */
440 _issue_bcn:
441
442 #if defined(CONFIG_88EU_AP_MODE)
443         pmlmepriv->update_bcn = false;
444
445         spin_unlock_bh(&pmlmepriv->bcn_update_lock);
446 #endif /* if defined (CONFIG_88EU_AP_MODE) */
447
448         if ((pattrib->pktlen + TXDESC_SIZE) > 512) {
449                 DBG_88E("beacon frame too large\n");
450                 return;
451         }
452
453         pattrib->last_txcmdsz = pattrib->pktlen;
454
455         /* DBG_88E("issue bcn_sz=%d\n", pattrib->last_txcmdsz); */
456         if (timeout_ms > 0)
457                 dump_mgntframe_and_wait(padapter, pmgntframe, timeout_ms);
458         else
459                 dump_mgntframe(padapter, pmgntframe);
460 }
461
462 static void issue_probersp(struct adapter *padapter, unsigned char *da)
463 {
464         struct xmit_frame                       *pmgntframe;
465         struct pkt_attrib                       *pattrib;
466         unsigned char                                   *pframe;
467         struct rtw_ieee80211_hdr        *pwlanhdr;
468         __le16 *fctrl;
469         unsigned char                                   *mac, *bssid;
470         struct xmit_priv        *pxmitpriv = &(padapter->xmitpriv);
471 #if defined(CONFIG_88EU_AP_MODE)
472         u8 *pwps_ie;
473         uint wps_ielen;
474         struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
475 #endif /* if defined (CONFIG_88EU_AP_MODE) */
476         struct mlme_ext_priv    *pmlmeext = &(padapter->mlmeextpriv);
477         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
478         struct wlan_bssid_ex            *cur_network = &(pmlmeinfo->network);
479         unsigned int    rate_len;
480
481         pmgntframe = alloc_mgtxmitframe(pxmitpriv);
482         if (pmgntframe == NULL) {
483                 DBG_88E("%s, alloc mgnt frame fail\n", __func__);
484                 return;
485         }
486
487         /* update attribute */
488         pattrib = &pmgntframe->attrib;
489         update_mgntframe_attrib(padapter, pattrib);
490
491         memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
492
493         pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
494         pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
495
496         mac = myid(&(padapter->eeprompriv));
497         bssid = cur_network->MacAddress;
498
499         fctrl = &(pwlanhdr->frame_ctl);
500         *(fctrl) = 0;
501         memcpy(pwlanhdr->addr1, da, ETH_ALEN);
502         memcpy(pwlanhdr->addr2, mac, ETH_ALEN);
503         memcpy(pwlanhdr->addr3, bssid, ETH_ALEN);
504
505         SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
506         pmlmeext->mgnt_seq++;
507         SetFrameSubType(fctrl, WIFI_PROBERSP);
508
509         pattrib->hdrlen = sizeof(struct rtw_ieee80211_hdr_3addr);
510         pattrib->pktlen = pattrib->hdrlen;
511         pframe += pattrib->hdrlen;
512
513         if (cur_network->IELength > MAX_IE_SZ)
514                 return;
515
516 #if defined(CONFIG_88EU_AP_MODE)
517         if ((pmlmeinfo->state&0x03) == WIFI_FW_AP_STATE) {
518                 pwps_ie = rtw_get_wps_ie(cur_network->IEs+_FIXED_IE_LENGTH_, cur_network->IELength-_FIXED_IE_LENGTH_, NULL, &wps_ielen);
519
520                 /* inerset & update wps_probe_resp_ie */
521                 if ((pmlmepriv->wps_probe_resp_ie != NULL) && pwps_ie && (wps_ielen > 0)) {
522                         uint wps_offset, remainder_ielen;
523                         u8 *premainder_ie;
524
525                         wps_offset = (uint)(pwps_ie - cur_network->IEs);
526
527                         premainder_ie = pwps_ie + wps_ielen;
528
529                         remainder_ielen = cur_network->IELength - wps_offset - wps_ielen;
530
531                         memcpy(pframe, cur_network->IEs, wps_offset);
532                         pframe += wps_offset;
533                         pattrib->pktlen += wps_offset;
534
535                         wps_ielen = (uint)pmlmepriv->wps_probe_resp_ie[1];/* to get ie data len */
536                         if ((wps_offset+wps_ielen+2) <= MAX_IE_SZ) {
537                                 memcpy(pframe, pmlmepriv->wps_probe_resp_ie, wps_ielen+2);
538                                 pframe += wps_ielen+2;
539                                 pattrib->pktlen += wps_ielen+2;
540                         }
541
542                         if ((wps_offset+wps_ielen+2+remainder_ielen) <= MAX_IE_SZ) {
543                                 memcpy(pframe, premainder_ie, remainder_ielen);
544                                 pframe += remainder_ielen;
545                                 pattrib->pktlen += remainder_ielen;
546                         }
547                 } else {
548                         memcpy(pframe, cur_network->IEs, cur_network->IELength);
549                         pframe += cur_network->IELength;
550                         pattrib->pktlen += cur_network->IELength;
551                 }
552         } else
553 #endif
554         {
555                 /* timestamp will be inserted by hardware */
556                 pframe += 8;
557                 pattrib->pktlen += 8;
558
559                 /*  beacon interval: 2 bytes */
560
561                 memcpy(pframe, (unsigned char *)(rtw_get_beacon_interval_from_ie(cur_network->IEs)), 2);
562
563                 pframe += 2;
564                 pattrib->pktlen += 2;
565
566                 /*  capability info: 2 bytes */
567
568                 memcpy(pframe, (unsigned char *)(rtw_get_capability_from_ie(cur_network->IEs)), 2);
569
570                 pframe += 2;
571                 pattrib->pktlen += 2;
572
573                 /* below for ad-hoc mode */
574
575                 /*  SSID */
576                 pframe = rtw_set_ie(pframe, _SSID_IE_, cur_network->Ssid.SsidLength, cur_network->Ssid.Ssid, &pattrib->pktlen);
577
578                 /*  supported rates... */
579                 rate_len = rtw_get_rateset_len(cur_network->SupportedRates);
580                 pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_, ((rate_len > 8) ? 8 : rate_len), cur_network->SupportedRates, &pattrib->pktlen);
581
582                 /*  DS parameter set */
583                 pframe = rtw_set_ie(pframe, _DSSET_IE_, 1, (unsigned char *)&(cur_network->Configuration.DSConfig), &pattrib->pktlen);
584
585                 if ((pmlmeinfo->state&0x03) == WIFI_FW_ADHOC_STATE) {
586                         u8 erpinfo = 0;
587                         u32 ATIMWindow;
588                         /*  IBSS Parameter Set... */
589                         /* ATIMWindow = cur->Configuration.ATIMWindow; */
590                         ATIMWindow = 0;
591                         pframe = rtw_set_ie(pframe, _IBSS_PARA_IE_, 2, (unsigned char *)(&ATIMWindow), &pattrib->pktlen);
592
593                         /* ERP IE */
594                         pframe = rtw_set_ie(pframe, _ERPINFO_IE_, 1, &erpinfo, &pattrib->pktlen);
595                 }
596
597
598                 /*  EXTERNDED SUPPORTED RATE */
599                 if (rate_len > 8)
600                         pframe = rtw_set_ie(pframe, _EXT_SUPPORTEDRATES_IE_, (rate_len - 8), (cur_network->SupportedRates + 8), &pattrib->pktlen);
601                 /* todo:HT for adhoc */
602         }
603
604         pattrib->last_txcmdsz = pattrib->pktlen;
605
606         dump_mgntframe(padapter, pmgntframe);
607
608         return;
609 }
610
611 static int _issue_probereq(struct adapter *padapter, struct ndis_802_11_ssid *pssid, u8 *da, int wait_ack)
612 {
613         int ret = _FAIL;
614         struct xmit_frame               *pmgntframe;
615         struct pkt_attrib               *pattrib;
616         unsigned char                   *pframe;
617         struct rtw_ieee80211_hdr        *pwlanhdr;
618         __le16 *fctrl;
619         unsigned char                   *mac;
620         unsigned char                   bssrate[NumRates];
621         struct xmit_priv                *pxmitpriv = &(padapter->xmitpriv);
622         struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
623         struct mlme_ext_priv    *pmlmeext = &(padapter->mlmeextpriv);
624         int     bssrate_len = 0;
625         u8      bc_addr[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
626
627         RT_TRACE(_module_rtl871x_mlme_c_, _drv_notice_, ("+issue_probereq\n"));
628
629         pmgntframe = alloc_mgtxmitframe(pxmitpriv);
630         if (pmgntframe == NULL)
631                 goto exit;
632
633         /* update attribute */
634         pattrib = &pmgntframe->attrib;
635         update_mgntframe_attrib(padapter, pattrib);
636
637
638         memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
639
640         pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
641         pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
642
643         mac = myid(&(padapter->eeprompriv));
644
645         fctrl = &(pwlanhdr->frame_ctl);
646         *(fctrl) = 0;
647
648         if (da) {
649                 /*      unicast probe request frame */
650                 memcpy(pwlanhdr->addr1, da, ETH_ALEN);
651                 memcpy(pwlanhdr->addr3, da, ETH_ALEN);
652         } else {
653                 /*      broadcast probe request frame */
654                 memcpy(pwlanhdr->addr1, bc_addr, ETH_ALEN);
655                 memcpy(pwlanhdr->addr3, bc_addr, ETH_ALEN);
656         }
657
658         memcpy(pwlanhdr->addr2, mac, ETH_ALEN);
659
660         SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
661         pmlmeext->mgnt_seq++;
662         SetFrameSubType(pframe, WIFI_PROBEREQ);
663
664         pframe += sizeof(struct rtw_ieee80211_hdr_3addr);
665         pattrib->pktlen = sizeof(struct rtw_ieee80211_hdr_3addr);
666
667         if (pssid)
668                 pframe = rtw_set_ie(pframe, _SSID_IE_, pssid->SsidLength, pssid->Ssid, &(pattrib->pktlen));
669         else
670                 pframe = rtw_set_ie(pframe, _SSID_IE_, 0, NULL, &(pattrib->pktlen));
671
672         get_rate_set(padapter, bssrate, &bssrate_len);
673
674         if (bssrate_len > 8) {
675                 pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_ , 8, bssrate, &(pattrib->pktlen));
676                 pframe = rtw_set_ie(pframe, _EXT_SUPPORTEDRATES_IE_ , (bssrate_len - 8), (bssrate + 8), &(pattrib->pktlen));
677         } else {
678                 pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_ , bssrate_len , bssrate, &(pattrib->pktlen));
679         }
680
681         /* add wps_ie for wps2.0 */
682         if (pmlmepriv->wps_probe_req_ie_len > 0 && pmlmepriv->wps_probe_req_ie) {
683                 memcpy(pframe, pmlmepriv->wps_probe_req_ie, pmlmepriv->wps_probe_req_ie_len);
684                 pframe += pmlmepriv->wps_probe_req_ie_len;
685                 pattrib->pktlen += pmlmepriv->wps_probe_req_ie_len;
686         }
687
688         pattrib->last_txcmdsz = pattrib->pktlen;
689
690         RT_TRACE(_module_rtl871x_mlme_c_, _drv_notice_,
691                  ("issuing probe_req, tx_len=%d\n", pattrib->last_txcmdsz));
692
693         if (wait_ack) {
694                 ret = dump_mgntframe_and_wait_ack(padapter, pmgntframe);
695         } else {
696                 dump_mgntframe(padapter, pmgntframe);
697                 ret = _SUCCESS;
698         }
699
700 exit:
701         return ret;
702 }
703
704 static inline void issue_probereq(struct adapter *padapter,
705                                   struct ndis_802_11_ssid *pssid, u8 *da)
706 {
707         _issue_probereq(padapter, pssid, da, false);
708 }
709
710 static int issue_probereq_ex(struct adapter *padapter,
711                              struct ndis_802_11_ssid *pssid, u8 *da,
712                              int try_cnt, int wait_ms)
713 {
714         int ret;
715         int i = 0;
716         u32 start = jiffies;
717
718         do {
719                 ret = _issue_probereq(padapter, pssid, da, wait_ms > 0 ? true : false);
720
721                 i++;
722
723                 if (padapter->bDriverStopped || padapter->bSurpriseRemoved)
724                         break;
725
726                 if (i < try_cnt && wait_ms > 0 && ret == _FAIL)
727                         msleep(wait_ms);
728
729         } while ((i < try_cnt) && ((ret == _FAIL) || (wait_ms == 0)));
730
731         if (ret != _FAIL) {
732                 ret = _SUCCESS;
733                 goto exit;
734         }
735
736         if (try_cnt && wait_ms) {
737                 if (da)
738                         DBG_88E(FUNC_ADPT_FMT" to %pM, ch:%u%s, %d/%d in %u ms\n",
739                                 FUNC_ADPT_ARG(padapter), da, rtw_get_oper_ch(padapter),
740                                 ret == _SUCCESS ? ", acked" : "", i, try_cnt, rtw_get_passing_time_ms(start));
741                 else
742                         DBG_88E(FUNC_ADPT_FMT", ch:%u%s, %d/%d in %u ms\n",
743                                 FUNC_ADPT_ARG(padapter), rtw_get_oper_ch(padapter),
744                                 ret == _SUCCESS ? ", acked" : "", i, try_cnt, rtw_get_passing_time_ms(start));
745         }
746 exit:
747         return ret;
748 }
749
750 /*  if psta == NULL, indicate we are station(client) now... */
751 static void issue_auth(struct adapter *padapter, struct sta_info *psta,
752                        unsigned short status)
753 {
754         struct xmit_frame *pmgntframe;
755         struct pkt_attrib *pattrib;
756         unsigned char *pframe;
757         struct rtw_ieee80211_hdr *pwlanhdr;
758         __le16 *fctrl;
759         unsigned int val32;
760         u16 val16;
761 #ifdef CONFIG_88EU_AP_MODE
762         __le16 le_val16;
763 #endif
764         int use_shared_key = 0;
765         struct xmit_priv *pxmitpriv = &(padapter->xmitpriv);
766         struct mlme_ext_priv    *pmlmeext = &(padapter->mlmeextpriv);
767         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
768         struct wlan_bssid_ex    *pnetwork = &(pmlmeinfo->network);
769
770         pmgntframe = alloc_mgtxmitframe(pxmitpriv);
771         if (pmgntframe == NULL)
772                 return;
773
774         /* update attribute */
775         pattrib = &pmgntframe->attrib;
776         update_mgntframe_attrib(padapter, pattrib);
777
778         memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
779
780         pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
781         pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
782
783         fctrl = &(pwlanhdr->frame_ctl);
784         *(fctrl) = 0;
785
786         SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
787         pmlmeext->mgnt_seq++;
788         SetFrameSubType(pframe, WIFI_AUTH);
789
790         pframe += sizeof(struct rtw_ieee80211_hdr_3addr);
791         pattrib->pktlen = sizeof(struct rtw_ieee80211_hdr_3addr);
792
793
794         if (psta) {/*  for AP mode */
795 #ifdef CONFIG_88EU_AP_MODE
796
797                 memcpy(pwlanhdr->addr1, psta->hwaddr, ETH_ALEN);
798                 memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN);
799                 memcpy(pwlanhdr->addr3, myid(&(padapter->eeprompriv)), ETH_ALEN);
800
801
802                 /*  setting auth algo number */
803                 val16 = (u16)psta->authalg;
804
805                 if (status != _STATS_SUCCESSFUL_)
806                         val16 = 0;
807
808                 if (val16) {
809                         le_val16 = cpu_to_le16(val16);
810                         use_shared_key = 1;
811                 } else {
812                         le_val16 = 0;
813                 }
814
815                 pframe = rtw_set_fixed_ie(pframe, _AUTH_ALGM_NUM_, (unsigned char *)&le_val16, &(pattrib->pktlen));
816
817                 /*  setting auth seq number */
818                 val16 = (u16)psta->auth_seq;
819                 le_val16 = cpu_to_le16(val16);
820                 pframe = rtw_set_fixed_ie(pframe, _AUTH_SEQ_NUM_, (unsigned char *)&le_val16, &(pattrib->pktlen));
821
822                 /*  setting status code... */
823                 val16 = status;
824                 le_val16 = cpu_to_le16(val16);
825                 pframe = rtw_set_fixed_ie(pframe, _STATUS_CODE_, (unsigned char *)&le_val16, &(pattrib->pktlen));
826
827                 /*  added challenging text... */
828                 if ((psta->auth_seq == 2) && (psta->state & WIFI_FW_AUTH_STATE) && (use_shared_key == 1))
829                         pframe = rtw_set_ie(pframe, _CHLGETXT_IE_, 128, psta->chg_txt, &(pattrib->pktlen));
830 #endif
831         } else {
832                 __le32 le_tmp32;
833                 __le16 le_tmp16;
834                 memcpy(pwlanhdr->addr1, pnetwork->MacAddress, ETH_ALEN);
835                 memcpy(pwlanhdr->addr2, myid(&padapter->eeprompriv), ETH_ALEN);
836                 memcpy(pwlanhdr->addr3, pnetwork->MacAddress, ETH_ALEN);
837
838                 /*  setting auth algo number */
839                 val16 = (pmlmeinfo->auth_algo == dot11AuthAlgrthm_Shared) ? 1 : 0;/*  0:OPEN System, 1:Shared key */
840                 if (val16)
841                         use_shared_key = 1;
842
843                 /* setting IV for auth seq #3 */
844                 if ((pmlmeinfo->auth_seq == 3) && (pmlmeinfo->state & WIFI_FW_AUTH_STATE) && (use_shared_key == 1)) {
845                         val32 = (pmlmeinfo->iv++) | (pmlmeinfo->key_index << 30);
846                         le_tmp32 = cpu_to_le32(val32);
847                         pframe = rtw_set_fixed_ie(pframe, 4, (unsigned char *)&le_tmp32, &(pattrib->pktlen));
848
849                         pattrib->iv_len = 4;
850                 }
851
852                 le_tmp16 = cpu_to_le16(val16);
853                 pframe = rtw_set_fixed_ie(pframe, _AUTH_ALGM_NUM_, (unsigned char *)&le_tmp16, &(pattrib->pktlen));
854
855                 /*  setting auth seq number */
856                 val16 = pmlmeinfo->auth_seq;
857                 le_tmp16 = cpu_to_le16(val16);
858                 pframe = rtw_set_fixed_ie(pframe, _AUTH_SEQ_NUM_, (unsigned char *)&le_tmp16, &(pattrib->pktlen));
859
860
861                 /*  setting status code... */
862                 le_tmp16 = cpu_to_le16(status);
863                 pframe = rtw_set_fixed_ie(pframe, _STATUS_CODE_, (unsigned char *)&le_tmp16, &(pattrib->pktlen));
864
865                 /*  then checking to see if sending challenging text... */
866                 if ((pmlmeinfo->auth_seq == 3) && (pmlmeinfo->state & WIFI_FW_AUTH_STATE) && (use_shared_key == 1)) {
867                         pframe = rtw_set_ie(pframe, _CHLGETXT_IE_, 128, pmlmeinfo->chg_txt, &(pattrib->pktlen));
868
869                         SetPrivacy(fctrl);
870
871                         pattrib->hdrlen = sizeof(struct rtw_ieee80211_hdr_3addr);
872
873                         pattrib->encrypt = _WEP40_;
874
875                         pattrib->icv_len = 4;
876
877                         pattrib->pktlen += pattrib->icv_len;
878                 }
879         }
880
881         pattrib->last_txcmdsz = pattrib->pktlen;
882
883         rtw_wep_encrypt(padapter, (u8 *)pmgntframe);
884         DBG_88E("%s\n", __func__);
885         dump_mgntframe(padapter, pmgntframe);
886
887         return;
888 }
889
890
891 #ifdef CONFIG_88EU_AP_MODE
892 static void issue_asocrsp(struct adapter *padapter, unsigned short status,
893                           struct sta_info *pstat, int pkt_type)
894 {
895         struct xmit_frame       *pmgntframe;
896         struct rtw_ieee80211_hdr        *pwlanhdr;
897         struct pkt_attrib *pattrib;
898         unsigned char   *pbuf, *pframe;
899         unsigned short val;
900         __le16 *fctrl;
901         struct xmit_priv *pxmitpriv = &(padapter->xmitpriv);
902         struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
903         struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
904         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
905         struct wlan_bssid_ex *pnetwork = &(pmlmeinfo->network);
906         u8 *ie = pnetwork->IEs;
907         __le16 lestatus, leval;
908
909         DBG_88E("%s\n", __func__);
910
911         pmgntframe = alloc_mgtxmitframe(pxmitpriv);
912         if (pmgntframe == NULL)
913                 return;
914
915         /* update attribute */
916         pattrib = &pmgntframe->attrib;
917         update_mgntframe_attrib(padapter, pattrib);
918
919
920         memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
921
922         pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
923         pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
924
925         fctrl = &(pwlanhdr->frame_ctl);
926         *(fctrl) = 0;
927
928         memcpy((void *)GetAddr1Ptr(pwlanhdr), pstat->hwaddr, ETH_ALEN);
929         memcpy((void *)GetAddr2Ptr(pwlanhdr), myid(&(padapter->eeprompriv)), ETH_ALEN);
930         memcpy((void *)GetAddr3Ptr(pwlanhdr), pnetwork->MacAddress, ETH_ALEN);
931
932
933         SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
934         pmlmeext->mgnt_seq++;
935         if ((pkt_type == WIFI_ASSOCRSP) || (pkt_type == WIFI_REASSOCRSP))
936                 SetFrameSubType(pwlanhdr, pkt_type);
937         else
938                 return;
939
940         pattrib->hdrlen = sizeof(struct rtw_ieee80211_hdr_3addr);
941         pattrib->pktlen += pattrib->hdrlen;
942         pframe += pattrib->hdrlen;
943
944         /* capability */
945         val = *(unsigned short *)rtw_get_capability_from_ie(ie);
946
947         pframe = rtw_set_fixed_ie(pframe, _CAPABILITY_ , (unsigned char *)&val, &(pattrib->pktlen));
948
949         lestatus = cpu_to_le16(status);
950         pframe = rtw_set_fixed_ie(pframe , _STATUS_CODE_ , (unsigned char *)&lestatus, &(pattrib->pktlen));
951
952         leval = cpu_to_le16(pstat->aid | BIT(14) | BIT(15));
953         pframe = rtw_set_fixed_ie(pframe, _ASOC_ID_ , (unsigned char *)&leval, &(pattrib->pktlen));
954
955         if (pstat->bssratelen <= 8) {
956                 pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_, pstat->bssratelen, pstat->bssrateset, &(pattrib->pktlen));
957         } else {
958                 pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_, 8, pstat->bssrateset, &(pattrib->pktlen));
959                 pframe = rtw_set_ie(pframe, _EXT_SUPPORTEDRATES_IE_, (pstat->bssratelen-8), pstat->bssrateset+8, &(pattrib->pktlen));
960         }
961
962         if ((pstat->flags & WLAN_STA_HT) && (pmlmepriv->htpriv.ht_option)) {
963                 uint ie_len = 0;
964
965                 /* FILL HT CAP INFO IE */
966                 pbuf = rtw_get_ie(ie + _BEACON_IE_OFFSET_, _HT_CAPABILITY_IE_, &ie_len, (pnetwork->IELength - _BEACON_IE_OFFSET_));
967                 if (pbuf && ie_len > 0) {
968                         memcpy(pframe, pbuf, ie_len+2);
969                         pframe += (ie_len+2);
970                         pattrib->pktlen += (ie_len+2);
971                 }
972
973                 /* FILL HT ADD INFO IE */
974                 pbuf = rtw_get_ie(ie + _BEACON_IE_OFFSET_, _HT_ADD_INFO_IE_, &ie_len, (pnetwork->IELength - _BEACON_IE_OFFSET_));
975                 if (pbuf && ie_len > 0) {
976                         memcpy(pframe, pbuf, ie_len+2);
977                         pframe += (ie_len+2);
978                         pattrib->pktlen += (ie_len+2);
979                 }
980         }
981
982         /* FILL WMM IE */
983         if ((pstat->flags & WLAN_STA_WME) && (pmlmepriv->qospriv.qos_option)) {
984                 uint ie_len = 0;
985                 unsigned char WMM_PARA_IE[] = {0x00, 0x50, 0xf2, 0x02, 0x01, 0x01};
986
987                 for (pbuf = ie + _BEACON_IE_OFFSET_;; pbuf += (ie_len + 2)) {
988                         pbuf = rtw_get_ie(pbuf, _VENDOR_SPECIFIC_IE_, &ie_len, (pnetwork->IELength - _BEACON_IE_OFFSET_ - (ie_len + 2)));
989                         if (pbuf && !memcmp(pbuf+2, WMM_PARA_IE, 6)) {
990                                 memcpy(pframe, pbuf, ie_len+2);
991                                 pframe += (ie_len+2);
992                                 pattrib->pktlen += (ie_len+2);
993                                 break;
994                         }
995
996                         if ((pbuf == NULL) || (ie_len == 0))
997                                 break;
998                 }
999         }
1000
1001         if (pmlmeinfo->assoc_AP_vendor == HT_IOT_PEER_REALTEK)
1002                 pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, 6 , REALTEK_96B_IE, &(pattrib->pktlen));
1003
1004         /* add WPS IE ie for wps 2.0 */
1005         if (pmlmepriv->wps_assoc_resp_ie && pmlmepriv->wps_assoc_resp_ie_len > 0) {
1006                 memcpy(pframe, pmlmepriv->wps_assoc_resp_ie, pmlmepriv->wps_assoc_resp_ie_len);
1007
1008                 pframe += pmlmepriv->wps_assoc_resp_ie_len;
1009                 pattrib->pktlen += pmlmepriv->wps_assoc_resp_ie_len;
1010         }
1011
1012         pattrib->last_txcmdsz = pattrib->pktlen;
1013         dump_mgntframe(padapter, pmgntframe);
1014 }
1015 #endif /* CONFIG_88EU_AP_MODE */
1016
1017 static void issue_assocreq(struct adapter *padapter)
1018 {
1019         int ret = _FAIL;
1020         struct xmit_frame       *pmgntframe;
1021         struct pkt_attrib       *pattrib;
1022         unsigned char           *pframe, *p;
1023         struct rtw_ieee80211_hdr        *pwlanhdr;
1024         __le16 *fctrl;
1025         __le16          le_tmp;
1026         unsigned int    i, j, ie_len, index = 0;
1027         unsigned char   rf_type, bssrate[NumRates], sta_bssrate[NumRates];
1028         struct ndis_802_11_var_ie *pIE;
1029         struct registry_priv    *pregpriv = &padapter->registrypriv;
1030         struct xmit_priv                *pxmitpriv = &(padapter->xmitpriv);
1031         struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
1032         struct mlme_ext_priv    *pmlmeext = &(padapter->mlmeextpriv);
1033         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
1034         int     bssrate_len = 0, sta_bssrate_len = 0;
1035         struct wlan_bssid_ex    *pnetwork = &(pmlmeinfo->network);
1036
1037         pmgntframe = alloc_mgtxmitframe(pxmitpriv);
1038         if (pmgntframe == NULL)
1039                 goto exit;
1040
1041         /* update attribute */
1042         pattrib = &pmgntframe->attrib;
1043         update_mgntframe_attrib(padapter, pattrib);
1044
1045         memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
1046         pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
1047         pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
1048
1049         fctrl = &(pwlanhdr->frame_ctl);
1050         *(fctrl) = 0;
1051         memcpy(pwlanhdr->addr1, pnetwork->MacAddress, ETH_ALEN);
1052         memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN);
1053         memcpy(pwlanhdr->addr3, pnetwork->MacAddress, ETH_ALEN);
1054
1055         SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
1056         pmlmeext->mgnt_seq++;
1057         SetFrameSubType(pframe, WIFI_ASSOCREQ);
1058
1059         pframe += sizeof(struct rtw_ieee80211_hdr_3addr);
1060         pattrib->pktlen = sizeof(struct rtw_ieee80211_hdr_3addr);
1061
1062         /* caps */
1063
1064         memcpy(pframe, rtw_get_capability_from_ie(pmlmeinfo->network.IEs), 2);
1065
1066         pframe += 2;
1067         pattrib->pktlen += 2;
1068
1069         /* listen interval */
1070         /* todo: listen interval for power saving */
1071         le_tmp = cpu_to_le16(3);
1072         memcpy(pframe , (unsigned char *)&le_tmp, 2);
1073         pframe += 2;
1074         pattrib->pktlen += 2;
1075
1076         /* SSID */
1077         pframe = rtw_set_ie(pframe, _SSID_IE_,  pmlmeinfo->network.Ssid.SsidLength, pmlmeinfo->network.Ssid.Ssid, &(pattrib->pktlen));
1078
1079         /* supported rate & extended supported rate */
1080
1081         /*  Check if the AP's supported rates are also supported by STA. */
1082         get_rate_set(padapter, sta_bssrate, &sta_bssrate_len);
1083
1084         if (pmlmeext->cur_channel == 14)/*  for JAPAN, channel 14 can only uses B Mode(CCK) */
1085                 sta_bssrate_len = 4;
1086
1087         for (i = 0; i < NDIS_802_11_LENGTH_RATES_EX; i++) {
1088                 if (pmlmeinfo->network.SupportedRates[i] == 0)
1089                         break;
1090                 DBG_88E("network.SupportedRates[%d]=%02X\n", i, pmlmeinfo->network.SupportedRates[i]);
1091         }
1092
1093         for (i = 0; i < NDIS_802_11_LENGTH_RATES_EX; i++) {
1094                 if (pmlmeinfo->network.SupportedRates[i] == 0)
1095                         break;
1096
1097                 /*  Check if the AP's supported rates are also supported by STA. */
1098                 for (j = 0; j < sta_bssrate_len; j++) {
1099                          /*  Avoid the proprietary data rate (22Mbps) of Handlink WSG-4000 AP */
1100                         if ((pmlmeinfo->network.SupportedRates[i]|IEEE80211_BASIC_RATE_MASK)
1101                                         == (sta_bssrate[j]|IEEE80211_BASIC_RATE_MASK))
1102                                 break;
1103                 }
1104
1105                 if (j == sta_bssrate_len) {
1106                         /*  the rate is not supported by STA */
1107                         DBG_88E("%s(): the rate[%d]=%02X is not supported by STA!\n", __func__, i, pmlmeinfo->network.SupportedRates[i]);
1108                 } else {
1109                         /*  the rate is supported by STA */
1110                         bssrate[index++] = pmlmeinfo->network.SupportedRates[i];
1111                 }
1112         }
1113
1114         bssrate_len = index;
1115         DBG_88E("bssrate_len=%d\n", bssrate_len);
1116
1117         if (bssrate_len == 0) {
1118                 rtw_free_xmitbuf(pxmitpriv, pmgntframe->pxmitbuf);
1119                 rtw_free_xmitframe(pxmitpriv, pmgntframe);
1120                 goto exit; /* don't connect to AP if no joint supported rate */
1121         }
1122
1123
1124         if (bssrate_len > 8) {
1125                 pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_ , 8, bssrate, &(pattrib->pktlen));
1126                 pframe = rtw_set_ie(pframe, _EXT_SUPPORTEDRATES_IE_ , (bssrate_len - 8), (bssrate + 8), &(pattrib->pktlen));
1127         } else {
1128                 pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_ , bssrate_len , bssrate, &(pattrib->pktlen));
1129         }
1130
1131         /* RSN */
1132         p = rtw_get_ie((pmlmeinfo->network.IEs + sizeof(struct ndis_802_11_fixed_ie)), _RSN_IE_2_, &ie_len, (pmlmeinfo->network.IELength - sizeof(struct ndis_802_11_fixed_ie)));
1133         if (p != NULL)
1134                 pframe = rtw_set_ie(pframe, _RSN_IE_2_, ie_len, (p + 2), &(pattrib->pktlen));
1135
1136         /* HT caps */
1137         if (padapter->mlmepriv.htpriv.ht_option) {
1138                 p = rtw_get_ie((pmlmeinfo->network.IEs + sizeof(struct ndis_802_11_fixed_ie)), _HT_CAPABILITY_IE_, &ie_len, (pmlmeinfo->network.IELength - sizeof(struct ndis_802_11_fixed_ie)));
1139                 if ((p != NULL) && (!(is_ap_in_tkip(padapter)))) {
1140                         memcpy(&(pmlmeinfo->HT_caps), (p + 2), sizeof(struct HT_caps_element));
1141
1142                         /* to disable 40M Hz support while gd_bw_40MHz_en = 0 */
1143                         if (pregpriv->cbw40_enable == 0)
1144                                 pmlmeinfo->HT_caps.u.HT_cap_element.HT_caps_info &= cpu_to_le16(~(BIT(6) | BIT(1)));
1145                         else
1146                                 pmlmeinfo->HT_caps.u.HT_cap_element.HT_caps_info |= cpu_to_le16(BIT(1));
1147
1148                         /* todo: disable SM power save mode */
1149                         pmlmeinfo->HT_caps.u.HT_cap_element.HT_caps_info |= cpu_to_le16(0x000c);
1150
1151                         rtw_hal_get_hwreg(padapter, HW_VAR_RF_TYPE, (u8 *)(&rf_type));
1152                         switch (rf_type) {
1153                         case RF_1T1R:
1154                                 if (pregpriv->rx_stbc)
1155                                         pmlmeinfo->HT_caps.u.HT_cap_element.HT_caps_info |= cpu_to_le16(0x0100);/* RX STBC One spatial stream */
1156                                 memcpy(pmlmeinfo->HT_caps.u.HT_cap_element.MCS_rate, MCS_rate_1R, 16);
1157                                 break;
1158                         case RF_2T2R:
1159                         case RF_1T2R:
1160                         default:
1161                                 if ((pregpriv->rx_stbc == 0x3) ||/* enable for 2.4/5 GHz */
1162                                     ((pmlmeext->cur_wireless_mode & WIRELESS_11_24N) && (pregpriv->rx_stbc == 0x1)) || /* enable for 2.4GHz */
1163                                     (pregpriv->wifi_spec == 1)) {
1164                                         DBG_88E("declare supporting RX STBC\n");
1165                                         pmlmeinfo->HT_caps.u.HT_cap_element.HT_caps_info |= cpu_to_le16(0x0200);/* RX STBC two spatial stream */
1166                                 }
1167                                 memcpy(pmlmeinfo->HT_caps.u.HT_cap_element.MCS_rate, MCS_rate_2R, 16);
1168                                 break;
1169                         }
1170                         pframe = rtw_set_ie(pframe, _HT_CAPABILITY_IE_, ie_len , (u8 *)(&(pmlmeinfo->HT_caps)), &(pattrib->pktlen));
1171                 }
1172         }
1173
1174         /* vendor specific IE, such as WPA, WMM, WPS */
1175         for (i = sizeof(struct ndis_802_11_fixed_ie); i < pmlmeinfo->network.IELength;) {
1176                 pIE = (struct ndis_802_11_var_ie *)(pmlmeinfo->network.IEs + i);
1177
1178                 switch (pIE->ElementID) {
1179                 case _VENDOR_SPECIFIC_IE_:
1180                         if ((!memcmp(pIE->data, RTW_WPA_OUI, 4)) ||
1181                             (!memcmp(pIE->data, WMM_OUI, 4)) ||
1182                             (!memcmp(pIE->data, WPS_OUI, 4))) {
1183                                 if (!padapter->registrypriv.wifi_spec) {
1184                                         /* Commented by Kurt 20110629 */
1185                                         /* In some older APs, WPS handshake */
1186                                         /* would be fail if we append vender extensions informations to AP */
1187                                         if (!memcmp(pIE->data, WPS_OUI, 4))
1188                                                 pIE->Length = 14;
1189                                 }
1190                                 pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, pIE->Length, pIE->data, &(pattrib->pktlen));
1191                         }
1192                         break;
1193                 default:
1194                         break;
1195                 }
1196                 i += (pIE->Length + 2);
1197         }
1198
1199         if (pmlmeinfo->assoc_AP_vendor == HT_IOT_PEER_REALTEK)
1200                 pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, 6 , REALTEK_96B_IE, &(pattrib->pktlen));
1201
1202         pattrib->last_txcmdsz = pattrib->pktlen;
1203         dump_mgntframe(padapter, pmgntframe);
1204
1205         ret = _SUCCESS;
1206
1207 exit:
1208         if (ret == _SUCCESS)
1209                 rtw_buf_update(&pmlmepriv->assoc_req, &pmlmepriv->assoc_req_len, (u8 *)pwlanhdr, pattrib->pktlen);
1210         else
1211                 rtw_buf_free(&pmlmepriv->assoc_req, &pmlmepriv->assoc_req_len);
1212
1213         return;
1214 }
1215
1216 /* when wait_ack is true, this function should be called at process context */
1217 static int _issue_nulldata(struct adapter *padapter, unsigned char *da, unsigned int power_mode, int wait_ack)
1218 {
1219         int ret = _FAIL;
1220         struct xmit_frame                       *pmgntframe;
1221         struct pkt_attrib                       *pattrib;
1222         unsigned char                                   *pframe;
1223         struct rtw_ieee80211_hdr        *pwlanhdr;
1224         __le16 *fctrl;
1225         struct xmit_priv        *pxmitpriv;
1226         struct mlme_ext_priv    *pmlmeext;
1227         struct mlme_ext_info    *pmlmeinfo;
1228         struct wlan_bssid_ex    *pnetwork;
1229
1230         if (!padapter)
1231                 goto exit;
1232
1233         pxmitpriv = &(padapter->xmitpriv);
1234         pmlmeext = &(padapter->mlmeextpriv);
1235         pmlmeinfo = &(pmlmeext->mlmext_info);
1236         pnetwork = &(pmlmeinfo->network);
1237
1238         pmgntframe = alloc_mgtxmitframe(pxmitpriv);
1239         if (pmgntframe == NULL)
1240                 goto exit;
1241
1242         /* update attribute */
1243         pattrib = &pmgntframe->attrib;
1244         update_mgntframe_attrib(padapter, pattrib);
1245         pattrib->retry_ctrl = false;
1246
1247         memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
1248
1249         pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
1250         pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
1251
1252         fctrl = &(pwlanhdr->frame_ctl);
1253         *(fctrl) = 0;
1254
1255         if ((pmlmeinfo->state&0x03) == WIFI_FW_AP_STATE)
1256                 SetFrDs(fctrl);
1257         else if ((pmlmeinfo->state&0x03) == WIFI_FW_STATION_STATE)
1258                 SetToDs(fctrl);
1259
1260         if (power_mode)
1261                 SetPwrMgt(fctrl);
1262
1263         memcpy(pwlanhdr->addr1, da, ETH_ALEN);
1264         memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN);
1265         memcpy(pwlanhdr->addr3, pnetwork->MacAddress, ETH_ALEN);
1266
1267         SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
1268         pmlmeext->mgnt_seq++;
1269         SetFrameSubType(pframe, WIFI_DATA_NULL);
1270
1271         pframe += sizeof(struct rtw_ieee80211_hdr_3addr);
1272         pattrib->pktlen = sizeof(struct rtw_ieee80211_hdr_3addr);
1273
1274         pattrib->last_txcmdsz = pattrib->pktlen;
1275
1276         if (wait_ack) {
1277                 ret = dump_mgntframe_and_wait_ack(padapter, pmgntframe);
1278         } else {
1279                 dump_mgntframe(padapter, pmgntframe);
1280                 ret = _SUCCESS;
1281         }
1282
1283 exit:
1284         return ret;
1285 }
1286
1287
1288 /* when wait_ms > 0 , this function should be called at process context */
1289 /* da == NULL for station mode */
1290 int issue_nulldata(struct adapter *padapter, unsigned char *da, unsigned int power_mode, int try_cnt, int wait_ms)
1291 {
1292         int ret;
1293         int i = 0;
1294         u32 start = jiffies;
1295         struct mlme_ext_priv    *pmlmeext = &(padapter->mlmeextpriv);
1296         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
1297         struct wlan_bssid_ex    *pnetwork = &(pmlmeinfo->network);
1298
1299         /* da == NULL, assume it's null data for sta to ap*/
1300         if (da == NULL)
1301                 da = pnetwork->MacAddress;
1302
1303         do {
1304                 ret = _issue_nulldata(padapter, da, power_mode, wait_ms > 0 ? true : false);
1305
1306                 i++;
1307
1308                 if (padapter->bDriverStopped || padapter->bSurpriseRemoved)
1309                         break;
1310
1311                 if (i < try_cnt && wait_ms > 0 && ret == _FAIL)
1312                         msleep(wait_ms);
1313         } while ((i < try_cnt) && ((ret == _FAIL) || (wait_ms == 0)));
1314
1315         if (ret != _FAIL) {
1316                 ret = _SUCCESS;
1317                 goto exit;
1318         }
1319
1320         if (try_cnt && wait_ms) {
1321                 if (da)
1322                         DBG_88E(FUNC_ADPT_FMT" to %pM, ch:%u%s, %d/%d in %u ms\n",
1323                                 FUNC_ADPT_ARG(padapter), da, rtw_get_oper_ch(padapter),
1324                                 ret == _SUCCESS ? ", acked" : "", i, try_cnt, rtw_get_passing_time_ms(start));
1325                 else
1326                         DBG_88E(FUNC_ADPT_FMT", ch:%u%s, %d/%d in %u ms\n",
1327                                 FUNC_ADPT_ARG(padapter), rtw_get_oper_ch(padapter),
1328                                 ret == _SUCCESS ? ", acked" : "", i, try_cnt, rtw_get_passing_time_ms(start));
1329         }
1330 exit:
1331         return ret;
1332 }
1333
1334 /* when wait_ack is true, this function should be called at process context */
1335 static int _issue_qos_nulldata(struct adapter *padapter, unsigned char *da, u16 tid, int wait_ack)
1336 {
1337         int ret = _FAIL;
1338         struct xmit_frame                       *pmgntframe;
1339         struct pkt_attrib                       *pattrib;
1340         unsigned char                                   *pframe;
1341         struct rtw_ieee80211_hdr        *pwlanhdr;
1342         __le16 *fctrl;
1343         unsigned short *qc;
1344         struct xmit_priv                        *pxmitpriv = &(padapter->xmitpriv);
1345         struct mlme_ext_priv    *pmlmeext = &(padapter->mlmeextpriv);
1346         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
1347         struct wlan_bssid_ex    *pnetwork = &(pmlmeinfo->network);
1348
1349         DBG_88E("%s\n", __func__);
1350
1351         pmgntframe = alloc_mgtxmitframe(pxmitpriv);
1352         if (pmgntframe == NULL)
1353                 goto exit;
1354
1355         /* update attribute */
1356         pattrib = &pmgntframe->attrib;
1357         update_mgntframe_attrib(padapter, pattrib);
1358
1359         pattrib->hdrlen += 2;
1360         pattrib->qos_en = true;
1361         pattrib->eosp = 1;
1362         pattrib->ack_policy = 0;
1363         pattrib->mdata = 0;
1364
1365         memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
1366
1367         pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
1368         pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
1369
1370         fctrl = &(pwlanhdr->frame_ctl);
1371         *(fctrl) = 0;
1372
1373         if ((pmlmeinfo->state&0x03) == WIFI_FW_AP_STATE)
1374                 SetFrDs(fctrl);
1375         else if ((pmlmeinfo->state&0x03) == WIFI_FW_STATION_STATE)
1376                 SetToDs(fctrl);
1377
1378         if (pattrib->mdata)
1379                 SetMData(fctrl);
1380
1381         qc = (unsigned short *)(pframe + pattrib->hdrlen - 2);
1382
1383         SetPriority(qc, tid);
1384
1385         SetEOSP(qc, pattrib->eosp);
1386
1387         SetAckpolicy(qc, pattrib->ack_policy);
1388
1389         memcpy(pwlanhdr->addr1, da, ETH_ALEN);
1390         memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN);
1391         memcpy(pwlanhdr->addr3, pnetwork->MacAddress, ETH_ALEN);
1392
1393         SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
1394         pmlmeext->mgnt_seq++;
1395         SetFrameSubType(pframe, WIFI_QOS_DATA_NULL);
1396
1397         pframe += sizeof(struct rtw_ieee80211_hdr_3addr_qos);
1398         pattrib->pktlen = sizeof(struct rtw_ieee80211_hdr_3addr_qos);
1399
1400         pattrib->last_txcmdsz = pattrib->pktlen;
1401
1402         if (wait_ack) {
1403                 ret = dump_mgntframe_and_wait_ack(padapter, pmgntframe);
1404         } else {
1405                 dump_mgntframe(padapter, pmgntframe);
1406                 ret = _SUCCESS;
1407         }
1408
1409 exit:
1410         return ret;
1411 }
1412
1413 /* when wait_ms > 0 , this function should be called at process context */
1414 /* da == NULL for station mode */
1415 int issue_qos_nulldata(struct adapter *padapter, unsigned char *da, u16 tid, int try_cnt, int wait_ms)
1416 {
1417         int ret;
1418         int i = 0;
1419         u32 start = jiffies;
1420         struct mlme_ext_priv    *pmlmeext = &(padapter->mlmeextpriv);
1421         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
1422         struct wlan_bssid_ex    *pnetwork = &(pmlmeinfo->network);
1423
1424         /* da == NULL, assume it's null data for sta to ap*/
1425         if (da == NULL)
1426                 da = pnetwork->MacAddress;
1427
1428         do {
1429                 ret = _issue_qos_nulldata(padapter, da, tid, wait_ms > 0 ? true : false);
1430
1431                 i++;
1432
1433                 if (padapter->bDriverStopped || padapter->bSurpriseRemoved)
1434                         break;
1435
1436                 if (i < try_cnt && wait_ms > 0 && ret == _FAIL)
1437                         msleep(wait_ms);
1438         } while ((i < try_cnt) && ((ret == _FAIL) || (wait_ms == 0)));
1439
1440         if (ret != _FAIL) {
1441                 ret = _SUCCESS;
1442                 goto exit;
1443         }
1444
1445         if (try_cnt && wait_ms) {
1446                 if (da)
1447                         DBG_88E(FUNC_ADPT_FMT" to %pM, ch:%u%s, %d/%d in %u ms\n",
1448                                 FUNC_ADPT_ARG(padapter), da, rtw_get_oper_ch(padapter),
1449                                 ret == _SUCCESS ? ", acked" : "", i, try_cnt, rtw_get_passing_time_ms(start));
1450                 else
1451                         DBG_88E(FUNC_ADPT_FMT", ch:%u%s, %d/%d in %u ms\n",
1452                                 FUNC_ADPT_ARG(padapter), rtw_get_oper_ch(padapter),
1453                                 ret == _SUCCESS ? ", acked" : "", i, try_cnt, rtw_get_passing_time_ms(start));
1454         }
1455 exit:
1456         return ret;
1457 }
1458
1459 static int _issue_deauth(struct adapter *padapter, unsigned char *da, unsigned short reason, u8 wait_ack)
1460 {
1461         struct xmit_frame                       *pmgntframe;
1462         struct pkt_attrib                       *pattrib;
1463         unsigned char                                   *pframe;
1464         struct rtw_ieee80211_hdr        *pwlanhdr;
1465         __le16 *fctrl;
1466         struct xmit_priv                        *pxmitpriv = &(padapter->xmitpriv);
1467         struct mlme_ext_priv    *pmlmeext = &(padapter->mlmeextpriv);
1468         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
1469         struct wlan_bssid_ex    *pnetwork = &(pmlmeinfo->network);
1470         int ret = _FAIL;
1471         __le16 le_tmp;
1472
1473         pmgntframe = alloc_mgtxmitframe(pxmitpriv);
1474         if (pmgntframe == NULL)
1475                 goto exit;
1476
1477         /* update attribute */
1478         pattrib = &pmgntframe->attrib;
1479         update_mgntframe_attrib(padapter, pattrib);
1480         pattrib->retry_ctrl = false;
1481
1482         memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
1483
1484         pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
1485         pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
1486
1487         fctrl = &(pwlanhdr->frame_ctl);
1488         *(fctrl) = 0;
1489
1490         memcpy(pwlanhdr->addr1, da, ETH_ALEN);
1491         memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN);
1492         memcpy(pwlanhdr->addr3, pnetwork->MacAddress, ETH_ALEN);
1493
1494         SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
1495         pmlmeext->mgnt_seq++;
1496         SetFrameSubType(pframe, WIFI_DEAUTH);
1497
1498         pframe += sizeof(struct rtw_ieee80211_hdr_3addr);
1499         pattrib->pktlen = sizeof(struct rtw_ieee80211_hdr_3addr);
1500
1501         le_tmp = cpu_to_le16(reason);
1502         pframe = rtw_set_fixed_ie(pframe, _RSON_CODE_ , (unsigned char *)&le_tmp, &(pattrib->pktlen));
1503
1504         pattrib->last_txcmdsz = pattrib->pktlen;
1505
1506
1507         if (wait_ack) {
1508                 ret = dump_mgntframe_and_wait_ack(padapter, pmgntframe);
1509         } else {
1510                 dump_mgntframe(padapter, pmgntframe);
1511                 ret = _SUCCESS;
1512         }
1513
1514 exit:
1515         return ret;
1516 }
1517
1518 int issue_deauth(struct adapter *padapter, unsigned char *da, unsigned short reason)
1519 {
1520         DBG_88E("%s to %pM\n", __func__, da);
1521         return _issue_deauth(padapter, da, reason, false);
1522 }
1523
1524 static int issue_deauth_ex(struct adapter *padapter, u8 *da,
1525                            unsigned short reason, int try_cnt,
1526                            int wait_ms)
1527 {
1528         int ret;
1529         int i = 0;
1530         u32 start = jiffies;
1531
1532         do {
1533                 ret = _issue_deauth(padapter, da, reason, wait_ms > 0 ? true : false);
1534
1535                 i++;
1536
1537                 if (padapter->bDriverStopped || padapter->bSurpriseRemoved)
1538                         break;
1539
1540                 if (i < try_cnt && wait_ms > 0 && ret == _FAIL)
1541                         msleep(wait_ms);
1542         } while ((i < try_cnt) && ((ret == _FAIL) || (wait_ms == 0)));
1543
1544         if (ret != _FAIL) {
1545                 ret = _SUCCESS;
1546                 goto exit;
1547         }
1548
1549         if (try_cnt && wait_ms) {
1550                 if (da)
1551                         DBG_88E(FUNC_ADPT_FMT" to %pM, ch:%u%s, %d/%d in %u ms\n",
1552                                 FUNC_ADPT_ARG(padapter), da, rtw_get_oper_ch(padapter),
1553                                 ret == _SUCCESS ? ", acked" : "", i, try_cnt, rtw_get_passing_time_ms(start));
1554                 else
1555                         DBG_88E(FUNC_ADPT_FMT", ch:%u%s, %d/%d in %u ms\n",
1556                                 FUNC_ADPT_ARG(padapter), rtw_get_oper_ch(padapter),
1557                                 ret == _SUCCESS ? ", acked" : "", i, try_cnt, rtw_get_passing_time_ms(start));
1558         }
1559 exit:
1560         return ret;
1561 }
1562
1563 void issue_action_spct_ch_switch(struct adapter *padapter, u8 *ra, u8 new_ch, u8 ch_offset)
1564 {
1565         struct xmit_frame                       *pmgntframe;
1566         struct pkt_attrib                       *pattrib;
1567         unsigned char                           *pframe;
1568         struct rtw_ieee80211_hdr        *pwlanhdr;
1569         __le16 *fctrl;
1570         struct xmit_priv                        *pxmitpriv = &(padapter->xmitpriv);
1571         struct mlme_ext_priv    *pmlmeext = &(padapter->mlmeextpriv);
1572
1573
1574         DBG_88E(FUNC_NDEV_FMT" ra =%pM, ch:%u, offset:%u\n",
1575                 FUNC_NDEV_ARG(padapter->pnetdev), ra, new_ch, ch_offset);
1576
1577         pmgntframe = alloc_mgtxmitframe(pxmitpriv);
1578         if (pmgntframe == NULL)
1579                 return;
1580
1581         /* update attribute */
1582         pattrib = &pmgntframe->attrib;
1583         update_mgntframe_attrib(padapter, pattrib);
1584
1585         memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
1586
1587         pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
1588         pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
1589
1590         fctrl = &(pwlanhdr->frame_ctl);
1591         *(fctrl) = 0;
1592
1593         memcpy(pwlanhdr->addr1, ra, ETH_ALEN); /* RA */
1594         memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN); /* TA */
1595         memcpy(pwlanhdr->addr3, ra, ETH_ALEN); /* DA = RA */
1596
1597         SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
1598         pmlmeext->mgnt_seq++;
1599         SetFrameSubType(pframe, WIFI_ACTION);
1600
1601         pframe += sizeof(struct rtw_ieee80211_hdr_3addr);
1602         pattrib->pktlen = sizeof(struct rtw_ieee80211_hdr_3addr);
1603
1604         /* category, action */
1605         {
1606                 u8 category, action;
1607                 category = RTW_WLAN_CATEGORY_SPECTRUM_MGMT;
1608                 action = RTW_WLAN_ACTION_SPCT_CHL_SWITCH;
1609
1610                 pframe = rtw_set_fixed_ie(pframe, 1, &(category), &(pattrib->pktlen));
1611                 pframe = rtw_set_fixed_ie(pframe, 1, &(action), &(pattrib->pktlen));
1612         }
1613
1614         pframe = rtw_set_ie_ch_switch(pframe, &(pattrib->pktlen), 0, new_ch, 0);
1615         pframe = rtw_set_ie_secondary_ch_offset(pframe, &(pattrib->pktlen),
1616                 hal_ch_offset_to_secondary_ch_offset(ch_offset));
1617
1618         pattrib->last_txcmdsz = pattrib->pktlen;
1619
1620         dump_mgntframe(padapter, pmgntframe);
1621 }
1622
1623 static void issue_action_BA(struct adapter *padapter, unsigned char *raddr,
1624                             unsigned char action, unsigned short status)
1625 {
1626         u8 category = RTW_WLAN_CATEGORY_BACK;
1627         u16 start_seq;
1628         u16 BA_para_set;
1629         u16 reason_code;
1630         u16 BA_timeout_value;
1631         __le16  le_tmp;
1632         u16 BA_starting_seqctrl = 0;
1633         enum ht_cap_ampdu_factor max_rx_ampdu_factor;
1634         struct xmit_frame *pmgntframe;
1635         struct pkt_attrib *pattrib;
1636         u8 *pframe;
1637         struct rtw_ieee80211_hdr *pwlanhdr;
1638         __le16 *fctrl;
1639         struct xmit_priv *pxmitpriv = &(padapter->xmitpriv);
1640         struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
1641         struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
1642         struct sta_info *psta;
1643         struct sta_priv *pstapriv = &padapter->stapriv;
1644         struct registry_priv *pregpriv = &padapter->registrypriv;
1645         struct wlan_bssid_ex    *pnetwork = &(pmlmeinfo->network);
1646
1647         DBG_88E("%s, category=%d, action=%d, status=%d\n", __func__, category, action, status);
1648
1649         pmgntframe = alloc_mgtxmitframe(pxmitpriv);
1650         if (pmgntframe == NULL)
1651                 return;
1652
1653         /* update attribute */
1654         pattrib = &pmgntframe->attrib;
1655         update_mgntframe_attrib(padapter, pattrib);
1656
1657         memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
1658
1659         pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
1660         pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
1661
1662         fctrl = &(pwlanhdr->frame_ctl);
1663         *(fctrl) = 0;
1664
1665         /* memcpy(pwlanhdr->addr1, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN); */
1666         memcpy(pwlanhdr->addr1, raddr, ETH_ALEN);
1667         memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN);
1668         memcpy(pwlanhdr->addr3, pnetwork->MacAddress, ETH_ALEN);
1669
1670         SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
1671         pmlmeext->mgnt_seq++;
1672         SetFrameSubType(pframe, WIFI_ACTION);
1673
1674         pframe += sizeof(struct rtw_ieee80211_hdr_3addr);
1675         pattrib->pktlen = sizeof(struct rtw_ieee80211_hdr_3addr);
1676
1677         pframe = rtw_set_fixed_ie(pframe, 1, &(category), &(pattrib->pktlen));
1678         pframe = rtw_set_fixed_ie(pframe, 1, &(action), &(pattrib->pktlen));
1679
1680         if (category == 3) {
1681                 switch (action) {
1682                 case 0: /* ADDBA req */
1683                         do {
1684                                 pmlmeinfo->dialogToken++;
1685                         } while (pmlmeinfo->dialogToken == 0);
1686                         pframe = rtw_set_fixed_ie(pframe, 1, &(pmlmeinfo->dialogToken), &(pattrib->pktlen));
1687
1688                         BA_para_set = 0x1002 | ((status & 0xf) << 2); /* immediate ack & 64 buffer size */
1689                         le_tmp = cpu_to_le16(BA_para_set);
1690                         pframe = rtw_set_fixed_ie(pframe, 2, (unsigned char *)(&(le_tmp)), &(pattrib->pktlen));
1691
1692                         BA_timeout_value = 5000;/*  5ms */
1693                         le_tmp = cpu_to_le16(BA_timeout_value);
1694                         pframe = rtw_set_fixed_ie(pframe, 2, (unsigned char *)(&(le_tmp)), &(pattrib->pktlen));
1695
1696                         psta = rtw_get_stainfo(pstapriv, raddr);
1697                         if (psta != NULL) {
1698                                 start_seq = (psta->sta_xmitpriv.txseq_tid[status & 0x07]&0xfff) + 1;
1699
1700                                 DBG_88E("BA_starting_seqctrl=%d for TID=%d\n", start_seq, status & 0x07);
1701
1702                                 psta->BA_starting_seqctrl[status & 0x07] = start_seq;
1703
1704                                 BA_starting_seqctrl = start_seq << 4;
1705                         }
1706                         le_tmp = cpu_to_le16(BA_starting_seqctrl);
1707                         pframe = rtw_set_fixed_ie(pframe, 2, (unsigned char *)(&(le_tmp)), &(pattrib->pktlen));
1708                         break;
1709                 case 1: /* ADDBA rsp */
1710                         pframe = rtw_set_fixed_ie(pframe, 1, &(pmlmeinfo->ADDBA_req.dialog_token), &(pattrib->pktlen));
1711                         pframe = rtw_set_fixed_ie(pframe, 2, (unsigned char *)(&status), &(pattrib->pktlen));
1712
1713                         BA_para_set = le16_to_cpu(pmlmeinfo->ADDBA_req.BA_para_set) & 0x3f;
1714                         rtw_hal_get_def_var(padapter, HW_VAR_MAX_RX_AMPDU_FACTOR, &max_rx_ampdu_factor);
1715                         switch (max_rx_ampdu_factor) {
1716                         case MAX_AMPDU_FACTOR_64K:
1717                                 BA_para_set |= 0x1000; /* 64 buffer size */
1718                                 break;
1719                         case MAX_AMPDU_FACTOR_32K:
1720                                 BA_para_set |= 0x0800; /* 32 buffer size */
1721                                 break;
1722                         case MAX_AMPDU_FACTOR_16K:
1723                                 BA_para_set |= 0x0400; /* 16 buffer size */
1724                                 break;
1725                         case MAX_AMPDU_FACTOR_8K:
1726                                 BA_para_set |= 0x0200; /* 8 buffer size */
1727                                 break;
1728                         default:
1729                                 BA_para_set |= 0x1000; /* 64 buffer size */
1730                                 break;
1731                         }
1732
1733                         if (pregpriv->ampdu_amsdu == 0)/* disabled */
1734                                 BA_para_set = BA_para_set & ~BIT(0);
1735                         else if (pregpriv->ampdu_amsdu == 1)/* enabled */
1736                                 BA_para_set = BA_para_set | BIT(0);
1737                         le_tmp = cpu_to_le16(BA_para_set);
1738
1739                         pframe = rtw_set_fixed_ie(pframe, 2, (unsigned char *)(&(le_tmp)), &(pattrib->pktlen));
1740                         pframe = rtw_set_fixed_ie(pframe, 2, (unsigned char *)(&(pmlmeinfo->ADDBA_req.BA_timeout_value)), &(pattrib->pktlen));
1741                         break;
1742                 case 2:/* DELBA */
1743                         BA_para_set = (status & 0x1F) << 3;
1744                         le_tmp = cpu_to_le16(BA_para_set);
1745                         pframe = rtw_set_fixed_ie(pframe, 2, (unsigned char *)(&(le_tmp)), &(pattrib->pktlen));
1746
1747                         reason_code = 37;/* Requested from peer STA as it does not want to use the mechanism */
1748                         le_tmp = cpu_to_le16(reason_code);
1749                         pframe = rtw_set_fixed_ie(pframe, 2, (unsigned char *)(&(le_tmp)), &(pattrib->pktlen));
1750                         break;
1751                 default:
1752                         break;
1753                 }
1754         }
1755
1756         pattrib->last_txcmdsz = pattrib->pktlen;
1757
1758         dump_mgntframe(padapter, pmgntframe);
1759 }
1760
1761 static void issue_action_BSSCoexistPacket(struct adapter *padapter)
1762 {
1763         struct list_head *plist, *phead;
1764         unsigned char category, action;
1765         struct xmit_frame                       *pmgntframe;
1766         struct pkt_attrib                       *pattrib;
1767         unsigned char                           *pframe;
1768         struct rtw_ieee80211_hdr        *pwlanhdr;
1769         __le16 *fctrl;
1770         struct  wlan_network    *pnetwork = NULL;
1771         struct xmit_priv                        *pxmitpriv = &(padapter->xmitpriv);
1772         struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1773         struct mlme_ext_priv    *pmlmeext = &(padapter->mlmeextpriv);
1774         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
1775         struct __queue *queue   = &(pmlmepriv->scanned_queue);
1776         u8 InfoContent[16] = {0};
1777         u8 ICS[8][15];
1778         struct wlan_bssid_ex  *cur_network   = &(pmlmeinfo->network);
1779
1780         if ((pmlmepriv->num_FortyMHzIntolerant == 0) || (pmlmepriv->num_sta_no_ht == 0))
1781                 return;
1782
1783         if (pmlmeinfo->bwmode_updated)
1784                 return;
1785
1786
1787         DBG_88E("%s\n", __func__);
1788
1789
1790         category = RTW_WLAN_CATEGORY_PUBLIC;
1791         action = ACT_PUBLIC_BSSCOEXIST;
1792
1793         pmgntframe = alloc_mgtxmitframe(pxmitpriv);
1794         if (pmgntframe == NULL)
1795                 return;
1796
1797         /* update attribute */
1798         pattrib = &pmgntframe->attrib;
1799         update_mgntframe_attrib(padapter, pattrib);
1800
1801         memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
1802
1803         pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
1804         pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
1805
1806         fctrl = &(pwlanhdr->frame_ctl);
1807         *(fctrl) = 0;
1808
1809         memcpy(pwlanhdr->addr1, cur_network->MacAddress, ETH_ALEN);
1810         memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN);
1811         memcpy(pwlanhdr->addr3, cur_network->MacAddress, ETH_ALEN);
1812
1813         SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
1814         pmlmeext->mgnt_seq++;
1815         SetFrameSubType(pframe, WIFI_ACTION);
1816
1817         pframe += sizeof(struct rtw_ieee80211_hdr_3addr);
1818         pattrib->pktlen = sizeof(struct rtw_ieee80211_hdr_3addr);
1819
1820         pframe = rtw_set_fixed_ie(pframe, 1, &(category), &(pattrib->pktlen));
1821         pframe = rtw_set_fixed_ie(pframe, 1, &(action), &(pattrib->pktlen));
1822
1823
1824         /*  */
1825         if (pmlmepriv->num_FortyMHzIntolerant > 0) {
1826                 u8 iedata = 0;
1827
1828                 iedata |= BIT(2);/* 20 MHz BSS Width Request */
1829
1830                 pframe = rtw_set_ie(pframe, EID_BSSCoexistence,  1, &iedata, &(pattrib->pktlen));
1831         }
1832
1833
1834         /*  */
1835         memset(ICS, 0, sizeof(ICS));
1836         if (pmlmepriv->num_sta_no_ht > 0) {
1837                 int i;
1838
1839                 spin_lock_bh(&(pmlmepriv->scanned_queue.lock));
1840
1841                 phead = get_list_head(queue);
1842                 plist = phead->next;
1843
1844                 while (phead != plist) {
1845                         int len;
1846                         u8 *p;
1847                         struct wlan_bssid_ex *pbss_network;
1848
1849                         pnetwork = container_of(plist, struct wlan_network, list);
1850
1851                         plist = plist->next;
1852
1853                         pbss_network = (struct wlan_bssid_ex *)&pnetwork->network;
1854
1855                         p = rtw_get_ie(pbss_network->IEs + _FIXED_IE_LENGTH_, _HT_CAPABILITY_IE_, &len, pbss_network->IELength - _FIXED_IE_LENGTH_);
1856                         if ((p == NULL) || (len == 0)) { /* non-HT */
1857                                 if ((pbss_network->Configuration.DSConfig <= 0) || (pbss_network->Configuration.DSConfig > 14))
1858                                         continue;
1859
1860                                 ICS[0][pbss_network->Configuration.DSConfig] = 1;
1861
1862                                 if (ICS[0][0] == 0)
1863                                         ICS[0][0] = 1;
1864                         }
1865                 }
1866                 spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
1867
1868                 for (i = 0; i < 8; i++) {
1869                         if (ICS[i][0] == 1) {
1870                                 int j, k = 0;
1871
1872                                 InfoContent[k] = i;
1873                                 /* SET_BSS_INTOLERANT_ELE_REG_CLASS(InfoContent, i); */
1874                                 k++;
1875
1876                                 for (j = 1; j <= 14; j++) {
1877                                         if (ICS[i][j] == 1) {
1878                                                 if (k < 16) {
1879                                                         InfoContent[k] = j; /* channel number */
1880                                                         /* SET_BSS_INTOLERANT_ELE_CHANNEL(InfoContent+k, j); */
1881                                                         k++;
1882                                                 }
1883                                         }
1884                                 }
1885
1886                                 pframe = rtw_set_ie(pframe, EID_BSSIntolerantChlReport, k, InfoContent, &(pattrib->pktlen));
1887                         }
1888                 }
1889         }
1890
1891
1892         pattrib->last_txcmdsz = pattrib->pktlen;
1893
1894         dump_mgntframe(padapter, pmgntframe);
1895 }
1896
1897 unsigned int send_delba(struct adapter *padapter, u8 initiator, u8 *addr)
1898 {
1899         struct sta_priv *pstapriv = &padapter->stapriv;
1900         struct sta_info *psta = NULL;
1901         /* struct recv_reorder_ctrl *preorder_ctrl; */
1902         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
1903         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
1904         u16 tid;
1905
1906         if ((pmlmeinfo->state&0x03) != WIFI_FW_AP_STATE)
1907                 if (!(pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS))
1908                         return _SUCCESS;
1909
1910         psta = rtw_get_stainfo(pstapriv, addr);
1911         if (psta == NULL)
1912                 return _SUCCESS;
1913
1914         if (initiator == 0) { /*  recipient */
1915                 for (tid = 0; tid < MAXTID; tid++) {
1916                         if (psta->recvreorder_ctrl[tid].enable) {
1917                                 DBG_88E("rx agg disable tid(%d)\n", tid);
1918                                 issue_action_BA(padapter, addr, RTW_WLAN_ACTION_DELBA, (((tid << 1) | initiator)&0x1F));
1919                                 psta->recvreorder_ctrl[tid].enable = false;
1920                                 psta->recvreorder_ctrl[tid].indicate_seq = 0xffff;
1921                         }
1922                 }
1923         } else if (initiator == 1) { /*  originator */
1924                 for (tid = 0; tid < MAXTID; tid++) {
1925                         if (psta->htpriv.agg_enable_bitmap & BIT(tid)) {
1926                                 DBG_88E("tx agg disable tid(%d)\n", tid);
1927                                 issue_action_BA(padapter, addr, RTW_WLAN_ACTION_DELBA, (((tid << 1) | initiator)&0x1F));
1928                                 psta->htpriv.agg_enable_bitmap &= ~BIT(tid);
1929                                 psta->htpriv.candidate_tid_bitmap &= ~BIT(tid);
1930                         }
1931                 }
1932         }
1933
1934         return _SUCCESS;
1935 }
1936
1937 unsigned int send_beacon(struct adapter *padapter)
1938 {
1939         u8 bxmitok = false;
1940         int     issue = 0;
1941         int poll = 0;
1942
1943         u32 start = jiffies;
1944
1945         rtw_hal_set_hwreg(padapter, HW_VAR_BCN_VALID, NULL);
1946         do {
1947                 issue_beacon(padapter, 100);
1948                 issue++;
1949                 do {
1950                         yield();
1951                         rtw_hal_get_hwreg(padapter, HW_VAR_BCN_VALID, (u8 *)(&bxmitok));
1952                         poll++;
1953                 } while ((poll%10) != 0 && !bxmitok && !padapter->bSurpriseRemoved && !padapter->bDriverStopped);
1954         } while (!bxmitok && issue < 100 && !padapter->bSurpriseRemoved && !padapter->bDriverStopped);
1955
1956         if (padapter->bSurpriseRemoved || padapter->bDriverStopped)
1957                 return _FAIL;
1958         if (!bxmitok) {
1959                 DBG_88E("%s fail! %u ms\n", __func__, rtw_get_passing_time_ms(start));
1960                 return _FAIL;
1961         } else {
1962                 u32 passing_time = rtw_get_passing_time_ms(start);
1963
1964                 if (passing_time > 100 || issue > 3)
1965                         DBG_88E("%s success, issue:%d, poll:%d, %u ms\n", __func__, issue, poll, rtw_get_passing_time_ms(start));
1966                 return _SUCCESS;
1967         }
1968 }
1969
1970 /****************************************************************************
1971
1972 Following are some utility functions for WiFi MLME
1973
1974 *****************************************************************************/
1975
1976 static void site_survey(struct adapter *padapter)
1977 {
1978         unsigned char           survey_channel = 0, val8;
1979         enum rt_scan_type ScanType = SCAN_PASSIVE;
1980         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
1981         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
1982         u32 initialgain = 0;
1983         struct rtw_ieee80211_channel *ch;
1984
1985         if (pmlmeext->sitesurvey_res.channel_idx < pmlmeext->sitesurvey_res.ch_num) {
1986                 ch = &pmlmeext->sitesurvey_res.ch[pmlmeext->sitesurvey_res.channel_idx];
1987                 survey_channel = ch->hw_value;
1988                 ScanType = (ch->flags & RTW_IEEE80211_CHAN_PASSIVE_SCAN) ? SCAN_PASSIVE : SCAN_ACTIVE;
1989         }
1990
1991
1992         if (survey_channel != 0) {
1993                 /* PAUSE 4-AC Queue when site_survey */
1994                 /* rtw_hal_get_hwreg(padapter, HW_VAR_TXPAUSE, (u8 *)(&val8)); */
1995                 /* val8 |= 0x0f; */
1996                 /* rtw_hal_set_hwreg(padapter, HW_VAR_TXPAUSE, (u8 *)(&val8)); */
1997                 if (pmlmeext->sitesurvey_res.channel_idx == 0)
1998                         set_channel_bwmode(padapter, survey_channel, HAL_PRIME_CHNL_OFFSET_DONT_CARE, HT_CHANNEL_WIDTH_20);
1999                 else
2000                         SelectChannel(padapter, survey_channel);
2001
2002                 if (ScanType == SCAN_ACTIVE) { /* obey the channel plan setting... */
2003                         int i;
2004                         for (i = 0; i < RTW_SSID_SCAN_AMOUNT; i++) {
2005                                 if (pmlmeext->sitesurvey_res.ssid[i].SsidLength) {
2006                                         /* todo: to issue two probe req??? */
2007                                         issue_probereq(padapter, &(pmlmeext->sitesurvey_res.ssid[i]), NULL);
2008                                         /* msleep(SURVEY_TO>>1); */
2009                                         issue_probereq(padapter, &(pmlmeext->sitesurvey_res.ssid[i]), NULL);
2010                                 }
2011                         }
2012
2013                         if (pmlmeext->sitesurvey_res.scan_mode == SCAN_ACTIVE) {
2014                                 /* todo: to issue two probe req??? */
2015                                 issue_probereq(padapter, NULL, NULL);
2016                                 /* msleep(SURVEY_TO>>1); */
2017                                 issue_probereq(padapter, NULL, NULL);
2018                         }
2019
2020                         if (pmlmeext->sitesurvey_res.scan_mode == SCAN_ACTIVE) {
2021                                 /* todo: to issue two probe req??? */
2022                                 issue_probereq(padapter, NULL, NULL);
2023                                 /* msleep(SURVEY_TO>>1); */
2024                                 issue_probereq(padapter, NULL, NULL);
2025                         }
2026                 }
2027
2028                 set_survey_timer(pmlmeext, pmlmeext->chan_scan_time);
2029         } else {
2030
2031                 /*  20100721:Interrupt scan operation here. */
2032                 /*  For SW antenna diversity before link, it needs to switch to another antenna and scan again. */
2033                 /*  It compares the scan result and select better one to do connection. */
2034                 if (rtw_hal_antdiv_before_linked(padapter)) {
2035                         pmlmeext->sitesurvey_res.bss_cnt = 0;
2036                         pmlmeext->sitesurvey_res.channel_idx = -1;
2037                         pmlmeext->chan_scan_time = SURVEY_TO / 2;
2038                         set_survey_timer(pmlmeext, pmlmeext->chan_scan_time);
2039                         return;
2040                 }
2041
2042                 pmlmeext->sitesurvey_res.state = SCAN_COMPLETE;
2043
2044                 /* switch back to the original channel */
2045
2046                 set_channel_bwmode(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode);
2047
2048                 /* flush 4-AC Queue after site_survey */
2049                 /* val8 = 0; */
2050                 /* rtw_hal_set_hwreg(padapter, HW_VAR_TXPAUSE, (u8 *)(&val8)); */
2051
2052                 /* config MSR */
2053                 Set_MSR(padapter, (pmlmeinfo->state & 0x3));
2054
2055                 initialgain = 0xff; /* restore RX GAIN */
2056                 rtw_hal_set_hwreg(padapter, HW_VAR_INITIAL_GAIN, (u8 *)(&initialgain));
2057                 /* turn on dynamic functions */
2058                 Restore_DM_Func_Flag(padapter);
2059                 /* Switch_DM_Func(padapter, DYNAMIC_ALL_FUNC_ENABLE, true); */
2060
2061                 if (is_client_associated_to_ap(padapter))
2062                         issue_nulldata(padapter, NULL, 0, 3, 500);
2063
2064                 val8 = 0; /* survey done */
2065                 rtw_hal_set_hwreg(padapter, HW_VAR_MLME_SITESURVEY, (u8 *)(&val8));
2066
2067                 report_surveydone_event(padapter);
2068
2069                 pmlmeext->chan_scan_time = SURVEY_TO;
2070                 pmlmeext->sitesurvey_res.state = SCAN_DISABLE;
2071
2072                 issue_action_BSSCoexistPacket(padapter);
2073                 issue_action_BSSCoexistPacket(padapter);
2074                 issue_action_BSSCoexistPacket(padapter);
2075         }
2076         return;
2077 }
2078
2079 /* collect bss info from Beacon and Probe request/response frames. */
2080 static u8 collect_bss_info(struct adapter *padapter,
2081                            struct recv_frame *precv_frame,
2082                            struct wlan_bssid_ex *bssid)
2083 {
2084         int     i;
2085         u32     len;
2086         u8 *p;
2087         u16 val16, subtype;
2088         u8 *pframe = precv_frame->rx_data;
2089         u32     packet_len = precv_frame->len;
2090         u8 ie_offset;
2091         struct registry_priv    *pregistrypriv = &padapter->registrypriv;
2092         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
2093         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
2094
2095         len = packet_len - sizeof(struct rtw_ieee80211_hdr_3addr);
2096
2097         if (len > MAX_IE_SZ)
2098                 return _FAIL;
2099
2100         memset(bssid, 0, sizeof(struct wlan_bssid_ex));
2101
2102         subtype = GetFrameSubType(pframe);
2103
2104         if (subtype == WIFI_BEACON) {
2105                 bssid->Reserved[0] = 1;
2106                 ie_offset = _BEACON_IE_OFFSET_;
2107         } else {
2108                 /*  FIXME : more type */
2109                 if (subtype == WIFI_PROBEREQ) {
2110                         ie_offset = _PROBEREQ_IE_OFFSET_;
2111                         bssid->Reserved[0] = 2;
2112                 } else if (subtype == WIFI_PROBERSP) {
2113                         ie_offset = _PROBERSP_IE_OFFSET_;
2114                         bssid->Reserved[0] = 3;
2115                 } else {
2116                         bssid->Reserved[0] = 0;
2117                         ie_offset = _FIXED_IE_LENGTH_;
2118                 }
2119         }
2120
2121         bssid->Length = sizeof(struct wlan_bssid_ex) - MAX_IE_SZ + len;
2122
2123         /* below is to copy the information element */
2124         bssid->IELength = len;
2125         memcpy(bssid->IEs, (pframe + sizeof(struct rtw_ieee80211_hdr_3addr)), bssid->IELength);
2126
2127         /* get the signal strength in dBM.raw data */
2128         bssid->Rssi = precv_frame->attrib.phy_info.recvpower;
2129         bssid->PhyInfo.SignalQuality = precv_frame->attrib.phy_info.SignalQuality;/* in percentage */
2130         bssid->PhyInfo.SignalStrength = precv_frame->attrib.phy_info.SignalStrength;/* in percentage */
2131         rtw_hal_get_def_var(padapter, HAL_DEF_CURRENT_ANTENNA,  &bssid->PhyInfo.Optimum_antenna);
2132
2133         /*  checking SSID */
2134         p = rtw_get_ie(bssid->IEs + ie_offset, _SSID_IE_, &len, bssid->IELength - ie_offset);
2135         if (p == NULL) {
2136                 DBG_88E("marc: cannot find SSID for survey event\n");
2137                 return _FAIL;
2138         }
2139
2140         if (len) {
2141                 if (len > NDIS_802_11_LENGTH_SSID) {
2142                         DBG_88E("%s()-%d: IE too long (%d) for survey event\n", __func__, __LINE__, len);
2143                         return _FAIL;
2144                 }
2145                 memcpy(bssid->Ssid.Ssid, (p + 2), len);
2146                 bssid->Ssid.SsidLength = len;
2147         } else {
2148                 bssid->Ssid.SsidLength = 0;
2149         }
2150
2151         memset(bssid->SupportedRates, 0, NDIS_802_11_LENGTH_RATES_EX);
2152
2153         /* checking rate info... */
2154         i = 0;
2155         p = rtw_get_ie(bssid->IEs + ie_offset, _SUPPORTEDRATES_IE_, &len, bssid->IELength - ie_offset);
2156         if (p != NULL) {
2157                 if (len > NDIS_802_11_LENGTH_RATES_EX) {
2158                         DBG_88E("%s()-%d: IE too long (%d) for survey event\n", __func__, __LINE__, len);
2159                         return _FAIL;
2160                 }
2161                 memcpy(bssid->SupportedRates, (p + 2), len);
2162                 i = len;
2163         }
2164
2165         p = rtw_get_ie(bssid->IEs + ie_offset, _EXT_SUPPORTEDRATES_IE_, &len, bssid->IELength - ie_offset);
2166         if (p != NULL) {
2167                 if (len > (NDIS_802_11_LENGTH_RATES_EX-i)) {
2168                         DBG_88E("%s()-%d: IE too long (%d) for survey event\n", __func__, __LINE__, len);
2169                         return _FAIL;
2170                 }
2171                 memcpy(bssid->SupportedRates + i, (p + 2), len);
2172         }
2173
2174         /* todo: */
2175         bssid->NetworkTypeInUse = Ndis802_11OFDM24;
2176
2177         if (bssid->IELength < 12)
2178                 return _FAIL;
2179
2180         /*  Checking for DSConfig */
2181         p = rtw_get_ie(bssid->IEs + ie_offset, _DSSET_IE_, &len, bssid->IELength - ie_offset);
2182
2183         bssid->Configuration.DSConfig = 0;
2184         bssid->Configuration.Length = 0;
2185
2186         if (p) {
2187                 bssid->Configuration.DSConfig = *(p + 2);
2188         } else {/*  In 5G, some ap do not have DSSET IE */
2189                 /*  checking HT info for channel */
2190                 p = rtw_get_ie(bssid->IEs + ie_offset, _HT_ADD_INFO_IE_, &len, bssid->IELength - ie_offset);
2191                 if (p) {
2192                         struct HT_info_element *HT_info = (struct HT_info_element *)(p + 2);
2193                         bssid->Configuration.DSConfig = HT_info->primary_channel;
2194                 } else { /*  use current channel */
2195                         bssid->Configuration.DSConfig = rtw_get_oper_ch(padapter);
2196                 }
2197         }
2198
2199         if (subtype == WIFI_PROBEREQ) {
2200                 /*  FIXME */
2201                 bssid->InfrastructureMode = Ndis802_11Infrastructure;
2202                 memcpy(bssid->MacAddress, GetAddr2Ptr(pframe), ETH_ALEN);
2203                 bssid->Privacy = 1;
2204                 return _SUCCESS;
2205         }
2206
2207         bssid->Configuration.BeaconPeriod =
2208                 get_unaligned_le16(rtw_get_beacon_interval_from_ie(bssid->IEs));
2209
2210         val16 = rtw_get_capability((struct wlan_bssid_ex *)bssid);
2211
2212         if (val16 & BIT(0)) {
2213                 bssid->InfrastructureMode = Ndis802_11Infrastructure;
2214                 memcpy(bssid->MacAddress, GetAddr2Ptr(pframe), ETH_ALEN);
2215         } else {
2216                 bssid->InfrastructureMode = Ndis802_11IBSS;
2217                 memcpy(bssid->MacAddress, GetAddr3Ptr(pframe), ETH_ALEN);
2218         }
2219
2220         if (val16 & BIT(4))
2221                 bssid->Privacy = 1;
2222         else
2223                 bssid->Privacy = 0;
2224
2225         bssid->Configuration.ATIMWindow = 0;
2226
2227         /* 20/40 BSS Coexistence check */
2228         if ((pregistrypriv->wifi_spec == 1) && (!pmlmeinfo->bwmode_updated)) {
2229                 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
2230                 p = rtw_get_ie(bssid->IEs + ie_offset, _HT_CAPABILITY_IE_, &len, bssid->IELength - ie_offset);
2231                 if (p && len > 0) {
2232                         struct HT_caps_element  *pHT_caps;
2233                         pHT_caps = (struct HT_caps_element *)(p + 2);
2234
2235                         if (le16_to_cpu(pHT_caps->u.HT_cap_element.HT_caps_info)&BIT(14))
2236                                 pmlmepriv->num_FortyMHzIntolerant++;
2237                 } else {
2238                         pmlmepriv->num_sta_no_ht++;
2239                 }
2240         }
2241
2242         /*  mark bss info receiving from nearby channel as SignalQuality 101 */
2243         if (bssid->Configuration.DSConfig != rtw_get_oper_ch(padapter))
2244                 bssid->PhyInfo.SignalQuality = 101;
2245         return _SUCCESS;
2246 }
2247
2248 static void start_create_ibss(struct adapter *padapter)
2249 {
2250         unsigned short  caps;
2251         u8 val8;
2252         u8 join_type;
2253         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
2254         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
2255         struct wlan_bssid_ex *pnetwork = (struct wlan_bssid_ex *)(&(pmlmeinfo->network));
2256         pmlmeext->cur_channel = (u8)pnetwork->Configuration.DSConfig;
2257         pmlmeinfo->bcn_interval = get_beacon_interval(pnetwork);
2258
2259         /* update wireless mode */
2260         update_wireless_mode(padapter);
2261
2262         /* update capability */
2263         caps = rtw_get_capability((struct wlan_bssid_ex *)pnetwork);
2264         update_capinfo(padapter, caps);
2265         if (caps&cap_IBSS) {/* adhoc master */
2266                 val8 = 0xcf;
2267                 rtw_hal_set_hwreg(padapter, HW_VAR_SEC_CFG, (u8 *)(&val8));
2268
2269                 /* switch channel */
2270                 /* SelectChannel(padapter, pmlmeext->cur_channel, HAL_PRIME_CHNL_OFFSET_DONT_CARE); */
2271                 set_channel_bwmode(padapter, pmlmeext->cur_channel, HAL_PRIME_CHNL_OFFSET_DONT_CARE, HT_CHANNEL_WIDTH_20);
2272
2273                 beacon_timing_control(padapter);
2274
2275                 /* set msr to WIFI_FW_ADHOC_STATE */
2276                 pmlmeinfo->state = WIFI_FW_ADHOC_STATE;
2277                 Set_MSR(padapter, (pmlmeinfo->state & 0x3));
2278
2279                 /* issue beacon */
2280                 if (send_beacon(padapter) == _FAIL) {
2281                         RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("issuing beacon frame fail....\n"));
2282
2283                         report_join_res(padapter, -1);
2284                         pmlmeinfo->state = WIFI_FW_NULL_STATE;
2285                 } else {
2286                         rtw_hal_set_hwreg(padapter, HW_VAR_BSSID, padapter->registrypriv.dev_network.MacAddress);
2287                         join_type = 0;
2288                         rtw_hal_set_hwreg(padapter, HW_VAR_MLME_JOIN, (u8 *)(&join_type));
2289
2290                         report_join_res(padapter, 1);
2291                         pmlmeinfo->state |= WIFI_FW_ASSOC_SUCCESS;
2292                 }
2293         } else {
2294                 DBG_88E("start_create_ibss, invalid cap:%x\n", caps);
2295                 return;
2296         }
2297 }
2298
2299 static void start_clnt_join(struct adapter *padapter)
2300 {
2301         unsigned short  caps;
2302         u8 val8;
2303         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
2304         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
2305         struct wlan_bssid_ex *pnetwork = (struct wlan_bssid_ex *)(&(pmlmeinfo->network));
2306         int beacon_timeout;
2307
2308         pmlmeext->cur_channel = (u8)pnetwork->Configuration.DSConfig;
2309         pmlmeinfo->bcn_interval = get_beacon_interval(pnetwork);
2310
2311         /* update wireless mode */
2312         update_wireless_mode(padapter);
2313
2314         /* update capability */
2315         caps = rtw_get_capability((struct wlan_bssid_ex *)pnetwork);
2316         update_capinfo(padapter, caps);
2317         if (caps&cap_ESS) {
2318                 Set_MSR(padapter, WIFI_FW_STATION_STATE);
2319
2320                 val8 = (pmlmeinfo->auth_algo == dot11AuthAlgrthm_8021X) ? 0xcc : 0xcf;
2321
2322                 rtw_hal_set_hwreg(padapter, HW_VAR_SEC_CFG, (u8 *)(&val8));
2323
2324                 /* switch channel */
2325                 set_channel_bwmode(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode);
2326
2327                 /* here wait for receiving the beacon to start auth */
2328                 /* and enable a timer */
2329                 beacon_timeout = decide_wait_for_beacon_timeout(pmlmeinfo->bcn_interval);
2330                 set_link_timer(pmlmeext, beacon_timeout);
2331                 mod_timer(&padapter->mlmepriv.assoc_timer, jiffies +
2332                           msecs_to_jiffies((REAUTH_TO * REAUTH_LIMIT) + (REASSOC_TO * REASSOC_LIMIT) + beacon_timeout));
2333
2334                 pmlmeinfo->state = WIFI_FW_AUTH_NULL | WIFI_FW_STATION_STATE;
2335         } else if (caps&cap_IBSS) { /* adhoc client */
2336                 Set_MSR(padapter, WIFI_FW_ADHOC_STATE);
2337
2338                 val8 = 0xcf;
2339                 rtw_hal_set_hwreg(padapter, HW_VAR_SEC_CFG, (u8 *)(&val8));
2340
2341                 /* switch channel */
2342                 set_channel_bwmode(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode);
2343
2344                 beacon_timing_control(padapter);
2345
2346                 pmlmeinfo->state = WIFI_FW_ADHOC_STATE;
2347
2348                 report_join_res(padapter, 1);
2349         } else {
2350                 return;
2351         }
2352 }
2353
2354 static void start_clnt_auth(struct adapter *padapter)
2355 {
2356         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
2357         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
2358
2359         del_timer_sync(&pmlmeext->link_timer);
2360
2361         pmlmeinfo->state &= (~WIFI_FW_AUTH_NULL);
2362         pmlmeinfo->state |= WIFI_FW_AUTH_STATE;
2363
2364         pmlmeinfo->auth_seq = 1;
2365         pmlmeinfo->reauth_count = 0;
2366         pmlmeinfo->reassoc_count = 0;
2367         pmlmeinfo->link_count = 0;
2368         pmlmeext->retry = 0;
2369
2370
2371         /*  Because of AP's not receiving deauth before */
2372         /*  AP may: 1)not response auth or 2)deauth us after link is complete */
2373         /*  issue deauth before issuing auth to deal with the situation */
2374         /*      Commented by Albert 2012/07/21 */
2375         /*      For the Win8 P2P connection, it will be hard to have a successful connection if this Wi-Fi doesn't connect to it. */
2376         issue_deauth(padapter, (&(pmlmeinfo->network))->MacAddress, WLAN_REASON_DEAUTH_LEAVING);
2377
2378         DBG_88E_LEVEL(_drv_info_, "start auth\n");
2379         issue_auth(padapter, NULL, 0);
2380
2381         set_link_timer(pmlmeext, REAUTH_TO);
2382 }
2383
2384
2385 static void start_clnt_assoc(struct adapter *padapter)
2386 {
2387         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
2388         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
2389
2390         del_timer_sync(&pmlmeext->link_timer);
2391
2392         pmlmeinfo->state &= (~(WIFI_FW_AUTH_NULL | WIFI_FW_AUTH_STATE));
2393         pmlmeinfo->state |= (WIFI_FW_AUTH_SUCCESS | WIFI_FW_ASSOC_STATE);
2394
2395         issue_assocreq(padapter);
2396
2397         set_link_timer(pmlmeext, REASSOC_TO);
2398 }
2399
2400 static unsigned int receive_disconnect(struct adapter *padapter,
2401                                        unsigned char *MacAddr,
2402                                        unsigned short reason)
2403 {
2404         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
2405         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
2406         struct wlan_bssid_ex    *pnetwork = &(pmlmeinfo->network);
2407
2408         /* check A3 */
2409         if (memcmp(MacAddr, pnetwork->MacAddress, ETH_ALEN))
2410                 return _SUCCESS;
2411
2412         DBG_88E("%s\n", __func__);
2413
2414         if ((pmlmeinfo->state&0x03) == WIFI_FW_STATION_STATE) {
2415                 if (pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS) {
2416                         pmlmeinfo->state = WIFI_FW_NULL_STATE;
2417                         report_del_sta_event(padapter, MacAddr, reason);
2418                 } else if (pmlmeinfo->state & WIFI_FW_LINKING_STATE) {
2419                         pmlmeinfo->state = WIFI_FW_NULL_STATE;
2420                         report_join_res(padapter, -2);
2421                 }
2422         }
2423         return _SUCCESS;
2424 }
2425
2426 static void process_80211d(struct adapter *padapter, struct wlan_bssid_ex *bssid)
2427 {
2428         struct registry_priv *pregistrypriv;
2429         struct mlme_ext_priv *pmlmeext;
2430         struct rt_channel_info *chplan_new;
2431         u8 channel;
2432         u8 i;
2433
2434         pregistrypriv = &padapter->registrypriv;
2435         pmlmeext = &padapter->mlmeextpriv;
2436
2437         /*  Adjust channel plan by AP Country IE */
2438         if (pregistrypriv->enable80211d &&
2439             (!pmlmeext->update_channel_plan_by_ap_done)) {
2440                 u8 *ie, *p;
2441                 u32 len;
2442                 struct rt_channel_plan chplan_ap;
2443                 struct rt_channel_info chplan_sta[MAX_CHANNEL_NUM];
2444                 u8 country[4];
2445                 u8 fcn; /*  first channel number */
2446                 u8 noc; /*  number of channel */
2447                 u8 j, k;
2448
2449                 ie = rtw_get_ie(bssid->IEs + _FIXED_IE_LENGTH_, _COUNTRY_IE_, &len, bssid->IELength - _FIXED_IE_LENGTH_);
2450                 if (!ie)
2451                         return;
2452                 if (len < 6)
2453                         return;
2454                 ie += 2;
2455                 p = ie;
2456                 ie += len;
2457
2458                 memset(country, 0, 4);
2459                 memcpy(country, p, 3);
2460                 p += 3;
2461                 RT_TRACE(_module_rtl871x_mlme_c_, _drv_notice_,
2462                          ("%s: 802.11d country =%s\n", __func__, country));
2463
2464                 i = 0;
2465                 while ((ie - p) >= 3) {
2466                         fcn = *(p++);
2467                         noc = *(p++);
2468                         p++;
2469
2470                         for (j = 0; j < noc; j++) {
2471                                 if (fcn <= 14)
2472                                         channel = fcn + j; /*  2.4 GHz */
2473                                 else
2474                                         channel = fcn + j*4; /*  5 GHz */
2475
2476                                 chplan_ap.Channel[i++] = channel;
2477                         }
2478                 }
2479                 chplan_ap.Len = i;
2480
2481                 memcpy(chplan_sta, pmlmeext->channel_set, sizeof(chplan_sta));
2482
2483                 memset(pmlmeext->channel_set, 0, sizeof(pmlmeext->channel_set));
2484                 chplan_new = pmlmeext->channel_set;
2485
2486                 i = 0;
2487                 j = 0;
2488                 k = 0;
2489                 if (pregistrypriv->wireless_mode & WIRELESS_11G) {
2490                         do {
2491                                 if ((i == MAX_CHANNEL_NUM) ||
2492                                     (chplan_sta[i].ChannelNum == 0) ||
2493                                     (chplan_sta[i].ChannelNum > 14))
2494                                         break;
2495
2496                                 if ((j == chplan_ap.Len) || (chplan_ap.Channel[j] > 14))
2497                                         break;
2498
2499                                 if (chplan_sta[i].ChannelNum == chplan_ap.Channel[j]) {
2500                                         chplan_new[k].ChannelNum = chplan_ap.Channel[j];
2501                                         chplan_new[k].ScanType = SCAN_ACTIVE;
2502                                         i++;
2503                                         j++;
2504                                         k++;
2505                                 } else if (chplan_sta[i].ChannelNum < chplan_ap.Channel[j]) {
2506                                         chplan_new[k].ChannelNum = chplan_sta[i].ChannelNum;
2507                                         chplan_new[k].ScanType = SCAN_PASSIVE;
2508                                         i++;
2509                                         k++;
2510                                 } else if (chplan_sta[i].ChannelNum > chplan_ap.Channel[j]) {
2511                                         chplan_new[k].ChannelNum = chplan_ap.Channel[j];
2512                                         chplan_new[k].ScanType = SCAN_ACTIVE;
2513                                         j++;
2514                                         k++;
2515                                 }
2516                         } while (1);
2517
2518                         /*  change AP not support channel to Passive scan */
2519                         while ((i < MAX_CHANNEL_NUM) &&
2520                                (chplan_sta[i].ChannelNum != 0) &&
2521                                (chplan_sta[i].ChannelNum <= 14)) {
2522                                 chplan_new[k].ChannelNum = chplan_sta[i].ChannelNum;
2523                                 chplan_new[k].ScanType = SCAN_PASSIVE;
2524                                 i++;
2525                                 k++;
2526                         }
2527
2528                         /*  add channel AP supported */
2529                         while ((j < chplan_ap.Len) && (chplan_ap.Channel[j] <= 14)) {
2530                                 chplan_new[k].ChannelNum = chplan_ap.Channel[j];
2531                                 chplan_new[k].ScanType = SCAN_ACTIVE;
2532                                 j++;
2533                                 k++;
2534                         }
2535                 } else {
2536                         /*  keep original STA 2.4G channel plan */
2537                         while ((i < MAX_CHANNEL_NUM) &&
2538                                (chplan_sta[i].ChannelNum != 0) &&
2539                                (chplan_sta[i].ChannelNum <= 14)) {
2540                                 chplan_new[k].ChannelNum = chplan_sta[i].ChannelNum;
2541                                 chplan_new[k].ScanType = chplan_sta[i].ScanType;
2542                                 i++;
2543                                 k++;
2544                         }
2545
2546                         /*  skip AP 2.4G channel plan */
2547                         while ((j < chplan_ap.Len) && (chplan_ap.Channel[j] <= 14))
2548                                 j++;
2549                 }
2550
2551                 /*  keep original STA 5G channel plan */
2552                 while ((i < MAX_CHANNEL_NUM) && (chplan_sta[i].ChannelNum != 0)) {
2553                         chplan_new[k].ChannelNum = chplan_sta[i].ChannelNum;
2554                         chplan_new[k].ScanType = chplan_sta[i].ScanType;
2555                         i++;
2556                         k++;
2557                 }
2558
2559                 pmlmeext->update_channel_plan_by_ap_done = 1;
2560         }
2561
2562         /*  If channel is used by AP, set channel scan type to active */
2563         channel = bssid->Configuration.DSConfig;
2564         chplan_new = pmlmeext->channel_set;
2565         i = 0;
2566         while ((i < MAX_CHANNEL_NUM) && (chplan_new[i].ChannelNum != 0)) {
2567                 if (chplan_new[i].ChannelNum == channel) {
2568                         if (chplan_new[i].ScanType == SCAN_PASSIVE) {
2569                                 chplan_new[i].ScanType = SCAN_ACTIVE;
2570                                 RT_TRACE(_module_rtl871x_mlme_c_, _drv_notice_,
2571                                          ("%s: change channel %d scan type from passive to active\n",
2572                                          __func__, channel));
2573                         }
2574                         break;
2575                 }
2576                 i++;
2577         }
2578 }
2579
2580 /****************************************************************************
2581
2582 Following are the callback functions for each subtype of the management frames
2583
2584 *****************************************************************************/
2585
2586 static unsigned int OnProbeReq(struct adapter *padapter,
2587                                struct recv_frame *precv_frame)
2588 {
2589         unsigned int    ielen;
2590         unsigned char   *p;
2591         struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
2592         struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
2593         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
2594         struct wlan_bssid_ex *cur = &(pmlmeinfo->network);
2595         u8 *pframe = precv_frame->rx_data;
2596         uint len = precv_frame->len;
2597
2598         if (check_fwstate(pmlmepriv, WIFI_STATION_STATE))
2599                 return _SUCCESS;
2600
2601         if (!check_fwstate(pmlmepriv, _FW_LINKED) &&
2602             !check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE|WIFI_AP_STATE))
2603                 return _SUCCESS;
2604
2605         p = rtw_get_ie(pframe + WLAN_HDR_A3_LEN + _PROBEREQ_IE_OFFSET_, _SSID_IE_, (int *)&ielen,
2606                         len - WLAN_HDR_A3_LEN - _PROBEREQ_IE_OFFSET_);
2607
2608         /* check (wildcard) SSID */
2609         if (p != NULL) {
2610                 if ((ielen != 0 && memcmp((void *)(p+2), (void *)cur->Ssid.Ssid, cur->Ssid.SsidLength)) ||
2611                     (ielen == 0 && pmlmeinfo->hidden_ssid_mode))
2612                         return _SUCCESS;
2613
2614                 if (check_fwstate(pmlmepriv, _FW_LINKED) &&
2615                     pmlmepriv->cur_network.join_res)
2616                         issue_probersp(padapter, get_sa(pframe));
2617         }
2618         return _SUCCESS;
2619 }
2620
2621 static unsigned int OnProbeRsp(struct adapter *padapter,
2622                                struct recv_frame *precv_frame)
2623 {
2624         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
2625
2626         if (pmlmeext->sitesurvey_res.state == SCAN_PROCESS) {
2627                 report_survey_event(padapter, precv_frame);
2628                 return _SUCCESS;
2629         }
2630
2631         return _SUCCESS;
2632 }
2633
2634 static unsigned int OnBeacon(struct adapter *padapter,
2635                              struct recv_frame *precv_frame)
2636 {
2637         int cam_idx;
2638         struct sta_info *psta;
2639         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
2640         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
2641         struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
2642         struct sta_priv *pstapriv = &padapter->stapriv;
2643         u8 *pframe = precv_frame->rx_data;
2644         uint len = precv_frame->len;
2645         struct wlan_bssid_ex *pbss;
2646         int ret = _SUCCESS;
2647         struct wlan_bssid_ex *pnetwork = &(pmlmeinfo->network);
2648
2649         if (pmlmeext->sitesurvey_res.state == SCAN_PROCESS) {
2650                 report_survey_event(padapter, precv_frame);
2651                 return _SUCCESS;
2652         }
2653
2654         if (!memcmp(GetAddr3Ptr(pframe), pnetwork->MacAddress, ETH_ALEN)) {
2655                 if (pmlmeinfo->state & WIFI_FW_AUTH_NULL) {
2656                         /* we should update current network before auth, or some IE is wrong */
2657                         pbss = (struct wlan_bssid_ex *)rtw_malloc(sizeof(struct wlan_bssid_ex));
2658                         if (pbss) {
2659                                 if (collect_bss_info(padapter, precv_frame, pbss) == _SUCCESS) {
2660                                         update_network(&(pmlmepriv->cur_network.network), pbss, padapter, true);
2661                                         rtw_get_bcn_info(&(pmlmepriv->cur_network));
2662                                 }
2663                                 kfree(pbss);
2664                         }
2665
2666                         /* check the vendor of the assoc AP */
2667                         pmlmeinfo->assoc_AP_vendor = check_assoc_AP(pframe+sizeof(struct rtw_ieee80211_hdr_3addr), len-sizeof(struct rtw_ieee80211_hdr_3addr));
2668
2669                         /* update TSF Value */
2670                         update_TSF(pmlmeext, pframe, len);
2671
2672                         /* start auth */
2673                         start_clnt_auth(padapter);
2674
2675                         return _SUCCESS;
2676                 }
2677
2678                 if (((pmlmeinfo->state&0x03) == WIFI_FW_STATION_STATE) && (pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS)) {
2679                         psta = rtw_get_stainfo(pstapriv, GetAddr2Ptr(pframe));
2680                         if (psta != NULL) {
2681                                 ret = rtw_check_bcn_info(padapter, pframe, len);
2682                                 if (!ret) {
2683                                                 DBG_88E_LEVEL(_drv_info_, "ap has changed, disconnect now\n ");
2684                                                 receive_disconnect(padapter, pmlmeinfo->network.MacAddress , 65535);
2685                                                 return _SUCCESS;
2686                                 }
2687                                 /* update WMM, ERP in the beacon */
2688                                 /* todo: the timer is used instead of the number of the beacon received */
2689                                 if ((sta_rx_pkts(psta) & 0xf) == 0)
2690                                         update_beacon_info(padapter, pframe, len, psta);
2691                         }
2692                 } else if ((pmlmeinfo->state&0x03) == WIFI_FW_ADHOC_STATE) {
2693                         psta = rtw_get_stainfo(pstapriv, GetAddr2Ptr(pframe));
2694                         if (psta != NULL) {
2695                                 /* update WMM, ERP in the beacon */
2696                                 /* todo: the timer is used instead of the number of the beacon received */
2697                                 if ((sta_rx_pkts(psta) & 0xf) == 0)
2698                                         update_beacon_info(padapter, pframe, len, psta);
2699                         } else {
2700                                 /* allocate a new CAM entry for IBSS station */
2701                                 cam_idx = allocate_fw_sta_entry(padapter);
2702                                 if (cam_idx == NUM_STA)
2703                                         goto _END_ONBEACON_;
2704
2705                                 /* get supported rate */
2706                                 if (update_sta_support_rate(padapter, (pframe + WLAN_HDR_A3_LEN + _BEACON_IE_OFFSET_), (len - WLAN_HDR_A3_LEN - _BEACON_IE_OFFSET_), cam_idx) == _FAIL) {
2707                                         pmlmeinfo->FW_sta_info[cam_idx].status = 0;
2708                                         goto _END_ONBEACON_;
2709                                 }
2710
2711                                 /* update TSF Value */
2712                                 update_TSF(pmlmeext, pframe, len);
2713
2714                                 /* report sta add event */
2715                                 report_add_sta_event(padapter, GetAddr2Ptr(pframe), cam_idx);
2716                         }
2717                 }
2718         }
2719
2720 _END_ONBEACON_:
2721
2722         return _SUCCESS;
2723 }
2724
2725 #ifdef CONFIG_88EU_AP_MODE
2726 static unsigned int OnAuth(struct adapter *padapter,
2727                            struct recv_frame *precv_frame)
2728 {
2729         unsigned int    auth_mode, ie_len;
2730         u16 seq;
2731         unsigned char   *sa, *p;
2732         u16 algorithm;
2733         int     status;
2734         static struct sta_info stat;
2735         struct  sta_info        *pstat = NULL;
2736         struct  sta_priv *pstapriv = &padapter->stapriv;
2737         struct security_priv *psecuritypriv = &padapter->securitypriv;
2738         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
2739         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
2740         u8 *pframe = precv_frame->rx_data;
2741         uint len = precv_frame->len;
2742
2743         if ((pmlmeinfo->state&0x03) != WIFI_FW_AP_STATE)
2744                 return _FAIL;
2745
2746         DBG_88E("+OnAuth\n");
2747
2748         sa = GetAddr2Ptr(pframe);
2749
2750         auth_mode = psecuritypriv->dot11AuthAlgrthm;
2751         seq = le16_to_cpu(*(__le16 *)((size_t)pframe + WLAN_HDR_A3_LEN + 2));
2752         algorithm = le16_to_cpu(*(__le16 *)((size_t)pframe + WLAN_HDR_A3_LEN));
2753
2754         DBG_88E("auth alg=%x, seq=%X\n", algorithm, seq);
2755
2756         if (auth_mode == 2 && psecuritypriv->dot11PrivacyAlgrthm != _WEP40_ &&
2757             psecuritypriv->dot11PrivacyAlgrthm != _WEP104_)
2758                 auth_mode = 0;
2759
2760         if ((algorithm > 0 && auth_mode == 0) ||        /*  rx a shared-key auth but shared not enabled */
2761             (algorithm == 0 && auth_mode == 1)) {       /*  rx a open-system auth but shared-key is enabled */
2762                 DBG_88E("auth rejected due to bad alg [alg=%d, auth_mib=%d] %02X%02X%02X%02X%02X%02X\n",
2763                         algorithm, auth_mode, sa[0], sa[1], sa[2], sa[3], sa[4], sa[5]);
2764
2765                 status = _STATS_NO_SUPP_ALG_;
2766
2767                 goto auth_fail;
2768         }
2769
2770         if (!rtw_access_ctrl(padapter, sa)) {
2771                 status = _STATS_UNABLE_HANDLE_STA_;
2772                 goto auth_fail;
2773         }
2774
2775         pstat = rtw_get_stainfo(pstapriv, sa);
2776         if (pstat == NULL) {
2777                 /*  allocate a new one */
2778                 DBG_88E("going to alloc stainfo for sa=%pM\n", sa);
2779                 pstat = rtw_alloc_stainfo(pstapriv, sa);
2780                 if (pstat == NULL) {
2781                         DBG_88E(" Exceed the upper limit of supported clients...\n");
2782                         status = _STATS_UNABLE_HANDLE_STA_;
2783                         goto auth_fail;
2784                 }
2785
2786                 pstat->state = WIFI_FW_AUTH_NULL;
2787                 pstat->auth_seq = 0;
2788         } else {
2789                 spin_lock_bh(&pstapriv->asoc_list_lock);
2790                 if (!list_empty(&pstat->asoc_list)) {
2791                         list_del_init(&pstat->asoc_list);
2792                         pstapriv->asoc_list_cnt--;
2793                 }
2794                 spin_unlock_bh(&pstapriv->asoc_list_lock);
2795
2796                 if (seq == 1) {
2797                         /* TODO: STA re_auth and auth timeout */
2798                 }
2799         }
2800
2801         spin_lock_bh(&pstapriv->auth_list_lock);
2802         if (list_empty(&pstat->auth_list)) {
2803                 list_add_tail(&pstat->auth_list, &pstapriv->auth_list);
2804                 pstapriv->auth_list_cnt++;
2805         }
2806         spin_unlock_bh(&pstapriv->auth_list_lock);
2807
2808         if (pstat->auth_seq == 0)
2809                 pstat->expire_to = pstapriv->auth_to;
2810
2811         if ((pstat->auth_seq + 1) != seq) {
2812                 DBG_88E("(1)auth rejected because out of seq [rx_seq=%d, exp_seq=%d]!\n",
2813                         seq, pstat->auth_seq+1);
2814                 status = _STATS_OUT_OF_AUTH_SEQ_;
2815                 goto auth_fail;
2816         }
2817
2818         if (algorithm == 0 && (auth_mode == 0 || auth_mode == 2)) {
2819                 if (seq == 1) {
2820                         pstat->state &= ~WIFI_FW_AUTH_NULL;
2821                         pstat->state |= WIFI_FW_AUTH_SUCCESS;
2822                         pstat->expire_to = pstapriv->assoc_to;
2823                         pstat->authalg = algorithm;
2824                 } else {
2825                         DBG_88E("(2)auth rejected because out of seq [rx_seq=%d, exp_seq=%d]!\n",
2826                                 seq, pstat->auth_seq+1);
2827                         status = _STATS_OUT_OF_AUTH_SEQ_;
2828                         goto auth_fail;
2829                 }
2830         } else { /*  shared system or auto authentication */
2831                 if (seq == 1) {
2832                         /* prepare for the challenging txt... */
2833
2834                         pstat->state &= ~WIFI_FW_AUTH_NULL;
2835                         pstat->state |= WIFI_FW_AUTH_STATE;
2836                         pstat->authalg = algorithm;
2837                         pstat->auth_seq = 2;
2838                 } else if (seq == 3) {
2839                         /* checking for challenging txt... */
2840                         DBG_88E("checking for challenging txt...\n");
2841
2842                         p = rtw_get_ie(pframe + WLAN_HDR_A3_LEN + 4 + _AUTH_IE_OFFSET_ , _CHLGETXT_IE_, (int *)&ie_len,
2843                                         len - WLAN_HDR_A3_LEN - _AUTH_IE_OFFSET_ - 4);
2844
2845                         if ((p == NULL) || (ie_len <= 0)) {
2846                                 DBG_88E("auth rejected because challenge failure!(1)\n");
2847                                 status = _STATS_CHALLENGE_FAIL_;
2848                                 goto auth_fail;
2849                         }
2850
2851                         if (!memcmp((void *)(p + 2), pstat->chg_txt, 128)) {
2852                                 pstat->state &= (~WIFI_FW_AUTH_STATE);
2853                                 pstat->state |= WIFI_FW_AUTH_SUCCESS;
2854                                 /*  challenging txt is correct... */
2855                                 pstat->expire_to =  pstapriv->assoc_to;
2856                         } else {
2857                                 DBG_88E("auth rejected because challenge failure!\n");
2858                                 status = _STATS_CHALLENGE_FAIL_;
2859                                 goto auth_fail;
2860                         }
2861                 } else {
2862                         DBG_88E("(3)auth rejected because out of seq [rx_seq=%d, exp_seq=%d]!\n",
2863                                 seq, pstat->auth_seq+1);
2864                         status = _STATS_OUT_OF_AUTH_SEQ_;
2865                         goto auth_fail;
2866                 }
2867         }
2868
2869         /*  Now, we are going to issue_auth... */
2870         pstat->auth_seq = seq + 1;
2871
2872         issue_auth(padapter, pstat, (unsigned short)(_STATS_SUCCESSFUL_));
2873
2874         if (pstat->state & WIFI_FW_AUTH_SUCCESS)
2875                 pstat->auth_seq = 0;
2876
2877         return _SUCCESS;
2878
2879 auth_fail:
2880
2881         if (pstat)
2882                 rtw_free_stainfo(padapter, pstat);
2883
2884         pstat = &stat;
2885         memset((char *)pstat, '\0', sizeof(stat));
2886         pstat->auth_seq = 2;
2887         memcpy(pstat->hwaddr, sa, 6);
2888
2889         issue_auth(padapter, pstat, (unsigned short)status);
2890
2891         return _FAIL;
2892 }
2893 #endif /* CONFIG_88EU_AP_MODE */
2894
2895 static unsigned int OnAuthClient(struct adapter *padapter,
2896                                  struct recv_frame *precv_frame)
2897 {
2898         unsigned int    seq, len, status, offset;
2899         unsigned char   *p;
2900         unsigned int    go2asoc = 0;
2901         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
2902         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
2903         u8 *pframe = precv_frame->rx_data;
2904         uint pkt_len = precv_frame->len;
2905
2906         DBG_88E("%s\n", __func__);
2907
2908         /* check A1 matches or not */
2909         if (memcmp(myid(&(padapter->eeprompriv)), get_da(pframe), ETH_ALEN))
2910                 return _SUCCESS;
2911
2912         if (!(pmlmeinfo->state & WIFI_FW_AUTH_STATE))
2913                 return _SUCCESS;
2914
2915         offset = (GetPrivacy(pframe)) ? 4 : 0;
2916
2917         seq     = le16_to_cpu(*(__le16 *)((size_t)pframe + WLAN_HDR_A3_LEN + offset + 2));
2918         status  = le16_to_cpu(*(__le16 *)((size_t)pframe + WLAN_HDR_A3_LEN + offset + 4));
2919
2920         if (status != 0) {
2921                 DBG_88E("clnt auth fail, status: %d\n", status);
2922                 if (status == 13) { /*  pmlmeinfo->auth_algo == dot11AuthAlgrthm_Auto) */
2923                         if (pmlmeinfo->auth_algo == dot11AuthAlgrthm_Shared)
2924                                 pmlmeinfo->auth_algo = dot11AuthAlgrthm_Open;
2925                         else
2926                                 pmlmeinfo->auth_algo = dot11AuthAlgrthm_Shared;
2927                 }
2928
2929                 set_link_timer(pmlmeext, 1);
2930                 goto authclnt_fail;
2931         }
2932
2933         if (seq == 2) {
2934                 if (pmlmeinfo->auth_algo == dot11AuthAlgrthm_Shared) {
2935                          /*  legendary shared system */
2936                         p = rtw_get_ie(pframe + WLAN_HDR_A3_LEN + _AUTH_IE_OFFSET_, _CHLGETXT_IE_, (int *)&len,
2937                                 pkt_len - WLAN_HDR_A3_LEN - _AUTH_IE_OFFSET_);
2938
2939                         if (p == NULL)
2940                                 goto authclnt_fail;
2941
2942                         memcpy((void *)(pmlmeinfo->chg_txt), (void *)(p + 2), len);
2943                         pmlmeinfo->auth_seq = 3;
2944                         issue_auth(padapter, NULL, 0);
2945                         set_link_timer(pmlmeext, REAUTH_TO);
2946
2947                         return _SUCCESS;
2948                 } else {
2949                         /*  open system */
2950                         go2asoc = 1;
2951                 }
2952         } else if (seq == 4) {
2953                 if (pmlmeinfo->auth_algo == dot11AuthAlgrthm_Shared)
2954                         go2asoc = 1;
2955                 else
2956                         goto authclnt_fail;
2957         } else {
2958                 /*  this is also illegal */
2959                 goto authclnt_fail;
2960         }
2961
2962         if (go2asoc) {
2963                 DBG_88E_LEVEL(_drv_info_, "auth success, start assoc\n");
2964                 start_clnt_assoc(padapter);
2965                 return _SUCCESS;
2966         }
2967 authclnt_fail:
2968         return _FAIL;
2969 }
2970
2971 static unsigned int OnAssocReq(struct adapter *padapter,
2972                                struct recv_frame *precv_frame)
2973 {
2974 #ifdef CONFIG_88EU_AP_MODE
2975         u16 capab_info;
2976         struct rtw_ieee802_11_elems elems;
2977         struct sta_info *pstat;
2978         unsigned char           reassoc, *p, *pos, *wpa_ie;
2979         unsigned char WMM_IE[] = {0x00, 0x50, 0xf2, 0x02, 0x00, 0x01};
2980         int             i, ie_len, wpa_ie_len, left;
2981         unsigned char           supportRate[16];
2982         int                                     supportRateNum;
2983         unsigned short          status = _STATS_SUCCESSFUL_;
2984         unsigned short          frame_type, ie_offset = 0;
2985         struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
2986         struct security_priv *psecuritypriv = &padapter->securitypriv;
2987         struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
2988         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
2989         struct wlan_bssid_ex *cur = &(pmlmeinfo->network);
2990         struct sta_priv *pstapriv = &padapter->stapriv;
2991         u8 *pframe = precv_frame->rx_data;
2992         uint pkt_len = precv_frame->len;
2993
2994         if ((pmlmeinfo->state&0x03) != WIFI_FW_AP_STATE)
2995                 return _FAIL;
2996
2997         frame_type = GetFrameSubType(pframe);
2998         if (frame_type == WIFI_ASSOCREQ) {
2999                 reassoc = 0;
3000                 ie_offset = _ASOCREQ_IE_OFFSET_;
3001         } else { /*  WIFI_REASSOCREQ */
3002                 reassoc = 1;
3003                 ie_offset = _REASOCREQ_IE_OFFSET_;
3004         }
3005
3006
3007         if (pkt_len < IEEE80211_3ADDR_LEN + ie_offset) {
3008                 DBG_88E("handle_assoc(reassoc=%d) - too short payload (len=%lu)"
3009                        "\n", reassoc, (unsigned long)pkt_len);
3010                 return _FAIL;
3011         }
3012
3013         pstat = rtw_get_stainfo(pstapriv, GetAddr2Ptr(pframe));
3014         if (pstat == NULL) {
3015                 status = _RSON_CLS2_;
3016                 goto asoc_class2_error;
3017         }
3018
3019         capab_info = get_unaligned_le16(pframe + WLAN_HDR_A3_LEN);
3020
3021         left = pkt_len - (IEEE80211_3ADDR_LEN + ie_offset);
3022         pos = pframe + (IEEE80211_3ADDR_LEN + ie_offset);
3023
3024
3025         DBG_88E("%s\n", __func__);
3026
3027         /*  check if this stat has been successfully authenticated/assocated */
3028         if (!((pstat->state) & WIFI_FW_AUTH_SUCCESS)) {
3029                 if (!((pstat->state) & WIFI_FW_ASSOC_SUCCESS)) {
3030                         status = _RSON_CLS2_;
3031                         goto asoc_class2_error;
3032                 } else {
3033                         pstat->state &= (~WIFI_FW_ASSOC_SUCCESS);
3034                         pstat->state |= WIFI_FW_ASSOC_STATE;
3035                 }
3036         } else {
3037                 pstat->state &= (~WIFI_FW_AUTH_SUCCESS);
3038                 pstat->state |= WIFI_FW_ASSOC_STATE;
3039         }
3040         pstat->capability = capab_info;
3041         /* now parse all ieee802_11 ie to point to elems */
3042         if (rtw_ieee802_11_parse_elems(pos, left, &elems, 1) == ParseFailed ||
3043             !elems.ssid) {
3044                 DBG_88E("STA %pM sent invalid association request\n",
3045                         pstat->hwaddr);
3046                 status = _STATS_FAILURE_;
3047                 goto OnAssocReqFail;
3048         }
3049
3050
3051         /*  now we should check all the fields... */
3052         /*  checking SSID */
3053         p = rtw_get_ie(pframe + WLAN_HDR_A3_LEN + ie_offset, _SSID_IE_, &ie_len,
3054                 pkt_len - WLAN_HDR_A3_LEN - ie_offset);
3055         if (p == NULL)
3056                 status = _STATS_FAILURE_;
3057
3058         if (ie_len == 0) { /*  broadcast ssid, however it is not allowed in assocreq */
3059                 status = _STATS_FAILURE_;
3060         } else {
3061                 /*  check if ssid match */
3062                 if (memcmp((void *)(p+2), cur->Ssid.Ssid, cur->Ssid.SsidLength))
3063                         status = _STATS_FAILURE_;
3064
3065                 if (ie_len != cur->Ssid.SsidLength)
3066                         status = _STATS_FAILURE_;
3067         }
3068
3069         if (_STATS_SUCCESSFUL_ != status)
3070                 goto OnAssocReqFail;
3071
3072         /*  check if the supported rate is ok */
3073         p = rtw_get_ie(pframe + WLAN_HDR_A3_LEN + ie_offset, _SUPPORTEDRATES_IE_, &ie_len, pkt_len - WLAN_HDR_A3_LEN - ie_offset);
3074         if (p == NULL) {
3075                 DBG_88E("Rx a sta assoc-req which supported rate is empty!\n");
3076                 /*  use our own rate set as statoin used */
3077                 /* memcpy(supportRate, AP_BSSRATE, AP_BSSRATE_LEN); */
3078                 /* supportRateNum = AP_BSSRATE_LEN; */
3079
3080                 status = _STATS_FAILURE_;
3081                 goto OnAssocReqFail;
3082         } else {
3083                 memcpy(supportRate, p+2, ie_len);
3084                 supportRateNum = ie_len;
3085
3086                 p = rtw_get_ie(pframe + WLAN_HDR_A3_LEN + ie_offset, _EXT_SUPPORTEDRATES_IE_ , &ie_len,
3087                                 pkt_len - WLAN_HDR_A3_LEN - ie_offset);
3088                 if (p !=  NULL) {
3089                         if (supportRateNum <= sizeof(supportRate)) {
3090                                 memcpy(supportRate+supportRateNum, p+2, ie_len);
3091                                 supportRateNum += ie_len;
3092                         }
3093                 }
3094         }
3095
3096         /* todo: mask supportRate between AP & STA -> move to update raid */
3097         /* get_matched_rate(pmlmeext, supportRate, &supportRateNum, 0); */
3098
3099         /* update station supportRate */
3100         pstat->bssratelen = supportRateNum;
3101         memcpy(pstat->bssrateset, supportRate, supportRateNum);
3102         UpdateBrateTblForSoftAP(pstat->bssrateset, pstat->bssratelen);
3103
3104         /* check RSN/WPA/WPS */
3105         pstat->dot8021xalg = 0;
3106         pstat->wpa_psk = 0;
3107         pstat->wpa_group_cipher = 0;
3108         pstat->wpa2_group_cipher = 0;
3109         pstat->wpa_pairwise_cipher = 0;
3110         pstat->wpa2_pairwise_cipher = 0;
3111         memset(pstat->wpa_ie, 0, sizeof(pstat->wpa_ie));
3112         if ((psecuritypriv->wpa_psk & BIT(1)) && elems.rsn_ie) {
3113                 int group_cipher = 0, pairwise_cipher = 0;
3114
3115                 wpa_ie = elems.rsn_ie;
3116                 wpa_ie_len = elems.rsn_ie_len;
3117
3118                 if (rtw_parse_wpa2_ie(wpa_ie-2, wpa_ie_len+2, &group_cipher, &pairwise_cipher, NULL) == _SUCCESS) {
3119                         pstat->dot8021xalg = 1;/* psk,  todo:802.1x */
3120                         pstat->wpa_psk |= BIT(1);
3121
3122                         pstat->wpa2_group_cipher = group_cipher&psecuritypriv->wpa2_group_cipher;
3123                         pstat->wpa2_pairwise_cipher = pairwise_cipher&psecuritypriv->wpa2_pairwise_cipher;
3124
3125                         if (!pstat->wpa2_group_cipher)
3126                                 status = WLAN_STATUS_INVALID_GROUP_CIPHER;
3127
3128                         if (!pstat->wpa2_pairwise_cipher)
3129                                 status = WLAN_STATUS_INVALID_PAIRWISE_CIPHER;
3130                 } else {
3131                         status = WLAN_STATUS_INVALID_IE;
3132                 }
3133         } else if ((psecuritypriv->wpa_psk & BIT(0)) && elems.wpa_ie) {
3134                 int group_cipher = 0, pairwise_cipher = 0;
3135
3136                 wpa_ie = elems.wpa_ie;
3137                 wpa_ie_len = elems.wpa_ie_len;
3138
3139                 if (rtw_parse_wpa_ie(wpa_ie-2, wpa_ie_len+2, &group_cipher, &pairwise_cipher, NULL) == _SUCCESS) {
3140                         pstat->dot8021xalg = 1;/* psk,  todo:802.1x */
3141                         pstat->wpa_psk |= BIT(0);
3142
3143                         pstat->wpa_group_cipher = group_cipher&psecuritypriv->wpa_group_cipher;
3144                         pstat->wpa_pairwise_cipher = pairwise_cipher&psecuritypriv->wpa_pairwise_cipher;
3145
3146                         if (!pstat->wpa_group_cipher)
3147                                 status = WLAN_STATUS_INVALID_GROUP_CIPHER;
3148
3149                         if (!pstat->wpa_pairwise_cipher)
3150                                 status = WLAN_STATUS_INVALID_PAIRWISE_CIPHER;
3151                 } else {
3152                         status = WLAN_STATUS_INVALID_IE;
3153                 }
3154         } else {
3155                 wpa_ie = NULL;
3156                 wpa_ie_len = 0;
3157         }
3158
3159         if (_STATS_SUCCESSFUL_ != status)
3160                 goto OnAssocReqFail;
3161
3162         pstat->flags &= ~(WLAN_STA_WPS | WLAN_STA_MAYBE_WPS);
3163         if (wpa_ie == NULL) {
3164                 if (elems.wps_ie) {
3165                         DBG_88E("STA included WPS IE in "
3166                                    "(Re)Association Request - assume WPS is "
3167                                    "used\n");
3168                         pstat->flags |= WLAN_STA_WPS;
3169                         /* wpabuf_free(sta->wps_ie); */
3170                         /* sta->wps_ie = wpabuf_alloc_copy(elems.wps_ie + 4, */
3171                         /*                              elems.wps_ie_len - 4); */
3172                 } else {
3173                         DBG_88E("STA did not include WPA/RSN IE "
3174                                    "in (Re)Association Request - possible WPS "
3175                                    "use\n");
3176                         pstat->flags |= WLAN_STA_MAYBE_WPS;
3177                 }
3178
3179
3180                 /*  AP support WPA/RSN, and sta is going to do WPS, but AP is not ready */
3181                 /*  that the selected registrar of AP is _FLASE */
3182                 if ((psecuritypriv->wpa_psk > 0) && (pstat->flags & (WLAN_STA_WPS|WLAN_STA_MAYBE_WPS))) {
3183                         if (pmlmepriv->wps_beacon_ie) {
3184                                 u8 selected_registrar = 0;
3185
3186                                 rtw_get_wps_attr_content(pmlmepriv->wps_beacon_ie, pmlmepriv->wps_beacon_ie_len, WPS_ATTR_SELECTED_REGISTRAR , &selected_registrar, NULL);
3187
3188                                 if (!selected_registrar) {
3189                                         DBG_88E("selected_registrar is false , or AP is not ready to do WPS\n");
3190
3191                                         status = _STATS_UNABLE_HANDLE_STA_;
3192
3193                                         goto OnAssocReqFail;
3194                                 }
3195                         }
3196                 }
3197         } else {
3198                 int copy_len;
3199
3200                 if (psecuritypriv->wpa_psk == 0) {
3201                         DBG_88E("STA %pM: WPA/RSN IE in association "
3202                         "request, but AP don't support WPA/RSN\n", pstat->hwaddr);
3203
3204                         status = WLAN_STATUS_INVALID_IE;
3205
3206                         goto OnAssocReqFail;
3207                 }
3208
3209                 if (elems.wps_ie) {
3210                         DBG_88E("STA included WPS IE in "
3211                                    "(Re)Association Request - WPS is "
3212                                    "used\n");
3213                         pstat->flags |= WLAN_STA_WPS;
3214                         copy_len = 0;
3215                 } else {
3216                         copy_len = ((wpa_ie_len+2) > sizeof(pstat->wpa_ie)) ? (sizeof(pstat->wpa_ie)) : (wpa_ie_len+2);
3217                 }
3218                 if (copy_len > 0)
3219                         memcpy(pstat->wpa_ie, wpa_ie-2, copy_len);
3220         }
3221         /*  check if there is WMM IE & support WWM-PS */
3222         pstat->flags &= ~WLAN_STA_WME;
3223         pstat->qos_option = 0;
3224         pstat->qos_info = 0;
3225         pstat->has_legacy_ac = true;
3226         pstat->uapsd_vo = 0;
3227         pstat->uapsd_vi = 0;
3228         pstat->uapsd_be = 0;
3229         pstat->uapsd_bk = 0;
3230         if (pmlmepriv->qospriv.qos_option) {
3231                 p = pframe + WLAN_HDR_A3_LEN + ie_offset; ie_len = 0;
3232                 for (;;) {
3233                         p = rtw_get_ie(p, _VENDOR_SPECIFIC_IE_, &ie_len, pkt_len - WLAN_HDR_A3_LEN - ie_offset);
3234                         if (p != NULL) {
3235                                 if (!memcmp(p+2, WMM_IE, 6)) {
3236                                         pstat->flags |= WLAN_STA_WME;
3237
3238                                         pstat->qos_option = 1;
3239                                         pstat->qos_info = *(p+8);
3240
3241                                         pstat->max_sp_len = (pstat->qos_info>>5)&0x3;
3242
3243                                         if ((pstat->qos_info&0xf) != 0xf)
3244                                                 pstat->has_legacy_ac = true;
3245                                         else
3246                                                 pstat->has_legacy_ac = false;
3247
3248                                         if (pstat->qos_info&0xf) {
3249                                                 if (pstat->qos_info&BIT(0))
3250                                                         pstat->uapsd_vo = BIT(0)|BIT(1);
3251                                                 else
3252                                                         pstat->uapsd_vo = 0;
3253
3254                                                 if (pstat->qos_info&BIT(1))
3255                                                         pstat->uapsd_vi = BIT(0)|BIT(1);
3256                                                 else
3257                                                         pstat->uapsd_vi = 0;
3258
3259                                                 if (pstat->qos_info&BIT(2))
3260                                                         pstat->uapsd_bk = BIT(0)|BIT(1);
3261                                                 else
3262                                                         pstat->uapsd_bk = 0;
3263
3264                                                 if (pstat->qos_info&BIT(3))
3265                                                         pstat->uapsd_be = BIT(0)|BIT(1);
3266                                                 else
3267                                                         pstat->uapsd_be = 0;
3268                                         }
3269                                         break;
3270                                 }
3271                         } else {
3272                                 break;
3273                         }
3274                         p = p + ie_len + 2;
3275                 }
3276         }
3277
3278         /* save HT capabilities in the sta object */
3279         memset(&pstat->htpriv.ht_cap, 0, sizeof(struct rtw_ieee80211_ht_cap));
3280         if (elems.ht_capabilities && elems.ht_capabilities_len >= sizeof(struct rtw_ieee80211_ht_cap)) {
3281                 pstat->flags |= WLAN_STA_HT;
3282
3283                 pstat->flags |= WLAN_STA_WME;
3284
3285                 memcpy(&pstat->htpriv.ht_cap, elems.ht_capabilities, sizeof(struct rtw_ieee80211_ht_cap));
3286         } else {
3287                 pstat->flags &= ~WLAN_STA_HT;
3288         }
3289         if ((!pmlmepriv->htpriv.ht_option) && (pstat->flags&WLAN_STA_HT)) {
3290                 status = _STATS_FAILURE_;
3291                 goto OnAssocReqFail;
3292         }
3293
3294         if ((pstat->flags & WLAN_STA_HT) &&
3295             ((pstat->wpa2_pairwise_cipher&WPA_CIPHER_TKIP) ||
3296             (pstat->wpa_pairwise_cipher&WPA_CIPHER_TKIP))) {
3297                 DBG_88E("HT: %pM tried to "
3298                         "use TKIP with HT association\n", pstat->hwaddr);
3299
3300                 /* status = WLAN_STATUS_CIPHER_REJECTED_PER_POLICY; */
3301                 /* goto OnAssocReqFail; */
3302         }
3303
3304         pstat->flags |= WLAN_STA_NONERP;
3305         for (i = 0; i < pstat->bssratelen; i++) {
3306                 if ((pstat->bssrateset[i] & 0x7f) > 22) {
3307                         pstat->flags &= ~WLAN_STA_NONERP;
3308                         break;
3309                 }
3310         }
3311
3312         if (pstat->capability & WLAN_CAPABILITY_SHORT_PREAMBLE)
3313                 pstat->flags |= WLAN_STA_SHORT_PREAMBLE;
3314         else
3315                 pstat->flags &= ~WLAN_STA_SHORT_PREAMBLE;
3316
3317
3318
3319         if (status != _STATS_SUCCESSFUL_)
3320                 goto OnAssocReqFail;
3321
3322         /* TODO: identify_proprietary_vendor_ie(); */
3323         /*  Realtek proprietary IE */
3324         /*  identify if this is Broadcom sta */
3325         /*  identify if this is ralink sta */
3326         /*  Customer proprietary IE */
3327
3328         /* get a unique AID */
3329         if (pstat->aid > 0) {
3330                 DBG_88E("  old AID %d\n", pstat->aid);
3331         } else {
3332                 for (pstat->aid = 1; pstat->aid <= NUM_STA; pstat->aid++)
3333                         if (pstapriv->sta_aid[pstat->aid - 1] == NULL)
3334                                 break;
3335
3336                 /* if (pstat->aid > NUM_STA) { */
3337                 if (pstat->aid > pstapriv->max_num_sta) {
3338                         pstat->aid = 0;
3339
3340                         DBG_88E("  no room for more AIDs\n");
3341
3342                         status = WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA;
3343
3344                         goto OnAssocReqFail;
3345                 } else {
3346                         pstapriv->sta_aid[pstat->aid - 1] = pstat;
3347                         DBG_88E("allocate new AID=(%d)\n", pstat->aid);
3348                 }
3349         }
3350
3351         pstat->state &= (~WIFI_FW_ASSOC_STATE);
3352         pstat->state |= WIFI_FW_ASSOC_SUCCESS;
3353
3354         spin_lock_bh(&pstapriv->auth_list_lock);
3355         if (!list_empty(&pstat->auth_list)) {
3356                 list_del_init(&pstat->auth_list);
3357                 pstapriv->auth_list_cnt--;
3358         }
3359         spin_unlock_bh(&pstapriv->auth_list_lock);
3360
3361         spin_lock_bh(&pstapriv->asoc_list_lock);
3362         if (list_empty(&pstat->asoc_list)) {
3363                 pstat->expire_to = pstapriv->expire_to;
3364                 list_add_tail(&pstat->asoc_list, &pstapriv->asoc_list);
3365                 pstapriv->asoc_list_cnt++;
3366         }
3367         spin_unlock_bh(&pstapriv->asoc_list_lock);
3368
3369         /*  now the station is qualified to join our BSS... */
3370         if (pstat && (pstat->state & WIFI_FW_ASSOC_SUCCESS) && (_STATS_SUCCESSFUL_ == status)) {
3371                 /* 1 bss_cap_update & sta_info_update */
3372                 bss_cap_update_on_sta_join(padapter, pstat);
3373                 sta_info_update(padapter, pstat);
3374
3375                 /* issue assoc rsp before notify station join event. */
3376                 if (frame_type == WIFI_ASSOCREQ)
3377                         issue_asocrsp(padapter, status, pstat, WIFI_ASSOCRSP);
3378                 else
3379                         issue_asocrsp(padapter, status, pstat, WIFI_REASSOCRSP);
3380
3381                 /* 2 - report to upper layer */
3382                 DBG_88E("indicate_sta_join_event to upper layer - hostapd\n");
3383                 rtw_indicate_sta_assoc_event(padapter, pstat);
3384
3385                 /* 3-(1) report sta add event */
3386                 report_add_sta_event(padapter, pstat->hwaddr, pstat->aid);
3387         }
3388
3389         return _SUCCESS;
3390
3391 asoc_class2_error:
3392
3393         issue_deauth(padapter, (void *)GetAddr2Ptr(pframe), status);
3394
3395         return _FAIL;
3396
3397 OnAssocReqFail:
3398
3399         pstat->aid = 0;
3400         if (frame_type == WIFI_ASSOCREQ)
3401                 issue_asocrsp(padapter, status, pstat, WIFI_ASSOCRSP);
3402         else
3403                 issue_asocrsp(padapter, status, pstat, WIFI_REASSOCRSP);
3404
3405 #endif /* CONFIG_88EU_AP_MODE */
3406
3407         return _FAIL;
3408 }
3409
3410 static unsigned int OnAssocRsp(struct adapter *padapter,
3411                                struct recv_frame *precv_frame)
3412 {
3413         uint i;
3414         int res;
3415         unsigned short  status;
3416         struct ndis_802_11_var_ie *pIE;
3417         struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
3418         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
3419         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
3420         /* struct wlan_bssid_ex *cur_network = &(pmlmeinfo->network); */
3421         u8 *pframe = precv_frame->rx_data;
3422         uint pkt_len = precv_frame->len;
3423
3424         DBG_88E("%s\n", __func__);
3425
3426         /* check A1 matches or not */
3427         if (memcmp(myid(&(padapter->eeprompriv)), get_da(pframe), ETH_ALEN))
3428                 return _SUCCESS;
3429
3430         if (!(pmlmeinfo->state & (WIFI_FW_AUTH_SUCCESS | WIFI_FW_ASSOC_STATE)))
3431                 return _SUCCESS;
3432
3433         if (pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS)
3434                 return _SUCCESS;
3435
3436         del_timer_sync(&pmlmeext->link_timer);
3437
3438         /* status */
3439         status = le16_to_cpu(*(__le16 *)(pframe + WLAN_HDR_A3_LEN + 2));
3440         if (status > 0) {
3441                 DBG_88E("assoc reject, status code: %d\n", status);
3442                 pmlmeinfo->state = WIFI_FW_NULL_STATE;
3443                 res = -4;
3444                 goto report_assoc_result;
3445         }
3446
3447         /* get capabilities */
3448         pmlmeinfo->capability = le16_to_cpu(*(__le16 *)(pframe + WLAN_HDR_A3_LEN));
3449
3450         /* set slot time */
3451         pmlmeinfo->slotTime = (pmlmeinfo->capability & BIT(10)) ? 9 : 20;
3452
3453         /* AID */
3454         pmlmeinfo->aid = (int)(le16_to_cpu(*(__le16 *)(pframe + WLAN_HDR_A3_LEN + 4))&0x3fff);
3455         res = pmlmeinfo->aid;
3456
3457         /* following are moved to join event callback function */
3458         /* to handle HT, WMM, rate adaptive, update MAC reg */
3459         /* for not to handle the synchronous IO in the tasklet */
3460         for (i = (6 + WLAN_HDR_A3_LEN); i < pkt_len;) {
3461                 pIE = (struct ndis_802_11_var_ie *)(pframe + i);
3462
3463                 switch (pIE->ElementID) {
3464                 case _VENDOR_SPECIFIC_IE_:
3465                         if (!memcmp(pIE->data, WMM_PARA_OUI, 6)) /* WMM */
3466                                 WMM_param_handler(padapter, pIE);
3467                         break;
3468                 case _HT_CAPABILITY_IE_:        /* HT caps */
3469                         HT_caps_handler(padapter, pIE);
3470                         break;
3471                 case _HT_EXTRA_INFO_IE_:        /* HT info */
3472                         HT_info_handler(padapter, pIE);
3473                         break;
3474                 case _ERPINFO_IE_:
3475                         ERP_IE_handler(padapter, pIE);
3476                 default:
3477                         break;
3478                 }
3479
3480                 i += (pIE->Length + 2);
3481         }
3482
3483         pmlmeinfo->state &= (~WIFI_FW_ASSOC_STATE);
3484         pmlmeinfo->state |= WIFI_FW_ASSOC_SUCCESS;
3485
3486         /* Update Basic Rate Table for spec, 2010-12-28 , by thomas */
3487         UpdateBrateTbl(padapter, pmlmeinfo->network.SupportedRates);
3488
3489 report_assoc_result:
3490         if (res > 0) {
3491                 rtw_buf_update(&pmlmepriv->assoc_rsp, &pmlmepriv->assoc_rsp_len, pframe, pkt_len);
3492         } else {
3493                 rtw_buf_free(&pmlmepriv->assoc_rsp, &pmlmepriv->assoc_rsp_len);
3494         }
3495
3496         report_join_res(padapter, res);
3497
3498         return _SUCCESS;
3499 }
3500
3501 static unsigned int OnDeAuth(struct adapter *padapter,
3502                              struct recv_frame *precv_frame)
3503 {
3504         unsigned short  reason;
3505         struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
3506         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
3507         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
3508         u8 *pframe = precv_frame->rx_data;
3509         struct wlan_bssid_ex *pnetwork = &(pmlmeinfo->network);
3510
3511         /* check A3 */
3512         if (memcmp(GetAddr3Ptr(pframe), pnetwork->MacAddress, ETH_ALEN))
3513                 return _SUCCESS;
3514
3515         reason = le16_to_cpu(*(__le16 *)(pframe + WLAN_HDR_A3_LEN));
3516
3517         DBG_88E("%s Reason code(%d)\n", __func__, reason);
3518
3519 #ifdef CONFIG_88EU_AP_MODE
3520         if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) {
3521                 struct sta_info *psta;
3522                 struct sta_priv *pstapriv = &padapter->stapriv;
3523
3524                 DBG_88E_LEVEL(_drv_always_, "ap recv deauth reason code(%d) sta:%pM\n",
3525                               reason, GetAddr2Ptr(pframe));
3526
3527                 psta = rtw_get_stainfo(pstapriv, GetAddr2Ptr(pframe));
3528                 if (psta) {
3529                         u8 updated = 0;
3530
3531                         spin_lock_bh(&pstapriv->asoc_list_lock);
3532                         if (!list_empty(&psta->asoc_list)) {
3533                                 list_del_init(&psta->asoc_list);
3534                                 pstapriv->asoc_list_cnt--;
3535                                 updated = ap_free_sta(padapter, psta, false, reason);
3536                         }
3537                         spin_unlock_bh(&pstapriv->asoc_list_lock);
3538
3539                         associated_clients_update(padapter, updated);
3540                 }
3541
3542
3543                 return _SUCCESS;
3544         } else
3545 #endif
3546         {
3547                 DBG_88E_LEVEL(_drv_always_, "sta recv deauth reason code(%d) sta:%pM\n",
3548                               reason, GetAddr3Ptr(pframe));
3549
3550                 receive_disconnect(padapter, GetAddr3Ptr(pframe) , reason);
3551         }
3552         pmlmepriv->LinkDetectInfo.bBusyTraffic = false;
3553         return _SUCCESS;
3554 }
3555
3556 static unsigned int OnDisassoc(struct adapter *padapter,
3557                                struct recv_frame *precv_frame)
3558 {
3559         u16 reason;
3560         struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
3561         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
3562         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
3563         u8 *pframe = precv_frame->rx_data;
3564         struct wlan_bssid_ex *pnetwork = &(pmlmeinfo->network);
3565
3566         /* check A3 */
3567         if (memcmp(GetAddr3Ptr(pframe), pnetwork->MacAddress, ETH_ALEN))
3568                 return _SUCCESS;
3569
3570         reason = le16_to_cpu(*(__le16 *)(pframe + WLAN_HDR_A3_LEN));
3571
3572         DBG_88E("%s Reason code(%d)\n", __func__, reason);
3573
3574 #ifdef CONFIG_88EU_AP_MODE
3575         if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) {
3576                 struct sta_info *psta;
3577                 struct sta_priv *pstapriv = &padapter->stapriv;
3578
3579                 DBG_88E_LEVEL(_drv_always_, "ap recv disassoc reason code(%d) sta:%pM\n",
3580                               reason, GetAddr2Ptr(pframe));
3581
3582                 psta = rtw_get_stainfo(pstapriv, GetAddr2Ptr(pframe));
3583                 if (psta) {
3584                         u8 updated = 0;
3585
3586                         spin_lock_bh(&pstapriv->asoc_list_lock);
3587                         if (!list_empty(&psta->asoc_list)) {
3588                                 list_del_init(&psta->asoc_list);
3589                                 pstapriv->asoc_list_cnt--;
3590                                 updated = ap_free_sta(padapter, psta, false, reason);
3591                         }
3592                         spin_unlock_bh(&pstapriv->asoc_list_lock);
3593
3594                         associated_clients_update(padapter, updated);
3595                 }
3596
3597                 return _SUCCESS;
3598         } else
3599 #endif
3600         {
3601                 DBG_88E_LEVEL(_drv_always_, "ap recv disassoc reason code(%d) sta:%pM\n",
3602                               reason, GetAddr3Ptr(pframe));
3603
3604                 receive_disconnect(padapter, GetAddr3Ptr(pframe), reason);
3605         }
3606         pmlmepriv->LinkDetectInfo.bBusyTraffic = false;
3607         return _SUCCESS;
3608 }
3609
3610 static unsigned int OnAtim(struct adapter *padapter,
3611                            struct recv_frame *precv_frame)
3612 {
3613         DBG_88E("%s\n", __func__);
3614         return _SUCCESS;
3615 }
3616
3617 static unsigned int on_action_spct(struct adapter *padapter,
3618                                    struct recv_frame *precv_frame)
3619 {
3620         struct sta_info *psta = NULL;
3621         struct sta_priv *pstapriv = &padapter->stapriv;
3622         u8 *pframe = precv_frame->rx_data;
3623         u8 *frame_body = (u8 *)(pframe + sizeof(struct rtw_ieee80211_hdr_3addr));
3624         u8 category;
3625         u8 action;
3626
3627         DBG_88E(FUNC_NDEV_FMT"\n", FUNC_NDEV_ARG(padapter->pnetdev));
3628
3629         psta = rtw_get_stainfo(pstapriv, GetAddr2Ptr(pframe));
3630
3631         if (!psta)
3632                 goto exit;
3633
3634         category = frame_body[0];
3635         if (category != RTW_WLAN_CATEGORY_SPECTRUM_MGMT)
3636                 goto exit;
3637
3638         action = frame_body[1];
3639         switch (action) {
3640         case RTW_WLAN_ACTION_SPCT_MSR_REQ:
3641         case RTW_WLAN_ACTION_SPCT_MSR_RPRT:
3642         case RTW_WLAN_ACTION_SPCT_TPC_REQ:
3643         case RTW_WLAN_ACTION_SPCT_TPC_RPRT:
3644                 break;
3645         case RTW_WLAN_ACTION_SPCT_CHL_SWITCH:
3646                 break;
3647         default:
3648                 break;
3649         }
3650
3651 exit:
3652         return _FAIL;
3653 }
3654
3655 static unsigned int OnAction_qos(struct adapter *padapter,
3656                                  struct recv_frame *precv_frame)
3657 {
3658         return _SUCCESS;
3659 }
3660
3661 static unsigned int OnAction_dls(struct adapter *padapter,
3662                                  struct recv_frame *precv_frame)
3663 {
3664         return _SUCCESS;
3665 }
3666
3667 static unsigned int OnAction_back(struct adapter *padapter,
3668                                   struct recv_frame *precv_frame)
3669 {
3670         u8 *addr;
3671         struct sta_info *psta = NULL;
3672         struct recv_reorder_ctrl *preorder_ctrl;
3673         unsigned char           *frame_body;
3674         unsigned char           category, action;
3675         unsigned short  tid, status, reason_code = 0;
3676         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
3677         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
3678         u8 *pframe = precv_frame->rx_data;
3679         struct sta_priv *pstapriv = &padapter->stapriv;
3680         /* check RA matches or not */
3681         if (memcmp(myid(&(padapter->eeprompriv)), GetAddr1Ptr(pframe),
3682                    ETH_ALEN))/* for if1, sta/ap mode */
3683                 return _SUCCESS;
3684
3685         DBG_88E("%s\n", __func__);
3686
3687         if ((pmlmeinfo->state&0x03) != WIFI_FW_AP_STATE)
3688                 if (!(pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS))
3689                         return _SUCCESS;
3690
3691         addr = GetAddr2Ptr(pframe);
3692         psta = rtw_get_stainfo(pstapriv, addr);
3693
3694         if (psta == NULL)
3695                 return _SUCCESS;
3696
3697         frame_body = (unsigned char *)(pframe + sizeof(struct rtw_ieee80211_hdr_3addr));
3698
3699         category = frame_body[0];
3700         if (category == RTW_WLAN_CATEGORY_BACK) { /*  representing Block Ack */
3701                 if (!pmlmeinfo->HT_enable)
3702                         return _SUCCESS;
3703                 action = frame_body[1];
3704                 DBG_88E("%s, action=%d\n", __func__, action);
3705                 switch (action) {
3706                 case RTW_WLAN_ACTION_ADDBA_REQ: /* ADDBA request */
3707                         memcpy(&(pmlmeinfo->ADDBA_req), &(frame_body[2]), sizeof(struct ADDBA_request));
3708                         process_addba_req(padapter, (u8 *)&(pmlmeinfo->ADDBA_req), addr);
3709
3710                         if (pmlmeinfo->bAcceptAddbaReq)
3711                                 issue_action_BA(padapter, addr, RTW_WLAN_ACTION_ADDBA_RESP, 0);
3712                         else
3713                                 issue_action_BA(padapter, addr, RTW_WLAN_ACTION_ADDBA_RESP, 37);/* reject ADDBA Req */
3714                         break;
3715                 case RTW_WLAN_ACTION_ADDBA_RESP: /* ADDBA response */
3716                         status = get_unaligned_le16(&frame_body[3]);
3717                         tid = (frame_body[5] >> 2) & 0x7;
3718                         if (status == 0) {      /* successful */
3719                                 DBG_88E("agg_enable for TID=%d\n", tid);
3720                                 psta->htpriv.agg_enable_bitmap |= 1 << tid;
3721                                 psta->htpriv.candidate_tid_bitmap &= ~BIT(tid);
3722                         } else {
3723                                 psta->htpriv.agg_enable_bitmap &= ~BIT(tid);
3724                         }
3725                         break;
3726                 case RTW_WLAN_ACTION_DELBA: /* DELBA */
3727                         if ((frame_body[3] & BIT(3)) == 0) {
3728                                 psta->htpriv.agg_enable_bitmap &= ~(1 << ((frame_body[3] >> 4) & 0xf));
3729                                 psta->htpriv.candidate_tid_bitmap &= ~(1 << ((frame_body[3] >> 4) & 0xf));
3730                                 reason_code = get_unaligned_le16(&frame_body[4]);
3731                         } else if ((frame_body[3] & BIT(3)) == BIT(3)) {
3732                                 tid = (frame_body[3] >> 4) & 0x0F;
3733                                 preorder_ctrl =  &psta->recvreorder_ctrl[tid];
3734                                 preorder_ctrl->enable = false;
3735                                 preorder_ctrl->indicate_seq = 0xffff;
3736                         }
3737                         DBG_88E("%s(): DELBA: %x(%x)\n", __func__, pmlmeinfo->agg_enable_bitmap, reason_code);
3738                         /* todo: how to notify the host while receiving DELETE BA */
3739                         break;
3740                 default:
3741                         break;
3742                 }
3743         }
3744         return _SUCCESS;
3745 }
3746
3747 static s32 rtw_action_public_decache(struct recv_frame *recv_frame, s32 token)
3748 {
3749         struct adapter *adapter = recv_frame->adapter;
3750         struct mlme_ext_priv *mlmeext = &(adapter->mlmeextpriv);
3751         u8 *frame = recv_frame->rx_data;
3752         u16 seq_ctrl = ((recv_frame->attrib.seq_num&0xffff) << 4) |
3753                 (recv_frame->attrib.frag_num & 0xf);
3754
3755         if (GetRetry(frame)) {
3756                 if (token >= 0) {
3757                         if ((seq_ctrl == mlmeext->action_public_rxseq) && (token == mlmeext->action_public_dialog_token)) {
3758                                 DBG_88E(FUNC_ADPT_FMT" seq_ctrl = 0x%x, rxseq = 0x%x, token:%d\n",
3759                                         FUNC_ADPT_ARG(adapter), seq_ctrl, mlmeext->action_public_rxseq, token);
3760                                 return _FAIL;
3761                         }
3762                 } else {
3763                         if (seq_ctrl == mlmeext->action_public_rxseq) {
3764                                 DBG_88E(FUNC_ADPT_FMT" seq_ctrl = 0x%x, rxseq = 0x%x\n",
3765                                         FUNC_ADPT_ARG(adapter), seq_ctrl, mlmeext->action_public_rxseq);
3766                                 return _FAIL;
3767                         }
3768                 }
3769         }
3770
3771         mlmeext->action_public_rxseq = seq_ctrl;
3772
3773         if (token >= 0)
3774                 mlmeext->action_public_dialog_token = token;
3775
3776         return _SUCCESS;
3777 }
3778
3779 static unsigned int on_action_public_p2p(struct recv_frame *precv_frame)
3780 {
3781         u8 *pframe = precv_frame->rx_data;
3782         u8 *frame_body;
3783         u8 dialogToken = 0;
3784         frame_body = (unsigned char *)(pframe + sizeof(struct rtw_ieee80211_hdr_3addr));
3785
3786         dialogToken = frame_body[7];
3787
3788         if (rtw_action_public_decache(precv_frame, dialogToken) == _FAIL)
3789                 return _FAIL;
3790
3791         return _SUCCESS;
3792 }
3793
3794 static unsigned int on_action_public_vendor(struct recv_frame *precv_frame)
3795 {
3796         unsigned int ret = _FAIL;
3797         u8 *pframe = precv_frame->rx_data;
3798         u8 *frame_body = pframe + sizeof(struct rtw_ieee80211_hdr_3addr);
3799
3800         if (!memcmp(frame_body + 2, P2P_OUI, 4))
3801                 ret = on_action_public_p2p(precv_frame);
3802
3803         return ret;
3804 }
3805
3806 static unsigned int on_action_public_default(struct recv_frame *precv_frame, u8 action)
3807 {
3808         unsigned int ret = _FAIL;
3809         u8 *pframe = precv_frame->rx_data;
3810         u8 *frame_body = pframe + sizeof(struct rtw_ieee80211_hdr_3addr);
3811         u8 token;
3812
3813         token = frame_body[2];
3814
3815         if (rtw_action_public_decache(precv_frame, token) == _FAIL)
3816                 goto exit;
3817
3818         ret = _SUCCESS;
3819
3820 exit:
3821         return ret;
3822 }
3823
3824 static unsigned int on_action_public(struct adapter *padapter,
3825                                      struct recv_frame *precv_frame)
3826 {
3827         unsigned int ret = _FAIL;
3828         u8 *pframe = precv_frame->rx_data;
3829         u8 *frame_body = pframe + sizeof(struct rtw_ieee80211_hdr_3addr);
3830         u8 category, action;
3831
3832         /* check RA matches or not */
3833         if (memcmp(myid(&(padapter->eeprompriv)), GetAddr1Ptr(pframe), ETH_ALEN))
3834                 goto exit;
3835
3836         category = frame_body[0];
3837         if (category != RTW_WLAN_CATEGORY_PUBLIC)
3838                 goto exit;
3839
3840         action = frame_body[1];
3841         switch (action) {
3842         case ACT_PUBLIC_VENDOR:
3843                 ret = on_action_public_vendor(precv_frame);
3844                 break;
3845         default:
3846                 ret = on_action_public_default(precv_frame, action);
3847                 break;
3848         }
3849
3850 exit:
3851         return ret;
3852 }
3853
3854 static unsigned int OnAction_ht(struct adapter *padapter,
3855                                 struct recv_frame *precv_frame)
3856 {
3857         return _SUCCESS;
3858 }
3859
3860 static unsigned int OnAction_wmm(struct adapter *padapter,
3861                                  struct recv_frame *precv_frame)
3862 {
3863         return _SUCCESS;
3864 }
3865
3866 static unsigned int OnAction_p2p(struct adapter *padapter,
3867                                  struct recv_frame *precv_frame)
3868 {
3869         return _SUCCESS;
3870 }
3871
3872 static unsigned int DoReserved(struct adapter *padapter,
3873                                struct recv_frame *precv_frame)
3874 {
3875         return _SUCCESS;
3876 }
3877
3878 static struct action_handler OnAction_tbl[] = {
3879         {RTW_WLAN_CATEGORY_SPECTRUM_MGMT,        "ACTION_SPECTRUM_MGMT", on_action_spct},
3880         {RTW_WLAN_CATEGORY_QOS, "ACTION_QOS", &OnAction_qos},
3881         {RTW_WLAN_CATEGORY_DLS, "ACTION_DLS", &OnAction_dls},
3882         {RTW_WLAN_CATEGORY_BACK, "ACTION_BACK", &OnAction_back},
3883         {RTW_WLAN_CATEGORY_PUBLIC, "ACTION_PUBLIC", on_action_public},
3884         {RTW_WLAN_CATEGORY_RADIO_MEASUREMENT, "ACTION_RADIO_MEASUREMENT", &DoReserved},
3885         {RTW_WLAN_CATEGORY_FT, "ACTION_FT",     &DoReserved},
3886         {RTW_WLAN_CATEGORY_HT,  "ACTION_HT",    &OnAction_ht},
3887         {RTW_WLAN_CATEGORY_SA_QUERY, "ACTION_SA_QUERY", &DoReserved},
3888         {RTW_WLAN_CATEGORY_WMM, "ACTION_WMM", &OnAction_wmm},
3889         {RTW_WLAN_CATEGORY_P2P, "ACTION_P2P", &OnAction_p2p},
3890 };
3891
3892 static unsigned int OnAction(struct adapter *padapter,
3893                              struct recv_frame *precv_frame)
3894 {
3895         int i;
3896         unsigned char   category;
3897         struct action_handler *ptable;
3898         unsigned char   *frame_body;
3899         u8 *pframe = precv_frame->rx_data;
3900
3901         frame_body = (unsigned char *)(pframe + sizeof(struct rtw_ieee80211_hdr_3addr));
3902
3903         category = frame_body[0];
3904
3905         for (i = 0; i < sizeof(OnAction_tbl)/sizeof(struct action_handler); i++) {
3906                 ptable = &OnAction_tbl[i];
3907                 if (category == ptable->num)
3908                         ptable->func(padapter, precv_frame);
3909         }
3910         return _SUCCESS;
3911 }
3912
3913 /****************************************************************************
3914
3915 Following are the initialization functions for WiFi MLME
3916
3917 *****************************************************************************/
3918
3919 static struct mlme_handler mlme_sta_tbl[] = {
3920         {WIFI_ASSOCREQ,         "OnAssocReq",   &OnAssocReq},
3921         {WIFI_ASSOCRSP,         "OnAssocRsp",   &OnAssocRsp},
3922         {WIFI_REASSOCREQ,       "OnReAssocReq", &OnAssocReq},
3923         {WIFI_REASSOCRSP,       "OnReAssocRsp", &OnAssocRsp},
3924         {WIFI_PROBEREQ,         "OnProbeReq",   &OnProbeReq},
3925         {WIFI_PROBERSP,         "OnProbeRsp",           &OnProbeRsp},
3926
3927         /*----------------------------------------------------------
3928                                         below 2 are reserved
3929         -----------------------------------------------------------*/
3930         {0,                                     "DoReserved",           &DoReserved},
3931         {0,                                     "DoReserved",           &DoReserved},
3932         {WIFI_BEACON,           "OnBeacon",             &OnBeacon},
3933         {WIFI_ATIM,                     "OnATIM",               &OnAtim},
3934         {WIFI_DISASSOC,         "OnDisassoc",           &OnDisassoc},
3935         {WIFI_AUTH,                     "OnAuth",               &OnAuthClient},
3936         {WIFI_DEAUTH,           "OnDeAuth",             &OnDeAuth},
3937         {WIFI_ACTION,           "OnAction",             &OnAction},
3938 };
3939
3940 int init_hw_mlme_ext(struct adapter *padapter)
3941 {
3942         struct  mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
3943
3944         set_channel_bwmode(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode);
3945         return _SUCCESS;
3946 }
3947
3948 static void init_mlme_ext_priv_value(struct adapter *padapter)
3949 {
3950         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
3951         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
3952         unsigned char   mixed_datarate[NumRates] = {
3953                 _1M_RATE_, _2M_RATE_, _5M_RATE_, _11M_RATE_, _6M_RATE_,
3954                 _9M_RATE_, _12M_RATE_, _18M_RATE_, _24M_RATE_, _36M_RATE_,
3955                  _48M_RATE_, _54M_RATE_, 0xff
3956         };
3957         unsigned char   mixed_basicrate[NumRates] = {
3958                 _1M_RATE_, _2M_RATE_, _5M_RATE_, _11M_RATE_, _6M_RATE_,
3959                 _12M_RATE_, _24M_RATE_, 0xff,
3960         };
3961
3962         atomic_set(&pmlmeext->event_seq, 0);
3963         pmlmeext->mgnt_seq = 0;/* reset to zero when disconnect at client mode */
3964
3965         pmlmeext->cur_channel = padapter->registrypriv.channel;
3966         pmlmeext->cur_bwmode = HT_CHANNEL_WIDTH_20;
3967         pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
3968         pmlmeext->oper_channel = pmlmeext->cur_channel;
3969         pmlmeext->oper_bwmode = pmlmeext->cur_bwmode;
3970         pmlmeext->oper_ch_offset = pmlmeext->cur_ch_offset;
3971         pmlmeext->retry = 0;
3972
3973         pmlmeext->cur_wireless_mode = padapter->registrypriv.wireless_mode;
3974
3975         memcpy(pmlmeext->datarate, mixed_datarate, NumRates);
3976         memcpy(pmlmeext->basicrate, mixed_basicrate, NumRates);
3977
3978         pmlmeext->tx_rate = IEEE80211_CCK_RATE_1MB;
3979
3980         pmlmeext->sitesurvey_res.state = SCAN_DISABLE;
3981         pmlmeext->sitesurvey_res.channel_idx = 0;
3982         pmlmeext->sitesurvey_res.bss_cnt = 0;
3983         pmlmeext->scan_abort = false;
3984
3985         pmlmeinfo->state = WIFI_FW_NULL_STATE;
3986         pmlmeinfo->reauth_count = 0;
3987         pmlmeinfo->reassoc_count = 0;
3988         pmlmeinfo->link_count = 0;
3989         pmlmeinfo->auth_seq = 0;
3990         pmlmeinfo->auth_algo = dot11AuthAlgrthm_Open;
3991         pmlmeinfo->key_index = 0;
3992         pmlmeinfo->iv = 0;
3993
3994         pmlmeinfo->enc_algo = _NO_PRIVACY_;
3995         pmlmeinfo->authModeToggle = 0;
3996
3997         memset(pmlmeinfo->chg_txt, 0, 128);
3998
3999         pmlmeinfo->slotTime = SHORT_SLOT_TIME;
4000         pmlmeinfo->preamble_mode = PREAMBLE_AUTO;
4001
4002         pmlmeinfo->dialogToken = 0;
4003
4004         pmlmeext->action_public_rxseq = 0xffff;
4005         pmlmeext->action_public_dialog_token = 0xff;
4006 }
4007
4008 static int has_channel(struct rt_channel_info *channel_set,
4009                                            u8 chanset_size,
4010                                            u8 chan) {
4011         int i;
4012
4013         for (i = 0; i < chanset_size; i++) {
4014                 if (channel_set[i].ChannelNum == chan)
4015                         return 1;
4016         }
4017         return 0;
4018 }
4019
4020 static void init_channel_list(struct adapter *padapter, struct rt_channel_info *channel_set,
4021                                                           u8 chanset_size,
4022                                                           struct p2p_channels *channel_list) {
4023         struct p2p_oper_class_map op_class[] = {
4024                 { IEEE80211G,  81,   1,  13,  1, BW20 },
4025                 { IEEE80211G,  82,  14,  14,  1, BW20 },
4026                 { -1, 0, 0, 0, 0, BW20 }
4027         };
4028
4029         int cla, op;
4030
4031         cla = 0;
4032
4033         for (op = 0; op_class[op].op_class; op++) {
4034                 u8 ch;
4035                 struct p2p_oper_class_map *o = &op_class[op];
4036                 struct p2p_reg_class *reg = NULL;
4037
4038                 for (ch = o->min_chan; ch <= o->max_chan; ch += o->inc) {
4039                         if (!has_channel(channel_set, chanset_size, ch)) {
4040                                 continue;
4041                         }
4042
4043                         if ((0 == padapter->registrypriv.ht_enable) && (8 == o->inc))
4044                                 continue;
4045
4046                         if ((0 == (padapter->registrypriv.cbw40_enable & BIT(1))) &&
4047                             ((BW40MINUS == o->bw) || (BW40PLUS == o->bw)))
4048                                 continue;
4049
4050                         if (reg == NULL) {
4051                                 reg = &channel_list->reg_class[cla];
4052                                 cla++;
4053                                 reg->reg_class = o->op_class;
4054                                 reg->channels = 0;
4055                         }
4056                         reg->channel[reg->channels] = ch;
4057                         reg->channels++;
4058                 }
4059         }
4060         channel_list->reg_classes = cla;
4061 }
4062
4063 static u8 init_channel_set(struct adapter *padapter, u8 ChannelPlan, struct rt_channel_info *channel_set)
4064 {
4065         u8 index, chanset_size = 0;
4066         u8 b2_4GBand = false;
4067         u8 Index2G = 0;
4068
4069         memset(channel_set, 0, sizeof(struct rt_channel_info) * MAX_CHANNEL_NUM);
4070
4071         if (ChannelPlan >= RT_CHANNEL_DOMAIN_MAX && ChannelPlan != RT_CHANNEL_DOMAIN_REALTEK_DEFINE) {
4072                 DBG_88E("ChannelPlan ID %x error !!!!!\n", ChannelPlan);
4073                 return chanset_size;
4074         }
4075
4076         if (padapter->registrypriv.wireless_mode & WIRELESS_11G) {
4077                 b2_4GBand = true;
4078                 if (RT_CHANNEL_DOMAIN_REALTEK_DEFINE == ChannelPlan)
4079                         Index2G = RTW_CHANNEL_PLAN_MAP_REALTEK_DEFINE.Index2G;
4080                 else
4081                         Index2G = RTW_ChannelPlanMap[ChannelPlan].Index2G;
4082         }
4083
4084         if (b2_4GBand) {
4085                 for (index = 0; index < RTW_ChannelPlan2G[Index2G].Len; index++) {
4086                         channel_set[chanset_size].ChannelNum = RTW_ChannelPlan2G[Index2G].Channel[index];
4087
4088                         if ((RT_CHANNEL_DOMAIN_GLOBAL_DOAMIN == ChannelPlan) ||/* Channel 1~11 is active, and 12~14 is passive */
4089                             (RT_CHANNEL_DOMAIN_GLOBAL_DOAMIN_2G == ChannelPlan)) {
4090                                 if (channel_set[chanset_size].ChannelNum >= 1 && channel_set[chanset_size].ChannelNum <= 11)
4091                                         channel_set[chanset_size].ScanType = SCAN_ACTIVE;
4092                                 else if ((channel_set[chanset_size].ChannelNum  >= 12 && channel_set[chanset_size].ChannelNum  <= 14))
4093                                         channel_set[chanset_size].ScanType  = SCAN_PASSIVE;
4094                         } else if (RT_CHANNEL_DOMAIN_WORLD_WIDE_13 == ChannelPlan ||
4095                                    RT_CHANNEL_DOMAIN_2G_WORLD == Index2G) {/*  channel 12~13, passive scan */
4096                                 if (channel_set[chanset_size].ChannelNum <= 11)
4097                                         channel_set[chanset_size].ScanType = SCAN_ACTIVE;
4098                                 else
4099                                         channel_set[chanset_size].ScanType = SCAN_PASSIVE;
4100                         } else {
4101                                 channel_set[chanset_size].ScanType = SCAN_ACTIVE;
4102                         }
4103
4104                         chanset_size++;
4105                 }
4106         }
4107         return chanset_size;
4108 }
4109
4110 int     init_mlme_ext_priv(struct adapter *padapter)
4111 {
4112         struct registry_priv *pregistrypriv = &padapter->registrypriv;
4113         struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
4114         struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
4115         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
4116
4117         pmlmeext->padapter = padapter;
4118
4119         init_mlme_ext_priv_value(padapter);
4120         pmlmeinfo->bAcceptAddbaReq = pregistrypriv->bAcceptAddbaReq;
4121
4122         init_mlme_ext_timer(padapter);
4123
4124 #ifdef CONFIG_88EU_AP_MODE
4125         init_mlme_ap_info(padapter);
4126 #endif
4127
4128         pmlmeext->max_chan_nums = init_channel_set(padapter, pmlmepriv->ChannelPlan, pmlmeext->channel_set);
4129         init_channel_list(padapter, pmlmeext->channel_set, pmlmeext->max_chan_nums, &pmlmeext->channel_list);
4130
4131         pmlmeext->chan_scan_time = SURVEY_TO;
4132         pmlmeext->mlmeext_init = true;
4133
4134
4135         pmlmeext->active_keep_alive_check = true;
4136
4137         return _SUCCESS;
4138 }
4139
4140 void free_mlme_ext_priv(struct mlme_ext_priv *pmlmeext)
4141 {
4142         struct adapter *padapter = pmlmeext->padapter;
4143
4144         if (!padapter)
4145                 return;
4146
4147         if (padapter->bDriverStopped) {
4148                 del_timer_sync(&pmlmeext->survey_timer);
4149                 del_timer_sync(&pmlmeext->link_timer);
4150         }
4151 }
4152
4153 static void _mgt_dispatcher(struct adapter *padapter, struct mlme_handler *ptable, struct recv_frame *precv_frame)
4154 {
4155         u8 bc_addr[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
4156         u8 *pframe = precv_frame->rx_data;
4157
4158           if (ptable->func) {
4159          /* receive the frames that ra(a1) is my address or ra(a1) is bc address. */
4160                 if (memcmp(GetAddr1Ptr(pframe), myid(&padapter->eeprompriv), ETH_ALEN) &&
4161                     memcmp(GetAddr1Ptr(pframe), bc_addr, ETH_ALEN))
4162                         return;
4163                 ptable->func(padapter, precv_frame);
4164         }
4165 }
4166
4167 void mgt_dispatcher(struct adapter *padapter, struct recv_frame *precv_frame)
4168 {
4169         int index;
4170         struct mlme_handler *ptable;
4171 #ifdef CONFIG_88EU_AP_MODE
4172         struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
4173 #endif /* CONFIG_88EU_AP_MODE */
4174         u8 bc_addr[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
4175         u8 *pframe = precv_frame->rx_data;
4176         struct sta_info *psta = rtw_get_stainfo(&padapter->stapriv, GetAddr2Ptr(pframe));
4177
4178         RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_,
4179                  ("+mgt_dispatcher: type(0x%x) subtype(0x%x)\n",
4180                   GetFrameType(pframe), GetFrameSubType(pframe)));
4181
4182         if (GetFrameType(pframe) != WIFI_MGT_TYPE) {
4183                 RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("mgt_dispatcher: type(0x%x) error!\n", GetFrameType(pframe)));
4184                 return;
4185         }
4186
4187         /* receive the frames that ra(a1) is my address or ra(a1) is bc address. */
4188         if (memcmp(GetAddr1Ptr(pframe), myid(&padapter->eeprompriv), ETH_ALEN) &&
4189             memcmp(GetAddr1Ptr(pframe), bc_addr, ETH_ALEN))
4190                 return;
4191
4192         ptable = mlme_sta_tbl;
4193
4194         index = GetFrameSubType(pframe) >> 4;
4195
4196         if (index > 13) {
4197                 RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("Currently we do not support reserved sub-fr-type=%d\n", index));
4198                 return;
4199         }
4200         ptable += index;
4201
4202         if (psta != NULL) {
4203                 if (GetRetry(pframe)) {
4204                         if (precv_frame->attrib.seq_num ==
4205                             psta->RxMgmtFrameSeqNum) {
4206                                 /* drop the duplicate management frame */
4207                                 DBG_88E("Drop duplicate management frame with seq_num=%d.\n",
4208                                         precv_frame->attrib.seq_num);
4209                                 return;
4210                         }
4211                 }
4212                 psta->RxMgmtFrameSeqNum = precv_frame->attrib.seq_num;
4213         }
4214
4215 #ifdef CONFIG_88EU_AP_MODE
4216         switch (GetFrameSubType(pframe)) {
4217         case WIFI_AUTH:
4218                 if (check_fwstate(pmlmepriv, WIFI_AP_STATE))
4219                         ptable->func = &OnAuth;
4220                 else
4221                         ptable->func = &OnAuthClient;
4222                 /* fall through */
4223         case WIFI_ASSOCREQ:
4224         case WIFI_REASSOCREQ:
4225         case WIFI_PROBEREQ:
4226         case WIFI_BEACON:
4227         case WIFI_ACTION:
4228                 _mgt_dispatcher(padapter, ptable, precv_frame);
4229                 break;
4230         default:
4231                 _mgt_dispatcher(padapter, ptable, precv_frame);
4232                 break;
4233         }
4234 #else
4235         _mgt_dispatcher(padapter, ptable, precv_frame);
4236 #endif
4237 }
4238
4239 /****************************************************************************
4240
4241 Following are the functions to report events
4242
4243 *****************************************************************************/
4244
4245 void report_survey_event(struct adapter *padapter,
4246                          struct recv_frame *precv_frame)
4247 {
4248         struct cmd_obj *pcmd_obj;
4249         u8 *pevtcmd;
4250         u32 cmdsz;
4251         struct survey_event     *psurvey_evt;
4252         struct C2HEvent_Header *pc2h_evt_hdr;
4253         struct mlme_ext_priv *pmlmeext;
4254         struct cmd_priv *pcmdpriv;
4255
4256         if (!padapter)
4257                 return;
4258
4259         pmlmeext = &padapter->mlmeextpriv;
4260         pcmdpriv = &padapter->cmdpriv;
4261
4262
4263         pcmd_obj = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC);
4264         if (pcmd_obj == NULL)
4265                 return;
4266
4267         cmdsz = sizeof(struct survey_event) + sizeof(struct C2HEvent_Header);
4268         pevtcmd = kzalloc(cmdsz, GFP_ATOMIC);
4269         if (pevtcmd == NULL) {
4270                 kfree(pcmd_obj);
4271                 return;
4272         }
4273
4274         INIT_LIST_HEAD(&pcmd_obj->list);
4275
4276         pcmd_obj->cmdcode = GEN_CMD_CODE(_Set_MLME_EVT);
4277         pcmd_obj->cmdsz = cmdsz;
4278         pcmd_obj->parmbuf = pevtcmd;
4279
4280         pcmd_obj->rsp = NULL;
4281         pcmd_obj->rspsz  = 0;
4282
4283         pc2h_evt_hdr = (struct C2HEvent_Header *)(pevtcmd);
4284         pc2h_evt_hdr->len = sizeof(struct survey_event);
4285         pc2h_evt_hdr->ID = GEN_EVT_CODE(_Survey);
4286         pc2h_evt_hdr->seq = atomic_inc_return(&pmlmeext->event_seq);
4287
4288         psurvey_evt = (struct survey_event *)(pevtcmd + sizeof(struct C2HEvent_Header));
4289
4290         if (collect_bss_info(padapter, precv_frame, (struct wlan_bssid_ex *)&psurvey_evt->bss) == _FAIL) {
4291                 kfree(pcmd_obj);
4292                 kfree(pevtcmd);
4293                 return;
4294         }
4295
4296         process_80211d(padapter, &psurvey_evt->bss);
4297
4298         rtw_enqueue_cmd(pcmdpriv, pcmd_obj);
4299
4300         pmlmeext->sitesurvey_res.bss_cnt++;
4301
4302         return;
4303 }
4304
4305 void report_surveydone_event(struct adapter *padapter)
4306 {
4307         struct cmd_obj *pcmd_obj;
4308         u8 *pevtcmd;
4309         u32 cmdsz;
4310         struct surveydone_event *psurveydone_evt;
4311         struct C2HEvent_Header  *pc2h_evt_hdr;
4312         struct mlme_ext_priv            *pmlmeext = &padapter->mlmeextpriv;
4313         struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
4314
4315         pcmd_obj = kzalloc(sizeof(struct cmd_obj), GFP_KERNEL);
4316         if (pcmd_obj == NULL)
4317                 return;
4318
4319         cmdsz = sizeof(struct surveydone_event) + sizeof(struct C2HEvent_Header);
4320         pevtcmd = kzalloc(cmdsz, GFP_KERNEL);
4321         if (pevtcmd == NULL) {
4322                 kfree(pcmd_obj);
4323                 return;
4324         }
4325
4326         INIT_LIST_HEAD(&pcmd_obj->list);
4327
4328         pcmd_obj->cmdcode = GEN_CMD_CODE(_Set_MLME_EVT);
4329         pcmd_obj->cmdsz = cmdsz;
4330         pcmd_obj->parmbuf = pevtcmd;
4331
4332         pcmd_obj->rsp = NULL;
4333         pcmd_obj->rspsz  = 0;
4334
4335         pc2h_evt_hdr = (struct C2HEvent_Header *)(pevtcmd);
4336         pc2h_evt_hdr->len = sizeof(struct surveydone_event);
4337         pc2h_evt_hdr->ID = GEN_EVT_CODE(_SurveyDone);
4338         pc2h_evt_hdr->seq = atomic_inc_return(&pmlmeext->event_seq);
4339
4340         psurveydone_evt = (struct surveydone_event *)(pevtcmd + sizeof(struct C2HEvent_Header));
4341         psurveydone_evt->bss_cnt = pmlmeext->sitesurvey_res.bss_cnt;
4342
4343         DBG_88E("survey done event(%x)\n", psurveydone_evt->bss_cnt);
4344
4345         rtw_enqueue_cmd(pcmdpriv, pcmd_obj);
4346
4347         return;
4348 }
4349
4350 void report_join_res(struct adapter *padapter, int res)
4351 {
4352         struct cmd_obj *pcmd_obj;
4353         u8 *pevtcmd;
4354         u32 cmdsz;
4355         struct joinbss_event            *pjoinbss_evt;
4356         struct C2HEvent_Header  *pc2h_evt_hdr;
4357         struct mlme_ext_priv            *pmlmeext = &padapter->mlmeextpriv;
4358         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
4359         struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
4360
4361         pcmd_obj = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC);
4362         if (pcmd_obj == NULL)
4363                 return;
4364
4365         cmdsz = sizeof(struct joinbss_event) + sizeof(struct C2HEvent_Header);
4366         pevtcmd = kzalloc(cmdsz, GFP_ATOMIC);
4367         if (pevtcmd == NULL) {
4368                 kfree(pcmd_obj);
4369                 return;
4370         }
4371
4372         INIT_LIST_HEAD(&pcmd_obj->list);
4373
4374         pcmd_obj->cmdcode = GEN_CMD_CODE(_Set_MLME_EVT);
4375         pcmd_obj->cmdsz = cmdsz;
4376         pcmd_obj->parmbuf = pevtcmd;
4377
4378         pcmd_obj->rsp = NULL;
4379         pcmd_obj->rspsz  = 0;
4380
4381         pc2h_evt_hdr = (struct C2HEvent_Header *)(pevtcmd);
4382         pc2h_evt_hdr->len = sizeof(struct joinbss_event);
4383         pc2h_evt_hdr->ID = GEN_EVT_CODE(_JoinBss);
4384         pc2h_evt_hdr->seq = atomic_inc_return(&pmlmeext->event_seq);
4385
4386         pjoinbss_evt = (struct joinbss_event *)(pevtcmd + sizeof(struct C2HEvent_Header));
4387         memcpy((unsigned char *)(&(pjoinbss_evt->network.network)), &(pmlmeinfo->network), sizeof(struct wlan_bssid_ex));
4388         pjoinbss_evt->network.join_res  = res;
4389         pjoinbss_evt->network.aid = res;
4390
4391         DBG_88E("report_join_res(%d)\n", res);
4392
4393
4394         rtw_joinbss_event_prehandle(padapter, (u8 *)&pjoinbss_evt->network);
4395
4396
4397         rtw_enqueue_cmd(pcmdpriv, pcmd_obj);
4398
4399         return;
4400 }
4401
4402 void report_del_sta_event(struct adapter *padapter, unsigned char *MacAddr, unsigned short reason)
4403 {
4404         struct cmd_obj *pcmd_obj;
4405         u8 *pevtcmd;
4406         u32 cmdsz;
4407         struct sta_info *psta;
4408         int     mac_id;
4409         struct stadel_event                     *pdel_sta_evt;
4410         struct C2HEvent_Header  *pc2h_evt_hdr;
4411         struct mlme_ext_priv            *pmlmeext = &padapter->mlmeextpriv;
4412         struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
4413
4414         pcmd_obj = kzalloc(sizeof(struct cmd_obj), GFP_KERNEL);
4415         if (pcmd_obj == NULL)
4416                 return;
4417
4418         cmdsz = sizeof(struct stadel_event) + sizeof(struct C2HEvent_Header);
4419         pevtcmd = kzalloc(cmdsz, GFP_KERNEL);
4420         if (pevtcmd == NULL) {
4421                 kfree(pcmd_obj);
4422                 return;
4423         }
4424
4425         INIT_LIST_HEAD(&pcmd_obj->list);
4426
4427         pcmd_obj->cmdcode = GEN_CMD_CODE(_Set_MLME_EVT);
4428         pcmd_obj->cmdsz = cmdsz;
4429         pcmd_obj->parmbuf = pevtcmd;
4430
4431         pcmd_obj->rsp = NULL;
4432         pcmd_obj->rspsz  = 0;
4433
4434         pc2h_evt_hdr = (struct C2HEvent_Header *)(pevtcmd);
4435         pc2h_evt_hdr->len = sizeof(struct stadel_event);
4436         pc2h_evt_hdr->ID = GEN_EVT_CODE(_DelSTA);
4437         pc2h_evt_hdr->seq = atomic_inc_return(&pmlmeext->event_seq);
4438
4439         pdel_sta_evt = (struct stadel_event *)(pevtcmd + sizeof(struct C2HEvent_Header));
4440         memcpy((unsigned char *)(&(pdel_sta_evt->macaddr)), MacAddr, ETH_ALEN);
4441         memcpy((unsigned char *)(pdel_sta_evt->rsvd), (unsigned char *)(&reason), 2);
4442
4443
4444         psta = rtw_get_stainfo(&padapter->stapriv, MacAddr);
4445         if (psta)
4446                 mac_id = (int)psta->mac_id;
4447         else
4448                 mac_id = -1;
4449
4450         pdel_sta_evt->mac_id = mac_id;
4451
4452         DBG_88E("report_del_sta_event: delete STA, mac_id =%d\n", mac_id);
4453
4454         rtw_enqueue_cmd(pcmdpriv, pcmd_obj);
4455
4456         return;
4457 }
4458
4459 void report_add_sta_event(struct adapter *padapter, unsigned char *MacAddr, int cam_idx)
4460 {
4461         struct cmd_obj *pcmd_obj;
4462         u8 *pevtcmd;
4463         u32 cmdsz;
4464         struct stassoc_event            *padd_sta_evt;
4465         struct C2HEvent_Header  *pc2h_evt_hdr;
4466         struct mlme_ext_priv            *pmlmeext = &padapter->mlmeextpriv;
4467         struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
4468
4469         pcmd_obj = kzalloc(sizeof(struct cmd_obj), GFP_KERNEL);
4470         if (pcmd_obj == NULL)
4471                 return;
4472
4473         cmdsz = sizeof(struct stassoc_event) + sizeof(struct C2HEvent_Header);
4474         pevtcmd = kzalloc(cmdsz, GFP_KERNEL);
4475         if (pevtcmd == NULL) {
4476                 kfree(pcmd_obj);
4477                 return;
4478         }
4479
4480         INIT_LIST_HEAD(&pcmd_obj->list);
4481
4482         pcmd_obj->cmdcode = GEN_CMD_CODE(_Set_MLME_EVT);
4483         pcmd_obj->cmdsz = cmdsz;
4484         pcmd_obj->parmbuf = pevtcmd;
4485
4486         pcmd_obj->rsp = NULL;
4487         pcmd_obj->rspsz  = 0;
4488
4489         pc2h_evt_hdr = (struct C2HEvent_Header *)(pevtcmd);
4490         pc2h_evt_hdr->len = sizeof(struct stassoc_event);
4491         pc2h_evt_hdr->ID = GEN_EVT_CODE(_AddSTA);
4492         pc2h_evt_hdr->seq = atomic_inc_return(&pmlmeext->event_seq);
4493
4494         padd_sta_evt = (struct stassoc_event *)(pevtcmd + sizeof(struct C2HEvent_Header));
4495         memcpy((unsigned char *)(&(padd_sta_evt->macaddr)), MacAddr, ETH_ALEN);
4496         padd_sta_evt->cam_id = cam_idx;
4497
4498         DBG_88E("report_add_sta_event: add STA\n");
4499
4500         rtw_enqueue_cmd(pcmdpriv, pcmd_obj);
4501
4502         return;
4503 }
4504
4505
4506 /****************************************************************************
4507
4508 Following are the event callback functions
4509
4510 *****************************************************************************/
4511
4512 /* for sta/adhoc mode */
4513 void update_sta_info(struct adapter *padapter, struct sta_info *psta)
4514 {
4515         struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
4516         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
4517         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
4518
4519         /* ERP */
4520         VCS_update(padapter, psta);
4521
4522         /* HT */
4523         if (pmlmepriv->htpriv.ht_option) {
4524                 psta->htpriv.ht_option = true;
4525
4526                 psta->htpriv.ampdu_enable = pmlmepriv->htpriv.ampdu_enable;
4527
4528                 if (support_short_GI(padapter, &(pmlmeinfo->HT_caps)))
4529                         psta->htpriv.sgi = true;
4530
4531                 psta->qos_option = true;
4532         } else {
4533                 psta->htpriv.ht_option = false;
4534
4535                 psta->htpriv.ampdu_enable = false;
4536
4537                 psta->htpriv.sgi = false;
4538                 psta->qos_option = false;
4539         }
4540         psta->htpriv.bwmode = pmlmeext->cur_bwmode;
4541         psta->htpriv.ch_offset = pmlmeext->cur_ch_offset;
4542
4543         psta->htpriv.agg_enable_bitmap = 0x0;/* reset */
4544         psta->htpriv.candidate_tid_bitmap = 0x0;/* reset */
4545
4546         /* QoS */
4547         if (pmlmepriv->qospriv.qos_option)
4548                 psta->qos_option = true;
4549
4550
4551         psta->state = _FW_LINKED;
4552 }
4553
4554 void mlmeext_joinbss_event_callback(struct adapter *padapter, int join_res)
4555 {
4556         struct sta_info         *psta, *psta_bmc;
4557         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
4558         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
4559         struct wlan_bssid_ex *cur_network = &(pmlmeinfo->network);
4560         struct sta_priv         *pstapriv = &padapter->stapriv;
4561         u8 join_type;
4562         u16 media_status;
4563
4564         if (join_res < 0) {
4565                 join_type = 1;
4566                 rtw_hal_set_hwreg(padapter, HW_VAR_MLME_JOIN, (u8 *)(&join_type));
4567                 rtw_hal_set_hwreg(padapter, HW_VAR_BSSID, null_addr);
4568
4569                 /* restore to initial setting. */
4570                 update_tx_basic_rate(padapter, padapter->registrypriv.wireless_mode);
4571
4572                 goto exit_mlmeext_joinbss_event_callback;
4573         }
4574
4575         if ((pmlmeinfo->state&0x03) == WIFI_FW_ADHOC_STATE) {
4576                 /* for bc/mc */
4577                 psta_bmc = rtw_get_bcmc_stainfo(padapter);
4578                 if (psta_bmc) {
4579                         pmlmeinfo->FW_sta_info[psta_bmc->mac_id].psta = psta_bmc;
4580                         update_bmc_sta_support_rate(padapter, psta_bmc->mac_id);
4581                         Update_RA_Entry(padapter, psta_bmc->mac_id);
4582                 }
4583         }
4584
4585
4586         /* turn on dynamic functions */
4587         Switch_DM_Func(padapter, DYNAMIC_ALL_FUNC_ENABLE, true);
4588
4589         /*  update IOT-related issue */
4590         update_IOT_info(padapter);
4591
4592         rtw_hal_set_hwreg(padapter, HW_VAR_BASIC_RATE, cur_network->SupportedRates);
4593
4594         /* BCN interval */
4595         rtw_hal_set_hwreg(padapter, HW_VAR_BEACON_INTERVAL, (u8 *)(&pmlmeinfo->bcn_interval));
4596
4597         /* update capability */
4598         update_capinfo(padapter, pmlmeinfo->capability);
4599
4600         /* WMM, Update EDCA param */
4601         WMMOnAssocRsp(padapter);
4602
4603         /* HT */
4604         HTOnAssocRsp(padapter);
4605
4606         set_channel_bwmode(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode);
4607
4608         psta = rtw_get_stainfo(pstapriv, cur_network->MacAddress);
4609         if (psta) { /* only for infra. mode */
4610                 pmlmeinfo->FW_sta_info[psta->mac_id].psta = psta;
4611
4612                 psta->wireless_mode = pmlmeext->cur_wireless_mode;
4613
4614                 /* set per sta rate after updating HT cap. */
4615                 set_sta_rate(padapter, psta);
4616                 rtw_hal_set_hwreg(padapter, HW_VAR_TX_RPT_MAX_MACID, (u8 *)&psta->mac_id);
4617                 media_status = (psta->mac_id<<8)|1; /*   MACID|OPMODE: 1 means connect */
4618                 rtw_hal_set_hwreg(padapter, HW_VAR_H2C_MEDIA_STATUS_RPT, (u8 *)&media_status);
4619         }
4620
4621         join_type = 2;
4622         rtw_hal_set_hwreg(padapter, HW_VAR_MLME_JOIN, (u8 *)(&join_type));
4623
4624         if ((pmlmeinfo->state&0x03) == WIFI_FW_STATION_STATE) {
4625                 /*  correcting TSF */
4626                 correct_TSF(padapter, pmlmeext);
4627         }
4628         rtw_lps_ctrl_wk_cmd(padapter, LPS_CTRL_CONNECT, 0);
4629
4630 exit_mlmeext_joinbss_event_callback:
4631
4632         DBG_88E("=>%s\n", __func__);
4633 }
4634
4635 void mlmeext_sta_add_event_callback(struct adapter *padapter, struct sta_info *psta)
4636 {
4637         struct mlme_ext_priv    *pmlmeext = &(padapter->mlmeextpriv);
4638         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
4639         u8 join_type;
4640
4641         DBG_88E("%s\n", __func__);
4642
4643         if ((pmlmeinfo->state&0x03) == WIFI_FW_ADHOC_STATE) {
4644                 if (pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS) {/* adhoc master or sta_count>1 */
4645                         /* nothing to do */
4646                 } else { /* adhoc client */
4647                         /*  correcting TSF */
4648                         correct_TSF(padapter, pmlmeext);
4649
4650                         /* start beacon */
4651                         if (send_beacon(padapter) == _FAIL) {
4652                                 pmlmeinfo->FW_sta_info[psta->mac_id].status = 0;
4653                                 pmlmeinfo->state ^= WIFI_FW_ADHOC_STATE;
4654                                 return;
4655                         }
4656                         pmlmeinfo->state |= WIFI_FW_ASSOC_SUCCESS;
4657                 }
4658
4659                 join_type = 2;
4660                 rtw_hal_set_hwreg(padapter, HW_VAR_MLME_JOIN, (u8 *)(&join_type));
4661         }
4662
4663         pmlmeinfo->FW_sta_info[psta->mac_id].psta = psta;
4664
4665         /* rate radaptive */
4666         Update_RA_Entry(padapter, psta->mac_id);
4667
4668         /* update adhoc sta_info */
4669         update_sta_info(padapter, psta);
4670 }
4671
4672 void mlmeext_sta_del_event_callback(struct adapter *padapter)
4673 {
4674         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
4675         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
4676
4677         if (is_client_associated_to_ap(padapter) || is_IBSS_empty(padapter)) {
4678                 rtw_hal_set_hwreg(padapter, HW_VAR_MLME_DISCONNECT, NULL);
4679                 rtw_hal_set_hwreg(padapter, HW_VAR_BSSID, null_addr);
4680
4681                 /* restore to initial setting. */
4682                 update_tx_basic_rate(padapter, padapter->registrypriv.wireless_mode);
4683
4684                 /* switch to the 20M Hz mode after disconnect */
4685                 pmlmeext->cur_bwmode = HT_CHANNEL_WIDTH_20;
4686                 pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
4687
4688                 /* SelectChannel(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset); */
4689                 set_channel_bwmode(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode);
4690
4691
4692                 flush_all_cam_entry(padapter);
4693
4694                 pmlmeinfo->state = WIFI_FW_NULL_STATE;
4695
4696                 /* set MSR to no link state -> infra. mode */
4697                 Set_MSR(padapter, _HW_STATE_STATION_);
4698
4699                 del_timer_sync(&pmlmeext->link_timer);
4700         }
4701 }
4702
4703 /****************************************************************************
4704
4705 Following are the functions for the timer handlers
4706
4707 *****************************************************************************/
4708 void _linked_rx_signal_strehgth_display(struct adapter *padapter);
4709 void _linked_rx_signal_strehgth_display(struct adapter *padapter)
4710 {
4711         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
4712       struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
4713         u8 mac_id;
4714         int UndecoratedSmoothedPWDB;
4715         if ((pmlmeinfo->state&0x03) == WIFI_FW_STATION_STATE)
4716                 mac_id = 0;
4717         else if ((pmlmeinfo->state&0x03) == _HW_STATE_AP_)
4718                 mac_id = 2;
4719
4720         rtw_hal_get_def_var(padapter, HW_DEF_RA_INFO_DUMP, &mac_id);
4721
4722         rtw_hal_get_def_var(padapter, HAL_DEF_UNDERCORATEDSMOOTHEDPWDB, &UndecoratedSmoothedPWDB);
4723         DBG_88E("UndecoratedSmoothedPWDB:%d\n", UndecoratedSmoothedPWDB);
4724 }
4725
4726 static u8 chk_ap_is_alive(struct adapter *padapter, struct sta_info *psta)
4727 {
4728         u8 ret = false;
4729
4730         if ((sta_rx_data_pkts(psta) == sta_last_rx_data_pkts(psta)) &&
4731             sta_rx_beacon_pkts(psta) == sta_last_rx_beacon_pkts(psta) &&
4732             sta_rx_probersp_pkts(psta) == sta_last_rx_probersp_pkts(psta))
4733                 ret = false;
4734         else
4735                 ret = true;
4736
4737         sta_update_last_rx_pkts(psta);
4738
4739         return ret;
4740 }
4741
4742 void linked_status_chk(struct adapter *padapter)
4743 {
4744         u32     i;
4745         struct sta_info         *psta;
4746         struct xmit_priv                *pxmitpriv = &(padapter->xmitpriv);
4747         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
4748         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
4749         struct sta_priv         *pstapriv = &padapter->stapriv;
4750
4751         if (padapter->bRxRSSIDisplay)
4752                 _linked_rx_signal_strehgth_display(padapter);
4753
4754         if (is_client_associated_to_ap(padapter)) {
4755                 /* linked infrastructure client mode */
4756
4757                 int tx_chk = _SUCCESS, rx_chk = _SUCCESS;
4758                 int rx_chk_limit;
4759
4760                 rx_chk_limit = 4;
4761                 psta = rtw_get_stainfo(pstapriv, pmlmeinfo->network.MacAddress);
4762                 if (psta != NULL) {
4763                         bool is_p2p_enable = false;
4764
4765                         if (!chk_ap_is_alive(padapter, psta))
4766                                 rx_chk = _FAIL;
4767
4768                         if (pxmitpriv->last_tx_pkts == pxmitpriv->tx_pkts)
4769                                 tx_chk = _FAIL;
4770
4771                         if (pmlmeext->active_keep_alive_check && (rx_chk == _FAIL || tx_chk == _FAIL)) {
4772                                 u8 backup_oper_channel = 0;
4773
4774                                 /* switch to correct channel of current network  before issue keep-alive frames */
4775                                 if (rtw_get_oper_ch(padapter) != pmlmeext->cur_channel) {
4776                                         backup_oper_channel = rtw_get_oper_ch(padapter);
4777                                         SelectChannel(padapter, pmlmeext->cur_channel);
4778                                 }
4779
4780                                 if (rx_chk != _SUCCESS)
4781                                         issue_probereq_ex(padapter, &pmlmeinfo->network.Ssid, psta->hwaddr, 3, 1);
4782
4783                                 if ((tx_chk != _SUCCESS && pmlmeinfo->link_count++ == 0xf) || rx_chk != _SUCCESS) {
4784                                         tx_chk = issue_nulldata(padapter, psta->hwaddr, 0, 3, 1);
4785                                         /* if tx acked and p2p disabled, set rx_chk _SUCCESS to reset retry count */
4786                                         if (tx_chk == _SUCCESS && !is_p2p_enable)
4787                                                 rx_chk = _SUCCESS;
4788                                 }
4789
4790                                 /* back to the original operation channel */
4791                                 if (backup_oper_channel > 0)
4792                                         SelectChannel(padapter, backup_oper_channel);
4793                         } else {
4794                                 if (rx_chk != _SUCCESS) {
4795                                         if (pmlmeext->retry == 0) {
4796                                                 issue_probereq(padapter, &pmlmeinfo->network.Ssid, pmlmeinfo->network.MacAddress);
4797                                                 issue_probereq(padapter, &pmlmeinfo->network.Ssid, pmlmeinfo->network.MacAddress);
4798                                                 issue_probereq(padapter, &pmlmeinfo->network.Ssid, pmlmeinfo->network.MacAddress);
4799                                         }
4800                                 }
4801
4802                                 if (tx_chk != _SUCCESS && pmlmeinfo->link_count++ == 0xf) {
4803                                         tx_chk = issue_nulldata(padapter, NULL, 0, 1, 0);
4804                                 }
4805                         }
4806
4807                         if (rx_chk == _FAIL) {
4808                                 pmlmeext->retry++;
4809                                 if (pmlmeext->retry > rx_chk_limit) {
4810                                         DBG_88E_LEVEL(_drv_always_, FUNC_ADPT_FMT" disconnect or roaming\n",
4811                                                       FUNC_ADPT_ARG(padapter));
4812                                         receive_disconnect(padapter, pmlmeinfo->network.MacAddress,
4813                                                            WLAN_REASON_EXPIRATION_CHK);
4814                                         return;
4815                                 }
4816                         } else {
4817                                 pmlmeext->retry = 0;
4818                         }
4819
4820                         if (tx_chk == _FAIL) {
4821                                 pmlmeinfo->link_count &= 0xf;
4822                         } else {
4823                                 pxmitpriv->last_tx_pkts = pxmitpriv->tx_pkts;
4824                                 pmlmeinfo->link_count = 0;
4825                         }
4826                 } /* end of if ((psta = rtw_get_stainfo(pstapriv, passoc_res->network.MacAddress)) != NULL) */
4827         } else if (is_client_associated_to_ibss(padapter)) {
4828                 /* linked IBSS mode */
4829                 /* for each assoc list entry to check the rx pkt counter */
4830                 for (i = IBSS_START_MAC_ID; i < NUM_STA; i++) {
4831                         if (pmlmeinfo->FW_sta_info[i].status == 1) {
4832                                 psta = pmlmeinfo->FW_sta_info[i].psta;
4833
4834                                 if (NULL == psta)
4835                                         continue;
4836                                 if (pmlmeinfo->FW_sta_info[i].rx_pkt == sta_rx_pkts(psta)) {
4837                                         if (pmlmeinfo->FW_sta_info[i].retry < 3) {
4838                                                 pmlmeinfo->FW_sta_info[i].retry++;
4839                                         } else {
4840                                                 pmlmeinfo->FW_sta_info[i].retry = 0;
4841                                                 pmlmeinfo->FW_sta_info[i].status = 0;
4842                                                 report_del_sta_event(padapter, psta->hwaddr
4843                                                         , 65535/*  indicate disconnect caused by no rx */
4844                                         );
4845                                         }
4846                                 } else {
4847                                         pmlmeinfo->FW_sta_info[i].retry = 0;
4848                                         pmlmeinfo->FW_sta_info[i].rx_pkt = (u32)sta_rx_pkts(psta);
4849                                 }
4850                         }
4851                 }
4852         }
4853 }
4854
4855 void survey_timer_hdl(unsigned long data)
4856 {
4857         struct adapter *padapter = (struct adapter *)data;
4858         struct cmd_obj  *ph2c;
4859         struct sitesurvey_parm  *psurveyPara;
4860         struct cmd_priv                                 *pcmdpriv = &padapter->cmdpriv;
4861         struct mlme_ext_priv            *pmlmeext = &padapter->mlmeextpriv;
4862
4863         /* issue rtw_sitesurvey_cmd */
4864         if (pmlmeext->sitesurvey_res.state > SCAN_START) {
4865                 if (pmlmeext->sitesurvey_res.state ==  SCAN_PROCESS)
4866                         pmlmeext->sitesurvey_res.channel_idx++;
4867
4868                 if (pmlmeext->scan_abort) {
4869                         pmlmeext->sitesurvey_res.channel_idx = pmlmeext->sitesurvey_res.ch_num;
4870                         DBG_88E("%s idx:%d\n", __func__
4871                                 , pmlmeext->sitesurvey_res.channel_idx);
4872
4873                         pmlmeext->scan_abort = false;/* reset */
4874                 }
4875
4876                 ph2c = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC);
4877                 if (ph2c == NULL)
4878                         goto exit_survey_timer_hdl;
4879
4880                 psurveyPara = kzalloc(sizeof(struct sitesurvey_parm), GFP_ATOMIC);
4881                 if (psurveyPara == NULL) {
4882                         kfree(ph2c);
4883                         goto exit_survey_timer_hdl;
4884                 }
4885
4886                 init_h2fwcmd_w_parm_no_rsp(ph2c, psurveyPara, GEN_CMD_CODE(_SiteSurvey));
4887                 rtw_enqueue_cmd(pcmdpriv, ph2c);
4888         }
4889
4890
4891 exit_survey_timer_hdl:
4892         return;
4893 }
4894
4895 void link_timer_hdl(unsigned long data)
4896 {
4897         struct adapter *padapter = (struct adapter *)data;
4898         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
4899         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
4900
4901         if (pmlmeinfo->state & WIFI_FW_AUTH_NULL) {
4902                 DBG_88E("link_timer_hdl:no beacon while connecting\n");
4903                 pmlmeinfo->state = WIFI_FW_NULL_STATE;
4904                 report_join_res(padapter, -3);
4905         } else if (pmlmeinfo->state & WIFI_FW_AUTH_STATE) {
4906                 /* re-auth timer */
4907                 if (++pmlmeinfo->reauth_count > REAUTH_LIMIT) {
4908                         pmlmeinfo->state = 0;
4909                         report_join_res(padapter, -1);
4910                         return;
4911                 }
4912
4913                 DBG_88E("link_timer_hdl: auth timeout and try again\n");
4914                 pmlmeinfo->auth_seq = 1;
4915                 issue_auth(padapter, NULL, 0);
4916                 set_link_timer(pmlmeext, REAUTH_TO);
4917         } else if (pmlmeinfo->state & WIFI_FW_ASSOC_STATE) {
4918                 /* re-assoc timer */
4919                 if (++pmlmeinfo->reassoc_count > REASSOC_LIMIT) {
4920                         pmlmeinfo->state = WIFI_FW_NULL_STATE;
4921                         report_join_res(padapter, -2);
4922                         return;
4923                 }
4924
4925                 DBG_88E("link_timer_hdl: assoc timeout and try again\n");
4926                 issue_assocreq(padapter);
4927                 set_link_timer(pmlmeext, REASSOC_TO);
4928         }
4929         return;
4930 }
4931
4932 void addba_timer_hdl(unsigned long data)
4933 {
4934         struct sta_info *psta = (struct sta_info *)data;
4935         struct ht_priv  *phtpriv;
4936
4937         if (!psta)
4938                 return;
4939
4940         phtpriv = &psta->htpriv;
4941
4942         if ((phtpriv->ht_option) && (phtpriv->ampdu_enable)) {
4943                 if (phtpriv->candidate_tid_bitmap)
4944                         phtpriv->candidate_tid_bitmap = 0x0;
4945         }
4946 }
4947
4948 u8 setopmode_hdl(struct adapter *padapter, u8 *pbuf)
4949 {
4950         u8 type;
4951         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
4952         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
4953         struct setopmode_parm *psetop = (struct setopmode_parm *)pbuf;
4954
4955         if (psetop->mode == Ndis802_11APMode) {
4956                 pmlmeinfo->state = WIFI_FW_AP_STATE;
4957                 type = _HW_STATE_AP_;
4958         } else if (psetop->mode == Ndis802_11Infrastructure) {
4959                 pmlmeinfo->state &= ~(BIT(0)|BIT(1));/*  clear state */
4960                 pmlmeinfo->state |= WIFI_FW_STATION_STATE;/* set to     STATION_STATE */
4961                 type = _HW_STATE_STATION_;
4962         } else if (psetop->mode == Ndis802_11IBSS) {
4963                 type = _HW_STATE_ADHOC_;
4964         } else {
4965                 type = _HW_STATE_NOLINK_;
4966         }
4967
4968         rtw_hal_set_hwreg(padapter, HW_VAR_SET_OPMODE, (u8 *)(&type));
4969         /* Set_NETYPE0_MSR(padapter, type); */
4970
4971         return H2C_SUCCESS;
4972 }
4973
4974 u8 createbss_hdl(struct adapter *padapter, u8 *pbuf)
4975 {
4976         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
4977         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
4978         struct wlan_bssid_ex *pnetwork = (struct wlan_bssid_ex *)(&(pmlmeinfo->network));
4979         struct wlan_bssid_ex *pparm = (struct wlan_bssid_ex *)pbuf;
4980         /* u32  initialgain; */
4981
4982
4983         if (pparm->InfrastructureMode == Ndis802_11APMode) {
4984 #ifdef CONFIG_88EU_AP_MODE
4985
4986                 if (pmlmeinfo->state == WIFI_FW_AP_STATE) {
4987                         /* todo: */
4988                         return H2C_SUCCESS;
4989                 }
4990 #endif
4991         }
4992
4993         /* below is for ad-hoc master */
4994         if (pparm->InfrastructureMode == Ndis802_11IBSS) {
4995                 rtw_joinbss_reset(padapter);
4996
4997                 pmlmeext->cur_bwmode = HT_CHANNEL_WIDTH_20;
4998                 pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
4999                 pmlmeinfo->ERP_enable = 0;
5000                 pmlmeinfo->WMM_enable = 0;
5001                 pmlmeinfo->HT_enable = 0;
5002                 pmlmeinfo->HT_caps_enable = 0;
5003                 pmlmeinfo->HT_info_enable = 0;
5004                 pmlmeinfo->agg_enable_bitmap = 0;
5005                 pmlmeinfo->candidate_tid_bitmap = 0;
5006
5007                 /* disable dynamic functions, such as high power, DIG */
5008                 Save_DM_Func_Flag(padapter);
5009                 Switch_DM_Func(padapter, DYNAMIC_FUNC_DISABLE, false);
5010
5011                 /* config the initial gain under linking, need to write the BB registers */
5012                 /* initialgain = 0x1E; */
5013                 /* rtw_hal_set_hwreg(padapter, HW_VAR_INITIAL_GAIN, (u8 *)(&initialgain)); */
5014
5015                 /* cancel link timer */
5016                 del_timer_sync(&pmlmeext->link_timer);
5017
5018                 /* clear CAM */
5019                 flush_all_cam_entry(padapter);
5020
5021                 memcpy(pnetwork, pbuf, FIELD_OFFSET(struct wlan_bssid_ex, IELength));
5022                 pnetwork->IELength = ((struct wlan_bssid_ex *)pbuf)->IELength;
5023
5024                 if (pnetwork->IELength > MAX_IE_SZ)/* Check pbuf->IELength */
5025                         return H2C_PARAMETERS_ERROR;
5026
5027                 memcpy(pnetwork->IEs, ((struct wlan_bssid_ex *)pbuf)->IEs, pnetwork->IELength);
5028
5029                 start_create_ibss(padapter);
5030         }
5031
5032         return H2C_SUCCESS;
5033 }
5034
5035 u8 join_cmd_hdl(struct adapter *padapter, u8 *pbuf)
5036 {
5037         u8 join_type;
5038         struct ndis_802_11_var_ie *pIE;
5039         struct registry_priv    *pregpriv = &padapter->registrypriv;
5040         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
5041         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
5042         struct wlan_bssid_ex *pnetwork = (struct wlan_bssid_ex *)(&(pmlmeinfo->network));
5043         struct wlan_bssid_ex *pparm = (struct wlan_bssid_ex *)pbuf;
5044         u32 i;
5045
5046         /* check already connecting to AP or not */
5047         if (pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS) {
5048                 if (pmlmeinfo->state & WIFI_FW_STATION_STATE)
5049                         issue_deauth_ex(padapter, pnetwork->MacAddress, WLAN_REASON_DEAUTH_LEAVING, 5, 100);
5050
5051                 pmlmeinfo->state = WIFI_FW_NULL_STATE;
5052
5053                 /* clear CAM */
5054                 flush_all_cam_entry(padapter);
5055
5056                 del_timer_sync(&pmlmeext->link_timer);
5057
5058                 /* set MSR to nolink -> infra. mode */
5059                 Set_MSR(padapter, _HW_STATE_STATION_);
5060
5061
5062                 rtw_hal_set_hwreg(padapter, HW_VAR_MLME_DISCONNECT, NULL);
5063         }
5064
5065         rtw_antenna_select_cmd(padapter, pparm->PhyInfo.Optimum_antenna, false);
5066
5067         rtw_joinbss_reset(padapter);
5068
5069         pmlmeext->cur_bwmode = HT_CHANNEL_WIDTH_20;
5070         pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
5071         pmlmeinfo->ERP_enable = 0;
5072         pmlmeinfo->WMM_enable = 0;
5073         pmlmeinfo->HT_enable = 0;
5074         pmlmeinfo->HT_caps_enable = 0;
5075         pmlmeinfo->HT_info_enable = 0;
5076         pmlmeinfo->agg_enable_bitmap = 0;
5077         pmlmeinfo->candidate_tid_bitmap = 0;
5078         pmlmeinfo->bwmode_updated = false;
5079
5080         memcpy(pnetwork, pbuf, FIELD_OFFSET(struct wlan_bssid_ex, IELength));
5081         pnetwork->IELength = ((struct wlan_bssid_ex *)pbuf)->IELength;
5082
5083         if (pnetwork->IELength > MAX_IE_SZ)/* Check pbuf->IELength */
5084                 return H2C_PARAMETERS_ERROR;
5085
5086         memcpy(pnetwork->IEs, ((struct wlan_bssid_ex *)pbuf)->IEs, pnetwork->IELength);
5087
5088         /* Check AP vendor to move rtw_joinbss_cmd() */
5089
5090         for (i = sizeof(struct ndis_802_11_fixed_ie); i < pnetwork->IELength;) {
5091                 pIE = (struct ndis_802_11_var_ie *)(pnetwork->IEs + i);
5092
5093                 switch (pIE->ElementID) {
5094                 case _VENDOR_SPECIFIC_IE_:/* Get WMM IE. */
5095                         if (!memcmp(pIE->data, WMM_OUI, 4))
5096                                 pmlmeinfo->WMM_enable = 1;
5097                         break;
5098                 case _HT_CAPABILITY_IE_:        /* Get HT Cap IE. */
5099                         pmlmeinfo->HT_caps_enable = 1;
5100                         break;
5101                 case _HT_EXTRA_INFO_IE_:        /* Get HT Info IE. */
5102                         pmlmeinfo->HT_info_enable = 1;
5103
5104                         /* spec case only for cisco's ap because cisco's ap issue assoc rsp using mcs rate @40MHz or @20MHz */
5105                         {
5106                                 struct HT_info_element *pht_info = (struct HT_info_element *)(pIE->data);
5107
5108                                 if ((pregpriv->cbw40_enable) &&  (pht_info->infos[0] & BIT(2))) {
5109                                         /* switch to the 40M Hz mode according to the AP */
5110                                         pmlmeext->cur_bwmode = HT_CHANNEL_WIDTH_40;
5111                                         switch (pht_info->infos[0] & 0x3) {
5112                                         case 1:
5113                                                 pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_LOWER;
5114                                                 break;
5115                                         case 3:
5116                                                 pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_UPPER;
5117                                                 break;
5118                                         default:
5119                                                 pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
5120                                                 break;
5121                                 }
5122
5123                                         DBG_88E("set ch/bw before connected\n");
5124                                 }
5125                         }
5126                         break;
5127                 default:
5128                         break;
5129                 }
5130
5131                 i += (pIE->Length + 2);
5132         }
5133         /* disable dynamic functions, such as high power, DIG */
5134
5135         /* config the initial gain under linking, need to write the BB registers */
5136
5137         rtw_hal_set_hwreg(padapter, HW_VAR_BSSID, pmlmeinfo->network.MacAddress);
5138         join_type = 0;
5139         rtw_hal_set_hwreg(padapter, HW_VAR_MLME_JOIN, (u8 *)(&join_type));
5140
5141         /* cancel link timer */
5142         del_timer_sync(&pmlmeext->link_timer);
5143
5144         start_clnt_join(padapter);
5145
5146         return H2C_SUCCESS;
5147 }
5148
5149 u8 disconnect_hdl(struct adapter *padapter, unsigned char *pbuf)
5150 {
5151         struct disconnect_parm *param = (struct disconnect_parm *)pbuf;
5152         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
5153         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
5154         struct wlan_bssid_ex *pnetwork = (struct wlan_bssid_ex *)(&(pmlmeinfo->network));
5155         u8 val8;
5156
5157         if (is_client_associated_to_ap(padapter))
5158                 issue_deauth_ex(padapter, pnetwork->MacAddress, WLAN_REASON_DEAUTH_LEAVING, param->deauth_timeout_ms/100, 100);
5159
5160         rtw_hal_set_hwreg(padapter, HW_VAR_MLME_DISCONNECT, NULL);
5161         rtw_hal_set_hwreg(padapter, HW_VAR_BSSID, null_addr);
5162
5163         /* restore to initial setting. */
5164         update_tx_basic_rate(padapter, padapter->registrypriv.wireless_mode);
5165
5166         if (((pmlmeinfo->state&0x03) == WIFI_FW_ADHOC_STATE) || ((pmlmeinfo->state&0x03) == WIFI_FW_AP_STATE)) {
5167                 /* Stop BCN */
5168                 val8 = 0;
5169                 rtw_hal_set_hwreg(padapter, HW_VAR_BCN_FUNC, (u8 *)(&val8));
5170         }
5171
5172
5173         /* set MSR to no link state -> infra. mode */
5174         Set_MSR(padapter, _HW_STATE_STATION_);
5175
5176         pmlmeinfo->state = WIFI_FW_NULL_STATE;
5177
5178         /* switch to the 20M Hz mode after disconnect */
5179         pmlmeext->cur_bwmode = HT_CHANNEL_WIDTH_20;
5180         pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
5181
5182         set_channel_bwmode(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode);
5183
5184         flush_all_cam_entry(padapter);
5185
5186         del_timer_sync(&pmlmeext->link_timer);
5187
5188         rtw_free_uc_swdec_pending_queue(padapter);
5189
5190         return  H2C_SUCCESS;
5191 }
5192
5193 static int rtw_scan_ch_decision(struct adapter *padapter, struct rtw_ieee80211_channel *out,
5194         u32 out_num, struct rtw_ieee80211_channel *in, u32 in_num)
5195 {
5196         int i, j;
5197         int set_idx;
5198         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
5199
5200         /* clear out first */
5201         memset(out, 0, sizeof(struct rtw_ieee80211_channel)*out_num);
5202
5203         /* acquire channels from in */
5204         j = 0;
5205         for (i = 0; i < in_num; i++) {
5206                 set_idx = rtw_ch_set_search_ch(pmlmeext->channel_set, in[i].hw_value);
5207                 if (in[i].hw_value && !(in[i].flags & RTW_IEEE80211_CHAN_DISABLED) &&
5208                     set_idx >= 0) {
5209                         out[j] = in[i];
5210
5211                         if (pmlmeext->channel_set[set_idx].ScanType == SCAN_PASSIVE)
5212                                 out[j].flags &= RTW_IEEE80211_CHAN_PASSIVE_SCAN;
5213
5214                         j++;
5215                 }
5216                 if (j >= out_num)
5217                         break;
5218         }
5219
5220         /* if out is empty, use channel_set as default */
5221         if (j == 0) {
5222                 for (i = 0; i < pmlmeext->max_chan_nums; i++) {
5223                         out[i].hw_value = pmlmeext->channel_set[i].ChannelNum;
5224
5225                         if (pmlmeext->channel_set[i].ScanType == SCAN_PASSIVE)
5226                                 out[i].flags &= RTW_IEEE80211_CHAN_PASSIVE_SCAN;
5227
5228                         j++;
5229                 }
5230         }
5231
5232         return j;
5233 }
5234
5235 u8 sitesurvey_cmd_hdl(struct adapter *padapter, u8 *pbuf)
5236 {
5237         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
5238         struct sitesurvey_parm  *pparm = (struct sitesurvey_parm *)pbuf;
5239         u8 bdelayscan = false;
5240         u8 val8;
5241         u32     initialgain;
5242         u32     i;
5243
5244         if (pmlmeext->sitesurvey_res.state == SCAN_DISABLE) {
5245                 /* for first time sitesurvey_cmd */
5246                 rtw_hal_set_hwreg(padapter, HW_VAR_CHECK_TXBUF, NULL);
5247
5248                 pmlmeext->sitesurvey_res.state = SCAN_START;
5249                 pmlmeext->sitesurvey_res.bss_cnt = 0;
5250                 pmlmeext->sitesurvey_res.channel_idx = 0;
5251
5252                 for (i = 0; i < RTW_SSID_SCAN_AMOUNT; i++) {
5253                         if (pparm->ssid[i].SsidLength) {
5254                                 memcpy(pmlmeext->sitesurvey_res.ssid[i].Ssid, pparm->ssid[i].Ssid, IW_ESSID_MAX_SIZE);
5255                                 pmlmeext->sitesurvey_res.ssid[i].SsidLength = pparm->ssid[i].SsidLength;
5256                         } else {
5257                                 pmlmeext->sitesurvey_res.ssid[i].SsidLength = 0;
5258                         }
5259                 }
5260
5261                 pmlmeext->sitesurvey_res.ch_num = rtw_scan_ch_decision(padapter
5262                         , pmlmeext->sitesurvey_res.ch, RTW_CHANNEL_SCAN_AMOUNT
5263                         , pparm->ch, pparm->ch_num
5264         );
5265
5266                 pmlmeext->sitesurvey_res.scan_mode = pparm->scan_mode;
5267
5268                 /* issue null data if associating to the AP */
5269                 if (is_client_associated_to_ap(padapter)) {
5270                         pmlmeext->sitesurvey_res.state = SCAN_TXNULL;
5271
5272                         issue_nulldata(padapter, NULL, 1, 3, 500);
5273
5274                         bdelayscan = true;
5275                 }
5276                 if (bdelayscan) {
5277                         /* delay 50ms to protect nulldata(1). */
5278                         set_survey_timer(pmlmeext, 50);
5279                         return H2C_SUCCESS;
5280                 }
5281         }
5282
5283         if ((pmlmeext->sitesurvey_res.state == SCAN_START) || (pmlmeext->sitesurvey_res.state == SCAN_TXNULL)) {
5284                 /* disable dynamic functions, such as high power, DIG */
5285                 Save_DM_Func_Flag(padapter);
5286                 Switch_DM_Func(padapter, DYNAMIC_FUNC_DISABLE, false);
5287
5288                 /* config the initial gain under scanning, need to write the BB registers */
5289                 initialgain = 0x1E;
5290
5291                 rtw_hal_set_hwreg(padapter, HW_VAR_INITIAL_GAIN, (u8 *)(&initialgain));
5292
5293                 /* set MSR to no link state */
5294                 Set_MSR(padapter, _HW_STATE_NOLINK_);
5295
5296                 val8 = 1; /* under site survey */
5297                 rtw_hal_set_hwreg(padapter, HW_VAR_MLME_SITESURVEY, (u8 *)(&val8));
5298
5299                 pmlmeext->sitesurvey_res.state = SCAN_PROCESS;
5300         }
5301
5302         site_survey(padapter);
5303
5304         return H2C_SUCCESS;
5305 }
5306
5307 u8 setauth_hdl(struct adapter *padapter, unsigned char *pbuf)
5308 {
5309         struct setauth_parm             *pparm = (struct setauth_parm *)pbuf;
5310         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
5311         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
5312
5313         if (pparm->mode < 4)
5314                 pmlmeinfo->auth_algo = pparm->mode;
5315         return  H2C_SUCCESS;
5316 }
5317
5318 u8 setkey_hdl(struct adapter *padapter, u8 *pbuf)
5319 {
5320         unsigned short                          ctrl;
5321         struct setkey_parm              *pparm = (struct setkey_parm *)pbuf;
5322         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
5323         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
5324         unsigned char                                   null_sta[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
5325
5326         /* main tx key for wep. */
5327         if (pparm->set_tx)
5328                 pmlmeinfo->key_index = pparm->keyid;
5329
5330         /* write cam */
5331         ctrl = BIT(15) | ((pparm->algorithm) << 2) | pparm->keyid;
5332
5333         DBG_88E_LEVEL(_drv_info_, "set group key to hw: alg:%d(WEP40-1 WEP104-5 TKIP-2 AES-4) "
5334                         "keyid:%d\n", pparm->algorithm, pparm->keyid);
5335         write_cam(padapter, pparm->keyid, ctrl, null_sta, pparm->key);
5336
5337         return H2C_SUCCESS;
5338 }
5339
5340 u8 set_stakey_hdl(struct adapter *padapter, u8 *pbuf)
5341 {
5342         u16 ctrl = 0;
5343         u8 cam_id;/* cam_entry */
5344         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
5345         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
5346         struct set_stakey_parm  *pparm = (struct set_stakey_parm *)pbuf;
5347
5348         /* cam_entry: */
5349         /* 0~3 for default key */
5350
5351         /* for concurrent mode (ap+sta): */
5352         /* default key is disable, using sw encrypt/decrypt */
5353         /* cam_entry = 4 for sta mode (macid = 0) */
5354         /* cam_entry(macid+3) = 5 ~ N for ap mode (aid = 1~N, macid = 2 ~N) */
5355
5356         /* for concurrent mode (sta+sta): */
5357         /* default key is disable, using sw encrypt/decrypt */
5358         /* cam_entry = 4 mapping to macid = 0 */
5359         /* cam_entry = 5 mapping to macid = 2 */
5360
5361         cam_id = 4;
5362
5363         DBG_88E_LEVEL(_drv_info_, "set pairwise key to hw: alg:%d(WEP40-1 WEP104-5 TKIP-2 AES-4) camid:%d\n",
5364                       pparm->algorithm, cam_id);
5365         if ((pmlmeinfo->state&0x03) == WIFI_FW_AP_STATE) {
5366                 struct sta_info *psta;
5367                 struct sta_priv *pstapriv = &padapter->stapriv;
5368
5369                 if (pparm->algorithm == _NO_PRIVACY_)   /*  clear cam entry */ {
5370                         clear_cam_entry(padapter, pparm->id);
5371                         return H2C_SUCCESS_RSP;
5372                 }
5373
5374                 psta = rtw_get_stainfo(pstapriv, pparm->addr);
5375                 if (psta) {
5376                         ctrl = BIT(15) | ((pparm->algorithm) << 2);
5377
5378                         DBG_88E("r871x_set_stakey_hdl(): enc_algorithm=%d\n", pparm->algorithm);
5379
5380                         if ((psta->mac_id < 1) || (psta->mac_id > (NUM_STA-4))) {
5381                                 DBG_88E("r871x_set_stakey_hdl():set_stakey failed, mac_id(aid)=%d\n", psta->mac_id);
5382                                 return H2C_REJECTED;
5383                         }
5384
5385                         cam_id = psta->mac_id + 3;/* 0~3 for default key, cmd_id = macid + 3, macid = aid+1; */
5386
5387                         DBG_88E("Write CAM, mac_addr =%x:%x:%x:%x:%x:%x, cam_entry=%d\n", pparm->addr[0],
5388                                 pparm->addr[1], pparm->addr[2], pparm->addr[3], pparm->addr[4],
5389                                 pparm->addr[5], cam_id);
5390
5391                         write_cam(padapter, cam_id, ctrl, pparm->addr, pparm->key);
5392
5393                         return H2C_SUCCESS_RSP;
5394                 } else {
5395                         DBG_88E("r871x_set_stakey_hdl(): sta has been free\n");
5396                         return H2C_REJECTED;
5397                 }
5398         }
5399
5400         /* below for sta mode */
5401
5402         if (pparm->algorithm == _NO_PRIVACY_) { /*  clear cam entry */
5403                 clear_cam_entry(padapter, pparm->id);
5404                 return H2C_SUCCESS;
5405         }
5406         ctrl = BIT(15) | ((pparm->algorithm) << 2);
5407         write_cam(padapter, cam_id, ctrl, pparm->addr, pparm->key);
5408         pmlmeinfo->enc_algo = pparm->algorithm;
5409         return H2C_SUCCESS;
5410 }
5411
5412 u8 add_ba_hdl(struct adapter *padapter, unsigned char *pbuf)
5413 {
5414         struct addBaReq_parm    *pparm = (struct addBaReq_parm *)pbuf;
5415         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
5416         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
5417
5418         struct sta_info *psta = rtw_get_stainfo(&padapter->stapriv, pparm->addr);
5419
5420         if (!psta)
5421                 return  H2C_SUCCESS;
5422
5423         if (((pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS) && (pmlmeinfo->HT_enable)) ||
5424             ((pmlmeinfo->state&0x03) == WIFI_FW_AP_STATE)) {
5425                 issue_action_BA(padapter, pparm->addr, RTW_WLAN_ACTION_ADDBA_REQ, (u16)pparm->tid);
5426                 mod_timer(&psta->addba_retry_timer,
5427                           jiffies + msecs_to_jiffies(ADDBA_TO));
5428         } else {
5429                 psta->htpriv.candidate_tid_bitmap &= ~BIT(pparm->tid);
5430         }
5431         return  H2C_SUCCESS;
5432 }
5433
5434 u8 set_tx_beacon_cmd(struct adapter *padapter)
5435 {
5436         struct cmd_obj  *ph2c;
5437         struct wlan_bssid_ex    *ptxBeacon_parm;
5438         struct cmd_priv *pcmdpriv = &(padapter->cmdpriv);
5439         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
5440         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
5441         u8 res = _SUCCESS;
5442         int len_diff = 0;
5443
5444
5445         ph2c = kzalloc(sizeof(struct cmd_obj), GFP_KERNEL);
5446         if (ph2c == NULL) {
5447                 res = _FAIL;
5448                 goto exit;
5449         }
5450
5451         ptxBeacon_parm = kmemdup(&(pmlmeinfo->network),
5452                                 sizeof(struct wlan_bssid_ex), GFP_KERNEL);
5453         if (ptxBeacon_parm == NULL) {
5454                 kfree(ph2c);
5455                 res = _FAIL;
5456                 goto exit;
5457         }
5458
5459         len_diff = update_hidden_ssid(ptxBeacon_parm->IEs+_BEACON_IE_OFFSET_,
5460                                       ptxBeacon_parm->IELength-_BEACON_IE_OFFSET_,
5461                                       pmlmeinfo->hidden_ssid_mode);
5462         ptxBeacon_parm->IELength += len_diff;
5463
5464         init_h2fwcmd_w_parm_no_rsp(ph2c, ptxBeacon_parm, GEN_CMD_CODE(_TX_Beacon));
5465
5466         res = rtw_enqueue_cmd(pcmdpriv, ph2c);
5467
5468
5469 exit:
5470
5471
5472         return res;
5473 }
5474
5475 u8 mlme_evt_hdl(struct adapter *padapter, unsigned char *pbuf)
5476 {
5477         u8 evt_code;
5478         u16 evt_sz;
5479         uint    *peventbuf;
5480         void (*event_callback)(struct adapter *dev, u8 *pbuf);
5481
5482         peventbuf = (uint *)pbuf;
5483         evt_sz = (u16)(*peventbuf&0xffff);
5484         evt_code = (u8)((*peventbuf>>16)&0xff);
5485
5486         /*  checking if event code is valid */
5487         if (evt_code >= MAX_C2HEVT) {
5488                 RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_, ("\nEvent Code(%d) mismatch!\n", evt_code));
5489                 goto _abort_event_;
5490         }
5491
5492         /*  checking if event size match the event parm size */
5493         if ((wlanevents[evt_code].parmsize != 0) &&
5494             (wlanevents[evt_code].parmsize != evt_sz)) {
5495                 RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_,
5496                          ("\nEvent(%d) Parm Size mismatch (%d vs %d)!\n",
5497                          evt_code, wlanevents[evt_code].parmsize, evt_sz));
5498                 goto _abort_event_;
5499         }
5500
5501         peventbuf += 2;
5502
5503         if (peventbuf) {
5504                 event_callback = wlanevents[evt_code].event_callback;
5505                 event_callback(padapter, (u8 *)peventbuf);
5506
5507         }
5508
5509 _abort_event_:
5510         return H2C_SUCCESS;
5511 }
5512
5513 u8 tx_beacon_hdl(struct adapter *padapter, unsigned char *pbuf)
5514 {
5515         if (send_beacon(padapter) == _FAIL) {
5516                 DBG_88E("issue_beacon, fail!\n");
5517                 return H2C_PARAMETERS_ERROR;
5518         }
5519 #ifdef CONFIG_88EU_AP_MODE
5520         else { /* tx bc/mc frames after update TIM */
5521                 struct sta_info *psta_bmc;
5522                 struct list_head *xmitframe_plist, *xmitframe_phead;
5523                 struct xmit_frame *pxmitframe = NULL;
5524                 struct sta_priv  *pstapriv = &padapter->stapriv;
5525
5526                 /* for BC/MC Frames */
5527                 psta_bmc = rtw_get_bcmc_stainfo(padapter);
5528                 if (!psta_bmc)
5529                         return H2C_SUCCESS;
5530
5531                 if ((pstapriv->tim_bitmap&BIT(0)) && (psta_bmc->sleepq_len > 0)) {
5532                         msleep(10);/*  10ms, ATIM(HIQ) Windows */
5533                         spin_lock_bh(&psta_bmc->sleep_q.lock);
5534
5535                         xmitframe_phead = get_list_head(&psta_bmc->sleep_q);
5536                         xmitframe_plist = xmitframe_phead->next;
5537
5538                         while (xmitframe_phead != xmitframe_plist) {
5539                                 pxmitframe = container_of(xmitframe_plist, struct xmit_frame, list);
5540
5541                                 xmitframe_plist = xmitframe_plist->next;
5542
5543                                 list_del_init(&pxmitframe->list);
5544
5545                                 psta_bmc->sleepq_len--;
5546                                 if (psta_bmc->sleepq_len > 0)
5547                                         pxmitframe->attrib.mdata = 1;
5548                                 else
5549                                         pxmitframe->attrib.mdata = 0;
5550
5551                                 pxmitframe->attrib.triggered = 1;
5552
5553                                 pxmitframe->attrib.qsel = 0x11;/* HIQ */
5554
5555                                 spin_unlock_bh(&psta_bmc->sleep_q.lock);
5556                                 if (rtw_hal_xmit(padapter, pxmitframe))
5557                                         rtw_os_xmit_complete(padapter, pxmitframe);
5558                                 spin_lock_bh(&psta_bmc->sleep_q.lock);
5559                         }
5560                         spin_unlock_bh(&psta_bmc->sleep_q.lock);
5561                 }
5562         }
5563 #endif
5564         return H2C_SUCCESS;
5565 }
5566
5567 u8 set_ch_hdl(struct adapter *padapter, u8 *pbuf)
5568 {
5569         struct set_ch_parm *set_ch_parm;
5570         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
5571
5572         if (!pbuf)
5573                 return H2C_PARAMETERS_ERROR;
5574
5575         set_ch_parm = (struct set_ch_parm *)pbuf;
5576
5577         DBG_88E(FUNC_NDEV_FMT" ch:%u, bw:%u, ch_offset:%u\n",
5578                 FUNC_NDEV_ARG(padapter->pnetdev),
5579                 set_ch_parm->ch, set_ch_parm->bw, set_ch_parm->ch_offset);
5580
5581         pmlmeext->cur_channel = set_ch_parm->ch;
5582         pmlmeext->cur_ch_offset = set_ch_parm->ch_offset;
5583         pmlmeext->cur_bwmode = set_ch_parm->bw;
5584
5585         set_channel_bwmode(padapter, set_ch_parm->ch, set_ch_parm->ch_offset, set_ch_parm->bw);
5586
5587         return  H2C_SUCCESS;
5588 }
5589
5590 u8 set_chplan_hdl(struct adapter *padapter, unsigned char *pbuf)
5591 {
5592         struct SetChannelPlan_param *setChannelPlan_param;
5593         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
5594
5595         if (!pbuf)
5596                 return H2C_PARAMETERS_ERROR;
5597
5598         setChannelPlan_param = (struct SetChannelPlan_param *)pbuf;
5599
5600         pmlmeext->max_chan_nums = init_channel_set(padapter, setChannelPlan_param->channel_plan, pmlmeext->channel_set);
5601         init_channel_list(padapter, pmlmeext->channel_set, pmlmeext->max_chan_nums, &pmlmeext->channel_list);
5602
5603         return  H2C_SUCCESS;
5604 }