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