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