staging: rtl8723au: Move {WPA,RSN}_TKIP_CIPHER23A to rtw_wlan_util.c and mark them...
[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 |= 1 << tid;
2038                                 psta->htpriv.candidate_tid_bitmap &=
2039                                         ~CHKBIT(tid);
2040                         } else
2041                                 psta->htpriv.agg_enable_bitmap &= ~CHKBIT(tid);
2042                         break;
2043
2044                 case WLAN_ACTION_DELBA: /* DELBA */
2045                         params = get_unaligned_le16(
2046                                 &mgmt->u.action.u.delba.params);
2047                         tid = params >> 12;
2048
2049                         if (params & IEEE80211_DELBA_PARAM_INITIATOR_MASK) {
2050                                 preorder_ctrl = &psta->recvreorder_ctrl[tid];
2051                                 preorder_ctrl->enable = false;
2052                                 preorder_ctrl->indicate_seq = 0xffff;
2053                         } else {
2054                                 psta->htpriv.agg_enable_bitmap &= ~(1 << tid);
2055                                 psta->htpriv.candidate_tid_bitmap &=
2056                                         ~(1 << tid);
2057                         }
2058                         reason_code = get_unaligned_le16(
2059                                 &mgmt->u.action.u.delba.reason_code);
2060                         DBG_8723A("%s(): DELBA: %x(%x)\n", __func__,
2061                                   pmlmeinfo->agg_enable_bitmap, reason_code);
2062                         /* todo: how to notify the host while receiving
2063                            DELETE BA */
2064                         break;
2065                 default:
2066                         break;
2067                 }
2068         }
2069         return _SUCCESS;
2070 }
2071
2072 static s32 rtw_action_public_decache(struct recv_frame *recv_frame, s32 token)
2073 {
2074         struct rtw_adapter *adapter = recv_frame->adapter;
2075         struct mlme_ext_priv *mlmeext = &adapter->mlmeextpriv;
2076         struct sk_buff *skb = recv_frame->pkt;
2077         struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
2078         u16 seq_ctrl;
2079
2080         seq_ctrl = ((recv_frame->attrib.seq_num&0xffff) << 4) |
2081                 (recv_frame->attrib.frag_num & 0xf);
2082
2083         if (ieee80211_has_retry(hdr->frame_control)) {
2084                 if (token >= 0) {
2085                         if ((seq_ctrl == mlmeext->action_public_rxseq) &&
2086                             (token == mlmeext->action_public_dialog_token)) {
2087                                 DBG_8723A("%s(%s): seq_ctrl = 0x%x, "
2088                                           "rxseq = 0x%x, token:%d\n", __func__,
2089                                           adapter->pnetdev->name, seq_ctrl,
2090                                           mlmeext->action_public_rxseq, token);
2091                                 return _FAIL;
2092                         }
2093                 } else {
2094                         if (seq_ctrl == mlmeext->action_public_rxseq) {
2095                                 DBG_8723A("%s(%s): seq_ctrl = 0x%x, "
2096                                           "rxseq = 0x%x\n", __func__,
2097                                           adapter->pnetdev->name, seq_ctrl,
2098                                           mlmeext->action_public_rxseq);
2099                                 return _FAIL;
2100                         }
2101                 }
2102         }
2103
2104         mlmeext->action_public_rxseq = seq_ctrl;
2105
2106         if (token >= 0)
2107                 mlmeext->action_public_dialog_token = token;
2108
2109         return _SUCCESS;
2110 }
2111
2112 static unsigned int on_action_public23a_p2p(struct recv_frame *precv_frame)
2113 {
2114         struct sk_buff *skb = precv_frame->pkt;
2115         u8 *pframe = skb->data;
2116         u8 *frame_body;
2117         u8 dialogToken = 0;
2118
2119         frame_body = (unsigned char *)
2120                 (pframe + sizeof(struct ieee80211_hdr_3addr));
2121
2122         dialogToken = frame_body[7];
2123
2124         if (rtw_action_public_decache(precv_frame, dialogToken) == _FAIL)
2125                 return _FAIL;
2126
2127         return _SUCCESS;
2128 }
2129
2130 static unsigned int on_action_public23a_vendor(struct recv_frame *precv_frame)
2131 {
2132         unsigned int ret = _FAIL;
2133         struct sk_buff *skb = precv_frame->pkt;
2134         u8 *pframe = skb->data;
2135         u8 *frame_body = pframe + sizeof(struct ieee80211_hdr_3addr);
2136
2137         if (!memcmp(frame_body + 2, P2P_OUI23A, 4)) {
2138                 ret = on_action_public23a_p2p(precv_frame);
2139         }
2140
2141         return ret;
2142 }
2143
2144 static unsigned int
2145 on_action_public23a_default(struct recv_frame *precv_frame, u8 action)
2146 {
2147         unsigned int ret = _FAIL;
2148         struct sk_buff *skb = precv_frame->pkt;
2149         u8 *pframe = skb->data;
2150         uint frame_len = skb->len;
2151         u8 *frame_body = pframe + sizeof(struct ieee80211_hdr_3addr);
2152         u8 token;
2153         struct rtw_adapter *adapter = precv_frame->adapter;
2154         int cnt = 0;
2155         char msg[64];
2156
2157         token = frame_body[2];
2158
2159         if (rtw_action_public_decache(precv_frame, token) == _FAIL)
2160                 goto exit;
2161
2162         cnt += sprintf((msg+cnt), "%s(token:%u)",
2163                        action_public_str23a(action), token);
2164         rtw_cfg80211_rx_action(adapter, pframe, frame_len, msg);
2165
2166         ret = _SUCCESS;
2167
2168 exit:
2169         return ret;
2170 }
2171
2172 static int on_action_public23a(struct rtw_adapter *padapter,
2173                                struct recv_frame *precv_frame)
2174 {
2175         unsigned int ret = _FAIL;
2176         struct sk_buff *skb = precv_frame->pkt;
2177         struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
2178         u8 *pframe = skb->data;
2179         u8 *frame_body = pframe + sizeof(struct ieee80211_hdr_3addr);
2180         u8 category, action;
2181
2182         /* check RA matches or not */
2183         if (!ether_addr_equal(myid(&padapter->eeprompriv), hdr->addr1))
2184                 goto exit;
2185
2186         category = frame_body[0];
2187         if (category != WLAN_CATEGORY_PUBLIC)
2188                 goto exit;
2189
2190         action = frame_body[1];
2191         switch (action) {
2192         case ACT_PUBLIC_VENDOR:
2193                 ret = on_action_public23a_vendor(precv_frame);
2194                 break;
2195         default:
2196                 ret = on_action_public23a_default(precv_frame, action);
2197                 break;
2198         }
2199
2200 exit:
2201         return ret;
2202 }
2203
2204 static int
2205 OnAction23a_ht(struct rtw_adapter *padapter, struct recv_frame *precv_frame)
2206 {
2207         return _SUCCESS;
2208 }
2209
2210 static int
2211 OnAction23a_wmm(struct rtw_adapter *padapter, struct recv_frame *precv_frame)
2212 {
2213         return _SUCCESS;
2214 }
2215
2216 static int
2217 OnAction23a_p2p(struct rtw_adapter *padapter, struct recv_frame *precv_frame)
2218 {
2219         return _SUCCESS;
2220 }
2221
2222 static int
2223 OnAction23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame)
2224 {
2225         int i;
2226         u8 category;
2227         struct action_handler *ptable;
2228         struct sk_buff *skb = precv_frame->pkt;
2229         struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *) skb->data;
2230
2231         category = mgmt->u.action.category;
2232
2233         for (i = 0;
2234              i < sizeof(OnAction23a_tbl) / sizeof(struct action_handler); i++) {
2235                 ptable = &OnAction23a_tbl[i];
2236
2237                 if (category == ptable->num)
2238                         ptable->func(padapter, precv_frame);
2239         }
2240
2241         return _SUCCESS;
2242 }
2243
2244 static int DoReserved23a(struct rtw_adapter *padapter,
2245                          struct recv_frame *precv_frame)
2246 {
2247         return _SUCCESS;
2248 }
2249
2250 struct xmit_frame *alloc_mgtxmitframe23a(struct xmit_priv *pxmitpriv)
2251 {
2252         struct xmit_frame *pmgntframe;
2253         struct xmit_buf *pxmitbuf;
2254
2255         pmgntframe = rtw_alloc_xmitframe23a_ext(pxmitpriv);
2256
2257         if (!pmgntframe) {
2258                 DBG_8723A("%s(%s): alloc xmitframe fail\n", __func__,
2259                           pxmitpriv->adapter->pnetdev->name);
2260                 goto exit;
2261         }
2262
2263         pxmitbuf = rtw_alloc_xmitbuf23a_ext(pxmitpriv);
2264         if (!pxmitbuf) {
2265                 DBG_8723A("%s(%s): alloc xmitbuf fail\n", __func__,
2266                           pxmitpriv->adapter->pnetdev->name);
2267                 rtw_free_xmitframe23a(pxmitpriv, pmgntframe);
2268                 pmgntframe = NULL;
2269                 goto exit;
2270         }
2271
2272         pmgntframe->frame_tag = MGNT_FRAMETAG;
2273         pmgntframe->pxmitbuf = pxmitbuf;
2274         pmgntframe->buf_addr = pxmitbuf->pbuf;
2275         pxmitbuf->priv_data = pmgntframe;
2276
2277 exit:
2278         return pmgntframe;
2279 }
2280
2281 /****************************************************************************
2282
2283 Following are some TX fuctions for WiFi MLME
2284
2285 *****************************************************************************/
2286
2287 void update_mgnt_tx_rate23a(struct rtw_adapter *padapter, u8 rate)
2288 {
2289         struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
2290
2291         pmlmeext->tx_rate = rate;
2292         DBG_8723A("%s(): rate = %x\n", __func__, rate);
2293 }
2294
2295 void update_mgntframe_attrib23a(struct rtw_adapter *padapter,
2296                                 struct pkt_attrib *pattrib)
2297 {
2298         struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
2299
2300         memset((u8 *)pattrib, 0, sizeof(struct pkt_attrib));
2301
2302         pattrib->hdrlen = 24;
2303         pattrib->nr_frags = 1;
2304         pattrib->priority = 7;
2305         pattrib->mac_id = 0;
2306         pattrib->qsel = 0x12;
2307
2308         pattrib->pktlen = 0;
2309
2310         if (pmlmeext->cur_wireless_mode & WIRELESS_11B)
2311                 pattrib->raid = 6;/* b mode */
2312         else
2313                 pattrib->raid = 5;/* a/g mode */
2314
2315         pattrib->encrypt = _NO_PRIVACY_;
2316         pattrib->bswenc = false;
2317
2318         pattrib->qos_en = false;
2319         pattrib->ht_en = false;
2320         pattrib->bwmode = HT_CHANNEL_WIDTH_20;
2321         pattrib->ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
2322         pattrib->sgi = false;
2323
2324         pattrib->seqnum = pmlmeext->mgnt_seq;
2325
2326         pattrib->retry_ctrl = true;
2327 }
2328
2329 void dump_mgntframe23a(struct rtw_adapter *padapter,
2330                        struct xmit_frame *pmgntframe)
2331 {
2332         if (padapter->bSurpriseRemoved == true ||
2333             padapter->bDriverStopped == true)
2334                 return;
2335
2336         rtw_hal_mgnt_xmit23a(padapter, pmgntframe);
2337 }
2338
2339 s32 dump_mgntframe23a_and_wait(struct rtw_adapter *padapter,
2340                                struct xmit_frame *pmgntframe, int timeout_ms)
2341 {
2342         s32 ret = _FAIL;
2343         unsigned long irqL;
2344         struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
2345         struct xmit_buf *pxmitbuf = pmgntframe->pxmitbuf;
2346         struct submit_ctx sctx;
2347
2348         if (padapter->bSurpriseRemoved == true ||
2349             padapter->bDriverStopped == true)
2350                 return ret;
2351
2352         rtw_sctx_init23a(&sctx, timeout_ms);
2353         pxmitbuf->sctx = &sctx;
2354
2355         ret = rtw_hal_mgnt_xmit23a(padapter, pmgntframe);
2356
2357         if (ret == _SUCCESS)
2358                 ret = rtw_sctx_wait23a(&sctx);
2359
2360         spin_lock_irqsave(&pxmitpriv->lock_sctx, irqL);
2361         pxmitbuf->sctx = NULL;
2362         spin_unlock_irqrestore(&pxmitpriv->lock_sctx, irqL);
2363
2364         return ret;
2365 }
2366
2367 s32 dump_mgntframe23a_and_wait_ack23a(struct rtw_adapter *padapter,
2368                                       struct xmit_frame *pmgntframe)
2369 {
2370         s32 ret = _FAIL;
2371         u32 timeout_ms = 500;/*   500ms */
2372         struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
2373
2374         if (padapter->bSurpriseRemoved == true ||
2375             padapter->bDriverStopped == true)
2376                 return -1;
2377
2378         mutex_lock(&pxmitpriv->ack_tx_mutex);
2379         pxmitpriv->ack_tx = true;
2380
2381         pmgntframe->ack_report = 1;
2382         if (rtw_hal_mgnt_xmit23a(padapter, pmgntframe) == _SUCCESS) {
2383                 ret = rtw_ack_tx_wait23a(pxmitpriv, timeout_ms);
2384         }
2385
2386         pxmitpriv->ack_tx = false;
2387         mutex_unlock(&pxmitpriv->ack_tx_mutex);
2388
2389         return ret;
2390 }
2391
2392 static int update_hidden_ssid(u8 *ies, u32 ies_len, u8 hidden_ssid_mode)
2393 {
2394         u8 *ssid_ie;
2395         int ssid_len_ori;
2396         int len_diff = 0;
2397         u8 *next_ie;
2398         u32 remain_len;
2399
2400         ssid_ie = rtw_get_ie23a(ies,  WLAN_EID_SSID, &ssid_len_ori, ies_len);
2401
2402         /* DBG_8723A("%s hidden_ssid_mode:%u, ssid_ie:%p, ssid_len_ori:%d\n",
2403            __func__, hidden_ssid_mode, ssid_ie, ssid_len_ori); */
2404
2405         if (ssid_ie && ssid_len_ori > 0) {
2406                 switch (hidden_ssid_mode)
2407                 {
2408                 case 1:
2409                         next_ie = ssid_ie + 2 + ssid_len_ori;
2410                         remain_len = 0;
2411
2412                         remain_len = ies_len -(next_ie-ies);
2413
2414                         ssid_ie[1] = 0;
2415                         memcpy(ssid_ie+2, next_ie, remain_len);
2416                         len_diff -= ssid_len_ori;
2417
2418                         break;
2419                 case 2:
2420                         memset(&ssid_ie[2], 0, ssid_len_ori);
2421                         break;
2422                 default:
2423                         break;
2424                 }
2425         }
2426
2427         return len_diff;
2428 }
2429
2430 void issue_beacon23a(struct rtw_adapter *padapter, int timeout_ms)
2431 {
2432         struct xmit_frame *pmgntframe;
2433         struct pkt_attrib *pattrib;
2434         unsigned char *pframe;
2435         struct ieee80211_hdr *pwlanhdr;
2436         __le16 *fctrl;
2437         unsigned int rate_len;
2438         struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
2439         struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
2440         struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
2441         struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
2442         struct wlan_bssid_ex *cur_network = &pmlmeinfo->network;
2443         u8 bc_addr[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
2444         u8 *wps_ie;
2445         u32 wps_ielen;
2446         u8 sr = 0;
2447         int len_diff;
2448
2449         /* DBG_8723A("%s\n", __func__); */
2450
2451         if ((pmgntframe = alloc_mgtxmitframe23a(pxmitpriv)) == NULL) {
2452                 DBG_8723A("%s, alloc mgnt frame fail\n", __func__);
2453                 return;
2454         }
2455 #ifdef CONFIG_8723AU_AP_MODE
2456         spin_lock_bh(&pmlmepriv->bcn_update_lock);
2457 #endif
2458
2459         /* update attribute */
2460         pattrib = &pmgntframe->attrib;
2461         update_mgntframe_attrib23a(padapter, pattrib);
2462         pattrib->qsel = 0x10;
2463
2464         memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
2465
2466         pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
2467         pwlanhdr = (struct ieee80211_hdr *)pframe;
2468
2469         fctrl = &pwlanhdr->frame_control;
2470         *fctrl = 0;
2471
2472         ether_addr_copy(pwlanhdr->addr1, bc_addr);
2473         ether_addr_copy(pwlanhdr->addr2, myid(&padapter->eeprompriv));
2474         ether_addr_copy(pwlanhdr->addr3, get_my_bssid23a(cur_network));
2475
2476         SetSeqNum(pwlanhdr, 0 /*pmlmeext->mgnt_seq*/);
2477         /* pmlmeext->mgnt_seq++; */
2478         SetFrameSubType(pframe, WIFI_BEACON);
2479
2480         pframe += sizeof(struct ieee80211_hdr_3addr);
2481         pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr);
2482
2483         if ((pmlmeinfo->state&0x03) == WIFI_FW_AP_STATE) {
2484                 /* DBG_8723A("ie len =%d\n", cur_network->IELength); */
2485                 memcpy(pframe, cur_network->IEs, cur_network->IELength);
2486                 len_diff = update_hidden_ssid(pframe + _BEACON_IE_OFFSET_,
2487                                               cur_network->IELength -
2488                                               _BEACON_IE_OFFSET_,
2489                                               pmlmeinfo->hidden_ssid_mode);
2490                 pframe += (cur_network->IELength+len_diff);
2491                 pattrib->pktlen += (cur_network->IELength+len_diff);
2492
2493                 wps_ie = rtw_get_wps_ie23a(pmgntframe->buf_addr + TXDESC_OFFSET+
2494                                            sizeof (struct ieee80211_hdr_3addr) +
2495                                            _BEACON_IE_OFFSET_, pattrib->pktlen -
2496                                            sizeof (struct ieee80211_hdr_3addr) -
2497                                            _BEACON_IE_OFFSET_, NULL,
2498                                            &wps_ielen);
2499                 if (wps_ie && wps_ielen > 0) {
2500                         rtw_get_wps_attr_content23a(wps_ie, wps_ielen,
2501                                                     WPS_ATTR_SELECTED_REGISTRAR,
2502                                                     (u8*)&sr, NULL);
2503                 }
2504                 if (sr != 0)
2505                         set_fwstate(pmlmepriv, WIFI_UNDER_WPS);
2506                 else
2507                         _clr_fwstate_(pmlmepriv, WIFI_UNDER_WPS);
2508
2509                 goto _issue_bcn;
2510         }
2511
2512         /* below for ad-hoc mode */
2513
2514         /* timestamp will be inserted by hardware */
2515         pframe += 8;
2516         pattrib->pktlen += 8;
2517
2518         /*  beacon interval: 2 bytes */
2519
2520         memcpy(pframe, (unsigned char *)
2521                rtw_get_beacon_interval23a_from_ie(cur_network->IEs), 2);
2522
2523         pframe += 2;
2524         pattrib->pktlen += 2;
2525
2526         /*  capability info: 2 bytes */
2527
2528         memcpy(pframe, (unsigned char *)
2529                rtw_get_capability23a_from_ie(cur_network->IEs), 2);
2530
2531         pframe += 2;
2532         pattrib->pktlen += 2;
2533
2534         /*  SSID */
2535         pframe = rtw_set_ie23a(pframe, WLAN_EID_SSID,
2536                                cur_network->Ssid.ssid_len,
2537                                cur_network->Ssid.ssid, &pattrib->pktlen);
2538
2539         /*  supported rates... */
2540         rate_len = rtw_get_rateset_len23a(cur_network->SupportedRates);
2541         pframe = rtw_set_ie23a(pframe, WLAN_EID_SUPP_RATES,
2542                                ((rate_len > 8)? 8: rate_len),
2543                                cur_network->SupportedRates, &pattrib->pktlen);
2544
2545         /*  DS parameter set */
2546         pframe = rtw_set_ie23a(pframe, WLAN_EID_DS_PARAMS, 1, (unsigned char *)
2547                                &cur_network->Configuration.DSConfig,
2548                                &pattrib->pktlen);
2549
2550         /* if ((pmlmeinfo->state&0x03) == WIFI_FW_ADHOC_STATE) */
2551         {
2552                 u8 erpinfo = 0;
2553                 u32 ATIMWindow;
2554                 /*  IBSS Parameter Set... */
2555                 /* ATIMWindow = cur->Configuration.ATIMWindow; */
2556                 ATIMWindow = 0;
2557                 pframe = rtw_set_ie23a(pframe, WLAN_EID_IBSS_PARAMS, 2,
2558                                        (unsigned char *)&ATIMWindow,
2559                                        &pattrib->pktlen);
2560
2561                 /* ERP IE */
2562                 pframe = rtw_set_ie23a(pframe, WLAN_EID_ERP_INFO, 1,
2563                                        &erpinfo, &pattrib->pktlen);
2564         }
2565
2566         /*  EXTERNDED SUPPORTED RATE */
2567         if (rate_len > 8)
2568                 pframe = rtw_set_ie23a(pframe, WLAN_EID_EXT_SUPP_RATES,
2569                                        rate_len - 8,
2570                                        cur_network->SupportedRates + 8,
2571                                        &pattrib->pktlen);
2572
2573         /* todo:HT for adhoc */
2574
2575 _issue_bcn:
2576
2577 #ifdef CONFIG_8723AU_AP_MODE
2578         pmlmepriv->update_bcn = false;
2579
2580         spin_unlock_bh(&pmlmepriv->bcn_update_lock);
2581 #endif
2582
2583         if ((pattrib->pktlen + TXDESC_SIZE) > 512) {
2584                 DBG_8723A("beacon frame too large\n");
2585                 return;
2586         }
2587
2588         pattrib->last_txcmdsz = pattrib->pktlen;
2589
2590         /* DBG_8723A("issue bcn_sz =%d\n", pattrib->last_txcmdsz); */
2591         if (timeout_ms > 0)
2592                 dump_mgntframe23a_and_wait(padapter, pmgntframe, timeout_ms);
2593         else
2594                 dump_mgntframe23a(padapter, pmgntframe);
2595 }
2596
2597 void issue_probersp23a(struct rtw_adapter *padapter, unsigned char *da,
2598                        u8 is_valid_p2p_probereq)
2599 {
2600         struct xmit_frame *pmgntframe;
2601         struct pkt_attrib *pattrib;
2602         unsigned char *pframe;
2603         struct ieee80211_hdr *pwlanhdr;
2604         __le16 *fctrl;
2605         unsigned char *mac, *bssid;
2606         struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
2607 #ifdef CONFIG_8723AU_AP_MODE
2608         u8 *pwps_ie;
2609         uint wps_ielen;
2610         u8 *ssid_ie;
2611         int ssid_ielen;
2612         int ssid_ielen_diff;
2613         u8 buf[MAX_IE_SZ];
2614         u8 *ies;
2615         struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
2616 #endif
2617         struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
2618         struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
2619         struct wlan_bssid_ex *cur_network = &pmlmeinfo->network;
2620         unsigned int rate_len;
2621
2622         /* DBG_8723A("%s\n", __func__); */
2623
2624         pmgntframe = alloc_mgtxmitframe23a(pxmitpriv);
2625         if (!pmgntframe) {
2626                 DBG_8723A("%s, alloc mgnt frame fail\n", __func__);
2627                 return;
2628         }
2629
2630         /* update attribute */
2631         pattrib = &pmgntframe->attrib;
2632         update_mgntframe_attrib23a(padapter, pattrib);
2633
2634         memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
2635
2636         pframe = (u8 *)pmgntframe->buf_addr + TXDESC_OFFSET;
2637         pwlanhdr = (struct ieee80211_hdr *)pframe;
2638
2639         mac = myid(&padapter->eeprompriv);
2640         bssid = cur_network->MacAddress;
2641
2642         fctrl = &pwlanhdr->frame_control;
2643         *fctrl = 0;
2644         ether_addr_copy(pwlanhdr->addr1, da);
2645         ether_addr_copy(pwlanhdr->addr2, mac);
2646         ether_addr_copy(pwlanhdr->addr3, bssid);
2647
2648         SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
2649         pmlmeext->mgnt_seq++;
2650         SetFrameSubType(fctrl, WIFI_PROBERSP);
2651
2652         pattrib->hdrlen = sizeof(struct ieee80211_hdr_3addr);
2653         pattrib->pktlen = pattrib->hdrlen;
2654         pframe += pattrib->hdrlen;
2655
2656         if (cur_network->IELength > MAX_IE_SZ)
2657                 return;
2658
2659 #ifdef CONFIG_8723AU_AP_MODE
2660         if ((pmlmeinfo->state & 0x03) == WIFI_FW_AP_STATE) {
2661                 pwps_ie = rtw_get_wps_ie23a(cur_network->IEs +
2662                                             _FIXED_IE_LENGTH_,
2663                                             cur_network->IELength -
2664                                             _FIXED_IE_LENGTH_, NULL,
2665                                             &wps_ielen);
2666
2667                 /* inerset & update wps_probe_resp_ie */
2668                 if (pmlmepriv->wps_probe_resp_ie && pwps_ie && wps_ielen > 0) {
2669                         uint wps_offset, remainder_ielen;
2670                         u8 *premainder_ie;
2671
2672                         wps_offset = (uint)(pwps_ie - cur_network->IEs);
2673
2674                         premainder_ie = pwps_ie + wps_ielen;
2675
2676                         remainder_ielen = cur_network->IELength - wps_offset -
2677                                 wps_ielen;
2678
2679                         memcpy(pframe, cur_network->IEs, wps_offset);
2680                         pframe += wps_offset;
2681                         pattrib->pktlen += wps_offset;
2682
2683                         /* to get ie data len */
2684                         wps_ielen = (uint)pmlmepriv->wps_probe_resp_ie[1];
2685                         if (wps_offset + wps_ielen + 2 <= MAX_IE_SZ) {
2686                                 memcpy(pframe, pmlmepriv->wps_probe_resp_ie,
2687                                        wps_ielen+2);
2688                                 pframe += wps_ielen+2;
2689                                 pattrib->pktlen += wps_ielen+2;
2690                         }
2691
2692                         if (wps_offset + wps_ielen + 2 + remainder_ielen <=
2693                             MAX_IE_SZ) {
2694                                 memcpy(pframe, premainder_ie, remainder_ielen);
2695                                 pframe += remainder_ielen;
2696                                 pattrib->pktlen += remainder_ielen;
2697                         }
2698                 } else {
2699                         memcpy(pframe, cur_network->IEs, cur_network->IELength);
2700                         pframe += cur_network->IELength;
2701                         pattrib->pktlen += cur_network->IELength;
2702                 }
2703
2704                 /* retrieve SSID IE from cur_network->Ssid */
2705                 ies = pmgntframe->buf_addr + TXDESC_OFFSET +
2706                         sizeof(struct ieee80211_hdr_3addr);
2707
2708                 ssid_ie = rtw_get_ie23a(ies + _FIXED_IE_LENGTH_, WLAN_EID_SSID,
2709                                         &ssid_ielen,
2710                                         pframe - ies - _FIXED_IE_LENGTH_);
2711
2712                 ssid_ielen_diff = cur_network->Ssid.ssid_len - ssid_ielen;
2713
2714                 if (ssid_ie && cur_network->Ssid.ssid_len) {
2715                         uint remainder_ielen;
2716                         u8 *remainder_ie;
2717                         remainder_ie = ssid_ie + 2;
2718                         remainder_ielen = pframe - remainder_ie;
2719
2720                         DBG_8723A_LEVEL(_drv_warning_, "%s(%s): "
2721                                         "remainder_ielen > MAX_IE_SZ\n",
2722                                         __func__, padapter->pnetdev->name);
2723                         if (remainder_ielen > MAX_IE_SZ)
2724                                 remainder_ielen = MAX_IE_SZ;
2725
2726                         memcpy(buf, remainder_ie, remainder_ielen);
2727                         memcpy(remainder_ie + ssid_ielen_diff, buf,
2728                                remainder_ielen);
2729                         *(ssid_ie + 1) = cur_network->Ssid.ssid_len;
2730                         memcpy(ssid_ie + 2, cur_network->Ssid.ssid,
2731                                cur_network->Ssid.ssid_len);
2732
2733                         pframe += ssid_ielen_diff;
2734                         pattrib->pktlen += ssid_ielen_diff;
2735                 }
2736         } else
2737 #endif
2738         {
2739
2740                 /* timestamp will be inserted by hardware */
2741                 pframe += 8;
2742                 pattrib->pktlen += 8;
2743
2744                 /*  beacon interval: 2 bytes */
2745
2746                 memcpy(pframe, (unsigned char *)
2747                        rtw_get_beacon_interval23a_from_ie(cur_network->IEs), 2);
2748
2749                 pframe += 2;
2750                 pattrib->pktlen += 2;
2751
2752                 /*  capability info: 2 bytes */
2753
2754                 memcpy(pframe, (unsigned char *)
2755                        rtw_get_capability23a_from_ie(cur_network->IEs), 2);
2756
2757                 pframe += 2;
2758                 pattrib->pktlen += 2;
2759
2760                 /* below for ad-hoc mode */
2761
2762                 /*  SSID */
2763                 pframe = rtw_set_ie23a(pframe, WLAN_EID_SSID,
2764                                        cur_network->Ssid.ssid_len,
2765                                        cur_network->Ssid.ssid,
2766                                        &pattrib->pktlen);
2767
2768                 /*  supported rates... */
2769                 rate_len = rtw_get_rateset_len23a(cur_network->SupportedRates);
2770                 pframe = rtw_set_ie23a(pframe, WLAN_EID_SUPP_RATES,
2771                                        ((rate_len > 8)? 8: rate_len),
2772                                        cur_network->SupportedRates,
2773                                        &pattrib->pktlen);
2774
2775                 /*  DS parameter set */
2776                 pframe = rtw_set_ie23a(pframe, WLAN_EID_DS_PARAMS, 1,
2777                                        (unsigned char *)
2778                                        &cur_network->Configuration.DSConfig,
2779                                        &pattrib->pktlen);
2780
2781                 if ((pmlmeinfo->state & 0x03) == WIFI_FW_ADHOC_STATE) {
2782                         u8 erpinfo = 0;
2783                         u32 ATIMWindow;
2784                         /*  IBSS Parameter Set... */
2785                         /* ATIMWindow = cur->Configuration.ATIMWindow; */
2786                         ATIMWindow = 0;
2787                         pframe = rtw_set_ie23a(pframe, WLAN_EID_IBSS_PARAMS, 2,
2788                                                (unsigned char *)&ATIMWindow,
2789                                                &pattrib->pktlen);
2790
2791                         /* ERP IE */
2792                         pframe = rtw_set_ie23a(pframe, WLAN_EID_ERP_INFO, 1,
2793                                                &erpinfo, &pattrib->pktlen);
2794                 }
2795
2796                 /*  EXTERNDED SUPPORTED RATE */
2797                 if (rate_len > 8)
2798                         pframe = rtw_set_ie23a(pframe, WLAN_EID_EXT_SUPP_RATES,
2799                                                rate_len - 8,
2800                                                cur_network->SupportedRates + 8,
2801                                                &pattrib->pktlen);
2802
2803                 /* todo:HT for adhoc */
2804         }
2805
2806         pattrib->last_txcmdsz = pattrib->pktlen;
2807
2808         dump_mgntframe23a(padapter, pmgntframe);
2809
2810         return;
2811 }
2812
2813 static int _issue_probereq23a(struct rtw_adapter *padapter,
2814                               struct cfg80211_ssid *pssid, u8 *da, int wait_ack)
2815 {
2816         int ret = _FAIL;
2817         struct xmit_frame               *pmgntframe;
2818         struct pkt_attrib               *pattrib;
2819         unsigned char                   *pframe;
2820         struct ieee80211_hdr    *pwlanhdr;
2821         __le16          *fctrl;
2822         unsigned char                   *mac;
2823         unsigned char                   bssrate[NumRates];
2824         struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
2825         struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
2826         struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
2827         int     bssrate_len = 0;
2828         u8      bc_addr[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
2829
2830         RT_TRACE(_module_rtl871x_mlme_c_, _drv_notice_,
2831                  ("+issue_probereq23a\n"));
2832
2833         if ((pmgntframe = alloc_mgtxmitframe23a(pxmitpriv)) == NULL)
2834                 goto exit;
2835
2836         /* update attribute */
2837         pattrib = &pmgntframe->attrib;
2838         update_mgntframe_attrib23a(padapter, pattrib);
2839
2840         memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
2841
2842         pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
2843         pwlanhdr = (struct ieee80211_hdr *)pframe;
2844
2845         mac = myid(&padapter->eeprompriv);
2846
2847                 fctrl = &pwlanhdr->frame_control;
2848         *fctrl = 0;
2849
2850         if (da) {
2851                 /*      unicast probe request frame */
2852                 ether_addr_copy(pwlanhdr->addr1, da);
2853                 ether_addr_copy(pwlanhdr->addr3, da);
2854         } else {
2855                 /*      broadcast probe request frame */
2856                 ether_addr_copy(pwlanhdr->addr1, bc_addr);
2857                 ether_addr_copy(pwlanhdr->addr3, bc_addr);
2858         }
2859
2860         ether_addr_copy(pwlanhdr->addr2, mac);
2861
2862         SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
2863         pmlmeext->mgnt_seq++;
2864         SetFrameSubType(pframe, WIFI_PROBEREQ);
2865
2866         pframe += sizeof (struct ieee80211_hdr_3addr);
2867         pattrib->pktlen = sizeof (struct ieee80211_hdr_3addr);
2868
2869         if (pssid)
2870                 pframe = rtw_set_ie23a(pframe, WLAN_EID_SSID, pssid->ssid_len,
2871                                        pssid->ssid, &pattrib->pktlen);
2872         else
2873                 pframe = rtw_set_ie23a(pframe, WLAN_EID_SSID, 0, NULL,
2874                                        &pattrib->pktlen);
2875
2876         get_rate_set23a(padapter, bssrate, &bssrate_len);
2877
2878         if (bssrate_len > 8) {
2879                 pframe = rtw_set_ie23a(pframe, WLAN_EID_SUPP_RATES, 8,
2880                                        bssrate, &pattrib->pktlen);
2881                 pframe = rtw_set_ie23a(pframe, WLAN_EID_EXT_SUPP_RATES,
2882                                        (bssrate_len - 8), (bssrate + 8),
2883                                        &pattrib->pktlen);
2884         } else {
2885                 pframe = rtw_set_ie23a(pframe, WLAN_EID_SUPP_RATES,
2886                                        bssrate_len, bssrate, &pattrib->pktlen);
2887         }
2888
2889         /* add wps_ie for wps2.0 */
2890         if (pmlmepriv->wps_probe_req_ie_len>0 && pmlmepriv->wps_probe_req_ie) {
2891                 memcpy(pframe, pmlmepriv->wps_probe_req_ie,
2892                        pmlmepriv->wps_probe_req_ie_len);
2893                 pframe += pmlmepriv->wps_probe_req_ie_len;
2894                 pattrib->pktlen += pmlmepriv->wps_probe_req_ie_len;
2895         }
2896
2897         pattrib->last_txcmdsz = pattrib->pktlen;
2898
2899         RT_TRACE(_module_rtl871x_mlme_c_, _drv_notice_,
2900                  ("issuing probe_req, tx_len =%d\n", pattrib->last_txcmdsz));
2901
2902         if (wait_ack) {
2903                 ret = dump_mgntframe23a_and_wait_ack23a(padapter, pmgntframe);
2904         } else {
2905                 dump_mgntframe23a(padapter, pmgntframe);
2906                 ret = _SUCCESS;
2907         }
2908
2909 exit:
2910         return ret;
2911 }
2912
2913 inline void issue_probereq23a(struct rtw_adapter *padapter,
2914                               struct cfg80211_ssid *pssid, u8 *da)
2915 {
2916         _issue_probereq23a(padapter, pssid, da, false);
2917 }
2918
2919 int issue_probereq23a_ex23a(struct rtw_adapter *padapter,
2920                       struct cfg80211_ssid *pssid, u8 *da,
2921                       int try_cnt, int wait_ms)
2922 {
2923         int ret;
2924         int i = 0;
2925         unsigned long start = jiffies;
2926
2927         do {
2928                 ret = _issue_probereq23a(padapter, pssid, da,
2929                                          wait_ms > 0 ? true : false);
2930
2931                 i++;
2932
2933                 if (padapter->bDriverStopped || padapter->bSurpriseRemoved)
2934                         break;
2935
2936                 if (i < try_cnt && wait_ms > 0 && ret == _FAIL)
2937                         msleep(wait_ms);
2938
2939         } while((i < try_cnt) && ((ret == _FAIL) || (wait_ms == 0)));
2940
2941         if (ret != _FAIL) {
2942                 ret = _SUCCESS;
2943                 goto exit;
2944         }
2945
2946         if (try_cnt && wait_ms) {
2947                 if (da)
2948                         DBG_8723A("%s(%s): to "MAC_FMT", ch:%u%s, %d/%d "
2949                                   "in %u ms\n", __func__,
2950                                   padapter->pnetdev->name,
2951                                   MAC_ARG(da), rtw_get_oper_ch23a(padapter),
2952                                   ret == _SUCCESS?", acked":"", i, try_cnt,
2953                                   jiffies_to_msecs(jiffies - start));
2954                 else
2955                         DBG_8723A("%s(%s):, ch:%u%s, %d/%d in %u ms\n",
2956                                   __func__, padapter->pnetdev->name,
2957                                   rtw_get_oper_ch23a(padapter),
2958                                   ret == _SUCCESS?", acked":"", i, try_cnt,
2959                                   jiffies_to_msecs(jiffies - start));
2960         }
2961 exit:
2962         return ret;
2963 }
2964
2965 /*  if psta == NULL, indiate we are station(client) now... */
2966 void issue_auth23a(struct rtw_adapter *padapter, struct sta_info *psta,
2967                    unsigned short status)
2968 {
2969         struct xmit_frame *pmgntframe;
2970         struct pkt_attrib *pattrib;
2971         unsigned char *pframe;
2972         struct ieee80211_hdr *pwlanhdr;
2973         __le16 *fctrl;
2974         unsigned int val32;
2975         unsigned short val16;
2976         int use_shared_key = 0;
2977         struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
2978         struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
2979         struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
2980
2981         if ((pmgntframe = alloc_mgtxmitframe23a(pxmitpriv)) == NULL)
2982                 return;
2983
2984         /* update attribute */
2985         pattrib = &pmgntframe->attrib;
2986         update_mgntframe_attrib23a(padapter, pattrib);
2987
2988         memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
2989
2990         pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
2991         pwlanhdr = (struct ieee80211_hdr *)pframe;
2992
2993         fctrl = &pwlanhdr->frame_control;
2994         *fctrl = 0;
2995
2996         SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
2997         pmlmeext->mgnt_seq++;
2998         SetFrameSubType(pframe, WIFI_AUTH);
2999
3000         pframe += sizeof(struct ieee80211_hdr_3addr);
3001         pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr);
3002
3003         if (psta) { /*  for AP mode */
3004 #ifdef CONFIG_8723AU_AP_MODE
3005
3006                 ether_addr_copy(pwlanhdr->addr1, psta->hwaddr);
3007                 ether_addr_copy(pwlanhdr->addr2, myid(&padapter->eeprompriv));
3008                 ether_addr_copy(pwlanhdr->addr3, myid(&padapter->eeprompriv));
3009
3010                 /*  setting auth algo number */
3011                 val16 = (u16)psta->authalg;
3012
3013                 if (status != WLAN_STATUS_SUCCESS)
3014                         val16 = 0;
3015
3016                 if (val16) {
3017                         val16 = cpu_to_le16(val16);
3018                         use_shared_key = 1;
3019                 }
3020
3021                 pframe = rtw_set_fixed_ie23a(pframe, _AUTH_ALGM_NUM_,
3022                                              (unsigned char *)&val16,
3023                                              &pattrib->pktlen);
3024
3025                 /*  setting auth seq number */
3026                 val16 = (u16)psta->auth_seq;
3027                 val16 = cpu_to_le16(val16);
3028                 pframe = rtw_set_fixed_ie23a(pframe, _AUTH_SEQ_NUM_,
3029                                              (unsigned char *)&val16,
3030                                              &pattrib->pktlen);
3031
3032                 /*  setting status code... */
3033                 val16 = status;
3034                 val16 = cpu_to_le16(val16);
3035                 pframe = rtw_set_fixed_ie23a(pframe, _STATUS_CODE_,
3036                                              (unsigned char *)&val16,
3037                                              &pattrib->pktlen);
3038
3039                 /*  added challenging text... */
3040                 if ((psta->auth_seq == 2) &&
3041                     (psta->state & WIFI_FW_AUTH_STATE) && (use_shared_key == 1))
3042                         pframe = rtw_set_ie23a(pframe, WLAN_EID_CHALLENGE, 128,
3043                                                psta->chg_txt, &pattrib->pktlen);
3044 #endif
3045         } else {
3046                 ether_addr_copy(pwlanhdr->addr1,
3047                                 get_my_bssid23a(&pmlmeinfo->network));
3048                 ether_addr_copy(pwlanhdr->addr2, myid(&padapter->eeprompriv));
3049                 ether_addr_copy(pwlanhdr->addr3,
3050                                 get_my_bssid23a(&pmlmeinfo->network));
3051
3052                 /*  setting auth algo number */
3053                 /*  0:OPEN System, 1:Shared key */
3054                 val16 = (pmlmeinfo->auth_algo == dot11AuthAlgrthm_Shared)? 1: 0;
3055                 if (val16) {
3056                         val16 = cpu_to_le16(val16);
3057                         use_shared_key = 1;
3058                 }
3059                 /* DBG_8723A("%s auth_algo = %s auth_seq =%d\n", __func__,
3060                    (pmlmeinfo->auth_algo == 0)?"OPEN":"SHARED",
3061                    pmlmeinfo->auth_seq); */
3062
3063                 /* setting IV for auth seq #3 */
3064                 if ((pmlmeinfo->auth_seq == 3) &&
3065                     (pmlmeinfo->state & WIFI_FW_AUTH_STATE) &&
3066                     (use_shared_key == 1)) {
3067                         /* DBG_8723A("==> iv(%d), key_index(%d)\n",
3068                            pmlmeinfo->iv, pmlmeinfo->key_index); */
3069                         val32 = ((pmlmeinfo->iv++) |
3070                                  (pmlmeinfo->key_index << 30));
3071                         val32 = cpu_to_le32(val32);
3072                         pframe = rtw_set_fixed_ie23a(pframe, 4,
3073                                                      (unsigned char *)&val32,
3074                                                      &pattrib->pktlen);
3075
3076                         pattrib->iv_len = 4;
3077                 }
3078
3079                 pframe = rtw_set_fixed_ie23a(pframe, _AUTH_ALGM_NUM_,
3080                                              (unsigned char *)&val16,
3081                                              &pattrib->pktlen);
3082
3083                 /*  setting auth seq number */
3084                 val16 = pmlmeinfo->auth_seq;
3085                 val16 = cpu_to_le16(val16);
3086                 pframe = rtw_set_fixed_ie23a(pframe, _AUTH_SEQ_NUM_,
3087                                              (unsigned char *)&val16,
3088                                              &pattrib->pktlen);
3089
3090                 /*  setting status code... */
3091                 val16 = status;
3092                 val16 = cpu_to_le16(val16);
3093                 pframe = rtw_set_fixed_ie23a(pframe, _STATUS_CODE_,
3094                                              (unsigned char *)&val16,
3095                                              &pattrib->pktlen);
3096
3097                 /*  then checking to see if sending challenging text... */
3098                 if ((pmlmeinfo->auth_seq == 3) &&
3099                     (pmlmeinfo->state & WIFI_FW_AUTH_STATE) &&
3100                     (use_shared_key == 1)) {
3101                         pframe = rtw_set_ie23a(pframe, WLAN_EID_CHALLENGE, 128,
3102                                                pmlmeinfo->chg_txt,
3103                                                &pattrib->pktlen);
3104
3105                         SetPrivacy(fctrl);
3106
3107                         pattrib->hdrlen = sizeof(struct ieee80211_hdr_3addr);
3108
3109                         pattrib->encrypt = _WEP40_;
3110
3111                         pattrib->icv_len = 4;
3112
3113                         pattrib->pktlen += pattrib->icv_len;
3114                 }
3115         }
3116
3117         pattrib->last_txcmdsz = pattrib->pktlen;
3118
3119         rtw_wep_encrypt23a(padapter, pmgntframe);
3120         DBG_8723A("%s\n", __func__);
3121         dump_mgntframe23a(padapter, pmgntframe);
3122
3123         return;
3124 }
3125
3126 void issue_asocrsp23a(struct rtw_adapter *padapter, unsigned short status,
3127                       struct sta_info *pstat, int pkt_type)
3128 {
3129 #ifdef CONFIG_8723AU_AP_MODE
3130         struct xmit_frame *pmgntframe;
3131         struct ieee80211_hdr *pwlanhdr;
3132         struct pkt_attrib *pattrib;
3133         unsigned char *pframe;
3134         unsigned short val;
3135         struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
3136         struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
3137         struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
3138         struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
3139         struct wlan_bssid_ex *pnetwork = &pmlmeinfo->network;
3140         const u8 *p;
3141         u8 *ie = pnetwork->IEs;
3142
3143         DBG_8723A("%s\n", __func__);
3144
3145         pmgntframe = alloc_mgtxmitframe23a(pxmitpriv);
3146         if (!pmgntframe)
3147                 return;
3148
3149         /* update attribute */
3150         pattrib = &pmgntframe->attrib;
3151         update_mgntframe_attrib23a(padapter, pattrib);
3152
3153         memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
3154
3155         pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
3156         pwlanhdr = (struct ieee80211_hdr *)pframe;
3157
3158         pwlanhdr->frame_control = 0;
3159
3160         ether_addr_copy(pwlanhdr->addr1, pstat->hwaddr);
3161         ether_addr_copy(pwlanhdr->addr2, myid(&padapter->eeprompriv));
3162         ether_addr_copy(pwlanhdr->addr3, get_my_bssid23a(&pmlmeinfo->network));
3163
3164         SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
3165         pmlmeext->mgnt_seq++;
3166         if (pkt_type == WIFI_ASSOCRSP || pkt_type == WIFI_REASSOCRSP)
3167                 SetFrameSubType(pwlanhdr, pkt_type);
3168         else
3169                 return;
3170
3171         pattrib->hdrlen = sizeof(struct ieee80211_hdr_3addr);
3172         pattrib->pktlen += pattrib->hdrlen;
3173         pframe += pattrib->hdrlen;
3174
3175         /* capability */
3176         val = *(unsigned short *)rtw_get_capability23a_from_ie(ie);
3177
3178         pframe = rtw_set_fixed_ie23a(pframe, _CAPABILITY_,
3179                                      (unsigned char *)&val, &pattrib->pktlen);
3180
3181         status = cpu_to_le16(status);
3182         pframe = rtw_set_fixed_ie23a(pframe, _STATUS_CODE_,
3183                                      (unsigned char *)&status,
3184                                      &pattrib->pktlen);
3185
3186         val = cpu_to_le16(pstat->aid | BIT(14) | BIT(15));
3187         pframe = rtw_set_fixed_ie23a(pframe, _ASOC_ID_, (unsigned char *)&val,
3188                                      &pattrib->pktlen);
3189
3190         if (pstat->bssratelen <= 8) {
3191                 pframe = rtw_set_ie23a(pframe, WLAN_EID_SUPP_RATES,
3192                                        pstat->bssratelen, pstat->bssrateset,
3193                                        &pattrib->pktlen);
3194         } else {
3195                 pframe = rtw_set_ie23a(pframe, WLAN_EID_SUPP_RATES, 8,
3196                                        pstat->bssrateset, &pattrib->pktlen);
3197                 pframe = rtw_set_ie23a(pframe, WLAN_EID_EXT_SUPP_RATES,
3198                                        pstat->bssratelen - 8,
3199                                        pstat->bssrateset + 8, &pattrib->pktlen);
3200         }
3201
3202         if (pstat->flags & WLAN_STA_HT && pmlmepriv->htpriv.ht_option) {
3203                 /* FILL HT CAP INFO IE */
3204                 /* p = hostapd_eid_ht_capabilities_info(hapd, p); */
3205                 p = cfg80211_find_ie(WLAN_EID_HT_CAPABILITY,
3206                                      ie + _BEACON_IE_OFFSET_,
3207                                      pnetwork->IELength -_BEACON_IE_OFFSET_);
3208                 if (p && p[1]) {
3209                         memcpy(pframe, p, p[1] + 2);
3210                         pframe += (p[1] + 2);
3211                         pattrib->pktlen += (p[1] + 2);
3212                 }
3213
3214                 /* FILL HT ADD INFO IE */
3215                 /* p = hostapd_eid_ht_operation(hapd, p); */
3216                 p = cfg80211_find_ie(WLAN_EID_HT_OPERATION,
3217                                      ie + _BEACON_IE_OFFSET_,
3218                                      pnetwork->IELength - _BEACON_IE_OFFSET_);
3219                 if (p && p[1] > 0) {
3220                         memcpy(pframe, p, p[1] + 2);
3221                         pframe += (p[1] + 2);
3222                         pattrib->pktlen += (p[1] + 2);
3223                 }
3224         }
3225
3226         /* FILL WMM IE */
3227         if (pstat->flags & WLAN_STA_WME && pmlmepriv->qos_option) {
3228                 unsigned char WMM_PARA_IE[] = {0x00, 0x50, 0xf2, 0x02,
3229                                                0x01, 0x01};
3230                 int ie_len = 0;
3231
3232                 for (p = ie + _BEACON_IE_OFFSET_; ; p += (ie_len + 2)) {
3233                         p = cfg80211_find_ie(WLAN_EID_VENDOR_SPECIFIC, p,
3234                                              pnetwork->IELength -
3235                                              _BEACON_IE_OFFSET_ - (ie_len + 2));
3236                         if (p)
3237                                 ie_len = p[1];
3238                         else
3239                                 ie_len = 0;
3240                         if (p && !memcmp(p + 2, WMM_PARA_IE, 6)) {
3241                                 memcpy(pframe, p, ie_len + 2);
3242                                 pframe += (ie_len + 2);
3243                                 pattrib->pktlen += (ie_len + 2);
3244
3245                                 break;
3246                         }
3247
3248                         if (!p || ie_len == 0)
3249                                 break;
3250                 }
3251         }
3252
3253         if (pmlmeinfo->assoc_AP_vendor == HT_IOT_PEER_REALTEK) {
3254                 pframe = rtw_set_ie23a(pframe, WLAN_EID_VENDOR_SPECIFIC, 6,
3255                                        REALTEK_96B_IE, &pattrib->pktlen);
3256         }
3257
3258         /* add WPS IE ie for wps 2.0 */
3259         if (pmlmepriv->wps_assoc_resp_ie &&
3260             pmlmepriv->wps_assoc_resp_ie_len > 0) {
3261                 memcpy(pframe, pmlmepriv->wps_assoc_resp_ie,
3262                        pmlmepriv->wps_assoc_resp_ie_len);
3263
3264                 pframe += pmlmepriv->wps_assoc_resp_ie_len;
3265                 pattrib->pktlen += pmlmepriv->wps_assoc_resp_ie_len;
3266         }
3267
3268         pattrib->last_txcmdsz = pattrib->pktlen;
3269
3270         dump_mgntframe23a(padapter, pmgntframe);
3271 #endif
3272 }
3273
3274 void issue_assocreq23a(struct rtw_adapter *padapter)
3275 {
3276         int ret = _FAIL;
3277         struct xmit_frame *pmgntframe;
3278         struct pkt_attrib *pattrib;
3279         unsigned char *pframe;
3280         const u8 *p;
3281         struct ieee80211_hdr *pwlanhdr;
3282         __le16 *fctrl;
3283         unsigned int i, j, index = 0;
3284         unsigned char rf_type, bssrate[NumRates], sta_bssrate[NumRates];
3285         struct ndis_802_11_var_ies *pIE;
3286         struct registry_priv *pregpriv = &padapter->registrypriv;
3287         struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
3288         struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
3289         struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
3290         struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
3291         int bssrate_len = 0, sta_bssrate_len = 0, pie_len;
3292         u8 * pie;
3293
3294         pmgntframe = alloc_mgtxmitframe23a(pxmitpriv);
3295         if (!pmgntframe)
3296                 goto exit;
3297
3298         /* update attribute */
3299         pattrib = &pmgntframe->attrib;
3300         update_mgntframe_attrib23a(padapter, pattrib);
3301
3302         memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
3303
3304         pframe = (u8 *)pmgntframe->buf_addr + TXDESC_OFFSET;
3305         pwlanhdr = (struct ieee80211_hdr *)pframe;
3306
3307         fctrl = &pwlanhdr->frame_control;
3308         *fctrl = 0;
3309         ether_addr_copy(pwlanhdr->addr1, get_my_bssid23a(&pmlmeinfo->network));
3310         ether_addr_copy(pwlanhdr->addr2, myid(&padapter->eeprompriv));
3311         ether_addr_copy(pwlanhdr->addr3, get_my_bssid23a(&pmlmeinfo->network));
3312
3313         SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
3314         pmlmeext->mgnt_seq++;
3315         SetFrameSubType(pframe, WIFI_ASSOCREQ);
3316
3317         pframe += sizeof(struct ieee80211_hdr_3addr);
3318         pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr);
3319
3320         /* caps */
3321         memcpy(pframe,
3322                rtw_get_capability23a_from_ie(pmlmeinfo->network.IEs), 2);
3323
3324         pframe += 2;
3325         pattrib->pktlen += 2;
3326
3327         /* listen interval */
3328         /* todo: listen interval for power saving */
3329         put_unaligned_le16(3, pframe);
3330         pframe += 2;
3331         pattrib->pktlen += 2;
3332
3333         /* SSID */
3334         pframe = rtw_set_ie23a(pframe, WLAN_EID_SSID,
3335                                pmlmeinfo->network.Ssid.ssid_len,
3336                                pmlmeinfo->network.Ssid.ssid, &pattrib->pktlen);
3337
3338         /* supported rate & extended supported rate */
3339
3340         get_rate_set23a(padapter, sta_bssrate, &sta_bssrate_len);
3341         /* DBG_8723A("sta_bssrate_len =%d\n", sta_bssrate_len); */
3342
3343         /*  for JAPAN, channel 14 can only uses B Mode(CCK) */
3344         if (pmlmeext->cur_channel == 14)
3345                 sta_bssrate_len = 4;
3346
3347         /* for (i = 0; i < sta_bssrate_len; i++) { */
3348         /*      DBG_8723A("sta_bssrate[%d]=%02X\n", i, sta_bssrate[i]); */
3349         /*  */
3350
3351         for (i = 0; i < NDIS_802_11_LENGTH_RATES_EX; i++) {
3352                 if (pmlmeinfo->network.SupportedRates[i] == 0)
3353                         break;
3354                 DBG_8723A("network.SupportedRates[%d]=%02X\n", i,
3355                           pmlmeinfo->network.SupportedRates[i]);
3356         }
3357
3358         for (i = 0; i < NDIS_802_11_LENGTH_RATES_EX; i++) {
3359                 if (pmlmeinfo->network.SupportedRates[i] == 0)
3360                         break;
3361
3362                 /*  Check if the AP's supported rates are also
3363                     supported by STA. */
3364                 for (j = 0; j < sta_bssrate_len; j++) {
3365                          /*  Avoid the proprietary data rate (22Mbps) of
3366                              Handlink WSG-4000 AP */
3367                         if ((pmlmeinfo->network.SupportedRates[i] |
3368                              IEEE80211_BASIC_RATE_MASK) ==
3369                             (sta_bssrate[j] | IEEE80211_BASIC_RATE_MASK)) {
3370                                 /* DBG_8723A("match i = %d, j =%d\n", i, j); */
3371                                 break;
3372                         }
3373                 }
3374
3375                 if (j == sta_bssrate_len) {
3376                         /*  the rate is not supported by STA */
3377                         DBG_8723A("%s(): the rate[%d]=%02X is not supported by "
3378                                   "STA!\n", __func__, i,
3379                                   pmlmeinfo->network.SupportedRates[i]);
3380                 } else {
3381                         /*  the rate is supported by STA */
3382                         bssrate[index++] = pmlmeinfo->network.SupportedRates[i];
3383                 }
3384         }
3385
3386         bssrate_len = index;
3387         DBG_8723A("bssrate_len = %d\n", bssrate_len);
3388
3389         if (bssrate_len == 0) {
3390                 rtw_free_xmitbuf23a(pxmitpriv, pmgntframe->pxmitbuf);
3391                 rtw_free_xmitframe23a(pxmitpriv, pmgntframe);
3392                 goto exit; /* don't connect to AP if no joint supported rate */
3393         }
3394
3395         if (bssrate_len > 8) {
3396                 pframe = rtw_set_ie23a(pframe, WLAN_EID_SUPP_RATES, 8,
3397                                        bssrate, &pattrib->pktlen);
3398                 pframe = rtw_set_ie23a(pframe, WLAN_EID_EXT_SUPP_RATES,
3399                                        (bssrate_len - 8), (bssrate + 8),
3400                                        &pattrib->pktlen);
3401         } else
3402                 pframe = rtw_set_ie23a(pframe, WLAN_EID_SUPP_RATES,
3403                                        bssrate_len, bssrate, &pattrib->pktlen);
3404
3405         /* RSN */
3406         pie = pmlmeinfo->network.IEs + sizeof(struct ndis_802_11_fixed_ies);
3407         pie_len = pmlmeinfo->network.IELength -
3408                 sizeof(struct ndis_802_11_fixed_ies);
3409
3410         p = cfg80211_find_ie(WLAN_EID_RSN, pie, pie_len);
3411         if (p)
3412                 pframe = rtw_set_ie23a(pframe, WLAN_EID_RSN, p[1], p + 2,
3413                                        &pattrib->pktlen);
3414
3415         /* HT caps */
3416         if (padapter->mlmepriv.htpriv.ht_option == true) {
3417                 p = cfg80211_find_ie(WLAN_EID_HT_CAPABILITY, pie, pie_len);
3418
3419                 if (p && !is_ap_in_tkip23a(padapter)) {
3420                         memcpy(&pmlmeinfo->HT_caps, p + 2,
3421                                sizeof(struct HT_caps_element));
3422
3423                         /* to disable 40M Hz support while gd_bw_40MHz_en = 0 */
3424                         if (pregpriv->cbw40_enable == 0) {
3425                                 pmlmeinfo->HT_caps.u.HT_cap_element.HT_caps_info &= (~(BIT(6) | BIT(1)));
3426                         } else {
3427                                 pmlmeinfo->HT_caps.u.HT_cap_element.HT_caps_info |= BIT(1);
3428                         }
3429
3430                         /* todo: disable SM power save mode */
3431                         pmlmeinfo->HT_caps.u.HT_cap_element.HT_caps_info |=
3432                                 0x000c;
3433
3434                         rf_type = rtl8723a_get_rf_type(padapter);
3435                         /* switch (pregpriv->rf_config) */
3436                         switch (rf_type) {
3437                         case RF_1T1R:
3438                                 /* RX STBC One spatial stream */
3439                                 if (pregpriv->rx_stbc)
3440                                         pmlmeinfo->HT_caps.u.HT_cap_element.HT_caps_info |= cpu_to_le16(0x0100);
3441
3442                                 memcpy(pmlmeinfo->HT_caps.u.HT_cap_element.MCS_rate, MCS_rate_1R23A, 16);
3443                                 break;
3444
3445                         case RF_2T2R:
3446                         case RF_1T2R:
3447                         default:
3448                                 /* enable for 2.4/5 GHz */
3449                                 if (pregpriv->rx_stbc == 0x3 ||
3450                                     (pmlmeext->cur_wireless_mode &
3451                                      WIRELESS_11_24N &&
3452                                      /* enable for 2.4GHz */
3453                                      pregpriv->rx_stbc == 0x1) ||
3454                                     (pmlmeext->cur_wireless_mode &
3455                                      WIRELESS_11_5N &&
3456                                      pregpriv->rx_stbc == 0x2) ||
3457                                     /* enable for 5GHz */
3458                                     pregpriv->wifi_spec == 1) {
3459                                         DBG_8723A("declare supporting RX "
3460                                                   "STBC\n");
3461                                         pmlmeinfo->HT_caps.u.HT_cap_element.HT_caps_info |= cpu_to_le16(0x0200);/* RX STBC two spatial stream */
3462                                 }
3463                                 memcpy(pmlmeinfo->HT_caps.u.HT_cap_element.MCS_rate, MCS_rate_2R23A, 16);
3464                                 break;
3465                         }
3466                         pmlmeinfo->HT_caps.u.HT_cap_element.HT_caps_info =
3467                                 cpu_to_le16(pmlmeinfo->HT_caps.u.HT_cap_element.HT_caps_info);
3468
3469 #ifdef CONFIG_8723AU_BT_COEXIST
3470                         if (BT_1Ant(padapter) == true) {
3471                                 /*  set to 8K */
3472                                 pmlmeinfo->HT_caps.u.HT_cap_element.AMPDU_para &= (u8)~IEEE80211_HT_AMPDU_PARM_FACTOR;
3473 /*                              pmlmeinfo->HT_caps.u.HT_cap_element.AMPDU_para |= MAX_AMPDU_FACTOR_8K */
3474                         }
3475 #endif
3476
3477                         pframe = rtw_set_ie23a(pframe, WLAN_EID_HT_CAPABILITY,
3478                                                p[1], (u8 *)&pmlmeinfo->HT_caps,
3479                                                &pattrib->pktlen);
3480                 }
3481         }
3482
3483         /* vendor specific IE, such as WPA, WMM, WPS */
3484         for (i = sizeof(struct ndis_802_11_fixed_ies);
3485              i < pmlmeinfo->network.IELength;) {
3486                 pIE = (struct ndis_802_11_var_ies *)
3487                         (pmlmeinfo->network.IEs + i);
3488
3489                 switch (pIE->ElementID)
3490                 {
3491                 case WLAN_EID_VENDOR_SPECIFIC:
3492                         if (!memcmp(pIE->data, RTW_WPA_OUI23A_TYPE, 4) ||
3493                             !memcmp(pIE->data, WMM_OUI23A, 4) ||
3494                             !memcmp(pIE->data, WPS_OUI23A, 4)) {
3495                                 if (!padapter->registrypriv.wifi_spec) {
3496                                         /* Commented by Kurt 20110629 */
3497                                         /* In some older APs, WPS handshake */
3498                                         /* would be fail if we append vender
3499                                            extensions informations to AP */
3500                                         if (!memcmp(pIE->data, WPS_OUI23A, 4))
3501                                                 pIE->Length = 14;
3502                                 }
3503                                 pframe = rtw_set_ie23a(pframe,
3504                                                        WLAN_EID_VENDOR_SPECIFIC,
3505                                                        pIE->Length, pIE->data,
3506                                                        &pattrib->pktlen);
3507                         }
3508                         break;
3509
3510                 default:
3511                         break;
3512                 }
3513
3514                 i += pIE->Length + 2;
3515         }
3516
3517         if (pmlmeinfo->assoc_AP_vendor == HT_IOT_PEER_REALTEK)
3518                 pframe = rtw_set_ie23a(pframe, WLAN_EID_VENDOR_SPECIFIC, 6,
3519                                        REALTEK_96B_IE, &pattrib->pktlen);
3520
3521         pattrib->last_txcmdsz = pattrib->pktlen;
3522         dump_mgntframe23a(padapter, pmgntframe);
3523
3524         ret = _SUCCESS;
3525
3526 exit:
3527         pmlmepriv->assoc_req_len = 0;
3528         if (ret == _SUCCESS) {
3529                 kfree(pmlmepriv->assoc_req);
3530                 pmlmepriv->assoc_req = kmalloc(pattrib->pktlen, GFP_ATOMIC);
3531                 if (pmlmepriv->assoc_req) {
3532                         memcpy(pmlmepriv->assoc_req, pwlanhdr, pattrib->pktlen);
3533                         pmlmepriv->assoc_req_len = pattrib->pktlen;
3534                 }
3535         } else
3536                 kfree(pmlmepriv->assoc_req);
3537
3538         return;
3539 }
3540
3541 /* when wait_ack is ture, this function shoule be called at process context */
3542 static int _issue_nulldata23a(struct rtw_adapter *padapter, unsigned char *da,
3543                               unsigned int power_mode, int wait_ack)
3544 {
3545         int ret = _FAIL;
3546         struct xmit_frame *pmgntframe;
3547         struct pkt_attrib *pattrib;
3548         unsigned char *pframe;
3549         struct ieee80211_hdr *pwlanhdr;
3550         __le16 *fctrl;
3551         struct xmit_priv *pxmitpriv;
3552         struct mlme_ext_priv *pmlmeext;
3553         struct mlme_ext_info *pmlmeinfo;
3554
3555         /* DBG_8723A("%s:%d\n", __func__, power_mode); */
3556
3557         if (!padapter)
3558                 goto exit;
3559
3560         pxmitpriv = &padapter->xmitpriv;
3561         pmlmeext = &padapter->mlmeextpriv;
3562         pmlmeinfo = &pmlmeext->mlmext_info;
3563
3564         if ((pmgntframe = alloc_mgtxmitframe23a(pxmitpriv)) == NULL)
3565                 goto exit;
3566
3567         /* update attribute */
3568         pattrib = &pmgntframe->attrib;
3569         update_mgntframe_attrib23a(padapter, pattrib);
3570         pattrib->retry_ctrl = false;
3571
3572         memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
3573
3574         pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
3575         pwlanhdr = (struct ieee80211_hdr *)pframe;
3576
3577         fctrl = &pwlanhdr->frame_control;
3578         *fctrl = 0;
3579
3580         if ((pmlmeinfo->state&0x03) == WIFI_FW_AP_STATE)
3581                 SetFrDs(fctrl);
3582         else if ((pmlmeinfo->state&0x03) == WIFI_FW_STATION_STATE)
3583                 SetToDs(fctrl);
3584
3585         if (power_mode)
3586                 SetPwrMgt(fctrl);
3587
3588         ether_addr_copy(pwlanhdr->addr1, da);
3589         ether_addr_copy(pwlanhdr->addr2, myid(&padapter->eeprompriv));
3590         ether_addr_copy(pwlanhdr->addr3, get_my_bssid23a(&pmlmeinfo->network));
3591
3592         SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
3593         pmlmeext->mgnt_seq++;
3594         SetFrameSubType(pframe, WIFI_DATA_NULL);
3595
3596         pframe += sizeof(struct ieee80211_hdr_3addr);
3597         pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr);
3598
3599         pattrib->last_txcmdsz = pattrib->pktlen;
3600
3601         if (wait_ack)
3602                 ret = dump_mgntframe23a_and_wait_ack23a(padapter, pmgntframe);
3603         else {
3604                 dump_mgntframe23a(padapter, pmgntframe);
3605                 ret = _SUCCESS;
3606         }
3607
3608 exit:
3609         return ret;
3610 }
3611
3612 /* when wait_ms >0 , this function shoule be called at process context */
3613 /* da == NULL for station mode */
3614 int issue_nulldata23a(struct rtw_adapter *padapter, unsigned char *da,
3615                       unsigned int power_mode, int try_cnt, int wait_ms)
3616 {
3617         int ret;
3618         int i = 0;
3619         unsigned long start = jiffies;
3620         struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
3621         struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
3622
3623         /* da == NULL, assum it's null data for sta to ap*/
3624         if (da == NULL)
3625                 da = get_my_bssid23a(&pmlmeinfo->network);
3626
3627         do {
3628                 ret = _issue_nulldata23a(padapter, da, power_mode,
3629                                          wait_ms > 0 ? true : false);
3630
3631                 i++;
3632
3633                 if (padapter->bDriverStopped || padapter->bSurpriseRemoved)
3634                         break;
3635
3636                 if (i < try_cnt && wait_ms > 0 && ret == _FAIL)
3637                         msleep(wait_ms);
3638
3639         } while((i < try_cnt) && ((ret == _FAIL) || (wait_ms == 0)));
3640
3641         if (ret != _FAIL) {
3642                 ret = _SUCCESS;
3643                 goto exit;
3644         }
3645
3646         if (try_cnt && wait_ms) {
3647                 if (da)
3648                         DBG_8723A("%s(%s): to "MAC_FMT", ch:%u%s, %d/%d "
3649                                   "in %u ms\n", __func__,
3650                                   padapter->pnetdev->name,
3651                                   MAC_ARG(da), rtw_get_oper_ch23a(padapter),
3652                                   ret == _SUCCESS?", acked":"", i, try_cnt,
3653                                   jiffies_to_msecs(jiffies - start));
3654                 else
3655                         DBG_8723A("%s(%s):, ch:%u%s, %d/%d in %u ms\n",
3656                                   __func__, padapter->pnetdev->name,
3657                                   rtw_get_oper_ch23a(padapter),
3658                                   ret == _SUCCESS?", acked":"", i, try_cnt,
3659                                   jiffies_to_msecs(jiffies - start));
3660         }
3661 exit:
3662         return ret;
3663 }
3664
3665 /* when wait_ack is ture, this function shoule be called at process context */
3666 static int _issue_qos_nulldata23a(struct rtw_adapter *padapter,
3667                                   unsigned char *da, u16 tid, int wait_ack)
3668 {
3669         int ret = _FAIL;
3670         struct xmit_frame *pmgntframe;
3671         struct pkt_attrib *pattrib;
3672         unsigned char *pframe;
3673         struct ieee80211_hdr *pwlanhdr;
3674         __le16 *fctrl;
3675         u16 *qc;
3676         struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
3677         struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
3678         struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
3679
3680         DBG_8723A("%s\n", __func__);
3681
3682         if ((pmgntframe = alloc_mgtxmitframe23a(pxmitpriv)) == NULL)
3683                 goto exit;
3684
3685         /* update attribute */
3686         pattrib = &pmgntframe->attrib;
3687         update_mgntframe_attrib23a(padapter, pattrib);
3688
3689         pattrib->hdrlen += 2;
3690         pattrib->qos_en = true;
3691         pattrib->eosp = 1;
3692         pattrib->ack_policy = 0;
3693         pattrib->mdata = 0;
3694
3695         memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
3696
3697         pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
3698         pwlanhdr = (struct ieee80211_hdr *)pframe;
3699
3700         fctrl = &pwlanhdr->frame_control;
3701         *fctrl = 0;
3702
3703         if ((pmlmeinfo->state&0x03) == WIFI_FW_AP_STATE)
3704                 SetFrDs(fctrl);
3705         else if ((pmlmeinfo->state&0x03) == WIFI_FW_STATION_STATE)
3706                 SetToDs(fctrl);
3707
3708         if (pattrib->mdata)
3709                 SetMData(fctrl);
3710
3711         qc = (unsigned short *)(pframe + pattrib->hdrlen - 2);
3712
3713         SetPriority(qc, tid);
3714
3715         SetEOSP(qc, pattrib->eosp);
3716
3717         SetAckpolicy(qc, pattrib->ack_policy);
3718
3719         ether_addr_copy(pwlanhdr->addr1, da);
3720         ether_addr_copy(pwlanhdr->addr2, myid(&padapter->eeprompriv));
3721         ether_addr_copy(pwlanhdr->addr3, get_my_bssid23a(&pmlmeinfo->network));
3722
3723         SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
3724         pmlmeext->mgnt_seq++;
3725         SetFrameSubType(pframe, WIFI_QOS_DATA_NULL);
3726
3727         pframe += sizeof(struct ieee80211_qos_hdr);
3728         pattrib->pktlen = sizeof(struct ieee80211_qos_hdr);
3729
3730         pattrib->last_txcmdsz = pattrib->pktlen;
3731
3732         if (wait_ack)
3733                 ret = dump_mgntframe23a_and_wait_ack23a(padapter, pmgntframe);
3734         else {
3735                 dump_mgntframe23a(padapter, pmgntframe);
3736                 ret = _SUCCESS;
3737         }
3738
3739 exit:
3740         return ret;
3741 }
3742
3743 /* when wait_ms >0 , this function shoule be called at process context */
3744 /* da == NULL for station mode */
3745 int issue_qos_nulldata23a(struct rtw_adapter *padapter, unsigned char *da,
3746                           u16 tid, int try_cnt, int wait_ms)
3747 {
3748         int ret;
3749         int i = 0;
3750         unsigned long start = jiffies;
3751         struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
3752         struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
3753
3754         /* da == NULL, assum it's null data for sta to ap*/
3755         if (da == NULL)
3756                 da = get_my_bssid23a(&pmlmeinfo->network);
3757
3758         do {
3759                 ret = _issue_qos_nulldata23a(padapter, da, tid,
3760                                              wait_ms > 0 ? true : false);
3761
3762                 i++;
3763
3764                 if (padapter->bDriverStopped || padapter->bSurpriseRemoved)
3765                         break;
3766
3767                 if (i < try_cnt && wait_ms > 0 && ret == _FAIL)
3768                         msleep(wait_ms);
3769         } while((i < try_cnt) && ((ret == _FAIL)||(wait_ms == 0)));
3770
3771         if (ret != _FAIL) {
3772                 ret = _SUCCESS;
3773                 goto exit;
3774         }
3775
3776         if (try_cnt && wait_ms) {
3777                 if (da)
3778                         DBG_8723A("%s(%s): to "MAC_FMT", ch:%u%s, %d/%d "
3779                                   "in %u ms\n", __func__,
3780                                   padapter->pnetdev->name,
3781                                   MAC_ARG(da), rtw_get_oper_ch23a(padapter),
3782                                   ret == _SUCCESS?", acked":"", i, try_cnt,
3783                                   jiffies_to_msecs(jiffies - start));
3784                 else
3785                         DBG_8723A("%s(%s):, ch:%u%s, %d/%d in %u ms\n",
3786                                   __func__, padapter->pnetdev->name,
3787                                   rtw_get_oper_ch23a(padapter),
3788                                   ret == _SUCCESS?", acked":"", i, try_cnt,
3789                                   jiffies_to_msecs(jiffies - start));
3790         }
3791 exit:
3792         return ret;
3793 }
3794
3795 static int _issue_deauth23a(struct rtw_adapter *padapter, unsigned char *da,
3796                             unsigned short reason, u8 wait_ack)
3797 {
3798         struct xmit_frame *pmgntframe;
3799         struct pkt_attrib *pattrib;
3800         unsigned char *pframe;
3801         struct ieee80211_hdr *pwlanhdr;
3802         __le16 *fctrl;
3803         struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
3804         struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
3805         struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
3806         int ret = _FAIL;
3807
3808         /* DBG_8723A("%s to "MAC_FMT"\n", __func__, MAC_ARG(da)); */
3809
3810         if ((pmgntframe = alloc_mgtxmitframe23a(pxmitpriv)) == NULL)
3811                 goto exit;
3812
3813         /* update attribute */
3814         pattrib = &pmgntframe->attrib;
3815         update_mgntframe_attrib23a(padapter, pattrib);
3816         pattrib->retry_ctrl = false;
3817
3818         memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
3819
3820         pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
3821         pwlanhdr = (struct ieee80211_hdr *)pframe;
3822
3823         fctrl = &pwlanhdr->frame_control;
3824         *fctrl = 0;
3825
3826         ether_addr_copy(pwlanhdr->addr1, da);
3827         ether_addr_copy(pwlanhdr->addr2, myid(&padapter->eeprompriv));
3828         ether_addr_copy(pwlanhdr->addr3, get_my_bssid23a(&pmlmeinfo->network));
3829
3830         SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
3831         pmlmeext->mgnt_seq++;
3832         SetFrameSubType(pframe, WIFI_DEAUTH);
3833
3834         pframe += sizeof(struct ieee80211_hdr_3addr);
3835         pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr);
3836
3837         reason = cpu_to_le16(reason);
3838         pframe = rtw_set_fixed_ie23a(pframe, WLAN_REASON_PREV_AUTH_NOT_VALID,
3839                                      (unsigned char *)&reason,
3840                                      &pattrib->pktlen);
3841
3842         pattrib->last_txcmdsz = pattrib->pktlen;
3843
3844         if (wait_ack)
3845                 ret = dump_mgntframe23a_and_wait_ack23a(padapter, pmgntframe);
3846         else {
3847                 dump_mgntframe23a(padapter, pmgntframe);
3848                 ret = _SUCCESS;
3849         }
3850
3851 exit:
3852         return ret;
3853 }
3854
3855 int issue_deauth23a(struct rtw_adapter *padapter, unsigned char *da,
3856                     unsigned short reason)
3857 {
3858         DBG_8723A("%s to "MAC_FMT"\n", __func__, MAC_ARG(da));
3859         return _issue_deauth23a(padapter, da, reason, false);
3860 }
3861
3862 int issue_deauth23a_ex23a(struct rtw_adapter *padapter, u8 *da,
3863                           unsigned short reason, int try_cnt, int wait_ms)
3864 {
3865         int ret;
3866         int i = 0;
3867         unsigned long start = jiffies;
3868
3869         do {
3870                 ret = _issue_deauth23a(padapter, da, reason,
3871                                        wait_ms >0 ? true : false);
3872
3873                 i++;
3874
3875                 if (padapter->bDriverStopped || padapter->bSurpriseRemoved)
3876                         break;
3877
3878                 if (i < try_cnt && wait_ms > 0 && ret == _FAIL)
3879                         msleep(wait_ms);
3880
3881         } while((i < try_cnt) && ((ret == _FAIL)||(wait_ms == 0)));
3882
3883         if (ret != _FAIL) {
3884                 ret = _SUCCESS;
3885                 goto exit;
3886         }
3887
3888         if (try_cnt && wait_ms) {
3889                 if (da)
3890                         DBG_8723A("%s(%s): to "MAC_FMT", ch:%u%s, %d/%d "
3891                                   "in %u ms\n", __func__,
3892                                   padapter->pnetdev->name,
3893                                   MAC_ARG(da), rtw_get_oper_ch23a(padapter),
3894                                   ret == _SUCCESS?", acked":"", i, try_cnt,
3895                                   jiffies_to_msecs(jiffies - start));
3896                 else
3897                         DBG_8723A("%s(%s):, ch:%u%s, %d/%d in %u ms\n",
3898                                   __func__, padapter->pnetdev->name,
3899                                   rtw_get_oper_ch23a(padapter),
3900                                   ret == _SUCCESS?", acked":"", i, try_cnt,
3901                                   jiffies_to_msecs(jiffies - start));
3902         }
3903 exit:
3904         return ret;
3905 }
3906
3907 void issue_action_spct_ch_switch23a(struct rtw_adapter *padapter,
3908                                     u8 *ra, u8 new_ch, u8 ch_offset)
3909 {
3910         struct xmit_frame *pmgntframe;
3911         struct pkt_attrib *pattrib;
3912         unsigned char *pframe;
3913         struct ieee80211_hdr *pwlanhdr;
3914         __le16 *fctrl;
3915         struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
3916         struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
3917         u8 category, action;
3918
3919         DBG_8723A("%s(%s): ra ="MAC_FMT", ch:%u, offset:%u\n", __func__,
3920                   padapter->pnetdev->name, MAC_ARG(ra), new_ch, ch_offset);
3921
3922         if ((pmgntframe = alloc_mgtxmitframe23a(pxmitpriv)) == NULL)
3923                 return;
3924
3925         /* update attribute */
3926         pattrib = &pmgntframe->attrib;
3927         update_mgntframe_attrib23a(padapter, pattrib);
3928
3929         memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
3930
3931         pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
3932         pwlanhdr = (struct ieee80211_hdr *)pframe;
3933
3934         fctrl = &pwlanhdr->frame_control;
3935         *fctrl = 0;
3936
3937         ether_addr_copy(pwlanhdr->addr1, ra); /* RA */
3938         ether_addr_copy(pwlanhdr->addr2, myid(&padapter->eeprompriv)); /* TA */
3939         ether_addr_copy(pwlanhdr->addr3, ra); /* DA = RA */
3940
3941         SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
3942         pmlmeext->mgnt_seq++;
3943         SetFrameSubType(pframe, WIFI_ACTION);
3944
3945         pframe += sizeof(struct ieee80211_hdr_3addr);
3946         pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr);
3947
3948         /* category, action */
3949         category = WLAN_CATEGORY_SPECTRUM_MGMT;
3950         action = WLAN_ACTION_SPCT_CHL_SWITCH;
3951
3952         pframe = rtw_set_fixed_ie23a(pframe, 1, &category, &pattrib->pktlen);
3953         pframe = rtw_set_fixed_ie23a(pframe, 1, &action, &pattrib->pktlen);
3954
3955         pframe = rtw_set_ie23a_ch_switch (pframe, &pattrib->pktlen, 0,
3956                                           new_ch, 0);
3957         pframe = rtw_set_ie23a_secondary_ch_offset(pframe, &pattrib->pktlen,
3958                 hal_ch_offset_to_secondary_ch_offset23a(ch_offset));
3959
3960         pattrib->last_txcmdsz = pattrib->pktlen;
3961
3962         dump_mgntframe23a(padapter, pmgntframe);
3963 }
3964
3965 void issue_action_BA23a(struct rtw_adapter *padapter,
3966                         const unsigned char *raddr,
3967                         unsigned char action, unsigned short status)
3968 {
3969         u8 category = WLAN_CATEGORY_BACK;
3970         u16 start_seq;
3971         u16 BA_para_set;
3972         u16 reason_code;
3973         u16 BA_timeout_value;
3974         u16 BA_starting_seqctrl;
3975         int max_rx_ampdu_factor;
3976         struct xmit_frame *pmgntframe;
3977         struct pkt_attrib *pattrib;
3978         u8 *pframe;
3979         struct ieee80211_hdr *pwlanhdr;
3980         __le16 *fctrl;
3981         struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
3982         struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
3983         struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
3984         struct sta_info *psta;
3985         struct sta_priv *pstapriv = &padapter->stapriv;
3986         struct registry_priv *pregpriv = &padapter->registrypriv;
3987 #ifdef CONFIG_8723AU_BT_COEXIST
3988         u8 tendaAPMac[] = {0xC8, 0x3A, 0x35};
3989 #endif
3990
3991         DBG_8723A("%s, category =%d, action =%d, status =%d\n",
3992                   __func__, category, action, status);
3993
3994         if ((pmgntframe = alloc_mgtxmitframe23a(pxmitpriv)) == NULL)
3995                 return;
3996
3997         /* update attribute */
3998         pattrib = &pmgntframe->attrib;
3999         update_mgntframe_attrib23a(padapter, pattrib);
4000
4001         memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
4002
4003         pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
4004         pwlanhdr = (struct ieee80211_hdr *)pframe;
4005
4006         fctrl = &pwlanhdr->frame_control;
4007         *fctrl = 0;
4008
4009         /* memcpy(pwlanhdr->addr1, get_my_bssid23a(&pmlmeinfo->network), ETH_ALEN); */
4010         ether_addr_copy(pwlanhdr->addr1, raddr);
4011         ether_addr_copy(pwlanhdr->addr2, myid(&padapter->eeprompriv));
4012         ether_addr_copy(pwlanhdr->addr3, get_my_bssid23a(&pmlmeinfo->network));
4013
4014         SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
4015         pmlmeext->mgnt_seq++;
4016         SetFrameSubType(pframe, WIFI_ACTION);
4017
4018         pframe += sizeof(struct ieee80211_hdr_3addr);
4019         pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr);
4020
4021         pframe = rtw_set_fixed_ie23a(pframe, 1, &category, &pattrib->pktlen);
4022         pframe = rtw_set_fixed_ie23a(pframe, 1, &action, &pattrib->pktlen);
4023
4024         status = cpu_to_le16(status);
4025
4026         if (category != 3)
4027                 goto out;
4028
4029         switch (action)
4030         {
4031         case 0: /* ADDBA req */
4032                 do {
4033                         pmlmeinfo->dialogToken++;
4034                 } while (pmlmeinfo->dialogToken == 0);
4035                 pframe = rtw_set_fixed_ie23a(pframe, 1, &pmlmeinfo->dialogToken,
4036                                              &pattrib->pktlen);
4037
4038 #ifdef CONFIG_8723AU_BT_COEXIST
4039                 if ((BT_1Ant(padapter) == true) &&
4040                     ((pmlmeinfo->assoc_AP_vendor != broadcomAP) ||
4041                      memcmp(raddr, tendaAPMac, 3))) {
4042                         /*  A-MSDU NOT Supported */
4043                         BA_para_set = 0;
4044                         /*  immediate Block Ack */
4045                         BA_para_set |= (1 << 1) &
4046                                 IEEE80211_ADDBA_PARAM_POLICY_MASK;
4047                         /*  TID */
4048                         BA_para_set |= (status << 2) &
4049                                 IEEE80211_ADDBA_PARAM_TID_MASK;
4050                         /*  max buffer size is 8 MSDU */
4051                         BA_para_set |= (8 << 6) &
4052                                 IEEE80211_ADDBA_PARAM_BUF_SIZE_MASK;
4053                 } else
4054 #endif
4055                 {
4056                         /* immediate ack & 64 buffer size */
4057                         BA_para_set = (0x1002 | ((status & 0xf) << 2));
4058                 }
4059                 BA_para_set = cpu_to_le16(BA_para_set);
4060                 pframe = rtw_set_fixed_ie23a(pframe, 2,
4061                                              (unsigned char *)&BA_para_set,
4062                                              &pattrib->pktlen);
4063
4064                 BA_timeout_value = 5000;/*  5ms */
4065                 BA_timeout_value = cpu_to_le16(BA_timeout_value);
4066                 pframe = rtw_set_fixed_ie23a(pframe, 2, (unsigned char *)
4067                                              &BA_timeout_value,
4068                                              &pattrib->pktlen);
4069
4070                 /* if ((psta = rtw_get_stainfo23a(pstapriv,
4071                    pmlmeinfo->network.MacAddress)) != NULL) */
4072                 if ((psta = rtw_get_stainfo23a(pstapriv, raddr))) {
4073                         start_seq = (psta->sta_xmitpriv.txseq_tid[status & 0x07]&0xfff) + 1;
4074
4075                         DBG_8723A("BA_starting_seqctrl = %d for TID =%d\n",
4076                                   start_seq, status & 0x07);
4077
4078                         psta->BA_starting_seqctrl[status & 0x07] = start_seq;
4079
4080                         BA_starting_seqctrl = start_seq << 4;
4081                 }
4082
4083                 BA_starting_seqctrl = cpu_to_le16(BA_starting_seqctrl);
4084                 pframe = rtw_set_fixed_ie23a(pframe, 2, (unsigned char *)&BA_starting_seqctrl, &pattrib->pktlen);
4085                 break;
4086
4087         case 1: /* ADDBA rsp */
4088                 pframe = rtw_set_fixed_ie23a(pframe, 1, &pmlmeinfo->ADDBA_req.dialog_token, &pattrib->pktlen);
4089                 pframe = rtw_set_fixed_ie23a(pframe, 2,
4090                                              (unsigned char *)&status,
4091                                              &pattrib->pktlen);
4092                 rtw_hal_get_def_var23a(padapter, HW_VAR_MAX_RX_AMPDU_FACTOR,
4093                                        &max_rx_ampdu_factor);
4094                 if (max_rx_ampdu_factor == IEEE80211_HT_MAX_AMPDU_64K)
4095                         BA_para_set = ((le16_to_cpu(pmlmeinfo->ADDBA_req.BA_para_set) & 0x3f) | 0x1000); /* 64 buffer size */
4096                 else if (max_rx_ampdu_factor == IEEE80211_HT_MAX_AMPDU_32K)
4097                         BA_para_set = ((le16_to_cpu(pmlmeinfo->ADDBA_req.BA_para_set) & 0x3f) | 0x0800); /* 32 buffer size */
4098                 else if (max_rx_ampdu_factor == IEEE80211_HT_MAX_AMPDU_16K)
4099                         BA_para_set = ((le16_to_cpu(pmlmeinfo->ADDBA_req.BA_para_set) & 0x3f) | 0x0400); /* 16 buffer size */
4100                 else if (max_rx_ampdu_factor == IEEE80211_HT_MAX_AMPDU_8K)
4101                         BA_para_set = ((le16_to_cpu(pmlmeinfo->ADDBA_req.BA_para_set) & 0x3f) | 0x0200); /* 8 buffer size */
4102                 else
4103                         BA_para_set = ((le16_to_cpu(pmlmeinfo->ADDBA_req.BA_para_set) & 0x3f) | 0x1000); /* 64 buffer size */
4104
4105 #ifdef CONFIG_8723AU_BT_COEXIST
4106                 if ((BT_1Ant(padapter) == true) &&
4107                     ((pmlmeinfo->assoc_AP_vendor != broadcomAP) ||
4108                      memcmp(raddr, tendaAPMac, 3))) {
4109                         /*  max buffer size is 8 MSDU */
4110                         BA_para_set &= ~IEEE80211_ADDBA_PARAM_BUF_SIZE_MASK;
4111                         BA_para_set |= (8 << 6) &
4112                                 IEEE80211_ADDBA_PARAM_BUF_SIZE_MASK;
4113                 }
4114 #endif
4115
4116                 if (pregpriv->ampdu_amsdu == 0)/* disabled */
4117                         BA_para_set = cpu_to_le16(BA_para_set & ~BIT(0));
4118                 else if (pregpriv->ampdu_amsdu == 1)/* enabled */
4119                         BA_para_set = cpu_to_le16(BA_para_set | BIT(0));
4120                 else /* auto */
4121                         BA_para_set = cpu_to_le16(BA_para_set);
4122
4123                 pframe = rtw_set_fixed_ie23a(pframe, 2,
4124                                              (unsigned char *)&BA_para_set,
4125                                              &pattrib->pktlen);
4126                 pframe = rtw_set_fixed_ie23a(pframe, 2, (unsigned char *)&pmlmeinfo->ADDBA_req.BA_timeout_value, &pattrib->pktlen);
4127                 break;
4128         case 2:/* DELBA */
4129                 BA_para_set = (status & 0x1F) << 3;
4130                 BA_para_set = cpu_to_le16(BA_para_set);
4131                 pframe = rtw_set_fixed_ie23a(pframe, 2,
4132                                              (unsigned char *)&BA_para_set,
4133                                              &pattrib->pktlen);
4134
4135                 reason_code = 37;/* Requested from peer STA as it does not
4136                                     want to use the mechanism */
4137                 reason_code = cpu_to_le16(reason_code);
4138                 pframe = rtw_set_fixed_ie23a(pframe, 2,
4139                                              (unsigned char *)&reason_code,
4140                                              &pattrib->pktlen);
4141                 break;
4142         default:
4143                 break;
4144         }
4145
4146 out:
4147         pattrib->last_txcmdsz = pattrib->pktlen;
4148
4149         dump_mgntframe23a(padapter, pmgntframe);
4150 }
4151
4152 static void issue_action_BSSCoexistPacket(struct rtw_adapter *padapter)
4153 {
4154         struct list_head *plist, *phead, *ptmp;
4155         unsigned char category, action;
4156         struct xmit_frame *pmgntframe;
4157         struct pkt_attrib *pattrib;
4158         u8 *pframe;
4159         struct ieee80211_hdr *pwlanhdr;
4160         __le16 *fctrl;
4161         struct wlan_network *pnetwork;
4162         struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
4163         struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
4164         struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
4165         struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
4166         struct rtw_queue *queue = &pmlmepriv->scanned_queue;
4167         u8 InfoContent[16] = {0};
4168         u8 ICS[8][15];
4169         int i;
4170
4171         if (pmlmepriv->num_FortyMHzIntolerant == 0 ||
4172             pmlmepriv->num_sta_no_ht == 0)
4173                 return;
4174
4175         if (pmlmeinfo->bwmode_updated)
4176                 return;
4177
4178         DBG_8723A("%s\n", __func__);
4179
4180         category = WLAN_CATEGORY_PUBLIC;
4181         action = ACT_PUBLIC_BSSCOEXIST;
4182
4183         pmgntframe = alloc_mgtxmitframe23a(pxmitpriv);
4184         if (!pmgntframe)
4185                 return;
4186
4187         /* update attribute */
4188         pattrib = &pmgntframe->attrib;
4189         update_mgntframe_attrib23a(padapter, pattrib);
4190
4191         memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
4192
4193         pframe = (u8 *)pmgntframe->buf_addr + TXDESC_OFFSET;
4194         pwlanhdr = (struct ieee80211_hdr *)pframe;
4195
4196         fctrl = &pwlanhdr->frame_control;
4197         *fctrl = 0;
4198
4199         ether_addr_copy(pwlanhdr->addr1, get_my_bssid23a(&pmlmeinfo->network));
4200         ether_addr_copy(pwlanhdr->addr2, myid(&padapter->eeprompriv));
4201         ether_addr_copy(pwlanhdr->addr3, get_my_bssid23a(&pmlmeinfo->network));
4202
4203         SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
4204         pmlmeext->mgnt_seq++;
4205         SetFrameSubType(pframe, WIFI_ACTION);
4206
4207         pframe += sizeof(struct ieee80211_hdr_3addr);
4208         pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr);
4209
4210         pframe = rtw_set_fixed_ie23a(pframe, 1, &category, &pattrib->pktlen);
4211         pframe = rtw_set_fixed_ie23a(pframe, 1, &action, &pattrib->pktlen);
4212
4213         if (pmlmepriv->num_FortyMHzIntolerant > 0) {
4214                 u8 iedata = BIT(2);/* 20 MHz BSS Width Request */
4215
4216                 pframe = rtw_set_ie23a(pframe, WLAN_EID_BSS_COEX_2040, 1,
4217                                        &iedata, &pattrib->pktlen);
4218         }
4219
4220         if (pmlmepriv->num_sta_no_ht <= 0)
4221                 goto out;
4222
4223         memset(ICS, 0, sizeof(ICS));
4224
4225         spin_lock_bh(&pmlmepriv->scanned_queue.lock);
4226
4227         phead = get_list_head(queue);
4228         plist = phead->next;
4229
4230         list_for_each_safe(plist, ptmp, phead) {
4231                 const u8 *p;
4232                 struct wlan_bssid_ex *pbss_network;
4233
4234                 pnetwork = container_of(plist, struct wlan_network, list);
4235
4236                 pbss_network = &pnetwork->network;
4237
4238                 p = cfg80211_find_ie(WLAN_EID_HT_CAPABILITY,
4239                                      pbss_network->IEs + _FIXED_IE_LENGTH_,
4240                                      pbss_network->IELength -_FIXED_IE_LENGTH_);
4241                 if (!p || !p[1]) { /* non-HT */
4242                         if (pbss_network->Configuration.DSConfig <= 0 ||
4243                             pbss_network->Configuration.DSConfig > 14)
4244                                 continue;
4245
4246                         ICS[0][pbss_network->Configuration.DSConfig] = 1;
4247
4248                         if (ICS[0][0] == 0)
4249                                 ICS[0][0] = 1;
4250                 }
4251
4252         }
4253
4254         spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
4255
4256         for (i = 0; i < 8;i++) {
4257                 if (ICS[i][0] == 1) {
4258                         int j, k = 0;
4259
4260                         InfoContent[k] = i;
4261                         /* SET_BSS_INTOLERANT_ELE_REG_CLASS(InfoContent, i); */
4262                         k++;
4263
4264                         for (j = 1; j <= 14; j++) {
4265                                 if (ICS[i][j] == 1) {
4266                                         if (k < 16) {
4267                                                 /* channel number */
4268                                                 InfoContent[k] = j;
4269                                                 k++;
4270                                         }
4271                                 }
4272                         }
4273
4274                         pframe = rtw_set_ie23a(pframe,
4275                                                EID_BSSIntolerantChlReport, k,
4276                                                InfoContent, &pattrib->pktlen);
4277                 }
4278         }
4279
4280 out:
4281         pattrib->last_txcmdsz = pattrib->pktlen;
4282
4283         dump_mgntframe23a(padapter, pmgntframe);
4284 }
4285
4286 unsigned int send_delba23a(struct rtw_adapter *padapter, u8 initiator, u8 *addr)
4287 {
4288         struct sta_priv *pstapriv = &padapter->stapriv;
4289         struct sta_info *psta = NULL;
4290         /* struct recv_reorder_ctrl *preorder_ctrl; */
4291         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
4292         struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
4293         u16 tid;
4294
4295         if ((pmlmeinfo->state&0x03) != WIFI_FW_AP_STATE)
4296                 if (!(pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS))
4297                         return _SUCCESS;
4298
4299         psta = rtw_get_stainfo23a(pstapriv, addr);
4300         if (psta == NULL)
4301                 return _SUCCESS;
4302
4303         if (initiator == 0) {  /*  recipient */
4304                 for (tid = 0; tid < MAXTID; tid++) {
4305                         if (psta->recvreorder_ctrl[tid].enable == true) {
4306                                 DBG_8723A("rx agg disable tid(%d)\n", tid);
4307                                 issue_action_BA23a(padapter, addr, WLAN_ACTION_DELBA, (((tid <<1) |initiator)&0x1F));
4308                                 psta->recvreorder_ctrl[tid].enable = false;
4309                                 psta->recvreorder_ctrl[tid].indicate_seq = 0xffff;
4310                         }
4311                 }
4312         } else if (initiator == 1) { /*  originator */
4313                 for (tid = 0; tid < MAXTID; tid++) {
4314                         if (psta->htpriv.agg_enable_bitmap & BIT(tid)) {
4315                                 DBG_8723A("tx agg disable tid(%d)\n", tid);
4316                                 issue_action_BA23a(padapter, addr, WLAN_ACTION_DELBA, (((tid <<1) |initiator)&0x1F));
4317                                 psta->htpriv.agg_enable_bitmap &= ~BIT(tid);
4318                                 psta->htpriv.candidate_tid_bitmap &= ~BIT(tid);
4319
4320                         }
4321                 }
4322         }
4323         return _SUCCESS;
4324 }
4325
4326 unsigned int send_beacon23a(struct rtw_adapter *padapter)
4327 {
4328         bool    bxmitok;
4329         int     issue = 0;
4330         int poll = 0;
4331         unsigned long start = jiffies;
4332         unsigned int passing_time;
4333
4334         rtl8723a_bcn_valid(padapter);
4335         do {
4336                 issue_beacon23a(padapter, 100);
4337                 issue++;
4338                 do {
4339                         yield();
4340                         bxmitok = rtl8723a_get_bcn_valid(padapter);
4341                         poll++;
4342                 } while ((poll % 10) != 0 && bxmitok == false &&
4343                          !padapter->bSurpriseRemoved &&
4344                          !padapter->bDriverStopped);
4345
4346         } while (!bxmitok && issue<100 && !padapter->bSurpriseRemoved &&
4347                  !padapter->bDriverStopped);
4348
4349         if (padapter->bSurpriseRemoved || padapter->bDriverStopped)
4350                 return _FAIL;
4351
4352         passing_time = jiffies_to_msecs(jiffies - start);
4353
4354         if (!bxmitok) {
4355                 DBG_8723A("%s fail! %u ms\n", __func__, passing_time);
4356                 return _FAIL;
4357         } else {
4358
4359                 if (passing_time > 100 || issue > 3)
4360                         DBG_8723A("%s success, issue:%d, poll:%d, %u ms\n",
4361                                   __func__, issue, poll, passing_time);
4362                 return _SUCCESS;
4363         }
4364 }
4365
4366 /****************************************************************************
4367
4368 Following are some utitity fuctions for WiFi MLME
4369
4370 *****************************************************************************/
4371
4372 bool IsLegal5GChannel(struct rtw_adapter *Adapter, u8 channel)
4373 {
4374
4375         int i = 0;
4376         u8 Channel_5G[45] = {36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58,
4377                 60, 62, 64, 100, 102, 104, 106, 108, 110, 112, 114, 116, 118, 120, 122,
4378                 124, 126, 128, 130, 132, 134, 136, 138, 140, 149, 151, 153, 155, 157, 159,
4379                 161, 163, 165};
4380         for (i = 0; i < sizeof(Channel_5G); i++)
4381                 if (channel == Channel_5G[i])
4382                         return true;
4383         return false;
4384 }
4385
4386 void site_survey23a(struct rtw_adapter *padapter)
4387 {
4388         unsigned char survey_channel = 0;
4389         enum rt_scan_type ScanType = SCAN_PASSIVE;
4390         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
4391         struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
4392         struct rtw_ieee80211_channel *ch;
4393
4394         if (pmlmeext->sitesurvey_res.channel_idx <
4395             pmlmeext->sitesurvey_res.ch_num) {
4396                 ch = &pmlmeext->sitesurvey_res.ch[pmlmeext->sitesurvey_res.channel_idx];
4397                 survey_channel = ch->hw_value;
4398                 ScanType = (ch->flags & IEEE80211_CHAN_NO_IR) ?
4399                         SCAN_PASSIVE : SCAN_ACTIVE;
4400         }
4401
4402         if (survey_channel != 0) {
4403                 /* PAUSE 4-AC Queue when site_survey23a */
4404                 if (pmlmeext->sitesurvey_res.channel_idx == 0)
4405                         set_channel_bwmode23a(padapter, survey_channel,
4406                                               HAL_PRIME_CHNL_OFFSET_DONT_CARE,
4407                                               HT_CHANNEL_WIDTH_20);
4408                 else
4409                         SelectChannel23a(padapter, survey_channel);
4410
4411                 if (ScanType == SCAN_ACTIVE) /* obey the channel plan setting... */
4412                 {
4413                         int i;
4414                         for (i = 0;i<RTW_SSID_SCAN_AMOUNT;i++) {
4415                                 if (pmlmeext->sitesurvey_res.ssid[i].ssid_len) {
4416                                         /* todo: to issue two probe req??? */
4417                                         issue_probereq23a(padapter, &pmlmeext->sitesurvey_res.ssid[i], NULL);
4418                                         /* msleep(SURVEY_TO>>1); */
4419                                         issue_probereq23a(padapter, &pmlmeext->sitesurvey_res.ssid[i], NULL);
4420                                 }
4421                         }
4422
4423                         if (pmlmeext->sitesurvey_res.scan_mode == SCAN_ACTIVE) {
4424                                 /* todo: to issue two probe req??? */
4425                                 issue_probereq23a(padapter, NULL, NULL);
4426                                 /* msleep(SURVEY_TO>>1); */
4427                                 issue_probereq23a(padapter, NULL, NULL);
4428                         }
4429                 }
4430
4431                 set_survey_timer(pmlmeext, pmlmeext->chan_scan_time);
4432         } else {
4433                 /*      channel number is 0 or this channel is not valid. */
4434                 pmlmeext->sitesurvey_res.state = SCAN_COMPLETE;
4435
4436                 /* switch back to the original channel */
4437
4438                 set_channel_bwmode23a(padapter, pmlmeext->cur_channel,
4439                                       pmlmeext->cur_ch_offset,
4440                                       pmlmeext->cur_bwmode);
4441
4442                 /* flush 4-AC Queue after site_survey23a */
4443                 /* val8 = 0; */
4444
4445                 /* config MSR */
4446                 Set_MSR23a(padapter, (pmlmeinfo->state & 0x3));
4447
4448                 /* restore RX GAIN */
4449                 rtl8723a_set_initial_gain(padapter, 0xff);
4450                 /* turn on dynamic functions */
4451                 rtl8723a_odm_support_ability_restore(padapter);
4452
4453                 if (is_client_associated_to_ap23a(padapter) == true)
4454                         issue_nulldata23a(padapter, NULL, 0, 3, 500);
4455
4456                 rtl8723a_mlme_sitesurvey(padapter, 0);
4457
4458                 report_surveydone_event23a(padapter);
4459
4460                 pmlmeext->chan_scan_time = SURVEY_TO;
4461                 pmlmeext->sitesurvey_res.state = SCAN_DISABLE;
4462
4463                 issue_action_BSSCoexistPacket(padapter);
4464                 issue_action_BSSCoexistPacket(padapter);
4465                 issue_action_BSSCoexistPacket(padapter);
4466         }
4467
4468         return;
4469 }
4470
4471 /* collect bss info from Beacon and Probe request/response frames. */
4472 u8 collect_bss_info23a(struct rtw_adapter *padapter,
4473                        struct recv_frame *precv_frame,
4474                        struct wlan_bssid_ex *bssid)
4475 {
4476         int i;
4477         const u8 *p;
4478         struct sk_buff *skb = precv_frame->pkt;
4479         struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *) skb->data;
4480         unsigned int length;
4481         u8 ie_offset;
4482         struct registry_priv *pregistrypriv = &padapter->registrypriv;
4483         struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
4484         struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
4485         u16 capab_info;
4486
4487         length = skb->len - sizeof(struct ieee80211_hdr_3addr);
4488
4489         if (length > MAX_IE_SZ) {
4490                 /* DBG_8723A("IE too long for survey event\n"); */
4491                 return _FAIL;
4492         }
4493
4494         memset(bssid, 0, sizeof(struct wlan_bssid_ex));
4495
4496         if (ieee80211_is_beacon(mgmt->frame_control)) {
4497                 bssid->reserved = 1;
4498                 ie_offset = offsetof(struct ieee80211_mgmt, u.beacon.variable);
4499                 capab_info = mgmt->u.beacon.capab_info;
4500         } else  if (ieee80211_is_probe_req(mgmt->frame_control)) {
4501                 ie_offset = offsetof(struct ieee80211_mgmt,
4502                                      u.probe_req.variable);
4503                 bssid->reserved = 2;
4504                 capab_info = 0;
4505         } else if (ieee80211_is_probe_resp(mgmt->frame_control)) {
4506                 ie_offset = offsetof(struct ieee80211_mgmt,
4507                                      u.probe_resp.variable);
4508                 bssid->reserved = 3;
4509                 capab_info = mgmt->u.probe_resp.capab_info;
4510         } else {
4511                 bssid->reserved = 0;
4512                 ie_offset = offsetof(struct ieee80211_mgmt, u.beacon.variable);
4513                 capab_info = mgmt->u.beacon.capab_info;
4514         }
4515         ie_offset -= offsetof(struct ieee80211_mgmt, u);
4516
4517         bssid->Length = offsetof(struct wlan_bssid_ex, IEs) + length;
4518
4519         /* below is to copy the information element */
4520         bssid->IELength = length;
4521         memcpy(bssid->IEs, &mgmt->u, bssid->IELength);
4522
4523         /* get the signal strength */
4524         /*  in dBM.raw data */
4525         bssid->Rssi = precv_frame->attrib.phy_info.RecvSignalPower;
4526         bssid->PhyInfo.SignalQuality =
4527                 precv_frame->attrib.phy_info.SignalQuality;/* in percentage */
4528         bssid->PhyInfo.SignalStrength =
4529                 precv_frame->attrib.phy_info.SignalStrength;/* in percentage */
4530
4531         /*  checking SSID */
4532         p = cfg80211_find_ie(WLAN_EID_SSID, bssid->IEs + ie_offset,
4533                              bssid->IELength - ie_offset);
4534
4535         if (!p) {
4536                 DBG_8723A("marc: cannot find SSID for survey event\n");
4537                 return _FAIL;
4538         }
4539
4540         if (p[1] > IEEE80211_MAX_SSID_LEN) {
4541                 DBG_8723A("%s()-%d: IE too long (%d) for survey "
4542                           "event\n", __func__, __LINE__, p[1]);
4543                 return _FAIL;
4544         }
4545         memcpy(bssid->Ssid.ssid, p + 2, p[1]);
4546         bssid->Ssid.ssid_len = p[1];
4547
4548         memset(bssid->SupportedRates, 0, NDIS_802_11_LENGTH_RATES_EX);
4549
4550         /* checking rate info... */
4551         i = 0;
4552         p = cfg80211_find_ie(WLAN_EID_SUPP_RATES, bssid->IEs + ie_offset,
4553                              bssid->IELength - ie_offset);
4554         if (p) {
4555                 if (p[1] > NDIS_802_11_LENGTH_RATES_EX) {
4556                         DBG_8723A("%s()-%d: IE too long (%d) for survey "
4557                                   "event\n", __func__, __LINE__, p[1]);
4558                         return _FAIL;
4559                 }
4560                 memcpy(bssid->SupportedRates, p + 2, p[1]);
4561                 i = p[1];
4562         }
4563
4564         p = cfg80211_find_ie(WLAN_EID_EXT_SUPP_RATES, bssid->IEs + ie_offset,
4565                              bssid->IELength - ie_offset);
4566         if (p) {
4567                 if (p[1] > (NDIS_802_11_LENGTH_RATES_EX-i)) {
4568                         DBG_8723A("%s()-%d: IE too long (%d) for survey "
4569                                   "event\n", __func__, __LINE__, p[1]);
4570                         return _FAIL;
4571                 }
4572                 memcpy(bssid->SupportedRates + i, p + 2, p[1]);
4573         }
4574
4575         bssid->NetworkTypeInUse = Ndis802_11OFDM24;
4576
4577         if (bssid->IELength < 12)
4578                 return _FAIL;
4579
4580         /*  Checking for DSConfig */
4581         p = cfg80211_find_ie(WLAN_EID_DS_PARAMS, bssid->IEs + ie_offset,
4582                              bssid->IELength - ie_offset);
4583
4584         bssid->Configuration.DSConfig = 0;
4585         bssid->Configuration.Length = 0;
4586
4587         if (p) {
4588                 bssid->Configuration.DSConfig = p[2];
4589         } else {/*  In 5G, some ap do not have DSSET IE */
4590                 /*  checking HT info for channel */
4591                 p = cfg80211_find_ie(WLAN_EID_HT_OPERATION,
4592                                      bssid->IEs + ie_offset,
4593                                      bssid->IELength - ie_offset);
4594                 if (p) {
4595                         struct HT_info_element *HT_info =
4596                                 (struct HT_info_element *)(p + 2);
4597                         bssid->Configuration.DSConfig =
4598                                 HT_info->primary_channel;
4599                 } else { /*  use current channel */
4600                         bssid->Configuration.DSConfig =
4601                                 rtw_get_oper_ch23a(padapter);
4602                 }
4603         }
4604
4605         if (ieee80211_is_probe_req(mgmt->frame_control)) {
4606                 /*  FIXME */
4607                 bssid->InfrastructureMode = Ndis802_11Infrastructure;
4608                 ether_addr_copy(bssid->MacAddress, mgmt->sa);
4609                 bssid->Privacy = 1;
4610                 return _SUCCESS;
4611         }
4612
4613         memcpy(&bssid->Configuration.BeaconPeriod,
4614                rtw_get_beacon_interval23a_from_ie(bssid->IEs), 2);
4615         bssid->Configuration.BeaconPeriod =
4616                 le32_to_cpu(bssid->Configuration.BeaconPeriod);
4617
4618         if (capab_info & BIT(0)) {
4619                 bssid->InfrastructureMode = Ndis802_11Infrastructure;
4620                 ether_addr_copy(bssid->MacAddress, mgmt->sa);
4621         } else {
4622                 bssid->InfrastructureMode = Ndis802_11IBSS;
4623                 ether_addr_copy(bssid->MacAddress, mgmt->bssid);
4624         }
4625
4626         if (capab_info & BIT(4))
4627                 bssid->Privacy = 1;
4628         else
4629                 bssid->Privacy = 0;
4630
4631         bssid->Configuration.ATIMWindow = 0;
4632
4633         /* 20/40 BSS Coexistence check */
4634         if (pregistrypriv->wifi_spec == 1 &&
4635             pmlmeinfo->bwmode_updated == false) {
4636                 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
4637
4638                 p = cfg80211_find_ie(WLAN_EID_HT_CAPABILITY,
4639                                      bssid->IEs + ie_offset,
4640                                      bssid->IELength - ie_offset);
4641                 if (p && p[1] > 0) {
4642                         struct HT_caps_element *pHT_caps;
4643                         pHT_caps = (struct HT_caps_element *)(p + 2);
4644
4645                         if (pHT_caps->u.HT_cap_element.HT_caps_info & BIT(14))
4646                                 pmlmepriv->num_FortyMHzIntolerant++;
4647                 } else
4648                         pmlmepriv->num_sta_no_ht++;
4649         }
4650
4651
4652         /*  mark bss info receving from nearby channel as SignalQuality 101 */
4653         if (bssid->Configuration.DSConfig != rtw_get_oper_ch23a(padapter))
4654                 bssid->PhyInfo.SignalQuality = 101;
4655
4656         return _SUCCESS;
4657 }
4658
4659 void start_create_ibss23a(struct rtw_adapter* padapter)
4660 {
4661         unsigned short  caps;
4662         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
4663         struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
4664         struct wlan_bssid_ex *pnetwork = &pmlmeinfo->network;
4665         pmlmeext->cur_channel = (u8)pnetwork->Configuration.DSConfig;
4666         pmlmeinfo->bcn_interval = get_beacon_interval23a(pnetwork);
4667
4668         /* update wireless mode */
4669         update_wireless_mode23a(padapter);
4670
4671         /* udpate capability */
4672         caps = rtw_get_capability23a(pnetwork);
4673         update_capinfo23a(padapter, caps);
4674         if (caps&cap_IBSS) {    /* adhoc master */
4675                 rtl8723a_set_sec_cfg(padapter, 0xcf);
4676
4677                 /* switch channel */
4678                 /* SelectChannel23a(padapter, pmlmeext->cur_channel, HAL_PRIME_CHNL_OFFSET_DONT_CARE); */
4679                 set_channel_bwmode23a(padapter, pmlmeext->cur_channel, HAL_PRIME_CHNL_OFFSET_DONT_CARE, HT_CHANNEL_WIDTH_20);
4680
4681                 beacon_timing_control23a(padapter);
4682
4683                 /* set msr to WIFI_FW_ADHOC_STATE */
4684                 pmlmeinfo->state = WIFI_FW_ADHOC_STATE;
4685                 Set_MSR23a(padapter, (pmlmeinfo->state & 0x3));
4686
4687                 /* issue beacon */
4688                 if (send_beacon23a(padapter) == _FAIL)
4689                 {
4690                         RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("issuing beacon frame fail....\n"));
4691
4692                         report_join_res23a(padapter, -1);
4693                         pmlmeinfo->state = WIFI_FW_NULL_STATE;
4694                 }
4695                 else
4696                 {
4697                         hw_var_set_bssid(padapter, padapter->registrypriv.dev_network.MacAddress);
4698                         hw_var_set_mlme_join(padapter, 0);
4699
4700                         report_join_res23a(padapter, 1);
4701                         pmlmeinfo->state |= WIFI_FW_ASSOC_SUCCESS;
4702                 }
4703         }
4704         else
4705         {
4706                 DBG_8723A("start_create_ibss23a, invalid cap:%x\n", caps);
4707                 return;
4708         }
4709 }
4710
4711 void start_clnt_join23a(struct rtw_adapter* padapter)
4712 {
4713         unsigned short  caps;
4714         u8      val8;
4715         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
4716         struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
4717         struct wlan_bssid_ex *pnetwork = &pmlmeinfo->network;
4718         int beacon_timeout;
4719
4720         pmlmeext->cur_channel = (u8)pnetwork->Configuration.DSConfig;
4721         pmlmeinfo->bcn_interval = get_beacon_interval23a(pnetwork);
4722
4723         /* update wireless mode */
4724         update_wireless_mode23a(padapter);
4725
4726         /* udpate capability */
4727         caps = rtw_get_capability23a(pnetwork);
4728         update_capinfo23a(padapter, caps);
4729         if (caps&cap_ESS) {
4730                 /* switch channel */
4731                 set_channel_bwmode23a(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode);
4732
4733                 Set_MSR23a(padapter, WIFI_FW_STATION_STATE);
4734
4735                 val8 = (pmlmeinfo->auth_algo == dot11AuthAlgrthm_8021X) ?
4736                         0xcc: 0xcf;
4737
4738                 rtl8723a_set_sec_cfg(padapter, val8);
4739
4740                 /* switch channel */
4741                 /* set_channel_bwmode23a(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode); */
4742
4743                 /* here wait for receiving the beacon to start auth */
4744                 /* and enable a timer */
4745                 beacon_timeout = decide_wait_for_beacon_timeout23a(pmlmeinfo->bcn_interval);
4746                 set_link_timer(pmlmeext, beacon_timeout);
4747                 mod_timer(&padapter->mlmepriv.assoc_timer, jiffies +
4748                           msecs_to_jiffies((REAUTH_TO * REAUTH_LIMIT) + (REASSOC_TO*REASSOC_LIMIT) + beacon_timeout));
4749                 pmlmeinfo->state = WIFI_FW_AUTH_NULL | WIFI_FW_STATION_STATE;
4750         }
4751         else if (caps&cap_IBSS) {       /* adhoc client */
4752                 Set_MSR23a(padapter, WIFI_FW_ADHOC_STATE);
4753
4754                 rtl8723a_set_sec_cfg(padapter, 0xcf);
4755
4756                 /* switch channel */
4757                 set_channel_bwmode23a(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode);
4758
4759                 beacon_timing_control23a(padapter);
4760
4761                 pmlmeinfo->state = WIFI_FW_ADHOC_STATE;
4762
4763                 report_join_res23a(padapter, 1);
4764         }
4765         else
4766         {
4767                 /* DBG_8723A("marc: invalid cap:%x\n", caps); */
4768                 return;
4769         }
4770 }
4771
4772 void start_clnt_auth23a(struct rtw_adapter* padapter)
4773 {
4774         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
4775         struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
4776
4777         del_timer_sync(&pmlmeext->link_timer);
4778
4779         pmlmeinfo->state &= (~WIFI_FW_AUTH_NULL);
4780         pmlmeinfo->state |= WIFI_FW_AUTH_STATE;
4781
4782         pmlmeinfo->auth_seq = 1;
4783         pmlmeinfo->reauth_count = 0;
4784         pmlmeinfo->reassoc_count = 0;
4785         pmlmeinfo->link_count = 0;
4786         pmlmeext->retry = 0;
4787
4788         /*  Because of AP's not receiving deauth before */
4789         /*  AP may: 1)not response auth or 2)deauth us after link is complete */
4790         /*  issue deauth before issuing auth to deal with the situation */
4791         /*      Commented by Albert 2012/07/21 */
4792         /*      For the Win8 P2P connection, it will be hard to have a successful connection if this Wi-Fi doesn't connect to it. */
4793         issue_deauth23a(padapter, (&pmlmeinfo->network)->MacAddress, WLAN_REASON_DEAUTH_LEAVING);
4794
4795         DBG_8723A_LEVEL(_drv_always_, "start auth\n");
4796         issue_auth23a(padapter, NULL, 0);
4797
4798         set_link_timer(pmlmeext, REAUTH_TO);
4799 }
4800
4801 void start_clnt_assoc23a(struct rtw_adapter* padapter)
4802 {
4803         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
4804         struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
4805
4806         del_timer_sync(&pmlmeext->link_timer);
4807
4808         pmlmeinfo->state &= (~(WIFI_FW_AUTH_NULL | WIFI_FW_AUTH_STATE));
4809         pmlmeinfo->state |= (WIFI_FW_AUTH_SUCCESS | WIFI_FW_ASSOC_STATE);
4810
4811         issue_assocreq23a(padapter);
4812
4813         set_link_timer(pmlmeext, REASSOC_TO);
4814 }
4815
4816 unsigned int receive_disconnect23a(struct rtw_adapter *padapter, unsigned char *MacAddr, unsigned short reason)
4817 {
4818         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
4819         struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
4820
4821         /* check A3 */
4822         if (!ether_addr_equal(MacAddr, get_my_bssid23a(&pmlmeinfo->network)))
4823                 return _SUCCESS;
4824
4825         DBG_8723A("%s\n", __func__);
4826
4827         if ((pmlmeinfo->state&0x03) == WIFI_FW_STATION_STATE)
4828         {
4829                 if (pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS)
4830                 {
4831                         pmlmeinfo->state = WIFI_FW_NULL_STATE;
4832                         report_del_sta_event23a(padapter, MacAddr, reason);
4833
4834                 }
4835                 else if (pmlmeinfo->state & WIFI_FW_LINKING_STATE)
4836                 {
4837                         pmlmeinfo->state = WIFI_FW_NULL_STATE;
4838                         report_join_res23a(padapter, -2);
4839                 }
4840         }
4841
4842         return _SUCCESS;
4843 }
4844
4845 static void process_80211d(struct rtw_adapter *padapter,
4846                            struct wlan_bssid_ex *bssid)
4847 {
4848         struct registry_priv *pregistrypriv;
4849         struct mlme_ext_priv *pmlmeext;
4850         struct rt_channel_info *chplan_new;
4851         u8 channel;
4852         u8 i;
4853
4854         pregistrypriv = &padapter->registrypriv;
4855         pmlmeext = &padapter->mlmeextpriv;
4856
4857         /*  Adjust channel plan by AP Country IE */
4858         if (pregistrypriv->enable80211d &&
4859             !pmlmeext->update_channel_plan_by_ap_done) {
4860                 const u8 *ie, *p;
4861                 struct rt_channel_plan chplan_ap;
4862                 struct rt_channel_info chplan_sta[MAX_CHANNEL_NUM];
4863                 u8 country[4];
4864                 u8 fcn; /*  first channel number */
4865                 u8 noc; /*  number of channel */
4866                 u8 j, k;
4867
4868                 ie = cfg80211_find_ie(WLAN_EID_COUNTRY,
4869                                       bssid->IEs + _FIXED_IE_LENGTH_,
4870                                       bssid->IELength - _FIXED_IE_LENGTH_);
4871                 if (!ie || ie[1] < IEEE80211_COUNTRY_IE_MIN_LEN)
4872                         return;
4873
4874                 p = ie + 2;
4875                 ie += ie[1];
4876                 ie += 2;
4877
4878                 memcpy(country, p, 3);
4879                 country[3] = '\0';
4880
4881                 p += 3;
4882                 RT_TRACE(_module_rtl871x_mlme_c_, _drv_notice_,
4883                          ("%s: 802.11d country =%s\n", __func__, country));
4884
4885                 i = 0;
4886                 while ((ie - p) >= 3) {
4887                         fcn = *(p++);
4888                         noc = *(p++);
4889                         p++;
4890
4891                         for (j = 0; j < noc; j++) {
4892                                 if (fcn <= 14)
4893                                         channel = fcn + j; /*  2.4 GHz */
4894                                 else
4895                                         channel = fcn + j * 4; /*  5 GHz */
4896
4897                                 chplan_ap.Channel[i++] = channel;
4898                         }
4899                 }
4900                 chplan_ap.Len = i;
4901
4902                 memcpy(chplan_sta, pmlmeext->channel_set, sizeof(chplan_sta));
4903                 memset(pmlmeext->channel_set, 0, sizeof(pmlmeext->channel_set));
4904                 chplan_new = pmlmeext->channel_set;
4905
4906                 i = j = k = 0;
4907                 if (pregistrypriv->wireless_mode & WIRELESS_11G) {
4908                         do {
4909                                 if (i == MAX_CHANNEL_NUM ||
4910                                     chplan_sta[i].ChannelNum == 0 ||
4911                                     chplan_sta[i].ChannelNum > 14)
4912                                         break;
4913
4914                                 if (j == chplan_ap.Len ||
4915                                     chplan_ap.Channel[j] > 14)
4916                                         break;
4917
4918                                 if (chplan_sta[i].ChannelNum ==
4919                                     chplan_ap.Channel[j]) {
4920                                         chplan_new[k].ChannelNum =
4921                                                 chplan_ap.Channel[j];
4922                                         chplan_new[k].ScanType = SCAN_ACTIVE;
4923                                         i++;
4924                                         j++;
4925                                         k++;
4926                                 } else if (chplan_sta[i].ChannelNum <
4927                                            chplan_ap.Channel[j]) {
4928                                         chplan_new[k].ChannelNum =
4929                                                 chplan_sta[i].ChannelNum;
4930                                         chplan_new[k].ScanType =
4931                                                 SCAN_PASSIVE;
4932                                         i++;
4933                                         k++;
4934                                 } else if (chplan_sta[i].ChannelNum >
4935                                            chplan_ap.Channel[j]) {
4936                                         chplan_new[k].ChannelNum =
4937                                                 chplan_ap.Channel[j];
4938                                         chplan_new[k].ScanType =
4939                                                 SCAN_ACTIVE;
4940                                         j++;
4941                                         k++;
4942                                 }
4943                         } while (1);
4944
4945                         /*  change AP not support channel to Passive scan */
4946                         while (i < MAX_CHANNEL_NUM &&
4947                                chplan_sta[i].ChannelNum != 0 &&
4948                                chplan_sta[i].ChannelNum <= 14) {
4949                                 chplan_new[k].ChannelNum =
4950                                         chplan_sta[i].ChannelNum;
4951                                 chplan_new[k].ScanType = SCAN_PASSIVE;
4952                                 i++;
4953                                 k++;
4954                         }
4955
4956                         /*  add channel AP supported */
4957                         while (j < chplan_ap.Len && chplan_ap.Channel[j] <= 14){
4958                                 chplan_new[k].ChannelNum = chplan_ap.Channel[j];
4959                                 chplan_new[k].ScanType = SCAN_ACTIVE;
4960                                 j++;
4961                                 k++;
4962                         }
4963                 } else {
4964                         /*  keep original STA 2.4G channel plan */
4965                         while (i < MAX_CHANNEL_NUM &&
4966                                chplan_sta[i].ChannelNum != 0 &&
4967                                chplan_sta[i].ChannelNum <= 14) {
4968                                 chplan_new[k].ChannelNum =
4969                                         chplan_sta[i].ChannelNum;
4970                                 chplan_new[k].ScanType = chplan_sta[i].ScanType;
4971                                 i++;
4972                                 k++;
4973                         }
4974
4975                         /*  skip AP 2.4G channel plan */
4976                         while (j < chplan_ap.Len && chplan_ap.Channel[j] <= 14)
4977                                 j++;
4978                 }
4979
4980                 if (pregistrypriv->wireless_mode & WIRELESS_11A) {
4981                         do {
4982                                 if (i == MAX_CHANNEL_NUM ||
4983                                     chplan_sta[i].ChannelNum == 0)
4984                                         break;
4985
4986                                 if (j == chplan_ap.Len ||
4987                                     chplan_ap.Channel[j] == 0)
4988                                         break;
4989
4990                                 if (chplan_sta[i].ChannelNum ==
4991                                     chplan_ap.Channel[j]) {
4992                                         chplan_new[k].ChannelNum =
4993                                                 chplan_ap.Channel[j];
4994                                         chplan_new[k].ScanType = SCAN_ACTIVE;
4995                                         i++;
4996                                         j++;
4997                                         k++;
4998                                 } else if (chplan_sta[i].ChannelNum <
4999                                            chplan_ap.Channel[j]) {
5000                                         chplan_new[k].ChannelNum =
5001                                                 chplan_sta[i].ChannelNum;
5002                                         chplan_new[k].ScanType = SCAN_PASSIVE;
5003                                         i++;
5004                                         k++;
5005                                 } else if (chplan_sta[i].ChannelNum >
5006                                            chplan_ap.Channel[j]) {
5007                                         chplan_new[k].ChannelNum =
5008                                                 chplan_ap.Channel[j];
5009                                         chplan_new[k].ScanType = SCAN_ACTIVE;
5010                                         j++;
5011                                         k++;
5012                                 }
5013                         } while (1);
5014
5015                         /*  change AP not support channel to Passive scan */
5016                         while (i < MAX_CHANNEL_NUM &&
5017                                chplan_sta[i].ChannelNum != 0) {
5018                                 chplan_new[k].ChannelNum =
5019                                         chplan_sta[i].ChannelNum;
5020                                 chplan_new[k].ScanType = SCAN_PASSIVE;
5021                                 i++;
5022                                 k++;
5023                         }
5024
5025                         /*  add channel AP supported */
5026                         while (j < chplan_ap.Len && chplan_ap.Channel[j] != 0) {
5027                                 chplan_new[k].ChannelNum = chplan_ap.Channel[j];
5028                                 chplan_new[k].ScanType = SCAN_ACTIVE;
5029                                 j++;
5030                                 k++;
5031                         }
5032                 } else {
5033                         /*  keep original STA 5G channel plan */
5034                         while (i < MAX_CHANNEL_NUM &&
5035                                chplan_sta[i].ChannelNum != 0) {
5036                                 chplan_new[k].ChannelNum =
5037                                         chplan_sta[i].ChannelNum;
5038                                 chplan_new[k].ScanType = chplan_sta[i].ScanType;
5039                                 i++;
5040                                 k++;
5041                         }
5042                 }
5043                 pmlmeext->update_channel_plan_by_ap_done = 1;
5044         }
5045
5046         /*  If channel is used by AP, set channel scan type to active */
5047         channel = bssid->Configuration.DSConfig;
5048         chplan_new = pmlmeext->channel_set;
5049         i = 0;
5050         while (i < MAX_CHANNEL_NUM && chplan_new[i].ChannelNum != 0) {
5051                 if (chplan_new[i].ChannelNum == channel) {
5052                         if (chplan_new[i].ScanType == SCAN_PASSIVE) {
5053                                 /* 5G Bnad 2, 3 (DFS) doesn't change
5054                                    to active scan */
5055                                 if (channel >= 52 && channel <= 144)
5056                                         break;
5057
5058                                 chplan_new[i].ScanType = SCAN_ACTIVE;
5059                                 RT_TRACE(_module_rtl871x_mlme_c_, _drv_notice_,
5060                                          ("%s: change channel %d scan type "
5061                                           "from passive to active\n",
5062                                           __func__, channel));
5063                         }
5064                         break;
5065                 }
5066                 i++;
5067         }
5068 }
5069
5070 /****************************************************************************
5071
5072 Following are the functions to report events
5073
5074 *****************************************************************************/
5075
5076 void report_survey_event23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame)
5077 {
5078         struct cmd_obj *pcmd_obj;
5079         u8      *pevtcmd;
5080         u32 cmdsz;
5081         struct survey_event     *psurvey_evt;
5082         struct C2HEvent_Header *pc2h_evt_hdr;
5083         struct mlme_ext_priv *pmlmeext;
5084         struct cmd_priv *pcmdpriv;
5085
5086         if (!padapter)
5087                 return;
5088
5089         pmlmeext = &padapter->mlmeextpriv;
5090         pcmdpriv = &padapter->cmdpriv;
5091
5092         pcmd_obj = (struct cmd_obj *)kzalloc(sizeof(struct cmd_obj),
5093                                              GFP_ATOMIC);
5094         if (!pcmd_obj)
5095                 return;
5096
5097         cmdsz = (sizeof(struct survey_event) + sizeof(struct C2HEvent_Header));
5098         pevtcmd = kzalloc(cmdsz, GFP_ATOMIC);
5099         if (!pevtcmd) {
5100                 kfree(pcmd_obj);
5101                 return;
5102         }
5103
5104         pcmd_obj->cmdcode = GEN_CMD_CODE(_Set_MLME_EVT);
5105         pcmd_obj->cmdsz = cmdsz;
5106         pcmd_obj->parmbuf = pevtcmd;
5107
5108         pcmd_obj->rsp = NULL;
5109         pcmd_obj->rspsz  = 0;
5110
5111         pc2h_evt_hdr = (struct C2HEvent_Header*)(pevtcmd);
5112         pc2h_evt_hdr->len = sizeof(struct survey_event);
5113         pc2h_evt_hdr->ID = GEN_EVT_CODE(_Survey);
5114         pc2h_evt_hdr->seq = atomic_inc_return(&pmlmeext->event_seq);
5115
5116         psurvey_evt = (struct survey_event*)(pevtcmd + sizeof(struct C2HEvent_Header));
5117
5118         if (collect_bss_info23a(padapter, precv_frame, &psurvey_evt->bss) == _FAIL) {
5119                 kfree(pcmd_obj);
5120                 kfree(pevtcmd);
5121                 return;
5122         }
5123
5124         process_80211d(padapter, &psurvey_evt->bss);
5125
5126         rtw_enqueue_cmd23a(pcmdpriv, pcmd_obj);
5127
5128         pmlmeext->sitesurvey_res.bss_cnt++;
5129
5130         return;
5131 }
5132
5133 void report_surveydone_event23a(struct rtw_adapter *padapter)
5134 {
5135         struct cmd_obj *pcmd_obj;
5136         u8      *pevtcmd;
5137         u32 cmdsz;
5138         struct surveydone_event *psurveydone_evt;
5139         struct C2HEvent_Header  *pc2h_evt_hdr;
5140         struct mlme_ext_priv            *pmlmeext = &padapter->mlmeextpriv;
5141         struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
5142
5143         pcmd_obj = (struct cmd_obj *)kzalloc(sizeof(struct cmd_obj),
5144                                              GFP_ATOMIC);
5145         if (!pcmd_obj)
5146                 return;
5147
5148         cmdsz = (sizeof(struct surveydone_event) + sizeof(struct C2HEvent_Header));
5149         pevtcmd = kzalloc(cmdsz, GFP_ATOMIC);
5150         if (!pevtcmd) {
5151                 kfree(pcmd_obj);
5152                 return;
5153         }
5154
5155         pcmd_obj->cmdcode = GEN_CMD_CODE(_Set_MLME_EVT);
5156         pcmd_obj->cmdsz = cmdsz;
5157         pcmd_obj->parmbuf = pevtcmd;
5158
5159         pcmd_obj->rsp = NULL;
5160         pcmd_obj->rspsz  = 0;
5161
5162         pc2h_evt_hdr = (struct C2HEvent_Header*)(pevtcmd);
5163         pc2h_evt_hdr->len = sizeof(struct surveydone_event);
5164         pc2h_evt_hdr->ID = GEN_EVT_CODE(_SurveyDone);
5165         pc2h_evt_hdr->seq = atomic_inc_return(&pmlmeext->event_seq);
5166
5167         psurveydone_evt = (struct surveydone_event*)(pevtcmd + sizeof(struct C2HEvent_Header));
5168         psurveydone_evt->bss_cnt = pmlmeext->sitesurvey_res.bss_cnt;
5169
5170         DBG_8723A("survey done event(%x)\n", psurveydone_evt->bss_cnt);
5171
5172         rtw_enqueue_cmd23a(pcmdpriv, pcmd_obj);
5173
5174         return;
5175 }
5176
5177 void report_join_res23a(struct rtw_adapter *padapter, int res)
5178 {
5179         struct cmd_obj *pcmd_obj;
5180         u8      *pevtcmd;
5181         u32 cmdsz;
5182         struct joinbss_event            *pjoinbss_evt;
5183         struct C2HEvent_Header  *pc2h_evt_hdr;
5184         struct mlme_ext_priv            *pmlmeext = &padapter->mlmeextpriv;
5185         struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
5186         struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
5187
5188         pcmd_obj = (struct cmd_obj *)kzalloc(sizeof(struct cmd_obj),
5189                                              GFP_ATOMIC);
5190         if (!pcmd_obj)
5191                 return;
5192
5193         cmdsz = (sizeof(struct joinbss_event) + sizeof(struct C2HEvent_Header));
5194         pevtcmd = kzalloc(cmdsz, GFP_ATOMIC);
5195         if (!pevtcmd) {
5196                 kfree(pcmd_obj);
5197                 return;
5198         }
5199
5200         pcmd_obj->cmdcode = GEN_CMD_CODE(_Set_MLME_EVT);
5201         pcmd_obj->cmdsz = cmdsz;
5202         pcmd_obj->parmbuf = pevtcmd;
5203
5204         pcmd_obj->rsp = NULL;
5205         pcmd_obj->rspsz  = 0;
5206
5207         pc2h_evt_hdr = (struct C2HEvent_Header*)(pevtcmd);
5208         pc2h_evt_hdr->len = sizeof(struct joinbss_event);
5209         pc2h_evt_hdr->ID = GEN_EVT_CODE(_JoinBss);
5210         pc2h_evt_hdr->seq = atomic_inc_return(&pmlmeext->event_seq);
5211
5212         pjoinbss_evt = (struct joinbss_event*)(pevtcmd + sizeof(struct C2HEvent_Header));
5213         memcpy((unsigned char *)&pjoinbss_evt->network.network,
5214                &pmlmeinfo->network, sizeof(struct wlan_bssid_ex));
5215         pjoinbss_evt->network.join_res  = pjoinbss_evt->network.aid = res;
5216
5217         DBG_8723A("report_join_res23a(%d)\n", res);
5218
5219         rtw_joinbss_event_prehandle23a(padapter, (u8 *)&pjoinbss_evt->network);
5220
5221         rtw_enqueue_cmd23a(pcmdpriv, pcmd_obj);
5222
5223         return;
5224 }
5225
5226 void report_del_sta_event23a(struct rtw_adapter *padapter, unsigned char* MacAddr, unsigned short reason)
5227 {
5228         struct cmd_obj *pcmd_obj;
5229         u8      *pevtcmd;
5230         u32 cmdsz;
5231         struct sta_info *psta;
5232         int     mac_id;
5233         struct stadel_event                     *pdel_sta_evt;
5234         struct C2HEvent_Header  *pc2h_evt_hdr;
5235         struct mlme_ext_priv            *pmlmeext = &padapter->mlmeextpriv;
5236         struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
5237
5238         pcmd_obj = (struct cmd_obj *)kzalloc(sizeof(struct cmd_obj),
5239                                              GFP_ATOMIC);
5240         if (!pcmd_obj)
5241                 return;
5242
5243         cmdsz = (sizeof(struct stadel_event) + sizeof(struct C2HEvent_Header));
5244         pevtcmd = kzalloc(cmdsz, GFP_ATOMIC);
5245         if (!pevtcmd) {
5246                 kfree(pcmd_obj);
5247                 return;
5248         }
5249
5250         pcmd_obj->cmdcode = GEN_CMD_CODE(_Set_MLME_EVT);
5251         pcmd_obj->cmdsz = cmdsz;
5252         pcmd_obj->parmbuf = pevtcmd;
5253
5254         pcmd_obj->rsp = NULL;
5255         pcmd_obj->rspsz  = 0;
5256
5257         pc2h_evt_hdr = (struct C2HEvent_Header*)(pevtcmd);
5258         pc2h_evt_hdr->len = sizeof(struct stadel_event);
5259         pc2h_evt_hdr->ID = GEN_EVT_CODE(_DelSTA);
5260         pc2h_evt_hdr->seq = atomic_inc_return(&pmlmeext->event_seq);
5261
5262         pdel_sta_evt = (struct stadel_event*)(pevtcmd + sizeof(struct C2HEvent_Header));
5263         ether_addr_copy((unsigned char *)&pdel_sta_evt->macaddr, MacAddr);
5264         memcpy((unsigned char *)pdel_sta_evt->rsvd, (unsigned char *)&reason,
5265                2);
5266
5267         psta = rtw_get_stainfo23a(&padapter->stapriv, MacAddr);
5268         if (psta)
5269                 mac_id = (int)psta->mac_id;
5270         else
5271                 mac_id = (-1);
5272
5273         pdel_sta_evt->mac_id = mac_id;
5274
5275         DBG_8723A("report_del_sta_event23a: delete STA, mac_id =%d\n", mac_id);
5276
5277         rtw_enqueue_cmd23a(pcmdpriv, pcmd_obj);
5278
5279         return;
5280 }
5281
5282 void report_add_sta_event23a(struct rtw_adapter *padapter, unsigned char* MacAddr, int cam_idx)
5283 {
5284         struct cmd_obj *pcmd_obj;
5285         u8      *pevtcmd;
5286         u32 cmdsz;
5287         struct stassoc_event            *padd_sta_evt;
5288         struct C2HEvent_Header  *pc2h_evt_hdr;
5289         struct mlme_ext_priv            *pmlmeext = &padapter->mlmeextpriv;
5290         struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
5291
5292         pcmd_obj = (struct cmd_obj *)kzalloc(sizeof(struct cmd_obj),
5293                                              GFP_ATOMIC);
5294         if (!pcmd_obj)
5295                 return;
5296
5297         cmdsz = (sizeof(struct stassoc_event) + sizeof(struct C2HEvent_Header));
5298         pevtcmd = kzalloc(cmdsz, GFP_ATOMIC);
5299         if (!pevtcmd) {
5300                 kfree(pcmd_obj);
5301                 return;
5302         }
5303
5304         pcmd_obj->cmdcode = GEN_CMD_CODE(_Set_MLME_EVT);
5305         pcmd_obj->cmdsz = cmdsz;
5306         pcmd_obj->parmbuf = pevtcmd;
5307
5308         pcmd_obj->rsp = NULL;
5309         pcmd_obj->rspsz  = 0;
5310
5311         pc2h_evt_hdr = (struct C2HEvent_Header*)(pevtcmd);
5312         pc2h_evt_hdr->len = sizeof(struct stassoc_event);
5313         pc2h_evt_hdr->ID = GEN_EVT_CODE(_AddSTA);
5314         pc2h_evt_hdr->seq = atomic_inc_return(&pmlmeext->event_seq);
5315
5316         padd_sta_evt = (struct stassoc_event*)(pevtcmd + sizeof(struct C2HEvent_Header));
5317         ether_addr_copy((unsigned char *)&padd_sta_evt->macaddr, MacAddr);
5318         padd_sta_evt->cam_id = cam_idx;
5319
5320         DBG_8723A("report_add_sta_event23a: add STA\n");
5321
5322         rtw_enqueue_cmd23a(pcmdpriv, pcmd_obj);
5323
5324         return;
5325 }
5326
5327 /****************************************************************************
5328
5329 Following are the event callback functions
5330
5331 *****************************************************************************/
5332
5333 /* for sta/adhoc mode */
5334 void update_sta_info23a(struct rtw_adapter *padapter, struct sta_info *psta)
5335 {
5336         struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
5337         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
5338         struct mlme_ext_info    *pmlmeinfo = &pmlmeext->mlmext_info;
5339
5340         /* ERP */
5341         VCS_update23a(padapter, psta);
5342
5343         /* HT */
5344         if (pmlmepriv->htpriv.ht_option)
5345         {
5346                 psta->htpriv.ht_option = true;
5347
5348                 psta->htpriv.ampdu_enable = pmlmepriv->htpriv.ampdu_enable;
5349
5350                 if (support_short_GI23a(padapter, &pmlmeinfo->HT_caps))
5351                         psta->htpriv.sgi = true;
5352
5353                 psta->qos_option = true;
5354
5355         }
5356         else
5357         {
5358                 psta->htpriv.ht_option = false;
5359
5360                 psta->htpriv.ampdu_enable = false;
5361
5362                 psta->htpriv.sgi = false;
5363                 psta->qos_option = false;
5364
5365         }
5366         psta->htpriv.bwmode = pmlmeext->cur_bwmode;
5367         psta->htpriv.ch_offset = pmlmeext->cur_ch_offset;
5368
5369         psta->htpriv.agg_enable_bitmap = 0x0;/* reset */
5370         psta->htpriv.candidate_tid_bitmap = 0x0;/* reset */
5371
5372         /* QoS */
5373         if (pmlmepriv->qos_option)
5374                 psta->qos_option = true;
5375
5376         psta->state = _FW_LINKED;
5377 }
5378
5379 void mlmeext_joinbss_event_callback23a(struct rtw_adapter *padapter, int join_res)
5380 {
5381         struct sta_info         *psta, *psta_bmc;
5382         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
5383         struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
5384         struct wlan_bssid_ex *cur_network = &pmlmeinfo->network;
5385         struct sta_priv         *pstapriv = &padapter->stapriv;
5386
5387         if (join_res < 0) {
5388                 hw_var_set_mlme_join(padapter, 1);
5389                 hw_var_set_bssid(padapter, null_addr);
5390
5391                 /* restore to initial setting. */
5392                 update_tx_basic_rate23a(padapter,
5393                                         padapter->registrypriv.wireless_mode);
5394
5395                 goto exit_mlmeext_joinbss_event_callback23a;
5396         }
5397
5398         if ((pmlmeinfo->state&0x03) == WIFI_FW_ADHOC_STATE)
5399         {
5400                 /* for bc/mc */
5401                 psta_bmc = rtw_get_bcmc_stainfo23a(padapter);
5402                 if (psta_bmc)
5403                 {
5404                         pmlmeinfo->FW_sta_info[psta_bmc->mac_id].psta = psta_bmc;
5405                         update_bmc_sta_support_rate23a(padapter, psta_bmc->mac_id);
5406                         Update_RA_Entry23a(padapter, psta_bmc);
5407                 }
5408         }
5409
5410         /* turn on dynamic functions */
5411         rtl8723a_odm_support_ability_set(padapter, DYNAMIC_ALL_FUNC_ENABLE);
5412
5413         /*  update IOT-releated issue */
5414         update_IOT_info23a(padapter);
5415
5416         HalSetBrateCfg23a(padapter, cur_network->SupportedRates);
5417
5418         /* BCN interval */
5419         rtl8723a_set_beacon_interval(padapter, pmlmeinfo->bcn_interval);
5420
5421         /* udpate capability */
5422         update_capinfo23a(padapter, pmlmeinfo->capability);
5423
5424         /* WMM, Update EDCA param */
5425         WMMOnAssocRsp23a(padapter);
5426
5427         /* HT */
5428         HTOnAssocRsp23a(padapter);
5429
5430         /* Set cur_channel&cur_bwmode&cur_ch_offset */
5431         set_channel_bwmode23a(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode);
5432
5433         psta = rtw_get_stainfo23a(pstapriv, cur_network->MacAddress);
5434         if (psta) /* only for infra. mode */
5435         {
5436                 pmlmeinfo->FW_sta_info[psta->mac_id].psta = psta;
5437
5438                 /* DBG_8723A("set_sta_rate23a\n"); */
5439
5440                 psta->wireless_mode = pmlmeext->cur_wireless_mode;
5441
5442                 /* set per sta rate after updating HT cap. */
5443                 set_sta_rate23a(padapter, psta);
5444         }
5445
5446         hw_var_set_mlme_join(padapter, 2);
5447
5448         if ((pmlmeinfo->state&0x03) == WIFI_FW_STATION_STATE) {
5449                 /*  correcting TSF */
5450                 rtw_correct_TSF(padapter);
5451
5452                 /* set_link_timer(pmlmeext, DISCONNECT_TO); */
5453         }
5454
5455         rtw_lps_ctrl_wk_cmd23a(padapter, LPS_CTRL_CONNECT, 0);
5456
5457 exit_mlmeext_joinbss_event_callback23a:
5458         DBG_8723A("=>%s\n", __func__);
5459 }
5460
5461 void mlmeext_sta_add_event_callback23a(struct rtw_adapter *padapter, struct sta_info *psta)
5462 {
5463         struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
5464         struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
5465
5466         DBG_8723A("%s\n", __func__);
5467
5468         if ((pmlmeinfo->state&0x03) == WIFI_FW_ADHOC_STATE)
5469         {
5470                 if (pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS)/* adhoc master or sta_count>1 */
5471                 {
5472                         /* nothing to do */
5473                 }
5474                 else/* adhoc client */
5475                 {
5476                         /*  correcting TSF */
5477                         rtw_correct_TSF(padapter);
5478
5479                         /* start beacon */
5480                         if (send_beacon23a(padapter) == _FAIL)
5481                         {
5482                                 pmlmeinfo->FW_sta_info[psta->mac_id].status = 0;
5483
5484                                 pmlmeinfo->state ^= WIFI_FW_ADHOC_STATE;
5485
5486                                 return;
5487                         }
5488
5489                         pmlmeinfo->state |= WIFI_FW_ASSOC_SUCCESS;
5490
5491                 }
5492
5493                 hw_var_set_mlme_join(padapter, 2);
5494         }
5495
5496         pmlmeinfo->FW_sta_info[psta->mac_id].psta = psta;
5497
5498         /* rate radaptive */
5499         Update_RA_Entry23a(padapter, psta);
5500
5501         /* update adhoc sta_info */
5502         update_sta_info23a(padapter, psta);
5503 }
5504
5505 void mlmeext_sta_del_event_callback23a(struct rtw_adapter *padapter)
5506 {
5507         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
5508         struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
5509
5510         if (is_client_associated_to_ap23a(padapter) || is_IBSS_empty23a(padapter))
5511         {
5512                 /* set_opmode_cmd(padapter, infra_client_with_mlme); */
5513
5514                 hw_var_set_mlme_disconnect(padapter);
5515                 hw_var_set_bssid(padapter, null_addr);
5516
5517                 /* restore to initial setting. */
5518                 update_tx_basic_rate23a(padapter, padapter->registrypriv.wireless_mode);
5519
5520                 /* switch to the 20M Hz mode after disconnect */
5521                 pmlmeext->cur_bwmode = HT_CHANNEL_WIDTH_20;
5522                 pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
5523
5524                 /* SelectChannel23a(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset); */
5525                 set_channel_bwmode23a(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode);
5526
5527                 flush_all_cam_entry23a(padapter);
5528
5529                 pmlmeinfo->state = WIFI_FW_NULL_STATE;
5530
5531                 /* set MSR to no link state -> infra. mode */
5532                 Set_MSR23a(padapter, _HW_STATE_STATION_);
5533
5534                 del_timer_sync(&pmlmeext->link_timer);
5535         }
5536 }
5537
5538 static u8 chk_ap_is_alive(struct rtw_adapter *padapter, struct sta_info *psta)
5539 {
5540         u8 ret = false;
5541
5542         if ((sta_rx_data_pkts(psta) == sta_last_rx_data_pkts(psta)) &&
5543             sta_rx_beacon_pkts(psta) == sta_last_rx_beacon_pkts(psta) &&
5544             sta_rx_probersp_pkts(psta) == sta_last_rx_probersp_pkts(psta))
5545                 ret = false;
5546         else
5547                 ret = true;
5548
5549         sta_update_last_rx_pkts(psta);
5550         return ret;
5551 }
5552
5553 void linked_status_chk23a(struct rtw_adapter *padapter)
5554 {
5555         u32     i;
5556         struct sta_info         *psta;
5557         struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
5558         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
5559         struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
5560         struct sta_priv         *pstapriv = &padapter->stapriv;
5561
5562         rtw_hal_sreset_linked_status_check23a(padapter);
5563
5564         if (is_client_associated_to_ap23a(padapter))
5565         {
5566                 /* linked infrastructure client mode */
5567
5568                 int tx_chk = _SUCCESS, rx_chk = _SUCCESS;
5569                 int rx_chk_limit;
5570
5571                 rx_chk_limit = 4;
5572
5573                 if ((psta = rtw_get_stainfo23a(pstapriv, pmlmeinfo->network.MacAddress)) != NULL)
5574                 {
5575                         bool is_p2p_enable = false;
5576
5577                         if (chk_ap_is_alive(padapter, psta) == false)
5578                                 rx_chk = _FAIL;
5579
5580                         if (pxmitpriv->last_tx_pkts == pxmitpriv->tx_pkts)
5581                                 tx_chk = _FAIL;
5582
5583                         if (pmlmeext->active_keep_alive_check && (rx_chk == _FAIL || tx_chk == _FAIL)) {
5584                                 u8 backup_oper_channel = 0;
5585
5586                                 /* switch to correct channel of current network  before issue keep-alive frames */
5587                                 if (rtw_get_oper_ch23a(padapter) != pmlmeext->cur_channel) {
5588                                         backup_oper_channel = rtw_get_oper_ch23a(padapter);
5589                                         SelectChannel23a(padapter, pmlmeext->cur_channel);
5590                                 }
5591
5592                                 if (rx_chk != _SUCCESS)
5593                                         issue_probereq23a_ex23a(padapter, &pmlmeinfo->network.Ssid, psta->hwaddr, 3, 1);
5594
5595                                 if ((tx_chk != _SUCCESS && pmlmeinfo->link_count++ == 0xf) || rx_chk != _SUCCESS) {
5596                                         tx_chk = issue_nulldata23a(padapter, psta->hwaddr, 0, 3, 1);
5597                                         /* if tx acked and p2p disabled, set rx_chk _SUCCESS to reset retry count */
5598                                         if (tx_chk == _SUCCESS && !is_p2p_enable)
5599                                                 rx_chk = _SUCCESS;
5600                                 }
5601
5602                                 /* back to the original operation channel */
5603                                 if (backup_oper_channel>0)
5604                                         SelectChannel23a(padapter, backup_oper_channel);
5605
5606                         } else {
5607                                 if (rx_chk != _SUCCESS) {
5608                                         if (pmlmeext->retry == 0) {
5609                                                 issue_probereq23a(padapter, &pmlmeinfo->network.Ssid, pmlmeinfo->network.MacAddress);
5610                                                 issue_probereq23a(padapter, &pmlmeinfo->network.Ssid, pmlmeinfo->network.MacAddress);
5611                                                 issue_probereq23a(padapter, &pmlmeinfo->network.Ssid, pmlmeinfo->network.MacAddress);
5612                                         }
5613                                 }
5614
5615                                 if (tx_chk != _SUCCESS && pmlmeinfo->link_count++ == 0xf)
5616                                         tx_chk = issue_nulldata23a(padapter, NULL, 0, 1, 0);
5617                         }
5618
5619                         if (rx_chk == _FAIL) {
5620                                 pmlmeext->retry++;
5621                                 if (pmlmeext->retry > rx_chk_limit) {
5622                                         DBG_8723A_LEVEL(_drv_always_,
5623                                                         "%s(%s): disconnect or "
5624                                                         "roaming\n", __func__,
5625                                                         padapter->pnetdev->name);
5626                                         receive_disconnect23a(padapter, pmlmeinfo->network.MacAddress,
5627                                                 WLAN_REASON_EXPIRATION_CHK);
5628                                         return;
5629                                 }
5630                         } else {
5631                                 pmlmeext->retry = 0;
5632                         }
5633
5634                         if (tx_chk == _FAIL) {
5635                                 pmlmeinfo->link_count &= 0xf;
5636                         } else {
5637                                 pxmitpriv->last_tx_pkts = pxmitpriv->tx_pkts;
5638                                 pmlmeinfo->link_count = 0;
5639                         }
5640
5641                 } /* end of if ((psta = rtw_get_stainfo23a(pstapriv, passoc_res->network.MacAddress)) != NULL) */
5642         }
5643         else if (is_client_associated_to_ibss23a(padapter))
5644         {
5645                 /* linked IBSS mode */
5646                 /* for each assoc list entry to check the rx pkt counter */
5647                 for (i = IBSS_START_MAC_ID; i < NUM_STA; i++)
5648                 {
5649                         if (pmlmeinfo->FW_sta_info[i].status == 1)
5650                         {
5651                                 psta = pmlmeinfo->FW_sta_info[i].psta;
5652
5653                                 if (NULL == psta) continue;
5654
5655                                 if (pmlmeinfo->FW_sta_info[i].rx_pkt == sta_rx_pkts(psta))
5656                                 {
5657
5658                                         if (pmlmeinfo->FW_sta_info[i].retry<3)
5659                                         {
5660                                                 pmlmeinfo->FW_sta_info[i].retry++;
5661                                         }
5662                                         else
5663                                         {
5664                                                 pmlmeinfo->FW_sta_info[i].retry = 0;
5665                                                 pmlmeinfo->FW_sta_info[i].status = 0;
5666                                                 report_del_sta_event23a(padapter, psta->hwaddr,
5667                                                         65535/*  indicate disconnect caused by no rx */
5668                                                 );
5669                                         }
5670                                 }
5671                                 else
5672                                 {
5673                                         pmlmeinfo->FW_sta_info[i].retry = 0;
5674                                         pmlmeinfo->FW_sta_info[i].rx_pkt = (u32)sta_rx_pkts(psta);
5675                                 }
5676                         }
5677                 }
5678
5679                 /* set_link_timer(pmlmeext, DISCONNECT_TO); */
5680
5681         }
5682 }
5683
5684 static void survey_timer_hdl(unsigned long data)
5685 {
5686         struct rtw_adapter *padapter = (struct rtw_adapter *)data;
5687         struct cmd_obj *ph2c;
5688         struct sitesurvey_parm *psurveyPara;
5689         struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
5690         struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
5691
5692         /* issue rtw_sitesurvey_cmd23a */
5693         if (pmlmeext->sitesurvey_res.state > SCAN_START) {
5694                 if (pmlmeext->sitesurvey_res.state ==  SCAN_PROCESS)
5695                         pmlmeext->sitesurvey_res.channel_idx++;
5696
5697                 if (pmlmeext->scan_abort == true) {
5698                         pmlmeext->sitesurvey_res.channel_idx =
5699                                 pmlmeext->sitesurvey_res.ch_num;
5700                         DBG_8723A("%s idx:%d\n", __func__,
5701                                   pmlmeext->sitesurvey_res.channel_idx);
5702
5703                         pmlmeext->scan_abort = false;/* reset */
5704                 }
5705
5706                 ph2c = (struct cmd_obj *)kzalloc(sizeof(struct cmd_obj),
5707                         GFP_ATOMIC);
5708                 if (!ph2c)
5709                         goto exit_survey_timer_hdl;
5710
5711                 psurveyPara = (struct sitesurvey_parm*)
5712                         kzalloc(sizeof(struct sitesurvey_parm), GFP_ATOMIC);
5713                 if (!psurveyPara) {
5714                         kfree(ph2c);
5715                         goto exit_survey_timer_hdl;
5716                 }
5717
5718                 init_h2fwcmd_w_parm_no_rsp(ph2c, psurveyPara, GEN_CMD_CODE(_SiteSurvey));
5719                 rtw_enqueue_cmd23a(pcmdpriv, ph2c);
5720         }
5721
5722 exit_survey_timer_hdl:
5723         return;
5724 }
5725
5726 static void link_timer_hdl(unsigned long data)
5727 {
5728         struct rtw_adapter *padapter = (struct rtw_adapter *)data;
5729         /* static unsigned int          rx_pkt = 0; */
5730         /* static u64                           tx_cnt = 0; */
5731         /* struct xmit_priv *pxmitpriv = &padapter->xmitpriv; */
5732         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
5733         struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
5734         /* struct sta_priv              *pstapriv = &padapter->stapriv; */
5735
5736         if (pmlmeinfo->state & WIFI_FW_AUTH_NULL)
5737         {
5738                 DBG_8723A("link_timer_hdl:no beacon while connecting\n");
5739                 pmlmeinfo->state = WIFI_FW_NULL_STATE;
5740                 report_join_res23a(padapter, -3);
5741         }
5742         else if (pmlmeinfo->state & WIFI_FW_AUTH_STATE)
5743         {
5744                 /* re-auth timer */
5745                 if (++pmlmeinfo->reauth_count > REAUTH_LIMIT)
5746                 {
5747                         /* if (pmlmeinfo->auth_algo != dot11AuthAlgrthm_Auto) */
5748                         /*  */
5749                                 pmlmeinfo->state = 0;
5750                                 report_join_res23a(padapter, -1);
5751                                 return;
5752                         /*  */
5753                         /* else */
5754                         /*  */
5755                         /*      pmlmeinfo->auth_algo = dot11AuthAlgrthm_Shared; */
5756                         /*      pmlmeinfo->reauth_count = 0; */
5757                         /*  */
5758                 }
5759
5760                 DBG_8723A("link_timer_hdl: auth timeout and try again\n");
5761                 pmlmeinfo->auth_seq = 1;
5762                 issue_auth23a(padapter, NULL, 0);
5763                 set_link_timer(pmlmeext, REAUTH_TO);
5764         }
5765         else if (pmlmeinfo->state & WIFI_FW_ASSOC_STATE)
5766         {
5767                 /* re-assoc timer */
5768                 if (++pmlmeinfo->reassoc_count > REASSOC_LIMIT)
5769                 {
5770                         pmlmeinfo->state = WIFI_FW_NULL_STATE;
5771                         report_join_res23a(padapter, -2);
5772                         return;
5773                 }
5774
5775                 DBG_8723A("link_timer_hdl: assoc timeout and try again\n");
5776                 issue_assocreq23a(padapter);
5777                 set_link_timer(pmlmeext, REASSOC_TO);
5778         }
5779
5780         return;
5781 }
5782
5783 static void addba_timer_hdl(unsigned long data)
5784 {
5785         struct sta_info *psta = (struct sta_info *)data;
5786         struct ht_priv  *phtpriv;
5787
5788         if (!psta)
5789                 return;
5790
5791         phtpriv = &psta->htpriv;
5792
5793         if ((phtpriv->ht_option == true) && (phtpriv->ampdu_enable == true))
5794         {
5795                 if (phtpriv->candidate_tid_bitmap)
5796                         phtpriv->candidate_tid_bitmap = 0x0;
5797
5798         }
5799 }
5800
5801 void init_addba_retry_timer23a(struct sta_info *psta)
5802 {
5803         setup_timer(&psta->addba_retry_timer, addba_timer_hdl,
5804                     (unsigned long)psta);
5805 }
5806
5807 void init_mlme_ext_timer23a(struct rtw_adapter *padapter)
5808 {
5809         struct  mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
5810
5811         setup_timer(&pmlmeext->survey_timer, survey_timer_hdl,
5812                     (unsigned long)padapter);
5813
5814         setup_timer(&pmlmeext->link_timer, link_timer_hdl,
5815                     (unsigned long)padapter);
5816 }
5817
5818 u8 NULL_hdl23a(struct rtw_adapter *padapter, const u8 *pbuf)
5819 {
5820         return H2C_SUCCESS;
5821 }
5822
5823 u8 setopmode_hdl23a(struct rtw_adapter *padapter, const u8 *pbuf)
5824 {
5825         u8      type;
5826         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
5827         struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
5828         const struct setopmode_parm *psetop = (struct setopmode_parm *)pbuf;
5829
5830         if (psetop->mode == Ndis802_11APMode) {
5831                 pmlmeinfo->state = WIFI_FW_AP_STATE;
5832                 type = _HW_STATE_AP_;
5833         } else if (psetop->mode == Ndis802_11Infrastructure) {
5834                 pmlmeinfo->state &= ~(BIT(0)|BIT(1));/*  clear state */
5835                 pmlmeinfo->state |= WIFI_FW_STATION_STATE;/* set to     STATION_STATE */
5836                 type = _HW_STATE_STATION_;
5837         } else if (psetop->mode == Ndis802_11IBSS)
5838                 type = _HW_STATE_ADHOC_;
5839         else
5840                 type = _HW_STATE_NOLINK_;
5841
5842         hw_var_set_opmode(padapter, type);
5843         /* Set_NETYPE0_MSR(padapter, type); */
5844
5845         return H2C_SUCCESS;
5846 }
5847
5848 u8 createbss_hdl23a(struct rtw_adapter *padapter, const u8 *pbuf)
5849 {
5850         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
5851         struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
5852         struct wlan_bssid_ex *pnetwork = &pmlmeinfo->network;
5853         const struct wlan_bssid_ex *pparm = (struct wlan_bssid_ex *)pbuf;
5854         /* u32  initialgain; */
5855
5856         if (pparm->InfrastructureMode == Ndis802_11APMode) {
5857 #ifdef CONFIG_8723AU_AP_MODE
5858
5859                 if (pmlmeinfo->state == WIFI_FW_AP_STATE)
5860                 {
5861                         /* todo: */
5862                         return H2C_SUCCESS;
5863                 }
5864 #endif
5865         }
5866
5867         /* below is for ad-hoc master */
5868         if (pparm->InfrastructureMode == Ndis802_11IBSS) {
5869                 rtw_joinbss_reset23a(padapter);
5870
5871                 pmlmeext->cur_bwmode = HT_CHANNEL_WIDTH_20;
5872                 pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
5873                 pmlmeinfo->ERP_enable = 0;
5874                 pmlmeinfo->WMM_enable = 0;
5875                 pmlmeinfo->HT_enable = 0;
5876                 pmlmeinfo->HT_caps_enable = 0;
5877                 pmlmeinfo->HT_info_enable = 0;
5878                 pmlmeinfo->agg_enable_bitmap = 0;
5879                 pmlmeinfo->candidate_tid_bitmap = 0;
5880
5881                 /* disable dynamic functions, such as high power, DIG */
5882                 rtl8723a_odm_support_ability_backup(padapter);
5883
5884                 rtl8723a_odm_support_ability_clr(padapter,
5885                                                  DYNAMIC_FUNC_DISABLE);
5886
5887                 /* cancel link timer */
5888                 del_timer_sync(&pmlmeext->link_timer);
5889
5890                 /* clear CAM */
5891                 flush_all_cam_entry23a(padapter);
5892
5893                 if (pparm->IELength > MAX_IE_SZ)/* Check pbuf->IELength */
5894                         return H2C_PARAMETERS_ERROR;
5895
5896                 memcpy(pnetwork, pparm, sizeof(struct wlan_bssid_ex));
5897
5898                 start_create_ibss23a(padapter);
5899         }
5900
5901         return H2C_SUCCESS;
5902 }
5903
5904 u8 join_cmd_hdl23a(struct rtw_adapter *padapter, const u8 *pbuf)
5905 {
5906         struct ndis_802_11_var_ies *    pIE;
5907         struct registry_priv    *pregpriv = &padapter->registrypriv;
5908         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
5909         struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
5910         struct wlan_bssid_ex *pnetwork = &pmlmeinfo->network;
5911         const struct wlan_bssid_ex *pparm = (struct wlan_bssid_ex *)pbuf;
5912         struct HT_info_element *pht_info;
5913         u32 i;
5914         /* u32  initialgain; */
5915         /* u32  acparm; */
5916
5917         /* check already connecting to AP or not */
5918         if (pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS)
5919         {
5920                 if (pmlmeinfo->state & WIFI_FW_STATION_STATE)
5921                         issue_deauth23a_ex23a(padapter, pnetwork->MacAddress,
5922                                         WLAN_REASON_DEAUTH_LEAVING, 5, 100);
5923
5924                 pmlmeinfo->state = WIFI_FW_NULL_STATE;
5925
5926                 /* clear CAM */
5927                 flush_all_cam_entry23a(padapter);
5928
5929                 del_timer_sync(&pmlmeext->link_timer);
5930
5931                 /* set MSR to nolink -> infra. mode */
5932                 /* Set_MSR23a(padapter, _HW_STATE_NOLINK_); */
5933                 Set_MSR23a(padapter, _HW_STATE_STATION_);
5934
5935                 hw_var_set_mlme_disconnect(padapter);
5936         }
5937
5938         rtw_joinbss_reset23a(padapter);
5939
5940         pmlmeext->cur_bwmode = HT_CHANNEL_WIDTH_20;
5941         pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
5942         pmlmeinfo->ERP_enable = 0;
5943         pmlmeinfo->WMM_enable = 0;
5944         pmlmeinfo->HT_enable = 0;
5945         pmlmeinfo->HT_caps_enable = 0;
5946         pmlmeinfo->HT_info_enable = 0;
5947         pmlmeinfo->agg_enable_bitmap = 0;
5948         pmlmeinfo->candidate_tid_bitmap = 0;
5949         pmlmeinfo->bwmode_updated = false;
5950         /* pmlmeinfo->assoc_AP_vendor = HT_IOT_PEER_MAX; */
5951
5952         if (pparm->IELength > MAX_IE_SZ)/* Check pbuf->IELength */
5953                 return H2C_PARAMETERS_ERROR;
5954
5955         memcpy(pnetwork, pbuf, sizeof(struct wlan_bssid_ex));
5956
5957         /* Check AP vendor to move rtw_joinbss_cmd23a() */
5958         /* pmlmeinfo->assoc_AP_vendor = check_assoc_AP23a(pnetwork->IEs,
5959            pnetwork->IELength); */
5960
5961         for (i = sizeof(struct ndis_802_11_fixed_ies); i < pnetwork->IELength;)
5962         {
5963                 pIE = (struct ndis_802_11_var_ies *)(pnetwork->IEs + i);
5964
5965                 switch (pIE->ElementID)
5966                 {
5967                 case WLAN_EID_VENDOR_SPECIFIC:/* Get WMM IE. */
5968                         if (!memcmp(pIE->data, WMM_OUI23A, 4))
5969                                 pmlmeinfo->WMM_enable = 1;
5970                         break;
5971
5972                 case WLAN_EID_HT_CAPABILITY:    /* Get HT Cap IE. */
5973                         pmlmeinfo->HT_caps_enable = 1;
5974                         break;
5975
5976                 case WLAN_EID_HT_OPERATION:     /* Get HT Info IE. */
5977                         pmlmeinfo->HT_info_enable = 1;
5978
5979                         /* spec case only for cisco's ap because cisco's ap
5980                          * issue assoc rsp using mcs rate @40MHz or @20MHz */
5981                         pht_info = (struct HT_info_element *)(pIE->data);
5982
5983                         if ((pregpriv->cbw40_enable) &&
5984                             (pht_info->infos[0] & BIT(2))) {
5985                                 /* switch to the 40M Hz mode according to AP */
5986                                 pmlmeext->cur_bwmode = HT_CHANNEL_WIDTH_40;
5987                                 switch (pht_info->infos[0] & 0x3)
5988                                 {
5989                                 case 1:
5990                                         pmlmeext->cur_ch_offset =
5991                                                 HAL_PRIME_CHNL_OFFSET_LOWER;
5992                                         break;
5993
5994                                 case 3:
5995                                         pmlmeext->cur_ch_offset =
5996                                                 HAL_PRIME_CHNL_OFFSET_UPPER;
5997                                         break;
5998
5999                                 default:
6000                                         pmlmeext->cur_ch_offset =
6001                                                 HAL_PRIME_CHNL_OFFSET_DONT_CARE;
6002                                         break;
6003                                 }
6004
6005                                 DBG_8723A("set ch/bw before connected\n");
6006                         }
6007                         break;
6008
6009                 default:
6010                         break;
6011                 }
6012
6013                 i += (pIE->Length + 2);
6014         }
6015
6016         hw_var_set_bssid(padapter, pmlmeinfo->network.MacAddress);
6017         hw_var_set_mlme_join(padapter, 0);
6018
6019         /* cancel link timer */
6020         del_timer_sync(&pmlmeext->link_timer);
6021
6022         start_clnt_join23a(padapter);
6023
6024         return H2C_SUCCESS;
6025 }
6026
6027 u8 disconnect_hdl23a(struct rtw_adapter *padapter, const u8 *pbuf)
6028 {
6029         const struct disconnect_parm *param = (struct disconnect_parm *)pbuf;
6030         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
6031         struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
6032         struct wlan_bssid_ex *pnetwork = &pmlmeinfo->network;
6033
6034         if (is_client_associated_to_ap23a(padapter))
6035         {
6036                 issue_deauth23a_ex23a(padapter, pnetwork->MacAddress, WLAN_REASON_DEAUTH_LEAVING, param->deauth_timeout_ms/100, 100);
6037         }
6038
6039         /* set_opmode_cmd(padapter, infra_client_with_mlme); */
6040
6041         /* pmlmeinfo->state = WIFI_FW_NULL_STATE; */
6042
6043         hw_var_set_mlme_disconnect(padapter);
6044         hw_var_set_bssid(padapter, null_addr);
6045
6046         /* restore to initial setting. */
6047         update_tx_basic_rate23a(padapter, padapter->registrypriv.wireless_mode);
6048
6049         if (((pmlmeinfo->state & 0x03) == WIFI_FW_ADHOC_STATE) ||
6050             ((pmlmeinfo->state & 0x03) == WIFI_FW_AP_STATE))
6051                 rtl8723a_set_bcn_func(padapter, 0);     /* Stop BCN */
6052
6053         /* set MSR to no link state -> infra. mode */
6054         Set_MSR23a(padapter, _HW_STATE_STATION_);
6055
6056         pmlmeinfo->state = WIFI_FW_NULL_STATE;
6057
6058         /* switch to the 20M Hz mode after disconnect */
6059         pmlmeext->cur_bwmode = HT_CHANNEL_WIDTH_20;
6060         pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
6061
6062         set_channel_bwmode23a(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode);
6063
6064         flush_all_cam_entry23a(padapter);
6065
6066         del_timer_sync(&pmlmeext->link_timer);
6067
6068         rtw_free_uc_swdec_pending_queue23a(padapter);
6069
6070         return  H2C_SUCCESS;
6071 }
6072
6073 static int
6074 rtw_scan_ch_decision(struct rtw_adapter *padapter,
6075                      struct rtw_ieee80211_channel *out, u32 out_num,
6076                      const struct rtw_ieee80211_channel *in, u32 in_num)
6077 {
6078         int i, j;
6079         int scan_ch_num = 0;
6080         int set_idx;
6081         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
6082
6083         /* clear out first */
6084         memset(out, 0, sizeof(struct rtw_ieee80211_channel)*out_num);
6085
6086         /* acquire channels from in */
6087         j = 0;
6088         for (i = 0;i<in_num;i++) {
6089                 if (in[i].hw_value && !(in[i].flags & IEEE80211_CHAN_DISABLED)
6090                         && (set_idx = rtw_ch_set_search_ch23a(pmlmeext->channel_set, in[i].hw_value)) >= 0
6091                 )
6092                 {
6093                         memcpy(&out[j], &in[i], sizeof(struct rtw_ieee80211_channel));
6094
6095                         if (pmlmeext->channel_set[set_idx].ScanType == SCAN_PASSIVE)
6096                                 out[j].flags &= IEEE80211_CHAN_NO_IR;
6097
6098                         j++;
6099                 }
6100                 if (j>= out_num)
6101                         break;
6102         }
6103
6104         /* if out is empty, use channel_set as default */
6105         if (j == 0) {
6106                 for (i = 0;i<pmlmeext->max_chan_nums;i++) {
6107                         out[i].hw_value = pmlmeext->channel_set[i].ChannelNum;
6108
6109                         if (pmlmeext->channel_set[i].ScanType == SCAN_PASSIVE)
6110                                 out[i].flags &= IEEE80211_CHAN_NO_IR;
6111
6112                         j++;
6113                 }
6114         }
6115
6116         if (padapter->setband == GHZ_24) {                              /*  2.4G */
6117                 for (i = 0; i < j ; i++) {
6118                         if (out[i].hw_value > 35)
6119                                 memset(&out[i], 0,
6120                                        sizeof(struct rtw_ieee80211_channel));
6121                         else
6122                                 scan_ch_num++;
6123                 }
6124                 j = scan_ch_num;
6125         } else if  (padapter->setband == GHZ_50) {                      /*  5G */
6126                 for (i = 0; i < j ; i++) {
6127                         if (out[i].hw_value > 35) {
6128                                 memcpy(&out[scan_ch_num++], &out[i], sizeof(struct rtw_ieee80211_channel));
6129                         }
6130                 }
6131                 j = scan_ch_num;
6132         } else
6133                 {}
6134
6135         return j;
6136 }
6137
6138 u8 sitesurvey_cmd_hdl23a(struct rtw_adapter *padapter, const u8 *pbuf)
6139 {
6140         struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
6141         const struct sitesurvey_parm *pparm = (struct sitesurvey_parm *)pbuf;
6142         u8 bdelayscan = false;
6143         u32 initialgain;
6144         u32 i;
6145
6146         if (pmlmeext->sitesurvey_res.state == SCAN_DISABLE) {
6147                 pmlmeext->sitesurvey_res.state = SCAN_START;
6148                 pmlmeext->sitesurvey_res.bss_cnt = 0;
6149                 pmlmeext->sitesurvey_res.channel_idx = 0;
6150
6151                 for (i = 0; i < RTW_SSID_SCAN_AMOUNT; i++) {
6152                         if (pparm->ssid[i].ssid_len) {
6153                                 memcpy(pmlmeext->sitesurvey_res.ssid[i].ssid,
6154                                        pparm->ssid[i].ssid, IW_ESSID_MAX_SIZE);
6155                                 pmlmeext->sitesurvey_res.ssid[i].ssid_len =
6156                                         pparm->ssid[i].ssid_len;
6157                         } else {
6158                                 pmlmeext->sitesurvey_res.ssid[i].ssid_len = 0;
6159                         }
6160                 }
6161
6162                 pmlmeext->sitesurvey_res.ch_num =
6163                         rtw_scan_ch_decision(padapter,
6164                                              pmlmeext->sitesurvey_res.ch,
6165                                              RTW_CHANNEL_SCAN_AMOUNT,
6166                                              pparm->ch, pparm->ch_num);
6167
6168                 pmlmeext->sitesurvey_res.scan_mode = pparm->scan_mode;
6169
6170                 /* issue null data if associating to the AP */
6171                 if (is_client_associated_to_ap23a(padapter)) {
6172                         pmlmeext->sitesurvey_res.state = SCAN_TXNULL;
6173
6174                         /* switch to correct channel of current network
6175                            before issue keep-alive frames */
6176                         if (rtw_get_oper_ch23a(padapter) != pmlmeext->cur_channel)
6177                                 SelectChannel23a(padapter, pmlmeext->cur_channel);
6178
6179                         issue_nulldata23a(padapter, NULL, 1, 3, 500);
6180
6181                         bdelayscan = true;
6182                 }
6183
6184                 if (bdelayscan) {
6185                         /* delay 50ms to protect nulldata(1). */
6186                         set_survey_timer(pmlmeext, 50);
6187                         return H2C_SUCCESS;
6188                 }
6189         }
6190
6191         if ((pmlmeext->sitesurvey_res.state == SCAN_START) ||
6192             (pmlmeext->sitesurvey_res.state == SCAN_TXNULL)) {
6193                 /* disable dynamic functions, such as high power, DIG */
6194                 rtl8723a_odm_support_ability_backup(padapter);
6195                 rtl8723a_odm_support_ability_clr(padapter,
6196                                                  DYNAMIC_FUNC_DISABLE);
6197
6198                 /* config the initial gain under scaning, need to
6199                    write the BB registers */
6200                 if (wdev_to_priv(padapter->rtw_wdev)->p2p_enabled == true)
6201                         initialgain = 0x30;
6202                 else
6203                         initialgain = 0x1E;
6204
6205                 rtl8723a_set_initial_gain(padapter, initialgain);
6206
6207                 /* set MSR to no link state */
6208                 Set_MSR23a(padapter, _HW_STATE_NOLINK_);
6209
6210                 rtl8723a_mlme_sitesurvey(padapter, 1);
6211
6212                 pmlmeext->sitesurvey_res.state = SCAN_PROCESS;
6213         }
6214
6215         site_survey23a(padapter);
6216
6217         return H2C_SUCCESS;
6218 }
6219
6220 u8 setauth_hdl23a(struct rtw_adapter *padapter, const u8 *pbuf)
6221 {
6222         const struct setauth_parm *pparm = (struct setauth_parm *)pbuf;
6223         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
6224         struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
6225
6226         if (pparm->mode < 4)
6227         {
6228                 pmlmeinfo->auth_algo = pparm->mode;
6229         }
6230
6231         return  H2C_SUCCESS;
6232 }
6233
6234 u8 setkey_hdl23a(struct rtw_adapter *padapter, const u8 *pbuf)
6235 {
6236         unsigned short                          ctrl;
6237         const struct setkey_parm *pparm = (struct setkey_parm *)pbuf;
6238         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
6239         struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
6240         unsigned char                                   null_sta[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
6241
6242         /* main tx key for wep. */
6243         if (pparm->set_tx)
6244                 pmlmeinfo->key_index = pparm->keyid;
6245
6246         /* write cam */
6247         ctrl = BIT(15) | ((pparm->algorithm) << 2) | pparm->keyid;
6248
6249         DBG_8723A_LEVEL(_drv_always_, "set group key to hw: alg:%d(WEP40-1 WEP104-5 TKIP-2 AES-4) "
6250                         "keyid:%d\n", pparm->algorithm, pparm->keyid);
6251         rtl8723a_cam_write(padapter, pparm->keyid, ctrl, null_sta, pparm->key);
6252
6253         /* allow multicast packets to driver */
6254         rtl8723a_on_rcr_am(padapter);
6255
6256         return H2C_SUCCESS;
6257 }
6258
6259 u8 set_stakey_hdl23a(struct rtw_adapter *padapter, const u8 *pbuf)
6260 {
6261         u16 ctrl = 0;
6262         u8 cam_id;/* cam_entry */
6263         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
6264         struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
6265         const struct set_stakey_parm *pparm = (struct set_stakey_parm *)pbuf;
6266
6267         /* cam_entry: */
6268         /* 0~3 for default key */
6269
6270         /* for concurrent mode (ap+sta): */
6271         /* default key is disable, using sw encrypt/decrypt */
6272         /* cam_entry = 4  for sta mode (macid = 0) */
6273         /* cam_entry(macid+3) = 5 ~ N for ap mode (aid = 1~N, macid = 2 ~N) */
6274
6275         /* for concurrent mode (sta+sta): */
6276         /* default key is disable, using sw encrypt/decrypt */
6277         /* cam_entry = 4 mapping to macid = 0 */
6278         /* cam_entry = 5 mapping to macid = 2 */
6279
6280         cam_id = 4;
6281
6282         DBG_8723A_LEVEL(_drv_always_, "set pairwise key to hw: alg:%d(WEP40-1 WEP104-5 TKIP-2 AES-4) camid:%d\n",
6283                         pparm->algorithm, cam_id);
6284         if ((pmlmeinfo->state&0x03) == WIFI_FW_AP_STATE)
6285         {
6286
6287                 struct sta_info *psta;
6288                 struct sta_priv *pstapriv = &padapter->stapriv;
6289
6290                 if (pparm->algorithm == _NO_PRIVACY_)   /*  clear cam entry */
6291                 {
6292                         clear_cam_entry23a(padapter, pparm->id);
6293                         return H2C_SUCCESS_RSP;
6294                 }
6295
6296                 psta = rtw_get_stainfo23a(pstapriv, pparm->addr);
6297                 if (psta)
6298                 {
6299                         ctrl = (BIT(15) | ((pparm->algorithm) << 2));
6300
6301                         DBG_8723A("r871x_set_stakey_hdl23a(): enc_algorithm =%d\n", pparm->algorithm);
6302
6303                         if ((psta->mac_id<1) || (psta->mac_id>(NUM_STA-4)))
6304                         {
6305                                 DBG_8723A("r871x_set_stakey_hdl23a():set_stakey failed, mac_id(aid) =%d\n", psta->mac_id);
6306                                 return H2C_REJECTED;
6307                         }
6308
6309                         cam_id = (psta->mac_id + 3);/* 0~3 for default key, cmd_id = macid + 3, macid = aid+1; */
6310
6311                         DBG_8723A("Write CAM, mac_addr =%x:%x:%x:%x:%x:%x, cam_entry =%d\n", pparm->addr[0],
6312                                                 pparm->addr[1], pparm->addr[2], pparm->addr[3], pparm->addr[4],
6313                                                 pparm->addr[5], cam_id);
6314
6315                         rtl8723a_cam_write(padapter, cam_id, ctrl,
6316                                            pparm->addr, pparm->key);
6317
6318                         return H2C_SUCCESS_RSP;
6319
6320                 }
6321                 else
6322                 {
6323                         DBG_8723A("r871x_set_stakey_hdl23a(): sta has been free\n");
6324                         return H2C_REJECTED;
6325                 }
6326
6327         }
6328
6329         /* below for sta mode */
6330
6331         if (pparm->algorithm == _NO_PRIVACY_)   /*  clear cam entry */
6332         {
6333                 clear_cam_entry23a(padapter, pparm->id);
6334                 return H2C_SUCCESS;
6335         }
6336
6337         ctrl = BIT(15) | ((pparm->algorithm) << 2);
6338
6339         rtl8723a_cam_write(padapter, cam_id, ctrl, pparm->addr, pparm->key);
6340
6341         pmlmeinfo->enc_algo = pparm->algorithm;
6342
6343         return H2C_SUCCESS;
6344 }
6345
6346 u8 add_ba_hdl23a(struct rtw_adapter *padapter, const u8 *pbuf)
6347 {
6348         const struct addBaReq_parm *pparm = (struct addBaReq_parm *)pbuf;
6349         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
6350         struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
6351
6352         struct sta_info *psta = rtw_get_stainfo23a(&padapter->stapriv, pparm->addr);
6353
6354         if (!psta)
6355                 return  H2C_SUCCESS;
6356
6357         if (((pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS) &&
6358              (pmlmeinfo->HT_enable)) ||
6359             ((pmlmeinfo->state & 0x03) == WIFI_FW_AP_STATE)) {
6360                 issue_action_BA23a(padapter, pparm->addr,
6361                                 WLAN_ACTION_ADDBA_REQ, (u16)pparm->tid);
6362                 mod_timer(&psta->addba_retry_timer,
6363                           jiffies + msecs_to_jiffies(ADDBA_TO));
6364         } else {
6365                 psta->htpriv.candidate_tid_bitmap &= ~CHKBIT(pparm->tid);
6366         }
6367         return  H2C_SUCCESS;
6368 }
6369
6370 u8 set_tx_beacon_cmd23a(struct rtw_adapter* padapter)
6371 {
6372         struct cmd_obj  *ph2c;
6373         struct Tx_Beacon_param  *ptxBeacon_parm;
6374         struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
6375         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
6376         struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
6377         u8      res = _SUCCESS;
6378         int len_diff = 0;
6379
6380
6381
6382         ph2c = (struct cmd_obj *)kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC);
6383         if (!ph2c) {
6384                 res = _FAIL;
6385                 goto exit;
6386         }
6387
6388         ptxBeacon_parm = (struct Tx_Beacon_param *)
6389                 kzalloc(sizeof(struct Tx_Beacon_param), GFP_ATOMIC);
6390         if (!ptxBeacon_parm) {
6391                 kfree(ph2c);
6392                 res = _FAIL;
6393                 goto exit;
6394         }
6395
6396         memcpy(&ptxBeacon_parm->network, &pmlmeinfo->network,
6397                sizeof(struct wlan_bssid_ex));
6398
6399         len_diff = update_hidden_ssid(
6400                 ptxBeacon_parm->network.IEs+_BEACON_IE_OFFSET_,
6401                 ptxBeacon_parm->network.IELength-_BEACON_IE_OFFSET_,
6402                 pmlmeinfo->hidden_ssid_mode);
6403         ptxBeacon_parm->network.IELength += len_diff;
6404
6405         init_h2fwcmd_w_parm_no_rsp(ph2c, ptxBeacon_parm, GEN_CMD_CODE(_TX_Beacon));
6406
6407         res = rtw_enqueue_cmd23a(pcmdpriv, ph2c);
6408
6409 exit:
6410
6411
6412
6413         return res;
6414 }
6415
6416 u8 mlme_evt_hdl23a(struct rtw_adapter *padapter, const u8 *pbuf)
6417 {
6418         u8 evt_code, evt_seq;
6419         u16 evt_sz;
6420         const struct C2HEvent_Header *c2h;
6421         void (*event_callback)(struct rtw_adapter *dev, const u8 *pbuf);
6422
6423         c2h = (struct C2HEvent_Header *)pbuf;
6424         evt_sz = c2h->len;
6425         evt_seq = c2h->seq;
6426         evt_code = c2h->ID;
6427
6428         /*  checking if event code is valid */
6429         if (evt_code >= MAX_C2HEVT) {
6430                 RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_, ("\nEvent Code(%d) mismatch!\n", evt_code));
6431                 goto _abort_event_;
6432         }
6433
6434         /*  checking if event size match the event parm size */
6435         if ((wlanevents[evt_code].parmsize != 0) &&
6436             (wlanevents[evt_code].parmsize != evt_sz)) {
6437                 RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_, ("\nEvent(%d) Parm Size mismatch (%d vs %d)!\n",
6438                         evt_code, wlanevents[evt_code].parmsize, evt_sz));
6439                 goto _abort_event_;
6440         }
6441
6442         event_callback = wlanevents[evt_code].event_callback;
6443         event_callback(padapter, pbuf + sizeof(struct C2HEvent_Header));
6444
6445 _abort_event_:
6446
6447         return H2C_SUCCESS;
6448 }
6449
6450 u8 h2c_msg_hdl23a(struct rtw_adapter *padapter, const u8 *pbuf)
6451 {
6452         if (!pbuf)
6453                 return H2C_PARAMETERS_ERROR;
6454
6455         return H2C_SUCCESS;
6456 }
6457
6458 u8 tx_beacon_hdl23a(struct rtw_adapter *padapter, const u8 *pbuf)
6459 {
6460         if (send_beacon23a(padapter) == _FAIL)
6461         {
6462                 DBG_8723A("issue_beacon23a, fail!\n");
6463                 return H2C_PARAMETERS_ERROR;
6464         }
6465 #ifdef CONFIG_8723AU_AP_MODE
6466         else /* tx bc/mc frames after update TIM */
6467         {
6468                 struct sta_info *psta_bmc;
6469                 struct list_head *plist, *phead, *ptmp;
6470                 struct xmit_frame *pxmitframe;
6471                 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
6472                 struct sta_priv  *pstapriv = &padapter->stapriv;
6473
6474                 /* for BC/MC Frames */
6475                 psta_bmc = rtw_get_bcmc_stainfo23a(padapter);
6476                 if (!psta_bmc)
6477                         return H2C_SUCCESS;
6478
6479                 if ((pstapriv->tim_bitmap&BIT(0)) && (psta_bmc->sleepq_len>0))
6480                 {
6481                         msleep(10);/*  10ms, ATIM(HIQ) Windows */
6482                         /* spin_lock_bh(&psta_bmc->sleep_q.lock); */
6483                         spin_lock_bh(&pxmitpriv->lock);
6484
6485                         phead = get_list_head(&psta_bmc->sleep_q);
6486
6487                         list_for_each_safe(plist, ptmp, phead) {
6488                                 pxmitframe = container_of(plist,
6489                                                           struct xmit_frame,
6490                                                           list);
6491
6492                                 list_del_init(&pxmitframe->list);
6493
6494                                 psta_bmc->sleepq_len--;
6495                                 if (psta_bmc->sleepq_len>0)
6496                                         pxmitframe->attrib.mdata = 1;
6497                                 else
6498                                         pxmitframe->attrib.mdata = 0;
6499
6500                                 pxmitframe->attrib.triggered = 1;
6501
6502                                 pxmitframe->attrib.qsel = 0x11;/* HIQ */
6503
6504                                 rtw_hal_xmit23aframe_enqueue(padapter, pxmitframe);
6505                         }
6506
6507                         /* spin_unlock_bh(&psta_bmc->sleep_q.lock); */
6508                         spin_unlock_bh(&pxmitpriv->lock);
6509                 }
6510
6511         }
6512 #endif
6513
6514         return H2C_SUCCESS;
6515 }
6516
6517 u8 set_ch_hdl23a(struct rtw_adapter *padapter, const u8 *pbuf)
6518 {
6519         const struct set_ch_parm *set_ch_parm;
6520         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
6521
6522         if (!pbuf)
6523                 return H2C_PARAMETERS_ERROR;
6524
6525         set_ch_parm = (struct set_ch_parm *)pbuf;
6526
6527         DBG_8723A("%s(%s): ch:%u, bw:%u, ch_offset:%u\n", __func__,
6528                   padapter->pnetdev->name, set_ch_parm->ch,
6529                   set_ch_parm->bw, set_ch_parm->ch_offset);
6530
6531         pmlmeext->cur_channel = set_ch_parm->ch;
6532         pmlmeext->cur_ch_offset = set_ch_parm->ch_offset;
6533         pmlmeext->cur_bwmode = set_ch_parm->bw;
6534
6535         set_channel_bwmode23a(padapter, set_ch_parm->ch, set_ch_parm->ch_offset, set_ch_parm->bw);
6536
6537         return  H2C_SUCCESS;
6538 }
6539
6540 u8 set_chplan_hdl23a(struct rtw_adapter *padapter, const u8 *pbuf)
6541 {
6542         const struct SetChannelPlan_param *setChannelPlan_param;
6543         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
6544
6545         if (!pbuf)
6546                 return H2C_PARAMETERS_ERROR;
6547
6548         setChannelPlan_param = (struct SetChannelPlan_param *)pbuf;
6549
6550         pmlmeext->max_chan_nums = init_channel_set(padapter, setChannelPlan_param->channel_plan, pmlmeext->channel_set);
6551         init_channel_list(padapter, pmlmeext->channel_set, pmlmeext->max_chan_nums, &pmlmeext->channel_list);
6552
6553         return  H2C_SUCCESS;
6554 }
6555
6556 u8 led_blink_hdl23a(struct rtw_adapter *padapter, const u8 *pbuf)
6557 {
6558         struct LedBlink_param *ledBlink_param;
6559
6560         if (!pbuf)
6561                 return H2C_PARAMETERS_ERROR;
6562
6563         ledBlink_param = (struct LedBlink_param *)pbuf;
6564
6565         return  H2C_SUCCESS;
6566 }
6567
6568 u8 set_csa_hdl23a(struct rtw_adapter *padapter, const u8 *pbuf)
6569 {
6570         return  H2C_REJECTED;
6571 }
6572
6573 /*  TDLS_WRCR           : write RCR DATA BIT */
6574 /*  TDLS_SD_PTI         : issue peer traffic indication */
6575 /*  TDLS_CS_OFF         : go back to the channel linked with AP, terminating channel switch procedure */
6576 /*  TDLS_INIT_CH_SEN    : init channel sensing, receive all data and mgnt frame */
6577 /*  TDLS_DONE_CH_SEN: channel sensing and report candidate channel */
6578 /*  TDLS_OFF_CH         : first time set channel to off channel */
6579 /*  TDLS_BASE_CH                : go back tp the channel linked with AP when set base channel as target channel */
6580 /*  TDLS_P_OFF_CH       : periodically go to off channel */
6581 /*  TDLS_P_BASE_CH      : periodically go back to base channel */
6582 /*  TDLS_RS_RCR         : restore RCR */
6583 /*  TDLS_CKALV_PH1      : check alive timer phase1 */
6584 /*  TDLS_CKALV_PH2      : check alive timer phase2 */
6585 /*  TDLS_FREE_STA       : free tdls sta */
6586 u8 tdls_hdl23a(struct rtw_adapter *padapter, const u8 *pbuf)
6587 {
6588         return H2C_REJECTED;
6589 }