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