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