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