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