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