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