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