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