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