• 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_WLAN_UTIL_C_
16 
17 #include <osdep_service.h>
18 #include <drv_types.h>
19 #include <linux/ieee80211.h>
20 #include <wifi.h>
21 #include <rtl8723a_spec.h>
22 
23 static unsigned char ARTHEROS_OUI1[] = {0x00, 0x03, 0x7f};
24 static unsigned char ARTHEROS_OUI2[] = {0x00, 0x13, 0x74};
25 
26 static unsigned char BROADCOM_OUI1[] = {0x00, 0x10, 0x18};
27 static unsigned char BROADCOM_OUI2[] = {0x00, 0x0a, 0xf7};
28 
29 static unsigned char CISCO_OUI[] = {0x00, 0x40, 0x96};
30 static unsigned char MARVELL_OUI[] = {0x00, 0x50, 0x43};
31 static unsigned char RALINK_OUI[] = {0x00, 0x0c, 0x43};
32 static unsigned char REALTEK_OUI[] = {0x00, 0xe0, 0x4c};
33 static unsigned char AIRGOCAP_OUI[] = {0x00, 0x0a, 0xf5};
34 static unsigned char EPIGRAM_OUI[] = {0x00, 0x90, 0x4c};
35 
36 static unsigned char WPA_TKIP_CIPHER[4] = {0x00, 0x50, 0xf2, 0x02};
37 static unsigned char RSN_TKIP_CIPHER[4] = {0x00, 0x0f, 0xac, 0x02};
38 
39 #define R2T_PHY_DELAY		0
40 
41 /* define WAIT_FOR_BCN_TO_MIN	3000 */
42 #define WAIT_FOR_BCN_TO_MIN	6000
43 #define WAIT_FOR_BCN_TO_MAX	20000
44 
45 static u8 rtw_basic_rate_cck[4] = {
46 	IEEE80211_CCK_RATE_1MB | IEEE80211_BASIC_RATE_MASK,
47 	IEEE80211_CCK_RATE_2MB | IEEE80211_BASIC_RATE_MASK,
48 	IEEE80211_CCK_RATE_5MB | IEEE80211_BASIC_RATE_MASK,
49 	IEEE80211_CCK_RATE_11MB | IEEE80211_BASIC_RATE_MASK
50 };
51 
52 static u8 rtw_basic_rate_ofdm[3] = {
53 	IEEE80211_OFDM_RATE_6MB | IEEE80211_BASIC_RATE_MASK,
54 	IEEE80211_OFDM_RATE_12MB | IEEE80211_BASIC_RATE_MASK,
55 	IEEE80211_OFDM_RATE_24MB | IEEE80211_BASIC_RATE_MASK
56 };
57 
58 static u8 rtw_basic_rate_mix[7] = {
59 	IEEE80211_CCK_RATE_1MB | IEEE80211_BASIC_RATE_MASK,
60 	IEEE80211_CCK_RATE_2MB | IEEE80211_BASIC_RATE_MASK,
61 	IEEE80211_CCK_RATE_5MB | IEEE80211_BASIC_RATE_MASK,
62 	IEEE80211_CCK_RATE_11MB | IEEE80211_BASIC_RATE_MASK,
63 	IEEE80211_OFDM_RATE_6MB | IEEE80211_BASIC_RATE_MASK,
64 	IEEE80211_OFDM_RATE_12MB | IEEE80211_BASIC_RATE_MASK,
65 	IEEE80211_OFDM_RATE_24MB | IEEE80211_BASIC_RATE_MASK
66 };
67 
cckrates_included23a(unsigned char * rate,int ratelen)68 int cckrates_included23a(unsigned char *rate, int ratelen)
69 {
70 	int	i;
71 
72 	for (i = 0; i < ratelen; i++) {
73 		if  (((rate[i]) & 0x7f) == 2 || ((rate[i]) & 0x7f) == 4 ||
74 		     ((rate[i]) & 0x7f) == 11  || ((rate[i]) & 0x7f) == 22)
75 			return true;
76 	}
77 
78 	return false;
79 }
80 
cckratesonly_included23a(unsigned char * rate,int ratelen)81 int cckratesonly_included23a(unsigned char *rate, int ratelen)
82 {
83 	int	i;
84 
85 	for (i = 0; i < ratelen; i++) {
86 		if  (((rate[i]) & 0x7f) != 2 && ((rate[i]) & 0x7f) != 4 &&
87 		     ((rate[i]) & 0x7f) != 11 && ((rate[i]) & 0x7f) != 22)
88 		return false;
89 	}
90 
91 	return true;
92 }
93 
networktype_to_raid23a(unsigned char network_type)94 unsigned char networktype_to_raid23a(unsigned char network_type)
95 {
96 	unsigned char raid;
97 
98 	switch (network_type) {
99 	case WIRELESS_11B:
100 		raid = RATR_INX_WIRELESS_B;
101 		break;
102 	case WIRELESS_11A:
103 	case WIRELESS_11G:
104 		raid = RATR_INX_WIRELESS_G;
105 		break;
106 	case WIRELESS_11BG:
107 		raid = RATR_INX_WIRELESS_GB;
108 		break;
109 	case WIRELESS_11_24N:
110 	case WIRELESS_11_5N:
111 		raid = RATR_INX_WIRELESS_N;
112 		break;
113 	case WIRELESS_11A_5N:
114 	case WIRELESS_11G_24N:
115 		raid = RATR_INX_WIRELESS_NG;
116 		break;
117 	case WIRELESS_11BG_24N:
118 		raid = RATR_INX_WIRELESS_NGB;
119 		break;
120 	default:
121 		raid = RATR_INX_WIRELESS_GB;
122 		break;
123 	}
124 	return raid;
125 }
126 
judge_network_type23a(struct rtw_adapter * padapter,unsigned char * rate,int ratelen)127 u8 judge_network_type23a(struct rtw_adapter *padapter,
128 			 unsigned char *rate, int ratelen)
129 {
130 	u8 network_type = 0;
131 	struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
132 	struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
133 
134 	if (pmlmeext->cur_channel > 14) {
135 		if (pmlmeinfo->HT_enable)
136 			network_type = WIRELESS_11_5N;
137 		network_type |= WIRELESS_11A;
138 	} else {
139 		if (pmlmeinfo->HT_enable)
140 			network_type = WIRELESS_11_24N;
141 
142 		if ((cckratesonly_included23a(rate, ratelen)) == true)
143 			network_type |= WIRELESS_11B;
144 		else if ((cckrates_included23a(rate, ratelen)) == true)
145 			network_type |= WIRELESS_11BG;
146 		else
147 			network_type |= WIRELESS_11G;
148 	}
149 	return	network_type;
150 }
151 
ratetbl_val_2wifirate(unsigned char rate)152 static unsigned char ratetbl_val_2wifirate(unsigned char rate)
153 {
154 	unsigned char val = 0;
155 
156 	switch (rate & 0x7f) {
157 	case 0:
158 		val = IEEE80211_CCK_RATE_1MB;
159 		break;
160 	case 1:
161 		val = IEEE80211_CCK_RATE_2MB;
162 		break;
163 	case 2:
164 		val = IEEE80211_CCK_RATE_5MB;
165 		break;
166 	case 3:
167 		val = IEEE80211_CCK_RATE_11MB;
168 		break;
169 	case 4:
170 		val = IEEE80211_OFDM_RATE_6MB;
171 		break;
172 	case 5:
173 		val = IEEE80211_OFDM_RATE_9MB;
174 		break;
175 	case 6:
176 		val = IEEE80211_OFDM_RATE_12MB;
177 		break;
178 	case 7:
179 		val = IEEE80211_OFDM_RATE_18MB;
180 		break;
181 	case 8:
182 		val = IEEE80211_OFDM_RATE_24MB;
183 		break;
184 	case 9:
185 		val = IEEE80211_OFDM_RATE_36MB;
186 		break;
187 	case 10:
188 		val = IEEE80211_OFDM_RATE_48MB;
189 		break;
190 	case 11:
191 		val = IEEE80211_OFDM_RATE_54MB;
192 		break;
193 	}
194 	return val;
195 }
196 
is_basicrate(struct rtw_adapter * padapter,unsigned char rate)197 static int is_basicrate(struct rtw_adapter *padapter, unsigned char rate)
198 {
199 	int i;
200 	unsigned char val;
201 	struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
202 
203 	for (i = 0; i < NumRates; i++) {
204 		val = pmlmeext->basicrate[i];
205 
206 		if (val != 0xff && val != 0xfe) {
207 			if (rate == ratetbl_val_2wifirate(val))
208 				return true;
209 		}
210 	}
211 
212 	return false;
213 }
214 
ratetbl2rateset(struct rtw_adapter * padapter,unsigned char * rateset)215 static unsigned int ratetbl2rateset(struct rtw_adapter *padapter,
216 				    unsigned char *rateset)
217 {
218 	int i;
219 	unsigned char rate;
220 	unsigned int len = 0;
221 	struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
222 
223 	for (i = 0; i < NumRates; i++) {
224 		rate = pmlmeext->datarate[i];
225 
226 		switch (rate) {
227 		case 0xff:
228 			return len;
229 		case 0xfe:
230 			continue;
231 		default:
232 			rate = ratetbl_val_2wifirate(rate);
233 
234 			if (is_basicrate(padapter, rate) == true)
235 				rate |= IEEE80211_BASIC_RATE_MASK;
236 
237 			rateset[len] = rate;
238 			len++;
239 			break;
240 		}
241 	}
242 	return len;
243 }
244 
get_rate_set23a(struct rtw_adapter * padapter,unsigned char * pbssrate,int * bssrate_len)245 void get_rate_set23a(struct rtw_adapter *padapter,
246 		     unsigned char *pbssrate, int *bssrate_len)
247 {
248 	unsigned char supportedrates[NumRates];
249 
250 	memset(supportedrates, 0, NumRates);
251 	*bssrate_len = ratetbl2rateset(padapter, supportedrates);
252 	memcpy(pbssrate, supportedrates, *bssrate_len);
253 }
254 
UpdateBrateTbl23a(struct rtw_adapter * Adapter,u8 * mBratesOS)255 void UpdateBrateTbl23a(struct rtw_adapter *Adapter, u8 *mBratesOS)
256 {
257 	u8 i;
258 	u8 rate;
259 
260 	/*  1M, 2M, 5.5M, 11M, 6M, 12M, 24M are mandatory. */
261 	for (i = 0; i < NDIS_802_11_LENGTH_RATES_EX; i++) {
262 		rate = mBratesOS[i] & 0x7f;
263 		switch (rate) {
264 		case IEEE80211_CCK_RATE_1MB:
265 		case IEEE80211_CCK_RATE_2MB:
266 		case IEEE80211_CCK_RATE_5MB:
267 		case IEEE80211_CCK_RATE_11MB:
268 		case IEEE80211_OFDM_RATE_6MB:
269 		case IEEE80211_OFDM_RATE_12MB:
270 		case IEEE80211_OFDM_RATE_24MB:
271 			mBratesOS[i] |= IEEE80211_BASIC_RATE_MASK;
272 			break;
273 		default:
274 			break;
275 		}
276 	}
277 }
278 
Update23aTblForSoftAP(u8 * bssrateset,u32 bssratelen)279 void Update23aTblForSoftAP(u8 *bssrateset, u32 bssratelen)
280 {
281 	u8 i;
282 	u8 rate;
283 
284 	for (i = 0; i < bssratelen; i++) {
285 		rate = bssrateset[i] & 0x7f;
286 		switch (rate) {
287 		case IEEE80211_CCK_RATE_1MB:
288 		case IEEE80211_CCK_RATE_2MB:
289 		case IEEE80211_CCK_RATE_5MB:
290 		case IEEE80211_CCK_RATE_11MB:
291 			bssrateset[i] |= IEEE80211_BASIC_RATE_MASK;
292 			break;
293 		}
294 	}
295 }
296 
rtw_get_oper_ch23a(struct rtw_adapter * adapter)297 inline u8 rtw_get_oper_ch23a(struct rtw_adapter *adapter)
298 {
299 	return adapter_to_dvobj(adapter)->oper_channel;
300 }
301 
rtw_set_oper_ch23a(struct rtw_adapter * adapter,u8 ch)302 inline void rtw_set_oper_ch23a(struct rtw_adapter *adapter, u8 ch)
303 {
304 	adapter_to_dvobj(adapter)->oper_channel = ch;
305 }
306 
rtw_get_oper_bw23a(struct rtw_adapter * adapter)307 inline u8 rtw_get_oper_bw23a(struct rtw_adapter *adapter)
308 {
309 	return adapter_to_dvobj(adapter)->oper_bwmode;
310 }
311 
rtw_set_oper_bw23a(struct rtw_adapter * adapter,u8 bw)312 inline void rtw_set_oper_bw23a(struct rtw_adapter *adapter, u8 bw)
313 {
314 	adapter_to_dvobj(adapter)->oper_bwmode = bw;
315 }
316 
rtw_get_oper_ch23aoffset(struct rtw_adapter * adapter)317 inline u8 rtw_get_oper_ch23aoffset(struct rtw_adapter *adapter)
318 {
319 	return adapter_to_dvobj(adapter)->oper_ch_offset;
320 }
321 
rtw_set_oper_ch23aoffset23a(struct rtw_adapter * adapter,u8 offset)322 inline void rtw_set_oper_ch23aoffset23a(struct rtw_adapter *adapter, u8 offset)
323 {
324 	adapter_to_dvobj(adapter)->oper_ch_offset = offset;
325 }
326 
SelectChannel23a(struct rtw_adapter * padapter,unsigned char channel)327 void SelectChannel23a(struct rtw_adapter *padapter, unsigned char channel)
328 {
329 	mutex_lock(&adapter_to_dvobj(padapter)->setch_mutex);
330 
331 	/* saved channel info */
332 	rtw_set_oper_ch23a(padapter, channel);
333 
334 	PHY_SwChnl8723A(padapter, channel);
335 
336 	mutex_unlock(&adapter_to_dvobj(padapter)->setch_mutex);
337 }
338 
set_bwmode(struct rtw_adapter * padapter,unsigned short bwmode,unsigned char channel_offset)339 static void set_bwmode(struct rtw_adapter *padapter, unsigned short bwmode,
340 		       unsigned char channel_offset)
341 {
342 	mutex_lock(&adapter_to_dvobj(padapter)->setbw_mutex);
343 
344 	/* saved bw info */
345 	rtw_set_oper_bw23a(padapter, bwmode);
346 	rtw_set_oper_ch23aoffset23a(padapter, channel_offset);
347 
348 	PHY_SetBWMode23a8723A(padapter, (enum ht_channel_width)bwmode,
349 			      channel_offset);
350 
351 	mutex_unlock(&adapter_to_dvobj(padapter)->setbw_mutex);
352 }
353 
set_channel_bwmode23a(struct rtw_adapter * padapter,unsigned char channel,unsigned char channel_offset,unsigned short bwmode)354 void set_channel_bwmode23a(struct rtw_adapter *padapter, unsigned char channel,
355 			   unsigned char channel_offset, unsigned short bwmode)
356 {
357 	u8 center_ch;
358 
359 	if (bwmode == HT_CHANNEL_WIDTH_20 ||
360 	    channel_offset == HAL_PRIME_CHNL_OFFSET_DONT_CARE) {
361 		/* SelectChannel23a(padapter, channel); */
362 		center_ch = channel;
363 	} else {
364 		/* switch to the proper channel */
365 		if (channel_offset == HAL_PRIME_CHNL_OFFSET_LOWER) {
366 			/* SelectChannel23a(padapter, channel + 2); */
367 			center_ch = channel + 2;
368 		} else {
369 			/* SelectChannel23a(padapter, channel - 2); */
370 			center_ch = channel - 2;
371 		}
372 	}
373 
374 	/* set Channel */
375 	mutex_lock(&adapter_to_dvobj(padapter)->setch_mutex);
376 
377 	/* saved channel/bw info */
378 	rtw_set_oper_ch23a(padapter, channel);
379 	rtw_set_oper_bw23a(padapter, bwmode);
380 	rtw_set_oper_ch23aoffset23a(padapter, channel_offset);
381 
382 	PHY_SwChnl8723A(padapter, center_ch); /*  set center channel */
383 
384 	mutex_unlock(&adapter_to_dvobj(padapter)->setch_mutex);
385 
386 	set_bwmode(padapter, bwmode, channel_offset);
387 }
388 
get_my_bssid23a(struct wlan_bssid_ex * pnetwork)389 inline u8 *get_my_bssid23a(struct wlan_bssid_ex *pnetwork)
390 {
391 	return pnetwork->MacAddress;
392 }
393 
is_client_associated_to_ap23a(struct rtw_adapter * padapter)394 bool is_client_associated_to_ap23a(struct rtw_adapter *padapter)
395 {
396 	struct mlme_ext_priv *pmlmeext;
397 	struct mlme_ext_info *pmlmeinfo;
398 
399 	if (!padapter)
400 		return false;
401 
402 	pmlmeext = &padapter->mlmeextpriv;
403 	pmlmeinfo = &pmlmeext->mlmext_info;
404 
405 	if (pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS &&
406 	    (pmlmeinfo->state & 0x03) == MSR_INFRA)
407 		return true;
408 	else
409 		return false;
410 }
411 
is_client_associated_to_ibss23a(struct rtw_adapter * padapter)412 bool is_client_associated_to_ibss23a(struct rtw_adapter *padapter)
413 {
414 	struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
415 	struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
416 
417 	if (pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS &&
418 	    (pmlmeinfo->state & 0x03) == MSR_ADHOC)
419 		return true;
420 	else
421 		return false;
422 }
423 
is_IBSS_empty23a(struct rtw_adapter * padapter)424 bool is_IBSS_empty23a(struct rtw_adapter *padapter)
425 {
426 	unsigned int i;
427 	struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
428 	struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
429 
430 	for (i = IBSS_START_MAC_ID; i < NUM_STA; i++) {
431 		if (pmlmeinfo->FW_sta_info[i].status == 1)
432 			return false;
433 	}
434 
435 	return true;
436 }
437 
decide_wait_for_beacon_timeout23a(unsigned int bcn_interval)438 unsigned int decide_wait_for_beacon_timeout23a(unsigned int bcn_interval)
439 {
440 	if ((bcn_interval << 2) < WAIT_FOR_BCN_TO_MIN)
441 		return WAIT_FOR_BCN_TO_MIN;
442 	else if ((bcn_interval << 2) > WAIT_FOR_BCN_TO_MAX)
443 		return WAIT_FOR_BCN_TO_MAX;
444 	else
445 		return bcn_interval << 2;
446 }
447 
clear_cam_entry23a(struct rtw_adapter * padapter,u8 entry)448 void clear_cam_entry23a(struct rtw_adapter *padapter, u8 entry)
449 {
450 	unsigned char null_sta[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
451 
452 	unsigned char null_key[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
453 				    0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
454 				    0x00, 0x00, 0x00, 0x00};
455 
456 	rtl8723a_cam_write(padapter, entry, 0, null_sta, null_key);
457 }
458 
allocate_fw_sta_entry23a(struct rtw_adapter * padapter)459 int allocate_fw_sta_entry23a(struct rtw_adapter *padapter)
460 {
461 	unsigned int mac_id;
462 	struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
463 	struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
464 
465 	for (mac_id = IBSS_START_MAC_ID; mac_id < NUM_STA; mac_id++) {
466 		if (pmlmeinfo->FW_sta_info[mac_id].status == 0) {
467 			pmlmeinfo->FW_sta_info[mac_id].status = 1;
468 			pmlmeinfo->FW_sta_info[mac_id].retry = 0;
469 			break;
470 		}
471 	}
472 
473 	return mac_id;
474 }
475 
flush_all_cam_entry23a(struct rtw_adapter * padapter)476 void flush_all_cam_entry23a(struct rtw_adapter *padapter)
477 {
478 	struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
479 	struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
480 
481 	rtl8723a_cam_invalidate_all(padapter);
482 
483 	memset(pmlmeinfo->FW_sta_info, 0, sizeof(pmlmeinfo->FW_sta_info));
484 }
485 
WMM_param_handler23a(struct rtw_adapter * padapter,const u8 * p)486 int WMM_param_handler23a(struct rtw_adapter *padapter, const u8 *p)
487 {
488 	/* struct registry_priv	*pregpriv = &padapter->registrypriv; */
489 	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
490 	struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
491 	struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
492 
493 	if (pmlmepriv->qos_option == 0) {
494 		pmlmeinfo->WMM_enable = 0;
495 		return _FAIL;
496 	}
497 
498 	pmlmeinfo->WMM_enable = 1;
499 	memcpy(&pmlmeinfo->WMM_param, p + 2 + 6,
500 	       sizeof(struct WMM_para_element));
501 	return true;
502 }
503 
WMMOnAssocRsp23a(struct rtw_adapter * padapter)504 void WMMOnAssocRsp23a(struct rtw_adapter *padapter)
505 {
506 	u8 ACI, ACM, AIFS, ECWMin, ECWMax, aSifsTime;
507 	u8 acm_mask;
508 	u16 TXOP;
509 	u32 acParm, i;
510 	u32 edca[4], inx[4];
511 	struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
512 	struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
513 	struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
514 	struct registry_priv *pregpriv = &padapter->registrypriv;
515 
516 	if (pmlmeinfo->WMM_enable == 0) {
517 		padapter->mlmepriv.acm_mask = 0;
518 		return;
519 	}
520 
521 	acm_mask = 0;
522 
523 	if (pmlmeext->cur_wireless_mode == WIRELESS_11B)
524 		aSifsTime = 10;
525 	else
526 		aSifsTime = 16;
527 
528 	for (i = 0; i < 4; i++) {
529 		ACI = (pmlmeinfo->WMM_param.ac_param[i].ACI_AIFSN >> 5) & 0x03;
530 		ACM = (pmlmeinfo->WMM_param.ac_param[i].ACI_AIFSN >> 4) & 0x01;
531 
532 		/* AIFS = AIFSN * slot time + SIFS - r2t phy delay */
533 		AIFS = (pmlmeinfo->WMM_param.ac_param[i].ACI_AIFSN & 0x0f) *
534 			pmlmeinfo->slotTime + aSifsTime;
535 
536 		ECWMin = pmlmeinfo->WMM_param.ac_param[i].CW & 0x0f;
537 		ECWMax = (pmlmeinfo->WMM_param.ac_param[i].CW & 0xf0) >> 4;
538 		TXOP = le16_to_cpu(pmlmeinfo->WMM_param.ac_param[i].TXOP_limit);
539 
540 		acParm = AIFS | (ECWMin << 8) | (ECWMax << 12) | (TXOP << 16);
541 
542 		switch (ACI) {
543 		case 0x0:
544 			rtl8723a_set_ac_param_be(padapter, acParm);
545 			acm_mask |= (ACM? BIT(1):0);
546 			edca[XMIT_BE_QUEUE] = acParm;
547 			break;
548 		case 0x1:
549 			rtl8723a_set_ac_param_bk(padapter, acParm);
550 			/* acm_mask |= (ACM? BIT(0):0); */
551 			edca[XMIT_BK_QUEUE] = acParm;
552 			break;
553 		case 0x2:
554 			rtl8723a_set_ac_param_vi(padapter, acParm);
555 			acm_mask |= (ACM? BIT(2):0);
556 			edca[XMIT_VI_QUEUE] = acParm;
557 			break;
558 		case 0x3:
559 			rtl8723a_set_ac_param_vo(padapter, acParm);
560 			acm_mask |= (ACM? BIT(3):0);
561 			edca[XMIT_VO_QUEUE] = acParm;
562 			break;
563 		}
564 
565 		DBG_8723A("WMM(%x): %x, %x\n", ACI, ACM, acParm);
566 	}
567 
568 	if (padapter->registrypriv.acm_method == 1)
569 		rtl8723a_set_acm_ctrl(padapter, acm_mask);
570 	else
571 		padapter->mlmepriv.acm_mask = acm_mask;
572 
573 	inx[0] = 0; inx[1] = 1; inx[2] = 2; inx[3] = 3;
574 
575 	if (pregpriv->wifi_spec == 1) {
576 		u32 j, tmp, change_inx = false;
577 
578 		/* entry indx: 0->vo, 1->vi, 2->be, 3->bk. */
579 		for (i = 0; i < 4; i++) {
580 			for (j = i+1; j < 4; j++) {
581 				/* compare CW and AIFS */
582 				if ((edca[j] & 0xFFFF) < (edca[i] & 0xFFFF)) {
583 					change_inx = true;
584 				} else if ((edca[j] & 0xFFFF) ==
585 					   (edca[i] & 0xFFFF)) {
586 					/* compare TXOP */
587 					if ((edca[j] >> 16) > (edca[i] >> 16))
588 						change_inx = true;
589 				}
590 
591 				if (change_inx) {
592 					tmp = edca[i];
593 					edca[i] = edca[j];
594 					edca[j] = tmp;
595 
596 					tmp = inx[i];
597 					inx[i] = inx[j];
598 					inx[j] = tmp;
599 
600 					change_inx = false;
601 				}
602 			}
603 		}
604 	}
605 
606 	for (i = 0; i<4; i++) {
607 		pxmitpriv->wmm_para_seq[i] = inx[i];
608 		DBG_8723A("wmm_para_seq(%d): %d\n", i,
609 			  pxmitpriv->wmm_para_seq[i]);
610 	}
611 
612 	return;
613 }
614 
bwmode_update_check(struct rtw_adapter * padapter,const u8 * p)615 static void bwmode_update_check(struct rtw_adapter *padapter, const u8 *p)
616 {
617 	struct ieee80211_ht_operation *pHT_info;
618 	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
619 	struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
620 	struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
621 	struct registry_priv *pregistrypriv = &padapter->registrypriv;
622 	struct ht_priv *phtpriv = &pmlmepriv->htpriv;
623 	unsigned char new_bwmode;
624 	unsigned char new_ch_offset;
625 
626 	if (!p)
627 		return;
628 	if (!phtpriv->ht_option)
629 		return;
630 	if (p[1] != sizeof(struct ieee80211_ht_operation))
631 		return;
632 
633 	pHT_info = (struct ieee80211_ht_operation *)(p + 2);
634 
635 	if ((pHT_info->ht_param & IEEE80211_HT_PARAM_CHAN_WIDTH_ANY) &&
636 	    pregistrypriv->cbw40_enable) {
637 		new_bwmode = HT_CHANNEL_WIDTH_40;
638 
639 		switch (pHT_info->ht_param & IEEE80211_HT_PARAM_CHA_SEC_OFFSET){
640 		case IEEE80211_HT_PARAM_CHA_SEC_ABOVE:
641 			new_ch_offset = HAL_PRIME_CHNL_OFFSET_LOWER;
642 			break;
643 		case IEEE80211_HT_PARAM_CHA_SEC_BELOW:
644 			new_ch_offset = HAL_PRIME_CHNL_OFFSET_UPPER;
645 			break;
646 		default:
647 			new_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
648 			break;
649 		}
650 	} else {
651 		new_bwmode = HT_CHANNEL_WIDTH_20;
652 		new_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
653 	}
654 
655 	if (new_bwmode != pmlmeext->cur_bwmode ||
656 	    new_ch_offset != pmlmeext->cur_ch_offset) {
657 		pmlmeinfo->bwmode_updated = true;
658 
659 		pmlmeext->cur_bwmode = new_bwmode;
660 		pmlmeext->cur_ch_offset = new_ch_offset;
661 
662 		/* update HT info also */
663 		HT_info_handler23a(padapter, p);
664 	} else
665 		pmlmeinfo->bwmode_updated = false;
666 
667 	if (pmlmeinfo->bwmode_updated) {
668 		struct sta_info *psta;
669 		struct wlan_bssid_ex *cur_network = &pmlmeinfo->network;
670 		struct sta_priv	*pstapriv = &padapter->stapriv;
671 
672 		/* set_channel_bwmode23a(padapter, pmlmeext->cur_channel,
673 		   pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode); */
674 
675 		/* update ap's stainfo */
676 		psta = rtw_get_stainfo23a(pstapriv, cur_network->MacAddress);
677 		if (psta) {
678 			struct ht_priv *phtpriv_sta = &psta->htpriv;
679 
680 			if (phtpriv_sta->ht_option) {
681 				/*  bwmode */
682 				phtpriv_sta->bwmode = pmlmeext->cur_bwmode;
683 				phtpriv_sta->ch_offset =
684 					pmlmeext->cur_ch_offset;
685 			} else {
686 				phtpriv_sta->bwmode = HT_CHANNEL_WIDTH_20;
687 				phtpriv_sta->ch_offset =
688 					HAL_PRIME_CHNL_OFFSET_DONT_CARE;
689 			}
690 		}
691 	}
692 }
693 
HT_caps_handler23a(struct rtw_adapter * padapter,const u8 * p)694 void HT_caps_handler23a(struct rtw_adapter *padapter, const u8 *p)
695 {
696 	unsigned int i;
697 	u8 rf_type;
698 	u8 max_AMPDU_len, min_MPDU_spacing;
699 	struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
700 	struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
701 	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
702 	struct ht_priv *phtpriv = &pmlmepriv->htpriv;
703 	struct ieee80211_ht_cap *cap;
704 	u8 *dstcap;
705 
706 	if (!p)
707 		return;
708 
709 	if (!phtpriv->ht_option)
710 		return;
711 
712 	pmlmeinfo->HT_caps_enable = 1;
713 
714 	cap = &pmlmeinfo->ht_cap;
715 	dstcap = (u8 *)cap;
716 	for (i = 0; i < p[1]; i++) {
717 		if (i != 2) {
718 			dstcap[i] &= p[i + 2];
719 		} else {
720 			/* modify from  fw by Thomas 2010/11/17 */
721 			if ((cap->ampdu_params_info &
722 			     IEEE80211_HT_AMPDU_PARM_FACTOR) >
723 			    (p[i + 2] & IEEE80211_HT_AMPDU_PARM_FACTOR))
724 				max_AMPDU_len = p[i + 2] &
725 					IEEE80211_HT_AMPDU_PARM_FACTOR;
726 			else
727 				max_AMPDU_len = cap->ampdu_params_info &
728 					IEEE80211_HT_AMPDU_PARM_FACTOR;
729 
730 			if ((cap->ampdu_params_info &
731 			     IEEE80211_HT_AMPDU_PARM_DENSITY) >
732 			    (p[i + 2] & IEEE80211_HT_AMPDU_PARM_DENSITY))
733 				min_MPDU_spacing = cap->ampdu_params_info &
734 					IEEE80211_HT_AMPDU_PARM_DENSITY;
735 			else
736 				min_MPDU_spacing = p[i + 2] &
737 					IEEE80211_HT_AMPDU_PARM_DENSITY;
738 
739 			cap->ampdu_params_info =
740 				max_AMPDU_len | min_MPDU_spacing;
741 		}
742 	}
743 
744 	rf_type = rtl8723a_get_rf_type(padapter);
745 
746 	/* update the MCS rates */
747 	for (i = 0; i < IEEE80211_HT_MCS_MASK_LEN; i++) {
748 		if (rf_type == RF_1T1R || rf_type == RF_1T2R)
749 			cap->mcs.rx_mask[i] &= MCS_rate_1R23A[i];
750 		else
751 			cap->mcs.rx_mask[i] &= MCS_rate_2R23A[i];
752 	}
753 	return;
754 }
755 
HT_info_handler23a(struct rtw_adapter * padapter,const u8 * p)756 void HT_info_handler23a(struct rtw_adapter *padapter, const u8 *p)
757 {
758 	struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
759 	struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
760 	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
761 	struct ht_priv *phtpriv = &pmlmepriv->htpriv;
762 
763 	if (!p)
764 		return;
765 
766 	if (!phtpriv->ht_option)
767 		return;
768 
769 	if (p[1] != sizeof(struct ieee80211_ht_operation))
770 		return;
771 
772 	pmlmeinfo->HT_info_enable = 1;
773 	memcpy(&pmlmeinfo->HT_info, p + 2, p[1]);
774 	return;
775 }
776 
HTOnAssocRsp23a(struct rtw_adapter * padapter)777 void HTOnAssocRsp23a(struct rtw_adapter *padapter)
778 {
779 	unsigned char max_AMPDU_len;
780 	unsigned char min_MPDU_spacing;
781 	/* struct registry_priv	 *pregpriv = &padapter->registrypriv; */
782 	struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
783 	struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
784 
785 	DBG_8723A("%s\n", __func__);
786 
787 	if (pmlmeinfo->HT_info_enable && pmlmeinfo->HT_caps_enable)
788 		pmlmeinfo->HT_enable = 1;
789 	else {
790 		pmlmeinfo->HT_enable = 0;
791 		/* set_channel_bwmode23a(padapter, pmlmeext->cur_channel,
792 		   pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode); */
793 		return;
794 	}
795 
796 	/* handle A-MPDU parameter field */
797 	/*
798 		AMPDU_para [1:0]:Max AMPDU Len => 0:8k , 1:16k, 2:32k, 3:64k
799 		AMPDU_para [4:2]:Min MPDU Start Spacing
800 	*/
801 	max_AMPDU_len = pmlmeinfo->ht_cap.ampdu_params_info &
802 		IEEE80211_HT_AMPDU_PARM_FACTOR;
803 
804 	min_MPDU_spacing =
805 		(pmlmeinfo->ht_cap.ampdu_params_info &
806 		 IEEE80211_HT_AMPDU_PARM_DENSITY) >> 2;
807 
808 	rtl8723a_set_ampdu_min_space(padapter, min_MPDU_spacing);
809 	rtl8723a_set_ampdu_factor(padapter, max_AMPDU_len);
810 }
811 
ERP_IE_handler23a(struct rtw_adapter * padapter,const u8 * p)812 void ERP_IE_handler23a(struct rtw_adapter *padapter, const u8 *p)
813 {
814 	struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
815 	struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
816 
817 	if (p[1] > 1)
818 		return;
819 
820 	pmlmeinfo->ERP_enable = 1;
821 	memcpy(&pmlmeinfo->ERP_IE, p + 2, p[1]);
822 }
823 
VCS_update23a(struct rtw_adapter * padapter,struct sta_info * psta)824 void VCS_update23a(struct rtw_adapter *padapter, struct sta_info *psta)
825 {
826 	struct registry_priv *pregpriv = &padapter->registrypriv;
827 	struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
828 	struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
829 
830 	switch (pregpriv->vrtl_carrier_sense) { /* 0:off 1:on 2:auto */
831 	case 0: /* off */
832 		psta->rtsen = 0;
833 		psta->cts2self = 0;
834 		break;
835 	case 1: /* on */
836 		if (pregpriv->vcs_type == 1) { /* 1:RTS/CTS 2:CTS to self */
837 			psta->rtsen = 1;
838 			psta->cts2self = 0;
839 		} else {
840 			psta->rtsen = 0;
841 			psta->cts2self = 1;
842 		}
843 		break;
844 	case 2: /* auto */
845 	default:
846 		if (pmlmeinfo->ERP_enable && pmlmeinfo->ERP_IE & BIT(1)) {
847 			if (pregpriv->vcs_type == 1) {
848 				psta->rtsen = 1;
849 				psta->cts2self = 0;
850 			} else {
851 				psta->rtsen = 0;
852 				psta->cts2self = 1;
853 			}
854 		} else {
855 			psta->rtsen = 0;
856 			psta->cts2self = 0;
857 		}
858 		break;
859 	}
860 }
861 
rtw_check_bcn_info23a(struct rtw_adapter * Adapter,struct ieee80211_mgmt * mgmt,u32 pkt_len)862 int rtw_check_bcn_info23a(struct rtw_adapter *Adapter,
863 			  struct ieee80211_mgmt *mgmt, u32 pkt_len)
864 {
865 	struct wlan_network *cur_network = &Adapter->mlmepriv.cur_network;
866 	struct ieee80211_ht_operation *pht_info;
867 	unsigned short val16;
868 	u8 crypto, bcn_channel;
869 	int group_cipher = 0, pairwise_cipher = 0, is_8021x = 0, r;
870 	int pie_len, ssid_len, privacy;
871 	const u8 *p, *ssid;
872 
873 	if (is_client_associated_to_ap23a(Adapter) == false)
874 		return _SUCCESS;
875 
876 	if (unlikely(!ieee80211_is_beacon(mgmt->frame_control))) {
877 		printk(KERN_WARNING "%s: received a non beacon frame!\n",
878 		       __func__);
879 		return _FAIL;
880 	}
881 
882 	if (!ether_addr_equal(cur_network->network.MacAddress, mgmt->bssid)) {
883 		DBG_8723A("%s: linked but recv other bssid bcn"
884 			  MAC_FMT MAC_FMT "\n", __func__, MAC_ARG(mgmt->bssid),
885 			  MAC_ARG(cur_network->network.MacAddress));
886 		return _FAIL;
887 	}
888 
889 	/* check bw and channel offset */
890 	/* parsing HT_CAP_IE */
891 	pie_len = pkt_len - offsetof(struct ieee80211_mgmt, u.beacon.variable);
892 
893 	/* Checking for channel */
894 	p = cfg80211_find_ie(WLAN_EID_DS_PARAMS, mgmt->u.beacon.variable,
895 			     pie_len);
896 	if (p)
897 		bcn_channel = p[2];
898 	else {
899 		/* In 5G, some ap do not have DSSET IE checking HT
900 		   info for channel */
901 		p = cfg80211_find_ie(WLAN_EID_HT_OPERATION,
902 				     mgmt->u.beacon.variable, pie_len);
903 
904 		if (p && p[1] > 0) {
905 			pht_info = (struct ieee80211_ht_operation *)(p + 2);
906 			bcn_channel = pht_info->primary_chan;
907 		} else { /* we don't find channel IE, so don't check it */
908 			DBG_8723A("Oops: %s we don't find channel IE, so don't "
909 				  "check it\n", __func__);
910 			bcn_channel = Adapter->mlmeextpriv.cur_channel;
911 		}
912 	}
913 	if (bcn_channel != Adapter->mlmeextpriv.cur_channel) {
914 		DBG_8723A("%s beacon channel:%d cur channel:%d disconnect\n",
915 			  __func__, bcn_channel,
916 			  Adapter->mlmeextpriv.cur_channel);
917 		goto _mismatch;
918 	}
919 
920 	/* checking SSID */
921 	p = cfg80211_find_ie(WLAN_EID_SSID, mgmt->u.beacon.variable, pie_len);
922 	if (p && p[1]) {
923 		ssid = p + 2;
924 		ssid_len = p[1];
925 	} else {
926 		DBG_8723A("%s marc: cannot find SSID for survey event\n",
927 			  __func__);
928 		ssid = NULL;
929 		ssid_len = 0;
930 	}
931 
932 	RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_,
933 		 ("%s bssid.Ssid.Ssid:%s bssid.Ssid.SsidLength:%d "
934 		  "cur_network->network.Ssid.Ssid:%s len:%d\n", __func__,
935 		  ssid, ssid_len, cur_network->network.Ssid.ssid,
936 		  cur_network->network.Ssid.ssid_len));
937 
938 	if (ssid_len != cur_network->network.Ssid.ssid_len || ssid_len > 32 ||
939 	    (ssid_len &&
940 	     memcmp(ssid, cur_network->network.Ssid.ssid, ssid_len))) {
941 		DBG_8723A("%s(), SSID is not match return FAIL\n", __func__);
942 		goto _mismatch;
943 	}
944 
945 	/* check encryption info */
946 	val16 = le16_to_cpu(mgmt->u.beacon.capab_info);
947 
948 	if (val16 & WLAN_CAPABILITY_PRIVACY)
949 		privacy = 1;
950 	else
951 		privacy = 0;
952 
953 	RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_,
954 		 ("%s(): cur_network->network.Privacy is %d, bssid.Privacy "
955 		  "is %d\n", __func__, cur_network->network.Privacy, privacy));
956 	if (cur_network->network.Privacy != privacy) {
957 		DBG_8723A("%s(), privacy is not match return FAIL\n", __func__);
958 		goto _mismatch;
959 	}
960 
961 	p = cfg80211_find_ie(WLAN_EID_RSN, mgmt->u.beacon.variable, pie_len);
962 	if (p && p[1]) {
963 		crypto = ENCRYP_PROTOCOL_WPA2;
964 		if (p && p[1]) {
965 			r = rtw_parse_wpa2_ie23a(p, p[1] + 2, &group_cipher,
966 						 &pairwise_cipher, &is_8021x);
967 			if (r == _SUCCESS)
968 				RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_,
969 					 ("%s pnetwork->pairwise_cipher: %d, "
970 					  "pnetwork->group_cipher: %d, is_802x "
971 					  ": %d\n", __func__, pairwise_cipher,
972 					  group_cipher, is_8021x));
973 			}
974 	} else {
975 		p = cfg80211_find_vendor_ie(WLAN_OUI_MICROSOFT,
976 					    WLAN_OUI_TYPE_MICROSOFT_WPA,
977 					    mgmt->u.beacon.variable, pie_len);
978 		if (p && p[1]) {
979 			crypto = ENCRYP_PROTOCOL_WPA;
980 			r = rtw_parse_wpa_ie23a(p, p[1] + 2, &group_cipher,
981 						&pairwise_cipher, &is_8021x);
982 			if (r == _SUCCESS)
983 				RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_,
984 					 ("%s pnetwork->pairwise_cipher: %d, "
985 					  "group_cipher is %d, is_8021x is "
986 					  "%d\n", __func__, pairwise_cipher,
987 					  group_cipher, is_8021x));
988 		} else {
989 			if (privacy)
990 				crypto = ENCRYP_PROTOCOL_WEP;
991 			else
992 				crypto = ENCRYP_PROTOCOL_OPENSYS;
993 		}
994 	}
995 
996 	if (cur_network->BcnInfo.encryp_protocol != crypto) {
997 		DBG_8723A("%s(): encryption mismatch, return FAIL\n", __func__);
998 		goto _mismatch;
999 	}
1000 
1001 	if (crypto == ENCRYP_PROTOCOL_WPA || crypto == ENCRYP_PROTOCOL_WPA2) {
1002 		RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_,
1003 			 ("%s cur_network->group_cipher is %d: %d\n", __func__,
1004 			  cur_network->BcnInfo.group_cipher, group_cipher));
1005 		if (pairwise_cipher != cur_network->BcnInfo.pairwise_cipher ||
1006 		    group_cipher != cur_network->BcnInfo.group_cipher) {
1007 			DBG_8723A("%s pairwise_cipher(%x:%x) or group_cipher "
1008 				  "(%x:%x) is not match, return FAIL\n",
1009 				  __func__, pairwise_cipher,
1010 				  cur_network->BcnInfo.pairwise_cipher,
1011 				  group_cipher,
1012 				  cur_network->BcnInfo.group_cipher);
1013 			goto _mismatch;
1014 		}
1015 
1016 		if (is_8021x != cur_network->BcnInfo.is_8021x) {
1017 			DBG_8723A("%s authentication is not match, return "
1018 				  "FAIL\n", __func__);
1019 			goto _mismatch;
1020 		}
1021 	}
1022 
1023 	return _SUCCESS;
1024 
1025 _mismatch:
1026 
1027 	return _FAIL;
1028 }
1029 
update_beacon23a_info(struct rtw_adapter * padapter,struct ieee80211_mgmt * mgmt,uint pkt_len,struct sta_info * psta)1030 void update_beacon23a_info(struct rtw_adapter *padapter,
1031 			   struct ieee80211_mgmt *mgmt,
1032 			   uint pkt_len, struct sta_info *psta)
1033 {
1034 	unsigned int len;
1035 	const u8 *p;
1036 
1037 	len = pkt_len - offsetof(struct ieee80211_mgmt, u.beacon.variable);
1038 
1039 	p = cfg80211_find_ie(WLAN_EID_HT_OPERATION, mgmt->u.beacon.variable,
1040 			     len);
1041 	if (p)
1042 		bwmode_update_check(padapter, p);
1043 
1044 	p = cfg80211_find_ie(WLAN_EID_ERP_INFO, mgmt->u.beacon.variable, len);
1045 	if (p) {
1046 		ERP_IE_handler23a(padapter, p);
1047 		VCS_update23a(padapter, psta);
1048 	}
1049 }
1050 
is_ap_in_tkip23a(struct rtw_adapter * padapter)1051 bool is_ap_in_tkip23a(struct rtw_adapter *padapter)
1052 {
1053 	u32 i;
1054 	struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
1055 	struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
1056 	struct wlan_bssid_ex *cur_network = &pmlmeinfo->network;
1057 	const u8 *p;
1058 
1059 	if (cur_network->capability & WLAN_CAPABILITY_PRIVACY) {
1060 		for (i = 0; i < pmlmeinfo->network.IELength;) {
1061 			p = pmlmeinfo->network.IEs + i;
1062 
1063 			switch (p[0]) {
1064 			case WLAN_EID_VENDOR_SPECIFIC:
1065 				if (!memcmp(p + 2, RTW_WPA_OUI23A_TYPE, 4) &&
1066 				    !memcmp(p + 2 + 12, WPA_TKIP_CIPHER, 4))
1067 					return true;
1068 				break;
1069 			case WLAN_EID_RSN:
1070 				if (!memcmp(p + 2 + 8, RSN_TKIP_CIPHER, 4))
1071 					return true;
1072 				break;
1073 			default:
1074 				break;
1075 			}
1076 			i += (p[1] + 2);
1077 		}
1078 		return false;
1079 	} else
1080 		return false;
1081 }
1082 
should_forbid_n_rate23a(struct rtw_adapter * padapter)1083 bool should_forbid_n_rate23a(struct rtw_adapter * padapter)
1084 {
1085 	u32 i;
1086 	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1087 	struct wlan_bssid_ex  *cur_network = &pmlmepriv->cur_network.network;
1088 	const u8 *p;
1089 
1090 	if (cur_network->capability & WLAN_CAPABILITY_PRIVACY) {
1091 		for (i = 0; i < cur_network->IELength;) {
1092 			p = cur_network->IEs + i;
1093 
1094 			switch (p[0]) {
1095 			case WLAN_EID_VENDOR_SPECIFIC:
1096 				if (!memcmp(p + 2, RTW_WPA_OUI23A_TYPE, 4) &&
1097 				    (!memcmp(p + 2 + 12,
1098 					     WPA_CIPHER_SUITE_CCMP23A, 4) ||
1099 				     !memcmp(p + 2 + 16,
1100 					     WPA_CIPHER_SUITE_CCMP23A, 4)))
1101 					return false;
1102 				break;
1103 			case WLAN_EID_RSN:
1104 				if (!memcmp(p + 2 + 8,
1105 					    RSN_CIPHER_SUITE_CCMP23A, 4) ||
1106 				    !memcmp(p + 2 + 12,
1107 					    RSN_CIPHER_SUITE_CCMP23A, 4))
1108 				return false;
1109 			default:
1110 				break;
1111 			}
1112 
1113 			i += (p[1] + 2);
1114 		}
1115 		return true;
1116 	} else {
1117 		return false;
1118 	}
1119 }
1120 
is_ap_in_wep23a(struct rtw_adapter * padapter)1121 bool is_ap_in_wep23a(struct rtw_adapter *padapter)
1122 {
1123 	u32 i;
1124 	struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
1125 	struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
1126 	struct wlan_bssid_ex *cur_network = &pmlmeinfo->network;
1127 	const u8 *p;
1128 
1129 	if (cur_network->capability & WLAN_CAPABILITY_PRIVACY) {
1130 		for (i = 0; i < pmlmeinfo->network.IELength;) {
1131 			p = pmlmeinfo->network.IEs + i;
1132 
1133 			switch (p[0]) {
1134 			case WLAN_EID_VENDOR_SPECIFIC:
1135 				if (!memcmp(p + 2, RTW_WPA_OUI23A_TYPE, 4))
1136 					return false;
1137 				break;
1138 			case WLAN_EID_RSN:
1139 				return false;
1140 
1141 			default:
1142 				break;
1143 			}
1144 
1145 			i += (p[1] + 2);
1146 		}
1147 
1148 		return true;
1149 	} else
1150 		return false;
1151 }
1152 
wifirate2_ratetbl_inx23a(unsigned char rate)1153 static int wifirate2_ratetbl_inx23a(unsigned char rate)
1154 {
1155 	int inx = 0;
1156 	rate = rate & 0x7f;
1157 
1158 	switch (rate) {
1159 	case 54*2:
1160 		inx = 11;
1161 		break;
1162 	case 48*2:
1163 		inx = 10;
1164 		break;
1165 	case 36*2:
1166 		inx = 9;
1167 		break;
1168 	case 24*2:
1169 		inx = 8;
1170 		break;
1171 	case 18*2:
1172 		inx = 7;
1173 		break;
1174 	case 12*2:
1175 		inx = 6;
1176 		break;
1177 	case 9*2:
1178 		inx = 5;
1179 		break;
1180 	case 6*2:
1181 		inx = 4;
1182 		break;
1183 	case 11*2:
1184 		inx = 3;
1185 		break;
1186 	case 11:
1187 		inx = 2;
1188 		break;
1189 	case 2*2:
1190 		inx = 1;
1191 		break;
1192 	case 1*2:
1193 		inx = 0;
1194 		break;
1195 	}
1196 	return inx;
1197 }
1198 
update_basic_rate23a(unsigned char * ptn,unsigned int ptn_sz)1199 unsigned int update_basic_rate23a(unsigned char *ptn, unsigned int ptn_sz)
1200 {
1201 	unsigned int i, num_of_rate;
1202 	unsigned int mask = 0;
1203 
1204 	num_of_rate = (ptn_sz > NumRates)? NumRates: ptn_sz;
1205 
1206 	for (i = 0; i < num_of_rate; i++) {
1207 		if ((*(ptn + i)) & 0x80)
1208 			mask |= 0x1 << wifirate2_ratetbl_inx23a(*(ptn + i));
1209 	}
1210 	return mask;
1211 }
1212 
update_supported_rate23a(unsigned char * ptn,unsigned int ptn_sz)1213 unsigned int update_supported_rate23a(unsigned char *ptn, unsigned int ptn_sz)
1214 {
1215 	unsigned int i, num_of_rate;
1216 	unsigned int mask = 0;
1217 
1218 	num_of_rate = (ptn_sz > NumRates) ? NumRates : ptn_sz;
1219 
1220 	for (i = 0; i < num_of_rate; i++)
1221 		mask |= 0x1 << wifirate2_ratetbl_inx23a(*(ptn + i));
1222 	return mask;
1223 }
1224 
update_MSC_rate23a(struct ieee80211_ht_cap * pHT_caps)1225 unsigned int update_MSC_rate23a(struct ieee80211_ht_cap *pHT_caps)
1226 {
1227 	unsigned int mask = 0;
1228 
1229 	mask = pHT_caps->mcs.rx_mask[0] << 12 |
1230 		pHT_caps->mcs.rx_mask[1] << 20;
1231 
1232 	return mask;
1233 }
1234 
support_short_GI23a(struct rtw_adapter * padapter,struct ieee80211_ht_cap * pHT_caps)1235 int support_short_GI23a(struct rtw_adapter *padapter,
1236 			struct ieee80211_ht_cap *pHT_caps)
1237 {
1238 	struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
1239 	struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
1240 	unsigned char bit_offset;
1241 
1242 	if (!pmlmeinfo->HT_enable)
1243 		return _FAIL;
1244 	if (pmlmeinfo->assoc_AP_vendor == HT_IOT_PEER_RALINK)
1245 		return _FAIL;
1246 	bit_offset = (pmlmeext->cur_bwmode & HT_CHANNEL_WIDTH_40)? 6: 5;
1247 
1248 	if (pHT_caps->cap_info & cpu_to_le16(0x1 << bit_offset))
1249 		return _SUCCESS;
1250 	else
1251 		return _FAIL;
1252 }
1253 
get_highest_rate_idx23a(u32 mask)1254 unsigned char get_highest_rate_idx23a(u32 mask)
1255 {
1256 	int i;
1257 	unsigned char rate_idx = 0;
1258 
1259 	for (i = 27; i >= 0; i--) {
1260 		if (mask & BIT(i)) {
1261 			rate_idx = i;
1262 			break;
1263 		}
1264 	}
1265 	return rate_idx;
1266 }
1267 
Update_RA_Entry23a(struct rtw_adapter * padapter,struct sta_info * psta)1268 void Update_RA_Entry23a(struct rtw_adapter *padapter, struct sta_info *psta)
1269 {
1270 	rtw_hal_update_ra_mask23a(psta, 0);
1271 }
1272 
enable_rate_adaptive(struct rtw_adapter * padapter,struct sta_info * psta)1273 static void enable_rate_adaptive(struct rtw_adapter *padapter,
1274 				 struct sta_info *psta)
1275 {
1276 	Update_RA_Entry23a(padapter, psta);
1277 }
1278 
set_sta_rate23a(struct rtw_adapter * padapter,struct sta_info * psta)1279 void set_sta_rate23a(struct rtw_adapter *padapter, struct sta_info *psta)
1280 {
1281 	/* rate adaptive */
1282 	enable_rate_adaptive(padapter, psta);
1283 }
1284 
1285 /*  Update RRSR and Rate for USERATE */
update_tx_basic_rate23a(struct rtw_adapter * padapter,u8 wirelessmode)1286 void update_tx_basic_rate23a(struct rtw_adapter *padapter, u8 wirelessmode)
1287 {
1288 	unsigned char supported_rates[NDIS_802_11_LENGTH_RATES_EX];
1289 
1290 	memset(supported_rates, 0, NDIS_802_11_LENGTH_RATES_EX);
1291 
1292 	if (wirelessmode == WIRELESS_11B) {
1293 		memcpy(supported_rates, rtw_basic_rate_cck, 4);
1294 	} else if (wirelessmode & WIRELESS_11B) {
1295 		memcpy(supported_rates, rtw_basic_rate_mix, 7);
1296 	} else {
1297 		memcpy(supported_rates, rtw_basic_rate_ofdm, 3);
1298 	}
1299 
1300 	if (wirelessmode & WIRELESS_11B)
1301 		update_mgnt_tx_rate23a(padapter, IEEE80211_CCK_RATE_1MB);
1302 	else
1303 		update_mgnt_tx_rate23a(padapter, IEEE80211_OFDM_RATE_6MB);
1304 
1305 	HalSetBrateCfg23a(padapter, supported_rates);
1306 }
1307 
check_assoc_AP23a(u8 * pframe,uint len)1308 unsigned char check_assoc_AP23a(u8 *pframe, uint len)
1309 {
1310 	int i;
1311 	u8 epigram_vendor_flag;
1312 	u8 ralink_vendor_flag;
1313 	const u8 *p;
1314 	epigram_vendor_flag = 0;
1315 	ralink_vendor_flag = 0;
1316 
1317 	for (i = 0; i < len;) {
1318 		p = pframe + i;
1319 
1320 		switch (p[0]) {
1321 		case WLAN_EID_VENDOR_SPECIFIC:
1322 			if (!memcmp(p + 2, ARTHEROS_OUI1, 3) ||
1323 			    !memcmp(p + 2, ARTHEROS_OUI2, 3)) {
1324 				DBG_8723A("link to Artheros AP\n");
1325 				return HT_IOT_PEER_ATHEROS;
1326 			} else if (!memcmp(p + 2, BROADCOM_OUI1, 3) ||
1327 				   !memcmp(p + 2, BROADCOM_OUI2, 3) ||
1328 				   !memcmp(p + 2, BROADCOM_OUI2, 3)) {
1329 				DBG_8723A("link to Broadcom AP\n");
1330 				return HT_IOT_PEER_BROADCOM;
1331 			} else if (!memcmp(p + 2, MARVELL_OUI, 3)) {
1332 				DBG_8723A("link to Marvell AP\n");
1333 				return HT_IOT_PEER_MARVELL;
1334 			} else if (!memcmp(p + 2, RALINK_OUI, 3)) {
1335 				if (!ralink_vendor_flag)
1336 					ralink_vendor_flag = 1;
1337 				else {
1338 					DBG_8723A("link to Ralink AP\n");
1339 					return HT_IOT_PEER_RALINK;
1340 				}
1341 			} else if (!memcmp(p + 2, CISCO_OUI, 3)) {
1342 				DBG_8723A("link to Cisco AP\n");
1343 				return HT_IOT_PEER_CISCO;
1344 			} else if (!memcmp(p + 2, REALTEK_OUI, 3)) {
1345 				DBG_8723A("link to Realtek 96B\n");
1346 				return HT_IOT_PEER_REALTEK;
1347 			} else if (!memcmp(p + 2, AIRGOCAP_OUI, 3)) {
1348 				DBG_8723A("link to Airgo Cap\n");
1349 				return HT_IOT_PEER_AIRGO;
1350 			} else if (!memcmp(p + 2, EPIGRAM_OUI, 3)) {
1351 				epigram_vendor_flag = 1;
1352 				if (ralink_vendor_flag) {
1353 					DBG_8723A("link to Tenda W311R AP\n");
1354 					return HT_IOT_PEER_TENDA;
1355 				} else
1356 					DBG_8723A("Capture EPIGRAM_OUI\n");
1357 			} else
1358 				break;
1359 		default:
1360 			break;
1361 		}
1362 
1363 		i += (p[1] + 2);
1364 	}
1365 
1366 	if (ralink_vendor_flag && !epigram_vendor_flag) {
1367 		DBG_8723A("link to Ralink AP\n");
1368 		return HT_IOT_PEER_RALINK;
1369 	} else if (ralink_vendor_flag && epigram_vendor_flag) {
1370 		DBG_8723A("link to Tenda W311R AP\n");
1371 		return HT_IOT_PEER_TENDA;
1372 	} else {
1373 		DBG_8723A("link to new AP\n");
1374 		return HT_IOT_PEER_UNKNOWN;
1375 	}
1376 }
1377 
update_IOT_info23a(struct rtw_adapter * padapter)1378 void update_IOT_info23a(struct rtw_adapter *padapter)
1379 {
1380 	struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
1381 	struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
1382 
1383 	switch (pmlmeinfo->assoc_AP_vendor) {
1384 	case HT_IOT_PEER_MARVELL:
1385 		pmlmeinfo->turboMode_cts2self = 1;
1386 		pmlmeinfo->turboMode_rtsen = 0;
1387 		break;
1388 	case HT_IOT_PEER_RALINK:
1389 		pmlmeinfo->turboMode_cts2self = 0;
1390 		pmlmeinfo->turboMode_rtsen = 1;
1391 		/* disable high power */
1392 		rtl8723a_odm_support_ability_clr(padapter, (u32)
1393 						 ~DYNAMIC_BB_DYNAMIC_TXPWR);
1394 		break;
1395 	case HT_IOT_PEER_REALTEK:
1396 		/* rtw_write16(padapter, 0x4cc, 0xffff); */
1397 		/* rtw_write16(padapter, 0x546, 0x01c0); */
1398 		/* disable high power */
1399 		rtl8723a_odm_support_ability_clr(padapter, (u32)
1400 						 ~DYNAMIC_BB_DYNAMIC_TXPWR);
1401 		break;
1402 	default:
1403 		pmlmeinfo->turboMode_cts2self = 0;
1404 		pmlmeinfo->turboMode_rtsen = 1;
1405 		break;
1406 	}
1407 }
1408 
update_capinfo23a(struct rtw_adapter * Adapter,u16 updateCap)1409 void update_capinfo23a(struct rtw_adapter *Adapter, u16 updateCap)
1410 {
1411 	struct mlme_ext_priv *pmlmeext = &Adapter->mlmeextpriv;
1412 	struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
1413 
1414 	if (updateCap & cShortPreamble) {
1415 		/*  Short Preamble */
1416 		if (pmlmeinfo->preamble_mode != PREAMBLE_SHORT) {
1417 			/*  PREAMBLE_LONG or PREAMBLE_AUTO */
1418 			pmlmeinfo->preamble_mode = PREAMBLE_SHORT;
1419 			rtl8723a_ack_preamble(Adapter, true);
1420 		}
1421 	} else { /*  Long Preamble */
1422 		if (pmlmeinfo->preamble_mode != PREAMBLE_LONG) {
1423 			/*  PREAMBLE_SHORT or PREAMBLE_AUTO */
1424 			pmlmeinfo->preamble_mode = PREAMBLE_LONG;
1425 			rtl8723a_ack_preamble(Adapter, false);
1426 		}
1427 	}
1428 	if (updateCap & cIBSS) {
1429 		/* Filen: See 802.11-2007 p.91 */
1430 		pmlmeinfo->slotTime = NON_SHORT_SLOT_TIME;
1431 	} else {
1432 		/* Filen: See 802.11-2007 p.90 */
1433 		if (pmlmeext->cur_wireless_mode &
1434 		    (WIRELESS_11G | WIRELESS_11_24N)) {
1435 			if (updateCap & cShortSlotTime) { /*  Short Slot Time */
1436 				if (pmlmeinfo->slotTime != SHORT_SLOT_TIME)
1437 					pmlmeinfo->slotTime = SHORT_SLOT_TIME;
1438 			} else { /*  Long Slot Time */
1439 				if (pmlmeinfo->slotTime != NON_SHORT_SLOT_TIME)
1440 					pmlmeinfo->slotTime =
1441 						NON_SHORT_SLOT_TIME;
1442 			}
1443 		} else if (pmlmeext->cur_wireless_mode &
1444 			   (WIRELESS_11A | WIRELESS_11_5N)) {
1445 			pmlmeinfo->slotTime = SHORT_SLOT_TIME;
1446 		} else {
1447 			/* B Mode */
1448 			pmlmeinfo->slotTime = NON_SHORT_SLOT_TIME;
1449 		}
1450 	}
1451 	rtl8723a_set_slot_time(Adapter, pmlmeinfo->slotTime);
1452 }
1453 
update_wireless_mode23a(struct rtw_adapter * padapter)1454 void update_wireless_mode23a(struct rtw_adapter *padapter)
1455 {
1456 	int ratelen, network_type = 0;
1457 	struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
1458 	struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
1459 	struct wlan_bssid_ex *cur_network = &pmlmeinfo->network;
1460 	unsigned char *rate = cur_network->SupportedRates;
1461 
1462 	ratelen = rtw_get_rateset_len23a(cur_network->SupportedRates);
1463 
1464 	if ((pmlmeinfo->HT_info_enable) && (pmlmeinfo->HT_caps_enable))
1465 		pmlmeinfo->HT_enable = 1;
1466 
1467 	if (pmlmeext->cur_channel > 14) {
1468 		if (pmlmeinfo->HT_enable)
1469 			network_type = WIRELESS_11_5N;
1470 		network_type |= WIRELESS_11A;
1471 	} else {
1472 		if (pmlmeinfo->HT_enable)
1473 			network_type = WIRELESS_11_24N;
1474 
1475 		if (cckratesonly_included23a(rate, ratelen) == true)
1476 			network_type |= WIRELESS_11B;
1477 		else if (cckrates_included23a(rate, ratelen) == true)
1478 			network_type |= WIRELESS_11BG;
1479 		else
1480 			network_type |= WIRELESS_11G;
1481 	}
1482 
1483 	pmlmeext->cur_wireless_mode =
1484 		network_type & padapter->registrypriv.wireless_mode;
1485 
1486 	/* 0x0808 -> for CCK, 0x0a0a -> for OFDM */
1487 	/* change this value if having IOT issues. */
1488 	rtl8723a_set_resp_sifs(padapter, 0x08, 0x08, 0x0a, 0x0a);
1489 
1490 	if (pmlmeext->cur_wireless_mode & WIRELESS_11B)
1491 		update_mgnt_tx_rate23a(padapter, IEEE80211_CCK_RATE_1MB);
1492 	 else
1493 		update_mgnt_tx_rate23a(padapter, IEEE80211_OFDM_RATE_6MB);
1494 }
1495 
update_bmc_sta_support_rate23a(struct rtw_adapter * padapter,u32 mac_id)1496 void update_bmc_sta_support_rate23a(struct rtw_adapter *padapter, u32 mac_id)
1497 {
1498 	struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
1499 	struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
1500 
1501 	if (pmlmeext->cur_wireless_mode & WIRELESS_11B) {
1502 		/*  Only B, B/G, and B/G/N AP could use CCK rate */
1503 		memcpy((pmlmeinfo->FW_sta_info[mac_id].SupportedRates),
1504 		       rtw_basic_rate_cck, 4);
1505 	} else {
1506 		memcpy(pmlmeinfo->FW_sta_info[mac_id].SupportedRates,
1507 		       rtw_basic_rate_ofdm, 3);
1508 	}
1509 }
1510 
update_sta_support_rate23a(struct rtw_adapter * padapter,u8 * pvar_ie,uint var_ie_len,int cam_idx)1511 int update_sta_support_rate23a(struct rtw_adapter *padapter, u8 *pvar_ie,
1512 			       uint var_ie_len, int cam_idx)
1513 {
1514 	int supportRateNum = 0;
1515 	struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
1516 	struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
1517 	const u8 *p;
1518 
1519 	p = cfg80211_find_ie(WLAN_EID_SUPP_RATES, pvar_ie, var_ie_len);
1520 	if (!p)
1521 		return _FAIL;
1522 
1523 	memcpy(pmlmeinfo->FW_sta_info[cam_idx].SupportedRates, p + 2, p[1]);
1524 	supportRateNum = p[1];
1525 
1526 	p = cfg80211_find_ie(WLAN_EID_EXT_SUPP_RATES, pvar_ie, var_ie_len);
1527 	if (p)
1528 		memcpy(pmlmeinfo->FW_sta_info[cam_idx].SupportedRates +
1529 		       supportRateNum, p + 2, p[1]);
1530 	return _SUCCESS;
1531 }
1532 
process_addba_req23a(struct rtw_adapter * padapter,u8 * paddba_req,u8 * addr)1533 void process_addba_req23a(struct rtw_adapter *padapter,
1534 			  u8 *paddba_req, u8 *addr)
1535 {
1536 	struct sta_info *psta;
1537 	u16 tid, start_seq, param;
1538 	struct recv_reorder_ctrl *preorder_ctrl;
1539 	struct sta_priv *pstapriv = &padapter->stapriv;
1540 	struct ADDBA_request *preq = (struct ADDBA_request *)paddba_req;
1541 	struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
1542 	struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
1543 
1544 	psta = rtw_get_stainfo23a(pstapriv, addr);
1545 
1546 	if (psta) {
1547 		start_seq = le16_to_cpu(preq->BA_starting_seqctrl) >> 4;
1548 
1549 		param = le16_to_cpu(preq->BA_para_set);
1550 		tid = (param >> 2) & 0x0f;
1551 
1552 		preorder_ctrl = &psta->recvreorder_ctrl[tid];
1553 
1554 		preorder_ctrl->indicate_seq = 0xffff;
1555 
1556 		preorder_ctrl->enable = (pmlmeinfo->bAcceptAddbaReq == true) ?
1557 			true : false;
1558 	}
1559 }
1560