These changes are the raw update to linux-4.4.6-rt14. Kernel sources
[kvmfornfv.git] / kernel / drivers / staging / rtl8723au / core / rtw_wlan_util.c
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
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
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
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
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
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
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
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
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
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
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
297 inline u8 rtw_get_oper_ch23a(struct rtw_adapter *adapter)
298 {
299         return adapter_to_dvobj(adapter)->oper_channel;
300 }
301
302 inline void rtw_set_oper_ch23a(struct rtw_adapter *adapter, u8 ch)
303 {
304         adapter_to_dvobj(adapter)->oper_channel = ch;
305 }
306
307 inline u8 rtw_get_oper_bw23a(struct rtw_adapter *adapter)
308 {
309         return adapter_to_dvobj(adapter)->oper_bwmode;
310 }
311
312 inline void rtw_set_oper_bw23a(struct rtw_adapter *adapter, u8 bw)
313 {
314         adapter_to_dvobj(adapter)->oper_bwmode = bw;
315 }
316
317 inline u8 rtw_get_oper_ch23aoffset(struct rtw_adapter *adapter)
318 {
319         return adapter_to_dvobj(adapter)->oper_ch_offset;
320 }
321
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
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
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
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
389 inline u8 *get_my_bssid23a(struct wlan_bssid_ex *pnetwork)
390 {
391         return pnetwork->MacAddress;
392 }
393
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
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
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
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
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
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
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
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
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, 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                                         swap(edca[i], edca[j]);
593                                         swap(inx[i], inx[j]);
594                                         change_inx = false;
595                                 }
596                         }
597                 }
598         }
599
600         for (i = 0; i<4; i++) {
601                 pxmitpriv->wmm_para_seq[i] = inx[i];
602                 DBG_8723A("wmm_para_seq(%d): %d\n", i,
603                           pxmitpriv->wmm_para_seq[i]);
604         }
605 }
606
607 static void bwmode_update_check(struct rtw_adapter *padapter, const u8 *p)
608 {
609         struct ieee80211_ht_operation *pHT_info;
610         struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
611         struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
612         struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
613         struct registry_priv *pregistrypriv = &padapter->registrypriv;
614         struct ht_priv *phtpriv = &pmlmepriv->htpriv;
615         unsigned char new_bwmode;
616         unsigned char new_ch_offset;
617
618         if (!p)
619                 return;
620         if (!phtpriv->ht_option)
621                 return;
622         if (p[1] != sizeof(struct ieee80211_ht_operation))
623                 return;
624
625         pHT_info = (struct ieee80211_ht_operation *)(p + 2);
626
627         if ((pHT_info->ht_param & IEEE80211_HT_PARAM_CHAN_WIDTH_ANY) &&
628             pregistrypriv->cbw40_enable) {
629                 new_bwmode = HT_CHANNEL_WIDTH_40;
630
631                 switch (pHT_info->ht_param & IEEE80211_HT_PARAM_CHA_SEC_OFFSET){
632                 case IEEE80211_HT_PARAM_CHA_SEC_ABOVE:
633                         new_ch_offset = HAL_PRIME_CHNL_OFFSET_LOWER;
634                         break;
635                 case IEEE80211_HT_PARAM_CHA_SEC_BELOW:
636                         new_ch_offset = HAL_PRIME_CHNL_OFFSET_UPPER;
637                         break;
638                 default:
639                         new_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
640                         break;
641                 }
642         } else {
643                 new_bwmode = HT_CHANNEL_WIDTH_20;
644                 new_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
645         }
646
647         if (new_bwmode != pmlmeext->cur_bwmode ||
648             new_ch_offset != pmlmeext->cur_ch_offset) {
649                 pmlmeinfo->bwmode_updated = true;
650
651                 pmlmeext->cur_bwmode = new_bwmode;
652                 pmlmeext->cur_ch_offset = new_ch_offset;
653
654                 /* update HT info also */
655                 HT_info_handler23a(padapter, p);
656         } else
657                 pmlmeinfo->bwmode_updated = false;
658
659         if (pmlmeinfo->bwmode_updated) {
660                 struct sta_info *psta;
661                 struct wlan_bssid_ex *cur_network = &pmlmeinfo->network;
662                 struct sta_priv *pstapriv = &padapter->stapriv;
663
664                 /* set_channel_bwmode23a(padapter, pmlmeext->cur_channel,
665                    pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode); */
666
667                 /* update ap's stainfo */
668                 psta = rtw_get_stainfo23a(pstapriv, cur_network->MacAddress);
669                 if (psta) {
670                         struct ht_priv *phtpriv_sta = &psta->htpriv;
671
672                         if (phtpriv_sta->ht_option) {
673                                 /*  bwmode */
674                                 phtpriv_sta->bwmode = pmlmeext->cur_bwmode;
675                                 phtpriv_sta->ch_offset =
676                                         pmlmeext->cur_ch_offset;
677                         } else {
678                                 phtpriv_sta->bwmode = HT_CHANNEL_WIDTH_20;
679                                 phtpriv_sta->ch_offset =
680                                         HAL_PRIME_CHNL_OFFSET_DONT_CARE;
681                         }
682                 }
683         }
684 }
685
686 void HT_caps_handler23a(struct rtw_adapter *padapter, const u8 *p)
687 {
688         unsigned int i;
689         u8 rf_type;
690         u8 max_AMPDU_len, min_MPDU_spacing;
691         struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
692         struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
693         struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
694         struct ht_priv *phtpriv = &pmlmepriv->htpriv;
695         struct ieee80211_ht_cap *cap;
696         u8 *dstcap;
697
698         if (!p)
699                 return;
700
701         if (!phtpriv->ht_option)
702                 return;
703
704         pmlmeinfo->HT_caps_enable = 1;
705
706         cap = &pmlmeinfo->ht_cap;
707         dstcap = (u8 *)cap;
708         for (i = 0; i < p[1]; i++) {
709                 if (i != 2) {
710                         dstcap[i] &= p[i + 2];
711                 } else {
712                         /* modify from  fw by Thomas 2010/11/17 */
713                         if ((cap->ampdu_params_info &
714                              IEEE80211_HT_AMPDU_PARM_FACTOR) >
715                             (p[i + 2] & IEEE80211_HT_AMPDU_PARM_FACTOR))
716                                 max_AMPDU_len = p[i + 2] &
717                                         IEEE80211_HT_AMPDU_PARM_FACTOR;
718                         else
719                                 max_AMPDU_len = cap->ampdu_params_info &
720                                         IEEE80211_HT_AMPDU_PARM_FACTOR;
721
722                         if ((cap->ampdu_params_info &
723                              IEEE80211_HT_AMPDU_PARM_DENSITY) >
724                             (p[i + 2] & IEEE80211_HT_AMPDU_PARM_DENSITY))
725                                 min_MPDU_spacing = cap->ampdu_params_info &
726                                         IEEE80211_HT_AMPDU_PARM_DENSITY;
727                         else
728                                 min_MPDU_spacing = p[i + 2] &
729                                         IEEE80211_HT_AMPDU_PARM_DENSITY;
730
731                         cap->ampdu_params_info =
732                                 max_AMPDU_len | min_MPDU_spacing;
733                 }
734         }
735
736         rf_type = rtl8723a_get_rf_type(padapter);
737
738         /* update the MCS rates */
739         for (i = 0; i < IEEE80211_HT_MCS_MASK_LEN; i++) {
740                 if (rf_type == RF_1T1R || rf_type == RF_1T2R)
741                         cap->mcs.rx_mask[i] &= MCS_rate_1R23A[i];
742                 else
743                         cap->mcs.rx_mask[i] &= MCS_rate_2R23A[i];
744         }
745 }
746
747 void HT_info_handler23a(struct rtw_adapter *padapter, const u8 *p)
748 {
749         struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
750         struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
751         struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
752         struct ht_priv *phtpriv = &pmlmepriv->htpriv;
753
754         if (!p)
755                 return;
756
757         if (!phtpriv->ht_option)
758                 return;
759
760         if (p[1] != sizeof(struct ieee80211_ht_operation))
761                 return;
762
763         pmlmeinfo->HT_info_enable = 1;
764         memcpy(&pmlmeinfo->HT_info, p + 2, p[1]);
765 }
766
767 void HTOnAssocRsp23a(struct rtw_adapter *padapter)
768 {
769         unsigned char max_AMPDU_len;
770         unsigned char min_MPDU_spacing;
771         /* struct registry_priv  *pregpriv = &padapter->registrypriv; */
772         struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
773         struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
774
775         DBG_8723A("%s\n", __func__);
776
777         if (pmlmeinfo->HT_info_enable && pmlmeinfo->HT_caps_enable)
778                 pmlmeinfo->HT_enable = 1;
779         else {
780                 pmlmeinfo->HT_enable = 0;
781                 /* set_channel_bwmode23a(padapter, pmlmeext->cur_channel,
782                    pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode); */
783                 return;
784         }
785
786         /* handle A-MPDU parameter field */
787         /*
788                 AMPDU_para [1:0]:Max AMPDU Len => 0:8k , 1:16k, 2:32k, 3:64k
789                 AMPDU_para [4:2]:Min MPDU Start Spacing
790         */
791         max_AMPDU_len = pmlmeinfo->ht_cap.ampdu_params_info &
792                 IEEE80211_HT_AMPDU_PARM_FACTOR;
793
794         min_MPDU_spacing =
795                 (pmlmeinfo->ht_cap.ampdu_params_info &
796                  IEEE80211_HT_AMPDU_PARM_DENSITY) >> 2;
797
798         rtl8723a_set_ampdu_min_space(padapter, min_MPDU_spacing);
799         rtl8723a_set_ampdu_factor(padapter, max_AMPDU_len);
800 }
801
802 void ERP_IE_handler23a(struct rtw_adapter *padapter, const u8 *p)
803 {
804         struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
805         struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
806
807         if (p[1] > 1)
808                 return;
809
810         pmlmeinfo->ERP_enable = 1;
811         memcpy(&pmlmeinfo->ERP_IE, p + 2, p[1]);
812 }
813
814 void VCS_update23a(struct rtw_adapter *padapter, struct sta_info *psta)
815 {
816         struct registry_priv *pregpriv = &padapter->registrypriv;
817         struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
818         struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
819
820         switch (pregpriv->vrtl_carrier_sense) { /* 0:off 1:on 2:auto */
821         case 0: /* off */
822                 psta->rtsen = 0;
823                 psta->cts2self = 0;
824                 break;
825         case 1: /* on */
826                 if (pregpriv->vcs_type == RTS_CTS) {
827                         psta->rtsen = 1;
828                         psta->cts2self = 0;
829                 } else {
830                         psta->rtsen = 0;
831                         psta->cts2self = 1;
832                 }
833                 break;
834         case 2: /* auto */
835         default:
836                 if (pmlmeinfo->ERP_enable && pmlmeinfo->ERP_IE & BIT(1)) {
837                         if (pregpriv->vcs_type == RTS_CTS) {
838                                 psta->rtsen = 1;
839                                 psta->cts2self = 0;
840                         } else {
841                                 psta->rtsen = 0;
842                                 psta->cts2self = 1;
843                         }
844                 } else {
845                         psta->rtsen = 0;
846                         psta->cts2self = 0;
847                 }
848                 break;
849         }
850 }
851
852 int rtw_check_bcn_info23a(struct rtw_adapter *Adapter,
853                           struct ieee80211_mgmt *mgmt, u32 pkt_len)
854 {
855         struct wlan_network *cur_network = &Adapter->mlmepriv.cur_network;
856         struct ieee80211_ht_operation *pht_info;
857         unsigned short val16;
858         u8 crypto, bcn_channel;
859         int group_cipher = 0, pairwise_cipher = 0, is_8021x = 0, r;
860         int pie_len, ssid_len, privacy;
861         const u8 *p, *ssid;
862
863         if (!is_client_associated_to_ap23a(Adapter))
864                 return _SUCCESS;
865
866         if (unlikely(!ieee80211_is_beacon(mgmt->frame_control))) {
867                 printk(KERN_WARNING "%s: received a non beacon frame!\n",
868                        __func__);
869                 return _FAIL;
870         }
871
872         if (!ether_addr_equal(cur_network->network.MacAddress, mgmt->bssid)) {
873                 DBG_8723A("%s: linked but recv other bssid bcn %pM %pM\n",
874                           __func__, mgmt->bssid,
875                           cur_network->network.MacAddress);
876                 return _FAIL;
877         }
878
879         /* check bw and channel offset */
880         /* parsing HT_CAP_IE */
881         pie_len = pkt_len - offsetof(struct ieee80211_mgmt, u.beacon.variable);
882
883         /* Checking for channel */
884         p = cfg80211_find_ie(WLAN_EID_DS_PARAMS, mgmt->u.beacon.variable,
885                              pie_len);
886         if (p)
887                 bcn_channel = p[2];
888         else {
889                 /* In 5G, some ap do not have DSSET IE checking HT
890                    info for channel */
891                 p = cfg80211_find_ie(WLAN_EID_HT_OPERATION,
892                                      mgmt->u.beacon.variable, pie_len);
893
894                 if (p && p[1] > 0) {
895                         pht_info = (struct ieee80211_ht_operation *)(p + 2);
896                         bcn_channel = pht_info->primary_chan;
897                 } else { /* we don't find channel IE, so don't check it */
898                         DBG_8723A("Oops: %s we don't find channel IE, so don't "
899                                   "check it\n", __func__);
900                         bcn_channel = Adapter->mlmeextpriv.cur_channel;
901                 }
902         }
903         if (bcn_channel != Adapter->mlmeextpriv.cur_channel) {
904                 DBG_8723A("%s beacon channel:%d cur channel:%d disconnect\n",
905                           __func__, bcn_channel,
906                           Adapter->mlmeextpriv.cur_channel);
907                 goto _mismatch;
908         }
909
910         /* checking SSID */
911         p = cfg80211_find_ie(WLAN_EID_SSID, mgmt->u.beacon.variable, pie_len);
912         if (p && p[1]) {
913                 ssid = p + 2;
914                 ssid_len = p[1];
915         } else {
916                 DBG_8723A("%s marc: cannot find SSID for survey event\n",
917                           __func__);
918                 ssid = NULL;
919                 ssid_len = 0;
920         }
921
922         RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_,
923                  "%s bssid.Ssid.Ssid:%s bssid.Ssid.SsidLength:%d cur_network->network.Ssid.Ssid:%s len:%d\n",
924                  __func__, ssid, ssid_len, cur_network->network.Ssid.ssid,
925                  cur_network->network.Ssid.ssid_len);
926
927         if (ssid_len != cur_network->network.Ssid.ssid_len || ssid_len > 32 ||
928             (ssid_len &&
929              memcmp(ssid, cur_network->network.Ssid.ssid, ssid_len))) {
930                 DBG_8723A("%s(), SSID is not match return FAIL\n", __func__);
931                 goto _mismatch;
932         }
933
934         /* check encryption info */
935         val16 = le16_to_cpu(mgmt->u.beacon.capab_info);
936
937         if (val16 & WLAN_CAPABILITY_PRIVACY)
938                 privacy = 1;
939         else
940                 privacy = 0;
941
942         RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_,
943                  "%s(): cur_network->network.Privacy is %d, bssid.Privacy is %d\n",
944                  __func__, cur_network->network.Privacy, privacy);
945         if (cur_network->network.Privacy != privacy) {
946                 DBG_8723A("%s(), privacy is not match return FAIL\n", __func__);
947                 goto _mismatch;
948         }
949
950         p = cfg80211_find_ie(WLAN_EID_RSN, mgmt->u.beacon.variable, pie_len);
951         if (p && p[1]) {
952                 crypto = ENCRYP_PROTOCOL_WPA2;
953                 if (p && p[1]) {
954                         r = rtw_parse_wpa2_ie23a(p, p[1] + 2, &group_cipher,
955                                                  &pairwise_cipher, &is_8021x);
956                         if (r == _SUCCESS)
957                                 RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_,
958                                          "%s pnetwork->pairwise_cipher: %d, pnetwork->group_cipher: %d, is_802x : %d\n",
959                                          __func__, pairwise_cipher,
960                                          group_cipher, is_8021x);
961                         }
962         } else {
963                 p = cfg80211_find_vendor_ie(WLAN_OUI_MICROSOFT,
964                                             WLAN_OUI_TYPE_MICROSOFT_WPA,
965                                             mgmt->u.beacon.variable, pie_len);
966                 if (p && p[1]) {
967                         crypto = ENCRYP_PROTOCOL_WPA;
968                         r = rtw_parse_wpa_ie23a(p, p[1] + 2, &group_cipher,
969                                                 &pairwise_cipher, &is_8021x);
970                         if (r == _SUCCESS)
971                                 RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_,
972                                          "%s pnetwork->pairwise_cipher: %d, group_cipher is %d, is_8021x is %d\n",
973                                          __func__, pairwise_cipher,
974                                          group_cipher, is_8021x);
975                 } else {
976                         if (privacy)
977                                 crypto = ENCRYP_PROTOCOL_WEP;
978                         else
979                                 crypto = ENCRYP_PROTOCOL_OPENSYS;
980                 }
981         }
982
983         if (cur_network->BcnInfo.encryp_protocol != crypto) {
984                 DBG_8723A("%s(): encryption mismatch, return FAIL\n", __func__);
985                 goto _mismatch;
986         }
987
988         if (crypto == ENCRYP_PROTOCOL_WPA || crypto == ENCRYP_PROTOCOL_WPA2) {
989                 RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_,
990                          "%s cur_network->group_cipher is %d: %d\n", __func__,
991                          cur_network->BcnInfo.group_cipher, group_cipher);
992                 if (pairwise_cipher != cur_network->BcnInfo.pairwise_cipher ||
993                     group_cipher != cur_network->BcnInfo.group_cipher) {
994                         DBG_8723A("%s pairwise_cipher(%x:%x) or group_cipher "
995                                   "(%x:%x) is not match, return FAIL\n",
996                                   __func__, pairwise_cipher,
997                                   cur_network->BcnInfo.pairwise_cipher,
998                                   group_cipher,
999                                   cur_network->BcnInfo.group_cipher);
1000                         goto _mismatch;
1001                 }
1002
1003                 if (is_8021x != cur_network->BcnInfo.is_8021x) {
1004                         DBG_8723A("%s authentication is not match, return "
1005                                   "FAIL\n", __func__);
1006                         goto _mismatch;
1007                 }
1008         }
1009
1010         return _SUCCESS;
1011
1012 _mismatch:
1013
1014         return _FAIL;
1015 }
1016
1017 void update_beacon23a_info(struct rtw_adapter *padapter,
1018                            struct ieee80211_mgmt *mgmt,
1019                            uint pkt_len, struct sta_info *psta)
1020 {
1021         unsigned int len;
1022         const u8 *p;
1023
1024         len = pkt_len - offsetof(struct ieee80211_mgmt, u.beacon.variable);
1025
1026         p = cfg80211_find_ie(WLAN_EID_HT_OPERATION, mgmt->u.beacon.variable,
1027                              len);
1028         if (p)
1029                 bwmode_update_check(padapter, p);
1030
1031         p = cfg80211_find_ie(WLAN_EID_ERP_INFO, mgmt->u.beacon.variable, len);
1032         if (p) {
1033                 ERP_IE_handler23a(padapter, p);
1034                 VCS_update23a(padapter, psta);
1035         }
1036 }
1037
1038 bool is_ap_in_tkip23a(struct rtw_adapter *padapter)
1039 {
1040         u32 i;
1041         struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
1042         struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
1043         struct wlan_bssid_ex *cur_network = &pmlmeinfo->network;
1044         const u8 *p;
1045
1046         if (cur_network->capability & WLAN_CAPABILITY_PRIVACY) {
1047                 for (i = 0; i < pmlmeinfo->network.IELength;) {
1048                         p = pmlmeinfo->network.IEs + i;
1049
1050                         switch (p[0]) {
1051                         case WLAN_EID_VENDOR_SPECIFIC:
1052                                 if (!memcmp(p + 2, RTW_WPA_OUI23A_TYPE, 4) &&
1053                                     !memcmp(p + 2 + 12, WPA_TKIP_CIPHER, 4))
1054                                         return true;
1055                                 break;
1056                         case WLAN_EID_RSN:
1057                                 if (!memcmp(p + 2 + 8, RSN_TKIP_CIPHER, 4))
1058                                         return true;
1059                                 break;
1060                         default:
1061                                 break;
1062                         }
1063                         i += (p[1] + 2);
1064                 }
1065                 return false;
1066         } else
1067                 return false;
1068 }
1069
1070 bool should_forbid_n_rate23a(struct rtw_adapter *padapter)
1071 {
1072         u32 i;
1073         struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1074         struct wlan_bssid_ex  *cur_network = &pmlmepriv->cur_network.network;
1075         const u8 *p;
1076
1077         if (cur_network->capability & WLAN_CAPABILITY_PRIVACY) {
1078                 for (i = 0; i < cur_network->IELength;) {
1079                         p = cur_network->IEs + i;
1080
1081                         switch (p[0]) {
1082                         case WLAN_EID_VENDOR_SPECIFIC:
1083                                 if (!memcmp(p + 2, RTW_WPA_OUI23A_TYPE, 4) &&
1084                                     (!memcmp(p + 2 + 12,
1085                                              WPA_CIPHER_SUITE_CCMP23A, 4) ||
1086                                      !memcmp(p + 2 + 16,
1087                                              WPA_CIPHER_SUITE_CCMP23A, 4)))
1088                                         return false;
1089                                 break;
1090                         case WLAN_EID_RSN:
1091                                 if (!memcmp(p + 2 + 8,
1092                                             RSN_CIPHER_SUITE_CCMP23A, 4) ||
1093                                     !memcmp(p + 2 + 12,
1094                                             RSN_CIPHER_SUITE_CCMP23A, 4))
1095                                 return false;
1096                         default:
1097                                 break;
1098                         }
1099
1100                         i += (p[1] + 2);
1101                 }
1102                 return true;
1103         } else {
1104                 return false;
1105         }
1106 }
1107
1108 bool is_ap_in_wep23a(struct rtw_adapter *padapter)
1109 {
1110         u32 i;
1111         struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
1112         struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
1113         struct wlan_bssid_ex *cur_network = &pmlmeinfo->network;
1114         const u8 *p;
1115
1116         if (cur_network->capability & WLAN_CAPABILITY_PRIVACY) {
1117                 for (i = 0; i < pmlmeinfo->network.IELength;) {
1118                         p = pmlmeinfo->network.IEs + i;
1119
1120                         switch (p[0]) {
1121                         case WLAN_EID_VENDOR_SPECIFIC:
1122                                 if (!memcmp(p + 2, RTW_WPA_OUI23A_TYPE, 4))
1123                                         return false;
1124                                 break;
1125                         case WLAN_EID_RSN:
1126                                 return false;
1127
1128                         default:
1129                                 break;
1130                         }
1131
1132                         i += (p[1] + 2);
1133                 }
1134
1135                 return true;
1136         } else
1137                 return false;
1138 }
1139
1140 static int wifirate2_ratetbl_inx23a(unsigned char rate)
1141 {
1142         int inx = 0;
1143
1144         rate = rate & 0x7f;
1145
1146         switch (rate) {
1147         case 54*2:
1148                 inx = 11;
1149                 break;
1150         case 48*2:
1151                 inx = 10;
1152                 break;
1153         case 36*2:
1154                 inx = 9;
1155                 break;
1156         case 24*2:
1157                 inx = 8;
1158                 break;
1159         case 18*2:
1160                 inx = 7;
1161                 break;
1162         case 12*2:
1163                 inx = 6;
1164                 break;
1165         case 9*2:
1166                 inx = 5;
1167                 break;
1168         case 6*2:
1169                 inx = 4;
1170                 break;
1171         case 11*2:
1172                 inx = 3;
1173                 break;
1174         case 11:
1175                 inx = 2;
1176                 break;
1177         case 2*2:
1178                 inx = 1;
1179                 break;
1180         case 1*2:
1181                 inx = 0;
1182                 break;
1183         }
1184         return inx;
1185 }
1186
1187 unsigned int update_basic_rate23a(unsigned char *ptn, unsigned int ptn_sz)
1188 {
1189         unsigned int i, num_of_rate;
1190         unsigned int mask = 0;
1191
1192         num_of_rate = (ptn_sz > NumRates)? NumRates: ptn_sz;
1193
1194         for (i = 0; i < num_of_rate; i++) {
1195                 if ((*(ptn + i)) & 0x80)
1196                         mask |= 0x1 << wifirate2_ratetbl_inx23a(*(ptn + i));
1197         }
1198         return mask;
1199 }
1200
1201 unsigned int update_supported_rate23a(unsigned char *ptn, unsigned int ptn_sz)
1202 {
1203         unsigned int i, num_of_rate;
1204         unsigned int mask = 0;
1205
1206         num_of_rate = (ptn_sz > NumRates) ? NumRates : ptn_sz;
1207
1208         for (i = 0; i < num_of_rate; i++)
1209                 mask |= 0x1 << wifirate2_ratetbl_inx23a(*(ptn + i));
1210         return mask;
1211 }
1212
1213 unsigned int update_MSC_rate23a(struct ieee80211_ht_cap *pHT_caps)
1214 {
1215         unsigned int mask;
1216
1217         mask = pHT_caps->mcs.rx_mask[0] << 12 |
1218                 pHT_caps->mcs.rx_mask[1] << 20;
1219
1220         return mask;
1221 }
1222
1223 int support_short_GI23a(struct rtw_adapter *padapter,
1224                         struct ieee80211_ht_cap *pHT_caps)
1225 {
1226         struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
1227         struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
1228         unsigned char bit_offset;
1229
1230         if (!pmlmeinfo->HT_enable)
1231                 return _FAIL;
1232         if (pmlmeinfo->assoc_AP_vendor == HT_IOT_PEER_RALINK)
1233                 return _FAIL;
1234         bit_offset = (pmlmeext->cur_bwmode & HT_CHANNEL_WIDTH_40)? 6: 5;
1235
1236         if (pHT_caps->cap_info & cpu_to_le16(0x1 << bit_offset))
1237                 return _SUCCESS;
1238         else
1239                 return _FAIL;
1240 }
1241
1242 unsigned char get_highest_rate_idx23a(u32 mask)
1243 {
1244         int i;
1245         unsigned char rate_idx = 0;
1246
1247         for (i = 27; i >= 0; i--) {
1248                 if (mask & BIT(i)) {
1249                         rate_idx = i;
1250                         break;
1251                 }
1252         }
1253         return rate_idx;
1254 }
1255
1256 void Update_RA_Entry23a(struct rtw_adapter *padapter, struct sta_info *psta)
1257 {
1258         rtw_hal_update_ra_mask23a(psta, 0);
1259 }
1260
1261 static void enable_rate_adaptive(struct rtw_adapter *padapter,
1262                                  struct sta_info *psta)
1263 {
1264         Update_RA_Entry23a(padapter, psta);
1265 }
1266
1267 void set_sta_rate23a(struct rtw_adapter *padapter, struct sta_info *psta)
1268 {
1269         /* rate adaptive */
1270         enable_rate_adaptive(padapter, psta);
1271 }
1272
1273 /*  Update RRSR and Rate for USERATE */
1274 void update_tx_basic_rate23a(struct rtw_adapter *padapter, u8 wirelessmode)
1275 {
1276         unsigned char supported_rates[NDIS_802_11_LENGTH_RATES_EX];
1277
1278         memset(supported_rates, 0, NDIS_802_11_LENGTH_RATES_EX);
1279
1280         if (wirelessmode == WIRELESS_11B) {
1281                 memcpy(supported_rates, rtw_basic_rate_cck, 4);
1282         } else if (wirelessmode & WIRELESS_11B) {
1283                 memcpy(supported_rates, rtw_basic_rate_mix, 7);
1284         } else {
1285                 memcpy(supported_rates, rtw_basic_rate_ofdm, 3);
1286         }
1287
1288         if (wirelessmode & WIRELESS_11B)
1289                 update_mgnt_tx_rate23a(padapter, IEEE80211_CCK_RATE_1MB);
1290         else
1291                 update_mgnt_tx_rate23a(padapter, IEEE80211_OFDM_RATE_6MB);
1292
1293         HalSetBrateCfg23a(padapter, supported_rates);
1294 }
1295
1296 unsigned char check_assoc_AP23a(u8 *pframe, uint len)
1297 {
1298         int i;
1299         u8 epigram_vendor_flag;
1300         u8 ralink_vendor_flag;
1301         const u8 *p;
1302
1303         epigram_vendor_flag = 0;
1304         ralink_vendor_flag = 0;
1305
1306         for (i = 0; i < len;) {
1307                 p = pframe + i;
1308
1309                 switch (p[0]) {
1310                 case WLAN_EID_VENDOR_SPECIFIC:
1311                         if (!memcmp(p + 2, ARTHEROS_OUI1, 3) ||
1312                             !memcmp(p + 2, ARTHEROS_OUI2, 3)) {
1313                                 DBG_8723A("link to Artheros AP\n");
1314                                 return HT_IOT_PEER_ATHEROS;
1315                         } else if (!memcmp(p + 2, BROADCOM_OUI1, 3) ||
1316                                    !memcmp(p + 2, BROADCOM_OUI2, 3)) {
1317                                 DBG_8723A("link to Broadcom AP\n");
1318                                 return HT_IOT_PEER_BROADCOM;
1319                         } else if (!memcmp(p + 2, MARVELL_OUI, 3)) {
1320                                 DBG_8723A("link to Marvell AP\n");
1321                                 return HT_IOT_PEER_MARVELL;
1322                         } else if (!memcmp(p + 2, RALINK_OUI, 3)) {
1323                                 if (!ralink_vendor_flag)
1324                                         ralink_vendor_flag = 1;
1325                                 else {
1326                                         DBG_8723A("link to Ralink AP\n");
1327                                         return HT_IOT_PEER_RALINK;
1328                                 }
1329                         } else if (!memcmp(p + 2, CISCO_OUI, 3)) {
1330                                 DBG_8723A("link to Cisco AP\n");
1331                                 return HT_IOT_PEER_CISCO;
1332                         } else if (!memcmp(p + 2, REALTEK_OUI, 3)) {
1333                                 DBG_8723A("link to Realtek 96B\n");
1334                                 return HT_IOT_PEER_REALTEK;
1335                         } else if (!memcmp(p + 2, AIRGOCAP_OUI, 3)) {
1336                                 DBG_8723A("link to Airgo Cap\n");
1337                                 return HT_IOT_PEER_AIRGO;
1338                         } else if (!memcmp(p + 2, EPIGRAM_OUI, 3)) {
1339                                 epigram_vendor_flag = 1;
1340                                 if (ralink_vendor_flag) {
1341                                         DBG_8723A("link to Tenda W311R AP\n");
1342                                         return HT_IOT_PEER_TENDA;
1343                                 } else
1344                                         DBG_8723A("Capture EPIGRAM_OUI\n");
1345                         } else
1346                                 break;
1347                 default:
1348                         break;
1349                 }
1350
1351                 i += (p[1] + 2);
1352         }
1353
1354         if (ralink_vendor_flag && !epigram_vendor_flag) {
1355                 DBG_8723A("link to Ralink AP\n");
1356                 return HT_IOT_PEER_RALINK;
1357         } else if (ralink_vendor_flag && epigram_vendor_flag) {
1358                 DBG_8723A("link to Tenda W311R AP\n");
1359                 return HT_IOT_PEER_TENDA;
1360         } else {
1361                 DBG_8723A("link to new AP\n");
1362                 return HT_IOT_PEER_UNKNOWN;
1363         }
1364 }
1365
1366 void update_IOT_info23a(struct rtw_adapter *padapter)
1367 {
1368         struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
1369         struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
1370
1371         switch (pmlmeinfo->assoc_AP_vendor) {
1372         case HT_IOT_PEER_MARVELL:
1373                 pmlmeinfo->turboMode_cts2self = 1;
1374                 pmlmeinfo->turboMode_rtsen = 0;
1375                 break;
1376         case HT_IOT_PEER_RALINK:
1377                 pmlmeinfo->turboMode_cts2self = 0;
1378                 pmlmeinfo->turboMode_rtsen = 1;
1379                 /* disable high power */
1380                 rtl8723a_odm_support_ability_clr(padapter, (u32)
1381                                                  ~DYNAMIC_BB_DYNAMIC_TXPWR);
1382                 break;
1383         case HT_IOT_PEER_REALTEK:
1384                 /* rtw_write16(padapter, 0x4cc, 0xffff); */
1385                 /* rtw_write16(padapter, 0x546, 0x01c0); */
1386                 /* disable high power */
1387                 rtl8723a_odm_support_ability_clr(padapter, (u32)
1388                                                  ~DYNAMIC_BB_DYNAMIC_TXPWR);
1389                 break;
1390         default:
1391                 pmlmeinfo->turboMode_cts2self = 0;
1392                 pmlmeinfo->turboMode_rtsen = 1;
1393                 break;
1394         }
1395 }
1396
1397 void update_capinfo23a(struct rtw_adapter *Adapter, u16 updateCap)
1398 {
1399         struct mlme_ext_priv *pmlmeext = &Adapter->mlmeextpriv;
1400         struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
1401
1402         if (updateCap & cShortPreamble) {
1403                 /*  Short Preamble */
1404                 if (pmlmeinfo->preamble_mode != PREAMBLE_SHORT) {
1405                         /*  PREAMBLE_LONG or PREAMBLE_AUTO */
1406                         pmlmeinfo->preamble_mode = PREAMBLE_SHORT;
1407                         rtl8723a_ack_preamble(Adapter, true);
1408                 }
1409         } else { /*  Long Preamble */
1410                 if (pmlmeinfo->preamble_mode != PREAMBLE_LONG) {
1411                         /*  PREAMBLE_SHORT or PREAMBLE_AUTO */
1412                         pmlmeinfo->preamble_mode = PREAMBLE_LONG;
1413                         rtl8723a_ack_preamble(Adapter, false);
1414                 }
1415         }
1416         if (updateCap & cIBSS) {
1417                 /* Filen: See 802.11-2007 p.91 */
1418                 pmlmeinfo->slotTime = NON_SHORT_SLOT_TIME;
1419         } else {
1420                 /* Filen: See 802.11-2007 p.90 */
1421                 if (pmlmeext->cur_wireless_mode &
1422                     (WIRELESS_11G | WIRELESS_11_24N)) {
1423                         if (updateCap & cShortSlotTime) { /*  Short Slot Time */
1424                                 if (pmlmeinfo->slotTime != SHORT_SLOT_TIME)
1425                                         pmlmeinfo->slotTime = SHORT_SLOT_TIME;
1426                         } else { /*  Long Slot Time */
1427                                 if (pmlmeinfo->slotTime != NON_SHORT_SLOT_TIME)
1428                                         pmlmeinfo->slotTime =
1429                                                 NON_SHORT_SLOT_TIME;
1430                         }
1431                 } else if (pmlmeext->cur_wireless_mode &
1432                            (WIRELESS_11A | WIRELESS_11_5N)) {
1433                         pmlmeinfo->slotTime = SHORT_SLOT_TIME;
1434                 } else {
1435                         /* B Mode */
1436                         pmlmeinfo->slotTime = NON_SHORT_SLOT_TIME;
1437                 }
1438         }
1439         rtl8723a_set_slot_time(Adapter, pmlmeinfo->slotTime);
1440 }
1441
1442 void update_wireless_mode23a(struct rtw_adapter *padapter)
1443 {
1444         int ratelen, network_type = 0;
1445         struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
1446         struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
1447         struct wlan_bssid_ex *cur_network = &pmlmeinfo->network;
1448         unsigned char *rate = cur_network->SupportedRates;
1449
1450         ratelen = rtw_get_rateset_len23a(cur_network->SupportedRates);
1451
1452         if ((pmlmeinfo->HT_info_enable) && (pmlmeinfo->HT_caps_enable))
1453                 pmlmeinfo->HT_enable = 1;
1454
1455         if (pmlmeext->cur_channel > 14) {
1456                 if (pmlmeinfo->HT_enable)
1457                         network_type = WIRELESS_11_5N;
1458                 network_type |= WIRELESS_11A;
1459         } else {
1460                 if (pmlmeinfo->HT_enable)
1461                         network_type = WIRELESS_11_24N;
1462
1463                 if (cckratesonly_included23a(rate, ratelen) == true)
1464                         network_type |= WIRELESS_11B;
1465                 else if (cckrates_included23a(rate, ratelen) == true)
1466                         network_type |= WIRELESS_11BG;
1467                 else
1468                         network_type |= WIRELESS_11G;
1469         }
1470
1471         pmlmeext->cur_wireless_mode =
1472                 network_type & padapter->registrypriv.wireless_mode;
1473
1474         /* 0x0808 -> for CCK, 0x0a0a -> for OFDM */
1475         /* change this value if having IOT issues. */
1476         rtl8723a_set_resp_sifs(padapter, 0x08, 0x08, 0x0a, 0x0a);
1477
1478         if (pmlmeext->cur_wireless_mode & WIRELESS_11B)
1479                 update_mgnt_tx_rate23a(padapter, IEEE80211_CCK_RATE_1MB);
1480          else
1481                 update_mgnt_tx_rate23a(padapter, IEEE80211_OFDM_RATE_6MB);
1482 }
1483
1484 void update_bmc_sta_support_rate23a(struct rtw_adapter *padapter, u32 mac_id)
1485 {
1486         struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
1487         struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
1488
1489         if (pmlmeext->cur_wireless_mode & WIRELESS_11B) {
1490                 /*  Only B, B/G, and B/G/N AP could use CCK rate */
1491                 memcpy((pmlmeinfo->FW_sta_info[mac_id].SupportedRates),
1492                        rtw_basic_rate_cck, 4);
1493         } else {
1494                 memcpy(pmlmeinfo->FW_sta_info[mac_id].SupportedRates,
1495                        rtw_basic_rate_ofdm, 3);
1496         }
1497 }
1498
1499 int update_sta_support_rate23a(struct rtw_adapter *padapter, u8 *pvar_ie,
1500                                uint var_ie_len, int cam_idx)
1501 {
1502         int supportRateNum = 0;
1503         struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
1504         struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
1505         const u8 *p;
1506
1507         p = cfg80211_find_ie(WLAN_EID_SUPP_RATES, pvar_ie, var_ie_len);
1508         if (!p)
1509                 return _FAIL;
1510
1511         memcpy(pmlmeinfo->FW_sta_info[cam_idx].SupportedRates, p + 2, p[1]);
1512         supportRateNum = p[1];
1513
1514         p = cfg80211_find_ie(WLAN_EID_EXT_SUPP_RATES, pvar_ie, var_ie_len);
1515         if (p)
1516                 memcpy(pmlmeinfo->FW_sta_info[cam_idx].SupportedRates +
1517                        supportRateNum, p + 2, p[1]);
1518         return _SUCCESS;
1519 }
1520
1521 void process_addba_req23a(struct rtw_adapter *padapter,
1522                           u8 *paddba_req, u8 *addr)
1523 {
1524         struct sta_info *psta;
1525         u16 tid, start_seq, param;
1526         struct recv_reorder_ctrl *preorder_ctrl;
1527         struct sta_priv *pstapriv = &padapter->stapriv;
1528         struct ADDBA_request *preq = (struct ADDBA_request *)paddba_req;
1529         struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
1530         struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
1531
1532         psta = rtw_get_stainfo23a(pstapriv, addr);
1533
1534         if (psta) {
1535                 start_seq = le16_to_cpu(preq->BA_starting_seqctrl) >> 4;
1536
1537                 param = le16_to_cpu(preq->BA_para_set);
1538                 tid = (param >> 2) & 0x0f;
1539
1540                 preorder_ctrl = &psta->recvreorder_ctrl[tid];
1541
1542                 preorder_ctrl->indicate_seq = 0xffff;
1543
1544                 preorder_ctrl->enable = (pmlmeinfo->bAcceptAddbaReq == true) ?
1545                         true : false;
1546         }
1547 }