Merge tag 'staging-5.6-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh...
[linux-2.6-microblaze.git] / drivers / staging / rtl8188eu / core / rtw_wlan_util.c
1 // SPDX-License-Identifier: GPL-2.0
2 /******************************************************************************
3  *
4  * Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved.
5  *
6  ******************************************************************************/
7 #define _RTW_WLAN_UTIL_C_
8
9 #include <linux/ieee80211.h>
10
11 #include <osdep_service.h>
12 #include <drv_types.h>
13 #include <wifi.h>
14
15 static const u8 ARTHEROS_OUI1[] = {0x00, 0x03, 0x7f};
16 static const u8 ARTHEROS_OUI2[] = {0x00, 0x13, 0x74};
17
18 static const u8 BROADCOM_OUI1[] = {0x00, 0x10, 0x18};
19 static const u8 BROADCOM_OUI2[] = {0x00, 0x0a, 0xf7};
20
21 static const u8 CISCO_OUI[] = {0x00, 0x40, 0x96};
22 static const u8 MARVELL_OUI[] = {0x00, 0x50, 0x43};
23 static const u8 RALINK_OUI[] = {0x00, 0x0c, 0x43};
24 static const u8 REALTEK_OUI[] = {0x00, 0xe0, 0x4c};
25 static const u8 AIRGOCAP_OUI[] = {0x00, 0x0a, 0xf5};
26 static const u8 EPIGRAM_OUI[] = {0x00, 0x90, 0x4c};
27
28 u8 REALTEK_96B_IE[] = {0x00, 0xe0, 0x4c, 0x02, 0x01, 0x20};
29
30 #define WAIT_FOR_BCN_TO_MIN     (6000)
31 #define WAIT_FOR_BCN_TO_MAX     (20000)
32
33 static const u8 rtw_basic_rate_cck[4] = {
34         IEEE80211_CCK_RATE_1MB | IEEE80211_BASIC_RATE_MASK,
35         IEEE80211_CCK_RATE_2MB | IEEE80211_BASIC_RATE_MASK,
36         IEEE80211_CCK_RATE_5MB | IEEE80211_BASIC_RATE_MASK,
37         IEEE80211_CCK_RATE_11MB | IEEE80211_BASIC_RATE_MASK
38 };
39
40 static const u8 rtw_basic_rate_ofdm[3] = {
41         IEEE80211_OFDM_RATE_6MB | IEEE80211_BASIC_RATE_MASK,
42         IEEE80211_OFDM_RATE_12MB | IEEE80211_BASIC_RATE_MASK,
43         IEEE80211_OFDM_RATE_24MB | IEEE80211_BASIC_RATE_MASK
44 };
45
46 static const u8 rtw_basic_rate_mix[7] = {
47         IEEE80211_CCK_RATE_1MB | IEEE80211_BASIC_RATE_MASK,
48         IEEE80211_CCK_RATE_2MB | IEEE80211_BASIC_RATE_MASK,
49         IEEE80211_CCK_RATE_5MB | IEEE80211_BASIC_RATE_MASK,
50         IEEE80211_CCK_RATE_11MB | IEEE80211_BASIC_RATE_MASK,
51         IEEE80211_OFDM_RATE_6MB | IEEE80211_BASIC_RATE_MASK,
52         IEEE80211_OFDM_RATE_12MB | IEEE80211_BASIC_RATE_MASK,
53         IEEE80211_OFDM_RATE_24MB | IEEE80211_BASIC_RATE_MASK
54 };
55
56 bool cckrates_included(unsigned char *rate, int ratelen)
57 {
58         int i;
59
60         for (i = 0; i < ratelen; i++) {
61                 u8 r = rate[i] & 0x7f;
62
63                 if (r == 2 || r == 4 || r == 11 || r == 22)
64                         return true;
65         }
66         return false;
67 }
68
69 bool cckratesonly_included(unsigned char *rate, int ratelen)
70 {
71         int i;
72
73         for (i = 0; i < ratelen; i++) {
74                 u8 r = rate[i] & 0x7f;
75
76                 if (r != 2 && r != 4 && r != 11 && r != 22)
77                         return false;
78         }
79         return true;
80 }
81
82 unsigned char networktype_to_raid(unsigned char network_type)
83 {
84         switch (network_type) {
85         case WIRELESS_11B:
86                 return RATR_INX_WIRELESS_B;
87         case WIRELESS_11A:
88         case WIRELESS_11G:
89                 return RATR_INX_WIRELESS_G;
90         case WIRELESS_11BG:
91                 return RATR_INX_WIRELESS_GB;
92         case WIRELESS_11_24N:
93         case WIRELESS_11_5N:
94                 return RATR_INX_WIRELESS_N;
95         case WIRELESS_11A_5N:
96         case WIRELESS_11G_24N:
97                 return  RATR_INX_WIRELESS_NG;
98         case WIRELESS_11BG_24N:
99                 return RATR_INX_WIRELESS_NGB;
100         default:
101                 return RATR_INX_WIRELESS_GB;
102         }
103 }
104
105 u8 judge_network_type(struct adapter *padapter, unsigned char *rate, int ratelen)
106 {
107         u8 network_type = 0;
108         struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
109         struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
110
111         if (pmlmeinfo->HT_enable)
112                 network_type = WIRELESS_11_24N;
113
114         if (cckratesonly_included(rate, ratelen))
115                 network_type |= WIRELESS_11B;
116         else if (cckrates_included(rate, ratelen))
117                 network_type |= WIRELESS_11BG;
118         else
119                 network_type |= WIRELESS_11G;
120
121         return network_type;
122 }
123
124 static unsigned char ratetbl_val_2wifirate(unsigned char rate)
125 {
126         switch (rate & 0x7f) {
127         case 0:
128                 return IEEE80211_CCK_RATE_1MB;
129         case 1:
130                 return IEEE80211_CCK_RATE_2MB;
131         case 2:
132                 return IEEE80211_CCK_RATE_5MB;
133         case 3:
134                 return IEEE80211_CCK_RATE_11MB;
135         case 4:
136                 return IEEE80211_OFDM_RATE_6MB;
137         case 5:
138                 return IEEE80211_OFDM_RATE_9MB;
139         case 6:
140                 return IEEE80211_OFDM_RATE_12MB;
141         case 7:
142                 return IEEE80211_OFDM_RATE_18MB;
143         case 8:
144                 return IEEE80211_OFDM_RATE_24MB;
145         case 9:
146                 return IEEE80211_OFDM_RATE_36MB;
147         case 10:
148                 return IEEE80211_OFDM_RATE_48MB;
149         case 11:
150                 return IEEE80211_OFDM_RATE_54MB;
151         default:
152                 return 0;
153         }
154 }
155
156 static bool is_basicrate(struct adapter *padapter, unsigned char rate)
157 {
158         int i;
159         unsigned char val;
160         struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
161
162         for (i = 0; i < NumRates; i++) {
163                 val = pmlmeext->basicrate[i];
164
165                 if ((val != 0xff) && (val != 0xfe)) {
166                         if (rate == ratetbl_val_2wifirate(val))
167                                 return true;
168                 }
169         }
170         return false;
171 }
172
173 static unsigned int ratetbl2rateset(struct adapter *padapter, unsigned char *rateset)
174 {
175         int i;
176         unsigned char rate;
177         unsigned int len = 0;
178         struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
179
180         for (i = 0; i < NumRates; i++) {
181                 rate = pmlmeext->datarate[i];
182
183                 switch (rate) {
184                 case 0xff:
185                         return len;
186                 case 0xfe:
187                         continue;
188                 default:
189                         rate = ratetbl_val_2wifirate(rate);
190
191                         if (is_basicrate(padapter, rate))
192                                 rate |= IEEE80211_BASIC_RATE_MASK;
193
194                         rateset[len] = rate;
195                         len++;
196                         break;
197                 }
198         }
199         return len;
200 }
201
202 void get_rate_set(struct adapter *padapter, unsigned char *pbssrate, int *bssrate_len)
203 {
204         unsigned char supportedrates[NumRates];
205
206         memset(supportedrates, 0, NumRates);
207         *bssrate_len = ratetbl2rateset(padapter, supportedrates);
208         memcpy(pbssrate, supportedrates, *bssrate_len);
209 }
210
211 void UpdateBrateTbl(struct adapter *Adapter, u8 *mbrate)
212 {
213         u8 i;
214         u8 rate;
215
216         /*  1M, 2M, 5.5M, 11M, 6M, 12M, 24M are mandatory. */
217         for (i = 0; i < NDIS_802_11_LENGTH_RATES_EX; i++) {
218                 rate = mbrate[i] & 0x7f;
219                 switch (rate) {
220                 case IEEE80211_CCK_RATE_1MB:
221                 case IEEE80211_CCK_RATE_2MB:
222                 case IEEE80211_CCK_RATE_5MB:
223                 case IEEE80211_CCK_RATE_11MB:
224                 case IEEE80211_OFDM_RATE_6MB:
225                 case IEEE80211_OFDM_RATE_12MB:
226                 case IEEE80211_OFDM_RATE_24MB:
227                         mbrate[i] |= IEEE80211_BASIC_RATE_MASK;
228                         break;
229                 }
230         }
231 }
232
233 void UpdateBrateTblForSoftAP(u8 *bssrateset, u32 bssratelen)
234 {
235         u8 i;
236         u8 rate;
237
238         for (i = 0; i < bssratelen; i++) {
239                 rate = bssrateset[i] & 0x7f;
240                 switch (rate) {
241                 case IEEE80211_CCK_RATE_1MB:
242                 case IEEE80211_CCK_RATE_2MB:
243                 case IEEE80211_CCK_RATE_5MB:
244                 case IEEE80211_CCK_RATE_11MB:
245                         bssrateset[i] |= IEEE80211_BASIC_RATE_MASK;
246                         break;
247                 }
248         }
249 }
250
251 void Save_DM_Func_Flag(struct adapter *padapter)
252 {
253         u8 saveflag = true;
254
255         rtw_hal_set_hwreg(padapter, HW_VAR_DM_FUNC_OP, (u8 *)(&saveflag));
256 }
257
258 void Restore_DM_Func_Flag(struct adapter *padapter)
259 {
260         u8 saveflag = false;
261
262         rtw_hal_set_hwreg(padapter, HW_VAR_DM_FUNC_OP, (u8 *)(&saveflag));
263 }
264
265 void Switch_DM_Func(struct adapter *padapter, u32 mode, u8 enable)
266 {
267         if (enable)
268                 rtw_hal_set_hwreg(padapter, HW_VAR_DM_FUNC_SET, (u8 *)(&mode));
269         else
270                 rtw_hal_set_hwreg(padapter, HW_VAR_DM_FUNC_CLR, (u8 *)(&mode));
271 }
272
273 void Set_MSR(struct adapter *padapter, u8 type)
274 {
275         rtw_hal_set_hwreg(padapter, HW_VAR_MEDIA_STATUS, (u8 *)(&type));
276 }
277
278 inline u8 rtw_get_oper_ch(struct adapter *adapter)
279 {
280         return adapter->mlmeextpriv.oper_channel;
281 }
282
283 inline void rtw_set_oper_ch(struct adapter *adapter, u8 ch)
284 {
285         adapter->mlmeextpriv.oper_channel = ch;
286 }
287
288 inline void rtw_set_oper_bw(struct adapter *adapter, u8 bw)
289 {
290         adapter->mlmeextpriv.oper_bwmode = bw;
291 }
292
293 inline void rtw_set_oper_choffset(struct adapter *adapter, u8 offset)
294 {
295         adapter->mlmeextpriv.oper_ch_offset = offset;
296 }
297
298 void SelectChannel(struct adapter *padapter, unsigned char channel)
299 {
300         /* saved channel info */
301         rtw_set_oper_ch(padapter, channel);
302         rtw_hal_set_chan(padapter, channel);
303 }
304
305 void SetBWMode(struct adapter *padapter, unsigned short bwmode,
306                unsigned char channel_offset)
307 {
308         /* saved bw info */
309         rtw_set_oper_bw(padapter, bwmode);
310         rtw_set_oper_choffset(padapter, channel_offset);
311
312         rtw_hal_set_bwmode(padapter, (enum ht_channel_width)bwmode, channel_offset);
313 }
314
315 void set_channel_bwmode(struct adapter *padapter, unsigned char channel, unsigned char channel_offset, unsigned short bwmode)
316 {
317         u8 center_ch;
318
319         if ((bwmode == HT_CHANNEL_WIDTH_20) ||
320             (channel_offset == HAL_PRIME_CHNL_OFFSET_DONT_CARE)) {
321                 /* SelectChannel(padapter, channel); */
322                 center_ch = channel;
323         } else {
324                 /* switch to the proper channel */
325                 if (channel_offset == HAL_PRIME_CHNL_OFFSET_LOWER) {
326                         /* SelectChannel(padapter, channel + 2); */
327                         center_ch = channel + 2;
328                 } else {
329                         /* SelectChannel(padapter, channel - 2); */
330                         center_ch = channel - 2;
331                 }
332         }
333
334         /* set Channel */
335         /* saved channel/bw info */
336         rtw_set_oper_ch(padapter, channel);
337         rtw_set_oper_bw(padapter, bwmode);
338         rtw_set_oper_choffset(padapter, channel_offset);
339
340         rtw_hal_set_chan(padapter, center_ch); /*  set center channel */
341         SetBWMode(padapter, bwmode, channel_offset);
342 }
343
344 u16 get_beacon_interval(struct wlan_bssid_ex *bss)
345 {
346         __le16 val;
347
348         memcpy((unsigned char *)&val, rtw_get_beacon_interval_from_ie(bss->ies), 2);
349
350         return le16_to_cpu(val);
351 }
352
353 int is_client_associated_to_ap(struct adapter *padapter)
354 {
355         struct mlme_ext_priv *pmlmeext;
356         struct mlme_ext_info *pmlmeinfo;
357
358         if (!padapter)
359                 return _FAIL;
360
361         pmlmeext = &padapter->mlmeextpriv;
362         pmlmeinfo = &pmlmeext->mlmext_info;
363
364         if ((pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS) &&
365             (pmlmeinfo->state & 0x03) == WIFI_FW_STATION_STATE)
366                 return true;
367         else
368                 return _FAIL;
369 }
370
371 int is_client_associated_to_ibss(struct adapter *padapter)
372 {
373         struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
374         struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
375
376         if ((pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS) &&
377             (pmlmeinfo->state & 0x03) == WIFI_FW_ADHOC_STATE)
378                 return true;
379         else
380                 return _FAIL;
381 }
382
383 int is_IBSS_empty(struct adapter *padapter)
384 {
385         unsigned int i;
386         struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
387         struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
388
389         for (i = IBSS_START_MAC_ID; i < NUM_STA; i++) {
390                 if (pmlmeinfo->FW_sta_info[i].status == 1)
391                         return _FAIL;
392         }
393         return true;
394 }
395
396 unsigned int decide_wait_for_beacon_timeout(unsigned int bcn_interval)
397 {
398         if ((bcn_interval << 2) < WAIT_FOR_BCN_TO_MIN)
399                 return WAIT_FOR_BCN_TO_MIN;
400         else if ((bcn_interval << 2) > WAIT_FOR_BCN_TO_MAX)
401                 return WAIT_FOR_BCN_TO_MAX;
402         else
403                 return bcn_interval << 2;
404 }
405
406 void invalidate_cam_all(struct adapter *padapter)
407 {
408         rtw_hal_set_hwreg(padapter, HW_VAR_CAM_INVALID_ALL, NULL);
409 }
410
411 void write_cam(struct adapter *padapter, u8 entry, u16 ctrl, u8 *mac, u8 *key)
412 {
413         unsigned int i, val, addr;
414         int j;
415         u32 cam_val[2];
416
417         addr = entry << 3;
418
419         for (j = 5; j >= 0; j--) {
420                 switch (j) {
421                 case 0:
422                         val = ctrl | (mac[0] << 16) | (mac[1] << 24);
423                         break;
424                 case 1:
425                         val = mac[2] | (mac[3] << 8) | (mac[4] << 16) | (mac[5] << 24);
426                         break;
427                 default:
428                         i = (j - 2) << 2;
429                         val = key[i] | (key[i + 1] << 8) | (key[i + 2] << 16) |
430                               (key[i + 3] << 24);
431                         break;
432                 }
433
434                 cam_val[0] = val;
435                 cam_val[1] = addr + (unsigned int)j;
436
437                 rtw_hal_set_hwreg(padapter, HW_VAR_CAM_WRITE, (u8 *)cam_val);
438         }
439 }
440
441 void clear_cam_entry(struct adapter *padapter, u8 entry)
442 {
443         u8 null_sta[ETH_ALEN] = {};
444         u8 null_key[16] = {};
445
446         write_cam(padapter, entry, 0, null_sta, null_key);
447 }
448
449 int allocate_fw_sta_entry(struct adapter *padapter)
450 {
451         unsigned int mac_id;
452         struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
453         struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
454
455         for (mac_id = IBSS_START_MAC_ID; mac_id < NUM_STA; mac_id++) {
456                 if (pmlmeinfo->FW_sta_info[mac_id].status == 0) {
457                         pmlmeinfo->FW_sta_info[mac_id].status = 1;
458                         pmlmeinfo->FW_sta_info[mac_id].retry = 0;
459                         break;
460                 }
461         }
462
463         return mac_id;
464 }
465
466 void flush_all_cam_entry(struct adapter *padapter)
467 {
468         struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
469         struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
470
471         rtw_hal_set_hwreg(padapter, HW_VAR_CAM_INVALID_ALL, NULL);
472
473         memset((u8 *)(pmlmeinfo->FW_sta_info), 0, sizeof(pmlmeinfo->FW_sta_info));
474 }
475
476 int WMM_param_handler(struct adapter *padapter, struct ndis_802_11_var_ie *pIE)
477 {
478         struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
479         struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
480         struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
481
482         if (pmlmepriv->qospriv.qos_option == 0) {
483                 pmlmeinfo->WMM_enable = 0;
484                 return _FAIL;
485         }
486
487         pmlmeinfo->WMM_enable = 1;
488         memcpy(&pmlmeinfo->WMM_param, pIE->data + 6, sizeof(struct WMM_para_element));
489         return true;
490 }
491
492 void WMMOnAssocRsp(struct adapter *padapter)
493 {
494         u8 ACI, ACM, AIFS, ECWMin, ECWMax, aSifsTime;
495         u8 acm_mask;
496         u16 TXOP;
497         u32 acParm, i;
498         u32 edca[4], inx[4];
499         struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
500         struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
501         struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
502         struct registry_priv *pregpriv = &padapter->registrypriv;
503
504         if (pmlmeinfo->WMM_enable == 0) {
505                 padapter->mlmepriv.acm_mask = 0;
506                 return;
507         }
508
509         acm_mask = 0;
510
511         if (pmlmeext->cur_wireless_mode == WIRELESS_11B)
512                 aSifsTime = 10;
513         else
514                 aSifsTime = 16;
515
516         for (i = 0; i < 4; i++) {
517                 ACI = (pmlmeinfo->WMM_param.ac_param[i].ACI_AIFSN >> 5) & 0x03;
518                 ACM = (pmlmeinfo->WMM_param.ac_param[i].ACI_AIFSN >> 4) & 0x01;
519
520                 /* AIFS = AIFSN * slot time + SIFS - r2t phy delay */
521                 AIFS = (pmlmeinfo->WMM_param.ac_param[i].ACI_AIFSN & 0x0f) * pmlmeinfo->slotTime + aSifsTime;
522
523                 ECWMin = pmlmeinfo->WMM_param.ac_param[i].CW & 0x0f;
524                 ECWMax = (pmlmeinfo->WMM_param.ac_param[i].CW & 0xf0) >> 4;
525                 TXOP = le16_to_cpu(pmlmeinfo->WMM_param.ac_param[i].TXOP_limit);
526
527                 acParm = AIFS | (ECWMin << 8) | (ECWMax << 12) | (TXOP << 16);
528
529                 switch (ACI) {
530                 case 0x0:
531                         rtw_hal_set_hwreg(padapter, HW_VAR_AC_PARAM_BE, (u8 *)(&acParm));
532                         acm_mask |= (ACM ? BIT(1) : 0);
533                         edca[XMIT_BE_QUEUE] = acParm;
534                         break;
535                 case 0x1:
536                         rtw_hal_set_hwreg(padapter, HW_VAR_AC_PARAM_BK, (u8 *)(&acParm));
537                         edca[XMIT_BK_QUEUE] = acParm;
538                         break;
539                 case 0x2:
540                         rtw_hal_set_hwreg(padapter, HW_VAR_AC_PARAM_VI, (u8 *)(&acParm));
541                         acm_mask |= (ACM ? BIT(2) : 0);
542                         edca[XMIT_VI_QUEUE] = acParm;
543                         break;
544                 case 0x3:
545                         rtw_hal_set_hwreg(padapter, HW_VAR_AC_PARAM_VO, (u8 *)(&acParm));
546                         acm_mask |= (ACM ? BIT(3) : 0);
547                         edca[XMIT_VO_QUEUE] = acParm;
548                         break;
549                 }
550
551                 DBG_88E("WMM(%x): %x, %x\n", ACI, ACM, acParm);
552         }
553
554         if (padapter->registrypriv.acm_method == 1)
555                 rtw_hal_set_hwreg(padapter, HW_VAR_ACM_CTRL, (u8 *)(&acm_mask));
556         else
557                 padapter->mlmepriv.acm_mask = acm_mask;
558
559         inx[0] = 0; inx[1] = 1; inx[2] = 2; inx[3] = 3;
560
561         if (pregpriv->wifi_spec == 1) {
562                 u32 j, change_inx = false;
563
564                 /* entry indx: 0->vo, 1->vi, 2->be, 3->bk. */
565                 for (i = 0; i < 4; i++) {
566                         for (j = i + 1; j < 4; j++) {
567                                 /* compare CW and AIFS */
568                                 if ((edca[j] & 0xFFFF) < (edca[i] & 0xFFFF)) {
569                                         change_inx = true;
570                                 } else if ((edca[j] & 0xFFFF) == (edca[i] & 0xFFFF)) {
571                                         /* compare TXOP */
572                                         if ((edca[j] >> 16) > (edca[i] >> 16))
573                                                 change_inx = true;
574                                 }
575
576                                 if (change_inx) {
577                                         swap(edca[i], edca[j]);
578                                         swap(inx[i], inx[j]);
579                                         change_inx = false;
580                                 }
581                         }
582                 }
583         }
584
585         for (i = 0; i < 4; i++) {
586                 pxmitpriv->wmm_para_seq[i] = inx[i];
587                 DBG_88E("wmm_para_seq(%d): %d\n", i, pxmitpriv->wmm_para_seq[i]);
588         }
589 }
590
591 static void bwmode_update_check(struct adapter *padapter, struct ndis_802_11_var_ie *pIE)
592 {
593         unsigned char new_bwmode;
594         unsigned char new_ch_offset;
595         struct HT_info_element *pHT_info;
596         struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
597         struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
598         struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
599         struct registry_priv *pregistrypriv = &padapter->registrypriv;
600         struct ht_priv *phtpriv = &pmlmepriv->htpriv;
601
602         if (!pIE)
603                 return;
604
605         if (!phtpriv)
606                 return;
607
608         if (pIE->Length > sizeof(struct HT_info_element))
609                 return;
610
611         pHT_info = (struct HT_info_element *)pIE->data;
612
613         if ((pHT_info->infos[0] & BIT(2)) && pregistrypriv->cbw40_enable) {
614                 new_bwmode = HT_CHANNEL_WIDTH_40;
615
616                 switch (pHT_info->infos[0] & 0x3) {
617                 case 1:
618                         new_ch_offset = HAL_PRIME_CHNL_OFFSET_LOWER;
619                         break;
620                 case 3:
621                         new_ch_offset = HAL_PRIME_CHNL_OFFSET_UPPER;
622                         break;
623                 default:
624                         new_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
625                         break;
626                 }
627         } else {
628                 new_bwmode = HT_CHANNEL_WIDTH_20;
629                 new_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
630         }
631
632         if ((new_bwmode != pmlmeext->cur_bwmode) ||
633             (new_ch_offset != pmlmeext->cur_ch_offset)) {
634                 pmlmeinfo->bwmode_updated = true;
635
636                 pmlmeext->cur_bwmode = new_bwmode;
637                 pmlmeext->cur_ch_offset = new_ch_offset;
638
639                 /* update HT info also */
640                 HT_info_handler(padapter, pIE);
641         } else {
642                 pmlmeinfo->bwmode_updated = false;
643         }
644
645         if (pmlmeinfo->bwmode_updated) {
646                 struct sta_info *psta;
647                 struct wlan_bssid_ex    *cur_network = &pmlmeinfo->network;
648                 struct sta_priv *pstapriv = &padapter->stapriv;
649
650                 /* update ap's stainfo */
651                 psta = rtw_get_stainfo(pstapriv, cur_network->MacAddress);
652                 if (psta) {
653                         struct ht_priv  *phtpriv_sta = &psta->htpriv;
654
655                         if (phtpriv_sta->ht_option) {
656                                 /*  bwmode */
657                                 phtpriv_sta->bwmode = pmlmeext->cur_bwmode;
658                                 phtpriv_sta->ch_offset = pmlmeext->cur_ch_offset;
659                         } else {
660                                 phtpriv_sta->bwmode = HT_CHANNEL_WIDTH_20;
661                                 phtpriv_sta->ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
662                         }
663                 }
664         }
665 }
666
667 void HT_caps_handler(struct adapter *padapter, struct ndis_802_11_var_ie *pIE)
668 {
669         unsigned int i;
670         u8 max_ampdu_len, min_mpdu_spacing;
671         struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
672         struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
673         struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
674         struct ht_priv *phtpriv = &pmlmepriv->htpriv;
675         u8 *HT_cap = (u8 *)(&pmlmeinfo->HT_caps);
676
677         if (!pIE)
678                 return;
679
680         if (!phtpriv->ht_option)
681                 return;
682
683         pmlmeinfo->HT_caps_enable = 1;
684
685         for (i = 0; i < (pIE->Length); i++) {
686                 if (i != 2) {
687                         /*      Got the endian issue here. */
688                         HT_cap[i] &= (pIE->data[i]);
689                 } else {
690                         /* modify from  fw by Thomas 2010/11/17 */
691                         if ((pmlmeinfo->HT_caps.ampdu_params_info & 0x3) > (pIE->data[i] & 0x3))
692                                 max_ampdu_len = pIE->data[i] & 0x3;
693                         else
694                                 max_ampdu_len = pmlmeinfo->HT_caps.ampdu_params_info & 0x3;
695
696                         if ((pmlmeinfo->HT_caps.ampdu_params_info & 0x1c) > (pIE->data[i] & 0x1c))
697                                 min_mpdu_spacing = pmlmeinfo->HT_caps.ampdu_params_info & 0x1c;
698                         else
699                                 min_mpdu_spacing = pIE->data[i] & 0x1c;
700
701                         pmlmeinfo->HT_caps.ampdu_params_info = max_ampdu_len | min_mpdu_spacing;
702                 }
703         }
704
705         /* update the MCS rates */
706         for (i = 0; i < 16; i++)
707                 ((u8 *)&pmlmeinfo->HT_caps.mcs)[i] &= MCS_rate_1R[i];
708 }
709
710 void HT_info_handler(struct adapter *padapter, struct ndis_802_11_var_ie *pIE)
711 {
712         struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
713         struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
714         struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
715         struct ht_priv *phtpriv = &pmlmepriv->htpriv;
716
717         if (!pIE)
718                 return;
719
720         if (!phtpriv->ht_option)
721                 return;
722
723         if (pIE->Length > sizeof(struct HT_info_element))
724                 return;
725
726         pmlmeinfo->HT_info_enable = 1;
727         memcpy(&pmlmeinfo->HT_info, pIE->data, pIE->Length);
728 }
729
730 void HTOnAssocRsp(struct adapter *padapter)
731 {
732         u8 max_ampdu_len;
733         u8 min_mpdu_spacing;
734         struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
735         struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
736
737         DBG_88E("%s\n", __func__);
738
739         if ((pmlmeinfo->HT_info_enable) && (pmlmeinfo->HT_caps_enable)) {
740                 pmlmeinfo->HT_enable = 1;
741         } else {
742                 pmlmeinfo->HT_enable = 0;
743                 return;
744         }
745
746         /* handle A-MPDU parameter field
747          *
748          * AMPDU_para [1:0]:Max AMPDU Len => 0:8k , 1:16k, 2:32k, 3:64k
749          * AMPDU_para [4:2]:Min MPDU Start Spacing
750          */
751         max_ampdu_len = pmlmeinfo->HT_caps.ampdu_params_info & 0x03;
752         min_mpdu_spacing = (pmlmeinfo->HT_caps.ampdu_params_info & 0x1c) >> 2;
753
754         rtw_hal_set_hwreg(padapter, HW_VAR_AMPDU_MIN_SPACE, &min_mpdu_spacing);
755         rtw_hal_set_hwreg(padapter, HW_VAR_AMPDU_FACTOR, &max_ampdu_len);
756 }
757
758 void ERP_IE_handler(struct adapter *padapter, struct ndis_802_11_var_ie *pIE)
759 {
760         struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
761         struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
762
763         if (pIE->Length > 1)
764                 return;
765
766         pmlmeinfo->ERP_enable = 1;
767         memcpy(&pmlmeinfo->ERP_IE, pIE->data, pIE->Length);
768 }
769
770 void VCS_update(struct adapter *padapter, struct sta_info *psta)
771 {
772         struct registry_priv *pregpriv = &padapter->registrypriv;
773         struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
774         struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
775
776         switch (pregpriv->vrtl_carrier_sense) { /* 0:off 1:on 2:auto */
777         case 0: /* off */
778                 psta->rtsen = 0;
779                 psta->cts2self = 0;
780                 break;
781         case 1: /* on */
782                 if (pregpriv->vcs_type == 1) { /* 1:RTS/CTS 2:CTS to self */
783                         psta->rtsen = 1;
784                         psta->cts2self = 0;
785                 } else {
786                         psta->rtsen = 0;
787                         psta->cts2self = 1;
788                 }
789                 break;
790         case 2: /* auto */
791         default:
792                 if ((pmlmeinfo->ERP_enable) && (pmlmeinfo->ERP_IE & BIT(1))) {
793                         if (pregpriv->vcs_type == 1) {
794                                 psta->rtsen = 1;
795                                 psta->cts2self = 0;
796                         } else {
797                                 psta->rtsen = 0;
798                                 psta->cts2self = 1;
799                         }
800                 } else {
801                         psta->rtsen = 0;
802                         psta->cts2self = 0;
803                 }
804                 break;
805         }
806 }
807
808 int rtw_check_bcn_info(struct adapter  *Adapter, u8 *pframe, u32 packet_len)
809 {
810         unsigned int len;
811         unsigned char *p;
812         unsigned short val16, subtype;
813         struct wlan_network *cur_network = &Adapter->mlmepriv.cur_network;
814         u16 wpa_len = 0, rsn_len = 0;
815         u8 encryp_protocol = 0;
816         struct wlan_bssid_ex *bssid;
817         int group_cipher = 0, pairwise_cipher = 0, is_8021x = 0;
818         unsigned char *pbuf;
819         u32 wpa_ielen = 0;
820         u8 *pbssid = GetAddr3Ptr(pframe);
821         struct HT_info_element *pht_info = NULL;
822         u32 bcn_channel;
823         unsigned short ht_cap_info;
824         unsigned char ht_info_infos_0;
825         int ssid_len;
826
827         if (!is_client_associated_to_ap(Adapter))
828                 return true;
829
830         len = packet_len - sizeof(struct ieee80211_hdr_3addr);
831
832         if (len > MAX_IE_SZ) {
833                 DBG_88E("%s IE too long for survey event\n", __func__);
834                 return _FAIL;
835         }
836
837         if (memcmp(cur_network->network.MacAddress, pbssid, 6)) {
838                 DBG_88E("Oops: rtw_check_network_encrypt linked but recv other bssid bcn\n%pM %pM\n",
839                         (pbssid), (cur_network->network.MacAddress));
840                 return true;
841         }
842
843         bssid = kzalloc(sizeof(struct wlan_bssid_ex), GFP_ATOMIC);
844         if (!bssid)
845                 return _FAIL;
846
847         subtype = GetFrameSubType(pframe) >> 4;
848
849         if (subtype == WIFI_BEACON)
850                 bssid->Reserved[0] = 1;
851
852         bssid->Length = sizeof(struct wlan_bssid_ex) - MAX_IE_SZ + len;
853
854         /* below is to copy the information element */
855         bssid->ie_length = len;
856         memcpy(bssid->ies, (pframe + sizeof(struct ieee80211_hdr_3addr)), bssid->ie_length);
857
858         /* check bw and channel offset */
859         /* parsing HT_CAP_IE */
860         p = rtw_get_ie(bssid->ies + _FIXED_IE_LENGTH_, _HT_CAPABILITY_IE_, &len, bssid->ie_length - _FIXED_IE_LENGTH_);
861         if (p && len > 0) {
862                 struct ieee80211_ht_cap *ht_cap =
863                         (struct ieee80211_ht_cap *)(p + 2);
864
865                 ht_cap_info = le16_to_cpu(ht_cap->cap_info);
866         } else {
867                 ht_cap_info = 0;
868         }
869         /* parsing HT_INFO_IE */
870         p = rtw_get_ie(bssid->ies + _FIXED_IE_LENGTH_, _HT_ADD_INFO_IE_, &len, bssid->ie_length - _FIXED_IE_LENGTH_);
871         if (p && len > 0) {
872                         pht_info = (struct HT_info_element *)(p + 2);
873                         ht_info_infos_0 = pht_info->infos[0];
874         } else {
875                         ht_info_infos_0 = 0;
876         }
877         if (ht_cap_info != cur_network->BcnInfo.ht_cap_info ||
878             ((ht_info_infos_0 & 0x03) != (cur_network->BcnInfo.ht_info_infos_0 & 0x03))) {
879                         DBG_88E("%s bcn now: ht_cap_info:%x ht_info_infos_0:%x\n", __func__,
880                                 ht_cap_info, ht_info_infos_0);
881                         DBG_88E("%s bcn link: ht_cap_info:%x ht_info_infos_0:%x\n", __func__,
882                                 cur_network->BcnInfo.ht_cap_info, cur_network->BcnInfo.ht_info_infos_0);
883                         DBG_88E("%s bw mode change, disconnect\n", __func__);
884                         /* bcn_info_update */
885                         cur_network->BcnInfo.ht_cap_info = ht_cap_info;
886                         cur_network->BcnInfo.ht_info_infos_0 = ht_info_infos_0;
887                         /* to do : need to check that whether modify related register of BB or not */
888                         /* goto _mismatch; */
889         }
890
891         /* Checking for channel */
892         p = rtw_get_ie(bssid->ies + _FIXED_IE_LENGTH_, _DSSET_IE_, &len, bssid->ie_length - _FIXED_IE_LENGTH_);
893         if (p) {
894                         bcn_channel = *(p + 2);
895         } else {/* In 5G, some ap do not have DSSET IE checking HT info for channel */
896                         p = rtw_get_ie(bssid->ies + _FIXED_IE_LENGTH_, _HT_ADD_INFO_IE_, &len, bssid->ie_length - _FIXED_IE_LENGTH_);
897                         if (pht_info) {
898                                         bcn_channel = pht_info->primary_channel;
899                         } else { /* we don't find channel IE, so don't check it */
900                                         DBG_88E("Oops: %s we don't find channel IE, so don't check it\n", __func__);
901                                         bcn_channel = Adapter->mlmeextpriv.cur_channel;
902                         }
903         }
904         if (bcn_channel != Adapter->mlmeextpriv.cur_channel) {
905                         DBG_88E("%s beacon channel:%d cur channel:%d disconnect\n", __func__,
906                                 bcn_channel, Adapter->mlmeextpriv.cur_channel);
907                         goto _mismatch;
908         }
909
910         /* checking SSID */
911         ssid_len = 0;
912         p = rtw_get_ie(bssid->ies + _FIXED_IE_LENGTH_, _SSID_IE_, &len, bssid->ie_length - _FIXED_IE_LENGTH_);
913         if (p) {
914                 ssid_len = *(p + 1);
915                 if (ssid_len > NDIS_802_11_LENGTH_SSID)
916                         ssid_len = 0;
917         }
918         memcpy(bssid->ssid.ssid, (p + 2), ssid_len);
919         bssid->ssid.ssid_length = ssid_len;
920
921         RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("%s bssid.ssid.ssid:%s bssid.ssid.ssid_length:%d "
922                                 "cur_network->network.ssid.ssid:%s len:%d\n", __func__, bssid->ssid.ssid,
923                                 bssid->ssid.ssid_length, cur_network->network.ssid.ssid,
924                                 cur_network->network.ssid.ssid_length));
925
926         if (memcmp(bssid->ssid.ssid, cur_network->network.ssid.ssid, 32) ||
927             bssid->ssid.ssid_length != cur_network->network.ssid.ssid_length) {
928                 if (bssid->ssid.ssid[0] != '\0' && bssid->ssid.ssid_length != 0) { /* not hidden ssid */
929                         DBG_88E("%s(), SSID is not match return FAIL\n", __func__);
930                         goto _mismatch;
931                 }
932         }
933
934         /* check encryption info */
935         val16 = rtw_get_capability((struct wlan_bssid_ex *)bssid);
936
937         if (val16 & BIT(4))
938                 bssid->Privacy = 1;
939         else
940                 bssid->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, bssid->Privacy));
945         if (cur_network->network.Privacy != bssid->Privacy) {
946                 DBG_88E("%s(), privacy is not match return FAIL\n", __func__);
947                 goto _mismatch;
948         }
949
950         rtw_get_sec_ie(bssid->ies, bssid->ie_length, NULL, &rsn_len, NULL, &wpa_len);
951
952         if (rsn_len > 0) {
953                 encryp_protocol = ENCRYP_PROTOCOL_WPA2;
954         } else if (wpa_len > 0) {
955                 encryp_protocol = ENCRYP_PROTOCOL_WPA;
956         } else {
957                 if (bssid->Privacy)
958                         encryp_protocol = ENCRYP_PROTOCOL_WEP;
959         }
960
961         if (cur_network->BcnInfo.encryp_protocol != encryp_protocol) {
962                 DBG_88E("%s(): encryption protocol is not match , return FAIL\n", __func__);
963                 goto _mismatch;
964         }
965
966         if (encryp_protocol == ENCRYP_PROTOCOL_WPA || encryp_protocol == ENCRYP_PROTOCOL_WPA2) {
967                 pbuf = rtw_get_wpa_ie(&bssid->ies[12], &wpa_ielen,
968                                       bssid->ie_length - 12);
969                 if (pbuf && (wpa_ielen > 0)) {
970                         if (_SUCCESS == rtw_parse_wpa_ie(pbuf, wpa_ielen + 2, &group_cipher, &pairwise_cipher, &is_8021x)) {
971                                 RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_,
972                                          ("%s pnetwork->pairwise_cipher: %d, group_cipher is %d, is_8021x is %d\n", __func__,
973                                          pairwise_cipher, group_cipher, is_8021x));
974                         }
975                 } else {
976                         pbuf = rtw_get_wpa2_ie(&bssid->ies[12], &wpa_ielen,
977                                                bssid->ie_length - 12);
978
979                         if (pbuf && (wpa_ielen > 0)) {
980                                 if (_SUCCESS == rtw_parse_wpa2_ie(pbuf, wpa_ielen + 2, &group_cipher, &pairwise_cipher, &is_8021x)) {
981                                         RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_,
982                                                  ("%s pnetwork->pairwise_cipher: %d, pnetwork->group_cipher is %d, is_802x is %d\n",
983                                                   __func__, pairwise_cipher, group_cipher, is_8021x));
984                                 }
985                         }
986                 }
987
988                 RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_,
989                          ("%s cur_network->group_cipher is %d: %d\n", __func__, cur_network->BcnInfo.group_cipher, group_cipher));
990                 if (pairwise_cipher != cur_network->BcnInfo.pairwise_cipher || group_cipher != cur_network->BcnInfo.group_cipher) {
991                         DBG_88E("%s pairwise_cipher(%x:%x) or group_cipher(%x:%x) is not match , return FAIL\n", __func__,
992                                 pairwise_cipher, cur_network->BcnInfo.pairwise_cipher,
993                                 group_cipher, cur_network->BcnInfo.group_cipher);
994                         goto _mismatch;
995                 }
996
997                 if (is_8021x != cur_network->BcnInfo.is_8021x) {
998                         DBG_88E("%s authentication is not match , return FAIL\n", __func__);
999                         goto _mismatch;
1000                 }
1001         }
1002
1003         kfree(bssid);
1004         return _SUCCESS;
1005
1006 _mismatch:
1007         kfree(bssid);
1008         return _FAIL;
1009 }
1010
1011 void update_beacon_info(struct adapter *padapter, u8 *pframe, uint pkt_len, struct sta_info *psta)
1012 {
1013         unsigned int i;
1014         unsigned int len;
1015         struct ndis_802_11_var_ie *pIE;
1016
1017         len = pkt_len - (_BEACON_IE_OFFSET_ + WLAN_HDR_A3_LEN);
1018
1019         for (i = 0; i < len;) {
1020                 pIE = (struct ndis_802_11_var_ie *)(pframe + (_BEACON_IE_OFFSET_ + WLAN_HDR_A3_LEN) + i);
1021
1022                 switch (pIE->ElementID) {
1023                 case _HT_EXTRA_INFO_IE_:        /* HT info */
1024                         bwmode_update_check(padapter, pIE);
1025                         break;
1026                 case _ERPINFO_IE_:
1027                         ERP_IE_handler(padapter, pIE);
1028                         VCS_update(padapter, psta);
1029                         break;
1030                 default:
1031                         break;
1032                 }
1033
1034                 i += (pIE->Length + 2);
1035         }
1036 }
1037
1038 unsigned int is_ap_in_tkip(struct adapter *padapter)
1039 {
1040         u32 i;
1041         struct ndis_802_11_var_ie *pIE;
1042         struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
1043         struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
1044         struct wlan_bssid_ex *cur_network = &pmlmeinfo->network;
1045
1046         if (rtw_get_capability((struct wlan_bssid_ex *)cur_network) & WLAN_CAPABILITY_PRIVACY) {
1047                 for (i = sizeof(struct ndis_802_11_fixed_ie); i < pmlmeinfo->network.ie_length;) {
1048                         pIE = (struct ndis_802_11_var_ie *)(pmlmeinfo->network.ies + i);
1049
1050                         switch (pIE->ElementID) {
1051                         case _VENDOR_SPECIFIC_IE_:
1052                                 if ((!memcmp(pIE->data, RTW_WPA_OUI, 4)) && (!memcmp((pIE->data + 12), WPA_TKIP_CIPHER, 4)))
1053                                         return true;
1054                                 break;
1055                         case _RSN_IE_2_:
1056                                 if (!memcmp((pIE->data + 8), RSN_TKIP_CIPHER, 4))
1057                                         return true;
1058                         default:
1059                                 break;
1060                         }
1061
1062                         i += (pIE->Length + 2);
1063                 }
1064                 return false;
1065         } else {
1066                 return false;
1067         }
1068 }
1069
1070 static int wifirate2_ratetbl_inx(unsigned char rate)
1071 {
1072         rate = rate & 0x7f;
1073
1074         switch (rate) {
1075         case 108:
1076                 return 11;
1077         case 96:
1078                 return 10;
1079         case 72:
1080                 return 9;
1081         case 48:
1082                 return 8;
1083         case 36:
1084                 return 7;
1085         case 24:
1086                 return 6;
1087         case 18:
1088                 return 5;
1089         case 12:
1090                 return 4;
1091         case 22:
1092                 return 3;
1093         case 11:
1094                 return 2;
1095         case 4:
1096                 return 1;
1097         case 2:
1098                 return 0;
1099         default:
1100                 return 0;
1101         }
1102 }
1103
1104 unsigned int update_basic_rate(unsigned char *ptn, unsigned int ptn_sz)
1105 {
1106         unsigned int i, num_of_rate;
1107         unsigned int mask = 0;
1108
1109         num_of_rate = min_t(unsigned int, ptn_sz, NumRates);
1110
1111         for (i = 0; i < num_of_rate; i++) {
1112                 if ((*(ptn + i)) & 0x80)
1113                         mask |= 0x1 << wifirate2_ratetbl_inx(*(ptn + i));
1114         }
1115         return mask;
1116 }
1117
1118 unsigned int update_supported_rate(unsigned char *ptn, unsigned int ptn_sz)
1119 {
1120         unsigned int i, num_of_rate;
1121         unsigned int mask = 0;
1122
1123         num_of_rate = min_t(unsigned int, ptn_sz, NumRates);
1124
1125         for (i = 0; i < num_of_rate; i++)
1126                 mask |= 0x1 << wifirate2_ratetbl_inx(*(ptn + i));
1127         return mask;
1128 }
1129
1130 unsigned int update_MSC_rate(struct ieee80211_ht_cap *pHT_caps)
1131 {
1132         return (pHT_caps->mcs.rx_mask[0] << 12) |
1133                (pHT_caps->mcs.rx_mask[1] << 20);
1134 }
1135
1136 int support_short_GI(struct adapter *padapter, struct ieee80211_ht_cap *pHT_caps)
1137 {
1138         unsigned char bit_offset;
1139         struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
1140         struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
1141
1142         if (!(pmlmeinfo->HT_enable))
1143                 return _FAIL;
1144
1145         if (pmlmeinfo->assoc_AP_vendor == HT_IOT_PEER_RALINK)
1146                 return _FAIL;
1147
1148         bit_offset = (pmlmeext->cur_bwmode & HT_CHANNEL_WIDTH_40) ? 6 : 5;
1149
1150         if (__le16_to_cpu(pHT_caps->cap_info) & (0x1 << bit_offset))
1151                 return _SUCCESS;
1152         else
1153                 return _FAIL;
1154 }
1155
1156 unsigned char get_highest_rate_idx(u32 mask)
1157 {
1158         int i;
1159         unsigned char rate_idx = 0;
1160
1161         for (i = 27; i >= 0; i--) {
1162                 if (mask & BIT(i)) {
1163                         rate_idx = i;
1164                         break;
1165                 }
1166         }
1167         return rate_idx;
1168 }
1169
1170 void Update_RA_Entry(struct adapter *padapter, u32 mac_id)
1171 {
1172         rtw_hal_update_ra_mask(padapter, mac_id, 0);
1173 }
1174
1175 void set_sta_rate(struct adapter *padapter, struct sta_info *psta)
1176 {
1177         /* rate adaptive */
1178         Update_RA_Entry(padapter, psta->mac_id);
1179 }
1180
1181 /*  Update RRSR and Rate for USERATE */
1182 void update_tx_basic_rate(struct adapter *padapter, u8 wirelessmode)
1183 {
1184         unsigned char supported_rates[NDIS_802_11_LENGTH_RATES_EX];
1185
1186         memset(supported_rates, 0, NDIS_802_11_LENGTH_RATES_EX);
1187
1188         if ((wirelessmode & WIRELESS_11B) && (wirelessmode == WIRELESS_11B))
1189                 memcpy(supported_rates, rtw_basic_rate_cck, 4);
1190         else if (wirelessmode & WIRELESS_11B)
1191                 memcpy(supported_rates, rtw_basic_rate_mix, 7);
1192         else
1193                 memcpy(supported_rates, rtw_basic_rate_ofdm, 3);
1194
1195         if (wirelessmode & WIRELESS_11B)
1196                 update_mgnt_tx_rate(padapter, IEEE80211_CCK_RATE_1MB);
1197         else
1198                 update_mgnt_tx_rate(padapter, IEEE80211_OFDM_RATE_6MB);
1199
1200         rtw_hal_set_hwreg(padapter, HW_VAR_BASIC_RATE, supported_rates);
1201 }
1202
1203 unsigned char check_assoc_AP(u8 *pframe, uint len)
1204 {
1205         unsigned int i;
1206         struct ndis_802_11_var_ie *pIE;
1207         u8 epigram_vendor_flag;
1208         u8 ralink_vendor_flag;
1209
1210         epigram_vendor_flag = 0;
1211         ralink_vendor_flag = 0;
1212
1213         for (i = sizeof(struct ndis_802_11_fixed_ie); i < len;) {
1214                 pIE = (struct ndis_802_11_var_ie *)(pframe + i);
1215
1216                 switch (pIE->ElementID) {
1217                 case _VENDOR_SPECIFIC_IE_:
1218                         if ((!memcmp(pIE->data, ARTHEROS_OUI1, 3)) ||
1219                             (!memcmp(pIE->data, ARTHEROS_OUI2, 3))) {
1220                                 DBG_88E("link to Artheros AP\n");
1221                                 return HT_IOT_PEER_ATHEROS;
1222                         } else if ((!memcmp(pIE->data, BROADCOM_OUI1, 3)) ||
1223                                    (!memcmp(pIE->data, BROADCOM_OUI2, 3))) {
1224                                 DBG_88E("link to Broadcom AP\n");
1225                                 return HT_IOT_PEER_BROADCOM;
1226                         } else if (!memcmp(pIE->data, MARVELL_OUI, 3)) {
1227                                 DBG_88E("link to Marvell AP\n");
1228                                 return HT_IOT_PEER_MARVELL;
1229                         } else if (!memcmp(pIE->data, RALINK_OUI, 3)) {
1230                                 if (!ralink_vendor_flag) {
1231                                         ralink_vendor_flag = 1;
1232                                 } else {
1233                                         DBG_88E("link to Ralink AP\n");
1234                                         return HT_IOT_PEER_RALINK;
1235                                 }
1236                         } else if (!memcmp(pIE->data, CISCO_OUI, 3)) {
1237                                 DBG_88E("link to Cisco AP\n");
1238                                 return HT_IOT_PEER_CISCO;
1239                         } else if (!memcmp(pIE->data, REALTEK_OUI, 3)) {
1240                                 DBG_88E("link to Realtek 96B\n");
1241                                 return HT_IOT_PEER_REALTEK;
1242                         } else if (!memcmp(pIE->data, AIRGOCAP_OUI, 3)) {
1243                                 DBG_88E("link to Airgo Cap\n");
1244                                 return HT_IOT_PEER_AIRGO;
1245                         } else if (!memcmp(pIE->data, EPIGRAM_OUI, 3)) {
1246                                 epigram_vendor_flag = 1;
1247                                 if (ralink_vendor_flag) {
1248                                         DBG_88E("link to Tenda W311R AP\n");
1249                                         return HT_IOT_PEER_TENDA;
1250                                 }
1251                                 DBG_88E("Capture EPIGRAM_OUI\n");
1252                         } else {
1253                                 break;
1254                         }
1255
1256                 default:
1257                         break;
1258                 }
1259                 i += (pIE->Length + 2);
1260         }
1261
1262         if (ralink_vendor_flag && !epigram_vendor_flag) {
1263                 DBG_88E("link to Ralink AP\n");
1264                 return HT_IOT_PEER_RALINK;
1265         } else if (ralink_vendor_flag && epigram_vendor_flag) {
1266                 DBG_88E("link to Tenda W311R AP\n");
1267                 return HT_IOT_PEER_TENDA;
1268         }
1269         DBG_88E("link to new AP\n");
1270         return HT_IOT_PEER_UNKNOWN;
1271 }
1272
1273 void update_IOT_info(struct adapter *padapter)
1274 {
1275         struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
1276         struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
1277
1278         switch (pmlmeinfo->assoc_AP_vendor) {
1279         case HT_IOT_PEER_MARVELL:
1280                 pmlmeinfo->turboMode_cts2self = 1;
1281                 pmlmeinfo->turboMode_rtsen = 0;
1282                 break;
1283         case HT_IOT_PEER_RALINK:
1284                 pmlmeinfo->turboMode_cts2self = 0;
1285                 pmlmeinfo->turboMode_rtsen = 1;
1286                 /* disable high power */
1287                 Switch_DM_Func(padapter, (u32)(~DYNAMIC_BB_DYNAMIC_TXPWR),
1288                                false);
1289                 break;
1290         case HT_IOT_PEER_REALTEK:
1291                 /* disable high power */
1292                 Switch_DM_Func(padapter, (u32)(~DYNAMIC_BB_DYNAMIC_TXPWR),
1293                                false);
1294                 break;
1295         default:
1296                 pmlmeinfo->turboMode_cts2self = 0;
1297                 pmlmeinfo->turboMode_rtsen = 1;
1298                 break;
1299         }
1300 }
1301
1302 void update_capinfo(struct adapter *Adapter, u16 updateCap)
1303 {
1304         struct mlme_ext_priv *pmlmeext = &Adapter->mlmeextpriv;
1305         struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
1306         bool ShortPreamble;
1307
1308         /*  Check preamble mode, 2005.01.06, by rcnjko. */
1309         /*  Mark to update preamble value forever, 2008.03.18 by lanhsin */
1310
1311         if (updateCap & cShortPreamble) { /*  Short Preamble */
1312                 if (pmlmeinfo->preamble_mode != PREAMBLE_SHORT) { /*  PREAMBLE_LONG or PREAMBLE_AUTO */
1313                         ShortPreamble = true;
1314                         pmlmeinfo->preamble_mode = PREAMBLE_SHORT;
1315                         rtw_hal_set_hwreg(Adapter, HW_VAR_ACK_PREAMBLE, (u8 *)&ShortPreamble);
1316                 }
1317         } else { /*  Long Preamble */
1318                 if (pmlmeinfo->preamble_mode != PREAMBLE_LONG) {  /*  PREAMBLE_SHORT or PREAMBLE_AUTO */
1319                         ShortPreamble = false;
1320                         pmlmeinfo->preamble_mode = PREAMBLE_LONG;
1321                         rtw_hal_set_hwreg(Adapter, HW_VAR_ACK_PREAMBLE, (u8 *)&ShortPreamble);
1322                 }
1323         }
1324
1325         if (updateCap & cIBSS) {
1326                 /* Filen: See 802.11-2007 p.91 */
1327                 pmlmeinfo->slotTime = NON_SHORT_SLOT_TIME;
1328         } else { /* Filen: See 802.11-2007 p.90 */
1329                 if (pmlmeext->cur_wireless_mode & (WIRELESS_11G | WIRELESS_11_24N)) {
1330                         if (updateCap & cShortSlotTime) { /*  Short Slot Time */
1331                                 if (pmlmeinfo->slotTime != SHORT_SLOT_TIME)
1332                                         pmlmeinfo->slotTime = SHORT_SLOT_TIME;
1333                         } else { /*  Long Slot Time */
1334                                 if (pmlmeinfo->slotTime != NON_SHORT_SLOT_TIME)
1335                                         pmlmeinfo->slotTime = NON_SHORT_SLOT_TIME;
1336                         }
1337                 } else if (pmlmeext->cur_wireless_mode & (WIRELESS_11A | WIRELESS_11_5N)) {
1338                         pmlmeinfo->slotTime = SHORT_SLOT_TIME;
1339                 } else {
1340                         /* B Mode */
1341                         pmlmeinfo->slotTime = NON_SHORT_SLOT_TIME;
1342                 }
1343         }
1344
1345         rtw_hal_set_hwreg(Adapter, HW_VAR_SLOT_TIME, &pmlmeinfo->slotTime);
1346 }
1347
1348 void update_wireless_mode(struct adapter *padapter)
1349 {
1350         int ratelen, network_type = 0;
1351         u32 SIFS_Timer;
1352         struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
1353         struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
1354         struct wlan_bssid_ex *cur_network = &pmlmeinfo->network;
1355         unsigned char *rate = cur_network->SupportedRates;
1356
1357         ratelen = rtw_get_rateset_len(cur_network->SupportedRates);
1358
1359         if (pmlmeinfo->HT_info_enable && pmlmeinfo->HT_caps_enable)
1360                 pmlmeinfo->HT_enable = 1;
1361
1362         if (pmlmeinfo->HT_enable)
1363                 network_type = WIRELESS_11_24N;
1364
1365         if (cckratesonly_included(rate, ratelen))
1366                 network_type |= WIRELESS_11B;
1367         else if (cckrates_included(rate, ratelen))
1368                 network_type |= WIRELESS_11BG;
1369         else
1370                 network_type |= WIRELESS_11G;
1371
1372         pmlmeext->cur_wireless_mode = network_type & padapter->registrypriv.wireless_mode;
1373
1374         SIFS_Timer = 0x0a0a0808;/* 0x0808 -> for CCK, 0x0a0a -> for OFDM */
1375                                 /* change this value if having IOT issues. */
1376
1377         rtw_hal_set_hwreg(padapter, HW_VAR_RESP_SIFS,  (u8 *)&SIFS_Timer);
1378
1379         update_mgnt_tx_rate(padapter,
1380                             pmlmeext->cur_wireless_mode & WIRELESS_11B ?
1381                             IEEE80211_CCK_RATE_1MB : IEEE80211_OFDM_RATE_6MB);
1382 }
1383
1384 void update_bmc_sta_support_rate(struct adapter *padapter, u32 mac_id)
1385 {
1386         struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
1387         struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
1388
1389         if (pmlmeext->cur_wireless_mode & WIRELESS_11B) {
1390                 /*  Only B, B/G, and B/G/N AP could use CCK rate */
1391                 memcpy((pmlmeinfo->FW_sta_info[mac_id].SupportedRates), rtw_basic_rate_cck, 4);
1392         } else {
1393                 memcpy((pmlmeinfo->FW_sta_info[mac_id].SupportedRates), rtw_basic_rate_ofdm, 3);
1394         }
1395 }
1396
1397 int update_sta_support_rate(struct adapter *padapter, u8 *pvar_ie, uint var_ie_len, int cam_idx)
1398 {
1399         unsigned int ie_len;
1400         struct ndis_802_11_var_ie *pIE;
1401         int supportRateNum = 0;
1402         struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
1403         struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
1404
1405         pIE = (struct ndis_802_11_var_ie *)rtw_get_ie(pvar_ie, _SUPPORTEDRATES_IE_, &ie_len, var_ie_len);
1406         if (!pIE)
1407                 return _FAIL;
1408         if (ie_len > NDIS_802_11_LENGTH_RATES_EX)
1409                 return _FAIL;
1410
1411         memcpy(pmlmeinfo->FW_sta_info[cam_idx].SupportedRates, pIE->data, ie_len);
1412         supportRateNum = ie_len;
1413
1414         pIE = (struct ndis_802_11_var_ie *)rtw_get_ie(pvar_ie, _EXT_SUPPORTEDRATES_IE_, &ie_len, var_ie_len);
1415         if (pIE) {
1416                 if (supportRateNum + ie_len > NDIS_802_11_LENGTH_RATES_EX)
1417                         return _FAIL;
1418                 memcpy((pmlmeinfo->FW_sta_info[cam_idx].SupportedRates + supportRateNum), pIE->data, ie_len);
1419         }
1420
1421         return _SUCCESS;
1422 }
1423
1424 void process_addba_req(struct adapter *padapter, u8 *paddba_req, u8 *addr)
1425 {
1426         struct sta_info *psta;
1427         u16 tid;
1428         u16 param;
1429         struct recv_reorder_ctrl *preorder_ctrl;
1430         struct sta_priv *pstapriv = &padapter->stapriv;
1431         struct ADDBA_request *preq = (struct ADDBA_request *)paddba_req;
1432         struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
1433         struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
1434
1435         psta = rtw_get_stainfo(pstapriv, addr);
1436
1437         if (psta) {
1438                 param = le16_to_cpu(preq->BA_para_set);
1439                 tid = (param >> 2) & 0x0f;
1440                 preorder_ctrl = &psta->recvreorder_ctrl[tid];
1441                 preorder_ctrl->indicate_seq = 0xffff;
1442                 preorder_ctrl->enable = pmlmeinfo->accept_addba_req;
1443         }
1444 }
1445
1446 void update_TSF(struct mlme_ext_priv *pmlmeext, u8 *pframe, uint len)
1447 {
1448         u8 *pIE;
1449         __le32 *pbuf;
1450
1451         pIE = pframe + sizeof(struct ieee80211_hdr_3addr);
1452         pbuf = (__le32 *)pIE;
1453
1454         pmlmeext->TSFValue = le32_to_cpu(*(pbuf + 1));
1455
1456         pmlmeext->TSFValue = pmlmeext->TSFValue << 32;
1457
1458         pmlmeext->TSFValue |= le32_to_cpu(*pbuf);
1459 }
1460
1461 void correct_TSF(struct adapter *padapter, struct mlme_ext_priv *pmlmeext)
1462 {
1463         rtw_hal_set_hwreg(padapter, HW_VAR_CORRECT_TSF, NULL);
1464 }