linux/drivers/staging/rtl8723bs/core/rtw_wlan_util.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/******************************************************************************
   3 *
   4 * Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved.
   5 *
   6 ******************************************************************************/
   7
   8#include <drv_types.h>
   9#include <rtw_debug.h>
  10#include <hal_com_h2c.h>
  11
  12static unsigned char ARTHEROS_OUI1[] = {0x00, 0x03, 0x7f};
  13static unsigned char ARTHEROS_OUI2[] = {0x00, 0x13, 0x74};
  14
  15static unsigned char BROADCOM_OUI1[] = {0x00, 0x10, 0x18};
  16static unsigned char BROADCOM_OUI2[] = {0x00, 0x0a, 0xf7};
  17static unsigned char BROADCOM_OUI3[] = {0x00, 0x05, 0xb5};
  18
  19static unsigned char CISCO_OUI[] = {0x00, 0x40, 0x96};
  20static unsigned char MARVELL_OUI[] = {0x00, 0x50, 0x43};
  21static unsigned char RALINK_OUI[] = {0x00, 0x0c, 0x43};
  22static unsigned char REALTEK_OUI[] = {0x00, 0xe0, 0x4c};
  23static unsigned char AIRGOCAP_OUI[] = {0x00, 0x0a, 0xf5};
  24static unsigned char RSN_TKIP_CIPHER[4] = {0x00, 0x0f, 0xac, 0x02};
  25static unsigned char WPA_TKIP_CIPHER[4] = {0x00, 0x50, 0xf2, 0x02};
  26
  27/* define WAIT_FOR_BCN_TO_MIN   (3000) */
  28#define WAIT_FOR_BCN_TO_MIN     (6000)
  29#define WAIT_FOR_BCN_TO_MAX     (20000)
  30
  31#define DISCONNECT_BY_CHK_BCN_FAIL_OBSERV_PERIOD_IN_MS 1000
  32#define DISCONNECT_BY_CHK_BCN_FAIL_THRESHOLD 3
  33
  34static u8 rtw_basic_rate_cck[4] = {
  35        IEEE80211_CCK_RATE_1MB | IEEE80211_BASIC_RATE_MASK,
  36        IEEE80211_CCK_RATE_2MB | IEEE80211_BASIC_RATE_MASK,
  37        IEEE80211_CCK_RATE_5MB | IEEE80211_BASIC_RATE_MASK,
  38        IEEE80211_CCK_RATE_11MB | IEEE80211_BASIC_RATE_MASK
  39};
  40
  41static u8 rtw_basic_rate_ofdm[3] = {
  42        IEEE80211_OFDM_RATE_6MB | IEEE80211_BASIC_RATE_MASK,
  43        IEEE80211_OFDM_RATE_12MB | IEEE80211_BASIC_RATE_MASK,
  44        IEEE80211_OFDM_RATE_24MB | IEEE80211_BASIC_RATE_MASK
  45};
  46
  47u8 networktype_to_raid_ex(struct adapter *adapter, struct sta_info *psta)
  48{
  49        u8 raid;
  50
  51        switch (psta->wireless_mode) {
  52        case WIRELESS_11B:
  53                raid = RATEID_IDX_B;
  54                break;
  55        case WIRELESS_11G:
  56                raid = RATEID_IDX_G;
  57                break;
  58        case WIRELESS_11BG:
  59                raid = RATEID_IDX_BG;
  60                break;
  61        case WIRELESS_11_24N:
  62        case WIRELESS_11G_24N:
  63                raid = RATEID_IDX_GN_N1SS;
  64                break;
  65        case WIRELESS_11B_24N:
  66        case WIRELESS_11BG_24N:
  67                if (psta->bw_mode == CHANNEL_WIDTH_20) {
  68                        raid = RATEID_IDX_BGN_20M_1SS_BN;
  69                } else {
  70                        raid = RATEID_IDX_BGN_40M_1SS;
  71                }
  72                break;
  73        default:
  74                raid = RATEID_IDX_BGN_40M_2SS;
  75                break;
  76        }
  77        return raid;
  78}
  79
  80unsigned char ratetbl_val_2wifirate(unsigned char rate);
  81unsigned char ratetbl_val_2wifirate(unsigned char rate)
  82{
  83        switch (rate & 0x7f) {
  84        case 0:
  85                return IEEE80211_CCK_RATE_1MB;
  86        case 1:
  87                return IEEE80211_CCK_RATE_2MB;
  88        case 2:
  89                return IEEE80211_CCK_RATE_5MB;
  90        case 3:
  91                return IEEE80211_CCK_RATE_11MB;
  92        case 4:
  93                return IEEE80211_OFDM_RATE_6MB;
  94        case 5:
  95                return IEEE80211_OFDM_RATE_9MB;
  96        case 6:
  97                return IEEE80211_OFDM_RATE_12MB;
  98        case 7:
  99                return IEEE80211_OFDM_RATE_18MB;
 100        case 8:
 101                return IEEE80211_OFDM_RATE_24MB;
 102        case 9:
 103                return IEEE80211_OFDM_RATE_36MB;
 104        case 10:
 105                return IEEE80211_OFDM_RATE_48MB;
 106        case 11:
 107                return IEEE80211_OFDM_RATE_54MB;
 108        default:
 109                return 0;
 110        }
 111}
 112
 113int is_basicrate(struct adapter *padapter, unsigned char rate);
 114int is_basicrate(struct adapter *padapter, unsigned char rate)
 115{
 116        int i;
 117        unsigned char val;
 118        struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
 119
 120        for (i = 0; i < NumRates; i++) {
 121                val = pmlmeext->basicrate[i];
 122
 123                if ((val != 0xff) && (val != 0xfe))
 124                        if (rate == ratetbl_val_2wifirate(val))
 125                                return true;
 126        }
 127
 128        return false;
 129}
 130
 131unsigned int ratetbl2rateset(struct adapter *padapter, unsigned char *rateset);
 132unsigned int ratetbl2rateset(struct adapter *padapter, unsigned char *rateset)
 133{
 134        int i;
 135        unsigned char rate;
 136        unsigned int    len = 0;
 137        struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
 138
 139        for (i = 0; i < NumRates; i++) {
 140                rate = pmlmeext->datarate[i];
 141
 142                switch (rate) {
 143                case 0xff:
 144                        return len;
 145
 146                case 0xfe:
 147                        continue;
 148
 149                default:
 150                        rate = ratetbl_val_2wifirate(rate);
 151
 152                        if (is_basicrate(padapter, rate) == true)
 153                                rate |= IEEE80211_BASIC_RATE_MASK;
 154
 155                        rateset[len] = rate;
 156                        len++;
 157                        break;
 158                }
 159        }
 160        return len;
 161}
 162
 163void get_rate_set(struct adapter *padapter, unsigned char *pbssrate, int *bssrate_len)
 164{
 165        unsigned char supportedrates[NumRates];
 166
 167        memset(supportedrates, 0, NumRates);
 168        *bssrate_len = ratetbl2rateset(padapter, supportedrates);
 169        memcpy(pbssrate, supportedrates, *bssrate_len);
 170}
 171
 172void set_mcs_rate_by_mask(u8 *mcs_set, u32 mask)
 173{
 174        u8 mcs_rate_1r = (u8)(mask&0xff);
 175        u8 mcs_rate_2r = (u8)((mask>>8)&0xff);
 176        u8 mcs_rate_3r = (u8)((mask>>16)&0xff);
 177        u8 mcs_rate_4r = (u8)((mask>>24)&0xff);
 178
 179        mcs_set[0] &= mcs_rate_1r;
 180        mcs_set[1] &= mcs_rate_2r;
 181        mcs_set[2] &= mcs_rate_3r;
 182        mcs_set[3] &= mcs_rate_4r;
 183}
 184
 185void UpdateBrateTbl(struct adapter *Adapter, u8 *mBratesOS)
 186{
 187        u8 i;
 188        u8 rate;
 189
 190        /*  1M, 2M, 5.5M, 11M, 6M, 12M, 24M are mandatory. */
 191        for (i = 0; i < NDIS_802_11_LENGTH_RATES_EX; i++) {
 192                rate = mBratesOS[i] & 0x7f;
 193                switch (rate) {
 194                case IEEE80211_CCK_RATE_1MB:
 195                case IEEE80211_CCK_RATE_2MB:
 196                case IEEE80211_CCK_RATE_5MB:
 197                case IEEE80211_CCK_RATE_11MB:
 198                case IEEE80211_OFDM_RATE_6MB:
 199                case IEEE80211_OFDM_RATE_12MB:
 200                case IEEE80211_OFDM_RATE_24MB:
 201                        mBratesOS[i] |= IEEE80211_BASIC_RATE_MASK;
 202                        break;
 203                }
 204        }
 205}
 206
 207void UpdateBrateTblForSoftAP(u8 *bssrateset, u32 bssratelen)
 208{
 209        u8 i;
 210        u8 rate;
 211
 212        for (i = 0; i < bssratelen; i++) {
 213                rate = bssrateset[i] & 0x7f;
 214                switch (rate) {
 215                case IEEE80211_CCK_RATE_1MB:
 216                case IEEE80211_CCK_RATE_2MB:
 217                case IEEE80211_CCK_RATE_5MB:
 218                case IEEE80211_CCK_RATE_11MB:
 219                        bssrateset[i] |= IEEE80211_BASIC_RATE_MASK;
 220                        break;
 221                }
 222        }
 223}
 224
 225void Save_DM_Func_Flag(struct adapter *padapter)
 226{
 227        u8 bSaveFlag = true;
 228
 229        rtw_hal_set_hwreg(padapter, HW_VAR_DM_FUNC_OP, (u8 *)(&bSaveFlag));
 230}
 231
 232void Restore_DM_Func_Flag(struct adapter *padapter)
 233{
 234        u8 bSaveFlag = false;
 235
 236        rtw_hal_set_hwreg(padapter, HW_VAR_DM_FUNC_OP, (u8 *)(&bSaveFlag));
 237}
 238
 239void Switch_DM_Func(struct adapter *padapter, u32 mode, u8 enable)
 240{
 241        if (enable == true)
 242                rtw_hal_set_hwreg(padapter, HW_VAR_DM_FUNC_SET, (u8 *)(&mode));
 243        else
 244                rtw_hal_set_hwreg(padapter, HW_VAR_DM_FUNC_CLR, (u8 *)(&mode));
 245}
 246
 247void Set_MSR(struct adapter *padapter, u8 type)
 248{
 249        rtw_hal_set_hwreg(padapter, HW_VAR_MEDIA_STATUS, (u8 *)(&type));
 250}
 251
 252inline u8 rtw_get_oper_ch(struct adapter *adapter)
 253{
 254        return adapter_to_dvobj(adapter)->oper_channel;
 255}
 256
 257inline void rtw_set_oper_ch(struct adapter *adapter, u8 ch)
 258{
 259#ifdef DBG_CH_SWITCH
 260        const int len = 128;
 261        char msg[128] = {0};
 262        int cnt = 0;
 263        int i = 0;
 264#endif  /* DBG_CH_SWITCH */
 265        struct dvobj_priv *dvobj = adapter_to_dvobj(adapter);
 266
 267        if (dvobj->oper_channel != ch) {
 268                dvobj->on_oper_ch_time = jiffies;
 269
 270#ifdef DBG_CH_SWITCH
 271                cnt += scnprintf(msg+cnt, len-cnt, "switch to ch %3u", ch);
 272
 273                for (i = 0; i < dvobj->iface_nums; i++) {
 274                        struct adapter *iface = dvobj->padapters[i];
 275
 276                        cnt += scnprintf(msg+cnt, len-cnt, " [%s:", ADPT_ARG(iface));
 277                        if (iface->mlmeextpriv.cur_channel == ch)
 278                                cnt += scnprintf(msg+cnt, len-cnt, "C");
 279                        else
 280                                cnt += scnprintf(msg+cnt, len-cnt, "_");
 281                        if (iface->wdinfo.listen_channel == ch && !rtw_p2p_chk_state(&iface->wdinfo, P2P_STATE_NONE))
 282                                cnt += scnprintf(msg+cnt, len-cnt, "L");
 283                        else
 284                                cnt += scnprintf(msg+cnt, len-cnt, "_");
 285                        cnt += scnprintf(msg+cnt, len-cnt, "]");
 286                }
 287
 288#endif /* DBG_CH_SWITCH */
 289        }
 290
 291        dvobj->oper_channel = ch;
 292}
 293
 294inline u8 rtw_get_oper_bw(struct adapter *adapter)
 295{
 296        return adapter_to_dvobj(adapter)->oper_bwmode;
 297}
 298
 299inline void rtw_set_oper_bw(struct adapter *adapter, u8 bw)
 300{
 301        adapter_to_dvobj(adapter)->oper_bwmode = bw;
 302}
 303
 304inline u8 rtw_get_oper_choffset(struct adapter *adapter)
 305{
 306        return adapter_to_dvobj(adapter)->oper_ch_offset;
 307}
 308
 309inline void rtw_set_oper_choffset(struct adapter *adapter, u8 offset)
 310{
 311        adapter_to_dvobj(adapter)->oper_ch_offset = offset;
 312}
 313
 314u8 rtw_get_center_ch(u8 channel, u8 chnl_bw, u8 chnl_offset)
 315{
 316        u8 center_ch = channel;
 317
 318        if (chnl_bw == CHANNEL_WIDTH_40) {
 319                if (chnl_offset == HAL_PRIME_CHNL_OFFSET_LOWER)
 320                        center_ch = channel + 2;
 321                else
 322                        center_ch = channel - 2;
 323        }
 324
 325        return center_ch;
 326}
 327
 328inline unsigned long rtw_get_on_cur_ch_time(struct adapter *adapter)
 329{
 330        if (adapter->mlmeextpriv.cur_channel == adapter_to_dvobj(adapter)->oper_channel)
 331                return adapter_to_dvobj(adapter)->on_oper_ch_time;
 332        else
 333                return 0;
 334}
 335
 336void SelectChannel(struct adapter *padapter, unsigned char channel)
 337{
 338        if (mutex_lock_interruptible(&(adapter_to_dvobj(padapter)->setch_mutex)))
 339                return;
 340
 341        /* saved channel info */
 342        rtw_set_oper_ch(padapter, channel);
 343
 344        rtw_hal_set_chan(padapter, channel);
 345
 346        mutex_unlock(&(adapter_to_dvobj(padapter)->setch_mutex));
 347}
 348
 349void set_channel_bwmode(struct adapter *padapter, unsigned char channel, unsigned char channel_offset, unsigned short bwmode)
 350{
 351        u8 center_ch, chnl_offset80 = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
 352
 353        center_ch = rtw_get_center_ch(channel, bwmode, channel_offset);
 354
 355
 356        /* set Channel */
 357        if (mutex_lock_interruptible(&(adapter_to_dvobj(padapter)->setch_mutex)))
 358                return;
 359
 360        /* saved channel/bw info */
 361        rtw_set_oper_ch(padapter, channel);
 362        rtw_set_oper_bw(padapter, bwmode);
 363        rtw_set_oper_choffset(padapter, channel_offset);
 364
 365        rtw_hal_set_chnl_bw(padapter, center_ch, bwmode, channel_offset, chnl_offset80); /*  set center channel */
 366
 367        mutex_unlock(&(adapter_to_dvobj(padapter)->setch_mutex));
 368}
 369
 370inline u8 *get_my_bssid(struct wlan_bssid_ex *pnetwork)
 371{
 372        return pnetwork->mac_address;
 373}
 374
 375u16 get_beacon_interval(struct wlan_bssid_ex *bss)
 376{
 377        __le16 val;
 378
 379        memcpy((unsigned char *)&val, rtw_get_beacon_interval_from_ie(bss->ies), 2);
 380
 381        return le16_to_cpu(val);
 382}
 383
 384int is_client_associated_to_ap(struct adapter *padapter)
 385{
 386        struct mlme_ext_priv *pmlmeext;
 387        struct mlme_ext_info *pmlmeinfo;
 388
 389        if (!padapter)
 390                return _FAIL;
 391
 392        pmlmeext = &padapter->mlmeextpriv;
 393        pmlmeinfo = &(pmlmeext->mlmext_info);
 394
 395        if ((pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS) && ((pmlmeinfo->state&0x03) == WIFI_FW_STATION_STATE))
 396                return true;
 397        else
 398                return _FAIL;
 399}
 400
 401int is_client_associated_to_ibss(struct adapter *padapter)
 402{
 403        struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
 404        struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
 405
 406        if ((pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS) && ((pmlmeinfo->state&0x03) == WIFI_FW_ADHOC_STATE))
 407                return true;
 408        else
 409                return _FAIL;
 410}
 411
 412int is_IBSS_empty(struct adapter *padapter)
 413{
 414        unsigned int i;
 415        struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
 416        struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
 417
 418        for (i = IBSS_START_MAC_ID; i < NUM_STA; i++) {
 419                if (pmlmeinfo->FW_sta_info[i].status == 1)
 420                        return _FAIL;
 421        }
 422
 423        return true;
 424}
 425
 426unsigned int decide_wait_for_beacon_timeout(unsigned int bcn_interval)
 427{
 428        if ((bcn_interval << 2) < WAIT_FOR_BCN_TO_MIN)
 429                return WAIT_FOR_BCN_TO_MIN;
 430        else if ((bcn_interval << 2) > WAIT_FOR_BCN_TO_MAX)
 431                return WAIT_FOR_BCN_TO_MAX;
 432        else
 433                return bcn_interval << 2;
 434}
 435
 436void invalidate_cam_all(struct adapter *padapter)
 437{
 438        struct dvobj_priv *dvobj = adapter_to_dvobj(padapter);
 439        struct cam_ctl_t *cam_ctl = &dvobj->cam_ctl;
 440
 441        rtw_hal_set_hwreg(padapter, HW_VAR_CAM_INVALID_ALL, NULL);
 442
 443        spin_lock_bh(&cam_ctl->lock);
 444        cam_ctl->bitmap = 0;
 445        memset(dvobj->cam_cache, 0, sizeof(struct cam_entry_cache)*TOTAL_CAM_ENTRY);
 446        spin_unlock_bh(&cam_ctl->lock);
 447}
 448
 449static u32 _ReadCAM(struct adapter *padapter, u32 addr)
 450{
 451        u32 count = 0, cmd;
 452
 453        cmd = CAM_POLLINIG | addr;
 454        rtw_write32(padapter, RWCAM, cmd);
 455
 456        do {
 457                if (0 == (rtw_read32(padapter, REG_CAMCMD) & CAM_POLLINIG))
 458                        break;
 459        } while (count++ < 100);
 460
 461        return rtw_read32(padapter, REG_CAMREAD);
 462}
 463
 464void read_cam(struct adapter *padapter, u8 entry, u8 *get_key)
 465{
 466        u32 j, addr, cmd;
 467
 468        addr = entry << 3;
 469
 470        for (j = 0; j < 6; j++) {
 471                cmd = _ReadCAM(padapter, addr+j);
 472                if (j > 1) /* get key from cam */
 473                        memcpy(get_key+(j-2)*4, &cmd, 4);
 474        }
 475}
 476
 477void _write_cam(struct adapter *padapter, u8 entry, u16 ctrl, u8 *mac, u8 *key)
 478{
 479        unsigned int i, val, addr;
 480        int j;
 481        u32 cam_val[2];
 482
 483        addr = entry << 3;
 484
 485        for (j = 5; j >= 0; j--) {
 486                switch (j) {
 487                case 0:
 488                        val = (ctrl | (mac[0] << 16) | (mac[1] << 24));
 489                        break;
 490                case 1:
 491                        val = (mac[2] | (mac[3] << 8) | (mac[4] << 16) | (mac[5] << 24));
 492                        break;
 493                default:
 494                        i = (j - 2) << 2;
 495                        val = (key[i] | (key[i+1] << 8) | (key[i+2] << 16) | (key[i+3] << 24));
 496                        break;
 497                }
 498
 499                cam_val[0] = val;
 500                cam_val[1] = addr + (unsigned int)j;
 501
 502                rtw_hal_set_hwreg(padapter, HW_VAR_CAM_WRITE, (u8 *)cam_val);
 503        }
 504}
 505
 506void _clear_cam_entry(struct adapter *padapter, u8 entry)
 507{
 508        unsigned char null_sta[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
 509        unsigned char null_key[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
 510
 511        _write_cam(padapter, entry, 0, null_sta, null_key);
 512}
 513
 514inline void write_cam(struct adapter *adapter, u8 id, u16 ctrl, u8 *mac, u8 *key)
 515{
 516        _write_cam(adapter, id, ctrl, mac, key);
 517        write_cam_cache(adapter, id, ctrl, mac, key);
 518}
 519
 520inline void clear_cam_entry(struct adapter *adapter, u8 id)
 521{
 522        _clear_cam_entry(adapter, id);
 523        clear_cam_cache(adapter, id);
 524}
 525
 526void write_cam_cache(struct adapter *adapter, u8 id, u16 ctrl, u8 *mac, u8 *key)
 527{
 528        struct dvobj_priv *dvobj = adapter_to_dvobj(adapter);
 529        struct cam_ctl_t *cam_ctl = &dvobj->cam_ctl;
 530
 531        spin_lock_bh(&cam_ctl->lock);
 532
 533        dvobj->cam_cache[id].ctrl = ctrl;
 534        memcpy(dvobj->cam_cache[id].mac, mac, ETH_ALEN);
 535        memcpy(dvobj->cam_cache[id].key, key, 16);
 536
 537        spin_unlock_bh(&cam_ctl->lock);
 538}
 539
 540void clear_cam_cache(struct adapter *adapter, u8 id)
 541{
 542        struct dvobj_priv *dvobj = adapter_to_dvobj(adapter);
 543        struct cam_ctl_t *cam_ctl = &dvobj->cam_ctl;
 544
 545        spin_lock_bh(&cam_ctl->lock);
 546
 547        memset(&(dvobj->cam_cache[id]), 0, sizeof(struct cam_entry_cache));
 548
 549        spin_unlock_bh(&cam_ctl->lock);
 550}
 551
 552static bool _rtw_camid_is_gk(struct adapter *adapter, u8 cam_id)
 553{
 554        struct dvobj_priv *dvobj = adapter_to_dvobj(adapter);
 555        struct cam_ctl_t *cam_ctl = &dvobj->cam_ctl;
 556        bool ret = false;
 557
 558        if (cam_id >= TOTAL_CAM_ENTRY)
 559                goto exit;
 560
 561        if (!(cam_ctl->bitmap & BIT(cam_id)))
 562                goto exit;
 563
 564        ret = (dvobj->cam_cache[cam_id].ctrl&BIT6)?true:false;
 565
 566exit:
 567        return ret;
 568}
 569
 570static s16 _rtw_camid_search(struct adapter *adapter, u8 *addr, s16 kid)
 571{
 572        struct dvobj_priv *dvobj = adapter_to_dvobj(adapter);
 573        int i;
 574        s16 cam_id = -1;
 575
 576        for (i = 0; i < TOTAL_CAM_ENTRY; i++) {
 577                if (addr && memcmp(dvobj->cam_cache[i].mac, addr, ETH_ALEN))
 578                        continue;
 579                if (kid >= 0 && kid != (dvobj->cam_cache[i].ctrl&0x03))
 580                        continue;
 581
 582                cam_id = i;
 583                break;
 584        }
 585
 586        return cam_id;
 587}
 588
 589s16 rtw_camid_search(struct adapter *adapter, u8 *addr, s16 kid)
 590{
 591        struct dvobj_priv *dvobj = adapter_to_dvobj(adapter);
 592        struct cam_ctl_t *cam_ctl = &dvobj->cam_ctl;
 593        s16 cam_id = -1;
 594
 595        spin_lock_bh(&cam_ctl->lock);
 596        cam_id = _rtw_camid_search(adapter, addr, kid);
 597        spin_unlock_bh(&cam_ctl->lock);
 598
 599        return cam_id;
 600}
 601
 602s16 rtw_camid_alloc(struct adapter *adapter, struct sta_info *sta, u8 kid)
 603{
 604        struct dvobj_priv *dvobj = adapter_to_dvobj(adapter);
 605        struct cam_ctl_t *cam_ctl = &dvobj->cam_ctl;
 606        s16 cam_id = -1;
 607        struct mlme_ext_info *mlmeinfo;
 608
 609        spin_lock_bh(&cam_ctl->lock);
 610
 611        mlmeinfo = &adapter->mlmeextpriv.mlmext_info;
 612
 613        if ((((mlmeinfo->state&0x03) == WIFI_FW_AP_STATE) || ((mlmeinfo->state&0x03) == WIFI_FW_ADHOC_STATE))
 614                && !sta) {
 615                /* AP/Ad-hoc mode group key: static alloction to default key by key ID */
 616                if (kid > 3) {
 617                        netdev_dbg(adapter->pnetdev,
 618                                   FUNC_ADPT_FMT " group key with invalid key id:%u\n",
 619                                   FUNC_ADPT_ARG(adapter), kid);
 620                        rtw_warn_on(1);
 621                        goto bitmap_handle;
 622                }
 623
 624                cam_id = kid;
 625        } else {
 626                int i;
 627                u8 *addr = sta?sta->hwaddr:NULL;
 628
 629                if (!sta) {
 630                        if (!(mlmeinfo->state & WIFI_FW_ASSOC_SUCCESS)) {
 631                                /* bypass STA mode group key setting before connected(ex:WEP) because bssid is not ready */
 632                                goto bitmap_handle;
 633                        }
 634
 635                        addr = get_bssid(&adapter->mlmepriv);
 636                }
 637
 638                i = _rtw_camid_search(adapter, addr, kid);
 639                if (i >= 0) {
 640                        /* Fix issue that pairwise and group key have same key id. Pairwise key first, group key can overwirte group only(ex: rekey) */
 641                        if (sta || _rtw_camid_is_gk(adapter, i))
 642                                cam_id = i;
 643                        else
 644                                netdev_dbg(adapter->pnetdev,
 645                                           FUNC_ADPT_FMT " group key id:%u the same key id as pairwise key\n",
 646                                           FUNC_ADPT_ARG(adapter), kid);
 647                        goto bitmap_handle;
 648                }
 649
 650                for (i = 4; i < TOTAL_CAM_ENTRY; i++)
 651                        if (!(cam_ctl->bitmap & BIT(i)))
 652                                break;
 653
 654                if (i == TOTAL_CAM_ENTRY) {
 655                        if (sta)
 656                                netdev_dbg(adapter->pnetdev,
 657                                           FUNC_ADPT_FMT " pairwise key with %pM id:%u no room\n",
 658                                           FUNC_ADPT_ARG(adapter),
 659                                           MAC_ARG(sta->hwaddr), kid);
 660                        else
 661                                netdev_dbg(adapter->pnetdev,
 662                                           FUNC_ADPT_FMT " group key id:%u no room\n",
 663                                           FUNC_ADPT_ARG(adapter), kid);
 664                        rtw_warn_on(1);
 665                        goto bitmap_handle;
 666                }
 667
 668                cam_id = i;
 669        }
 670
 671bitmap_handle:
 672        if (cam_id >= 0 && cam_id < 32)
 673                cam_ctl->bitmap |= BIT(cam_id);
 674
 675        spin_unlock_bh(&cam_ctl->lock);
 676
 677        return cam_id;
 678}
 679
 680void rtw_camid_free(struct adapter *adapter, u8 cam_id)
 681{
 682        struct dvobj_priv *dvobj = adapter_to_dvobj(adapter);
 683        struct cam_ctl_t *cam_ctl = &dvobj->cam_ctl;
 684
 685        spin_lock_bh(&cam_ctl->lock);
 686
 687        if (cam_id < TOTAL_CAM_ENTRY)
 688                cam_ctl->bitmap &= ~(BIT(cam_id));
 689
 690        spin_unlock_bh(&cam_ctl->lock);
 691}
 692
 693int allocate_fw_sta_entry(struct adapter *padapter)
 694{
 695        unsigned int mac_id;
 696        struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
 697        struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
 698
 699        for (mac_id = IBSS_START_MAC_ID; mac_id < NUM_STA; mac_id++) {
 700                if (pmlmeinfo->FW_sta_info[mac_id].status == 0) {
 701                        pmlmeinfo->FW_sta_info[mac_id].status = 1;
 702                        pmlmeinfo->FW_sta_info[mac_id].retry = 0;
 703                        break;
 704                }
 705        }
 706
 707        return mac_id;
 708}
 709
 710void flush_all_cam_entry(struct adapter *padapter)
 711{
 712        struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
 713        struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
 714
 715        invalidate_cam_all(padapter);
 716        /* clear default key related key search setting */
 717        rtw_hal_set_hwreg(padapter, HW_VAR_SEC_DK_CFG, (u8 *)false);
 718
 719        memset((u8 *)(pmlmeinfo->FW_sta_info), 0, sizeof(pmlmeinfo->FW_sta_info));
 720}
 721
 722int WMM_param_handler(struct adapter *padapter, struct ndis_80211_var_ie *pIE)
 723{
 724        /* struct registry_priv *pregpriv = &padapter->registrypriv; */
 725        struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
 726        struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
 727        struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
 728
 729        if (pmlmepriv->qospriv.qos_option == 0) {
 730                pmlmeinfo->WMM_enable = 0;
 731                return false;
 732        }
 733
 734        if (!memcmp(&(pmlmeinfo->WMM_param), (pIE->data + 6), sizeof(struct WMM_para_element)))
 735                return false;
 736        else
 737                memcpy(&(pmlmeinfo->WMM_param), (pIE->data + 6), sizeof(struct WMM_para_element));
 738
 739        pmlmeinfo->WMM_enable = 1;
 740        return true;
 741}
 742
 743static void sort_wmm_ac_params(u32 *inx, u32 *edca)
 744{
 745        u32 i, j, change_inx = false;
 746
 747        /* entry indx: 0->vo, 1->vi, 2->be, 3->bk. */
 748        for (i = 0; i < 4; i++) {
 749                for (j = i + 1; j < 4; j++) {
 750                        /* compare CW and AIFS */
 751                        if ((edca[j] & 0xFFFF) < (edca[i] & 0xFFFF)) {
 752                                change_inx = true;
 753                        } else if ((edca[j] & 0xFFFF) == (edca[i] & 0xFFFF)) {
 754                                /* compare TXOP */
 755                                if ((edca[j] >> 16) > (edca[i] >> 16))
 756                                        change_inx = true;
 757                        }
 758
 759                        if (change_inx) {
 760                                swap(edca[i], edca[j]);
 761                                swap(inx[i], inx[j]);
 762
 763                                change_inx = false;
 764                        }
 765                }
 766        }
 767}
 768
 769void WMMOnAssocRsp(struct adapter *padapter)
 770{
 771        u8 ACI, ACM, AIFS, ECWMin, ECWMax, aSifsTime;
 772        u8 acm_mask;
 773        u16 TXOP;
 774        u32 acParm, i;
 775        u32 edca[4], inx[4];
 776        struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
 777        struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
 778        struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
 779        struct registry_priv *pregpriv = &padapter->registrypriv;
 780
 781        acm_mask = 0;
 782
 783        if (pmlmeext->cur_wireless_mode & WIRELESS_11_24N)
 784                aSifsTime = 16;
 785        else
 786                aSifsTime = 10;
 787
 788        if (pmlmeinfo->WMM_enable == 0) {
 789                padapter->mlmepriv.acm_mask = 0;
 790
 791                AIFS = aSifsTime + (2 * pmlmeinfo->slotTime);
 792
 793                if (pmlmeext->cur_wireless_mode & WIRELESS_11G) {
 794                        ECWMin = 4;
 795                        ECWMax = 10;
 796                } else if (pmlmeext->cur_wireless_mode & WIRELESS_11B) {
 797                        ECWMin = 5;
 798                        ECWMax = 10;
 799                } else {
 800                        ECWMin = 4;
 801                        ECWMax = 10;
 802                }
 803
 804                TXOP = 0;
 805                acParm = AIFS | (ECWMin << 8) | (ECWMax << 12) | (TXOP << 16);
 806                rtw_hal_set_hwreg(padapter, HW_VAR_AC_PARAM_BE, (u8 *)(&acParm));
 807                rtw_hal_set_hwreg(padapter, HW_VAR_AC_PARAM_BK, (u8 *)(&acParm));
 808                rtw_hal_set_hwreg(padapter, HW_VAR_AC_PARAM_VI, (u8 *)(&acParm));
 809
 810                ECWMin = 2;
 811                ECWMax = 3;
 812                TXOP = 0x2f;
 813                acParm = AIFS | (ECWMin << 8) | (ECWMax << 12) | (TXOP << 16);
 814                rtw_hal_set_hwreg(padapter, HW_VAR_AC_PARAM_VO, (u8 *)(&acParm));
 815        } else {
 816                edca[0] = edca[1] = edca[2] = edca[3] = 0;
 817
 818                for (i = 0; i < 4; i++) {
 819                        ACI = (pmlmeinfo->WMM_param.ac_param[i].ACI_AIFSN >> 5) & 0x03;
 820                        ACM = (pmlmeinfo->WMM_param.ac_param[i].ACI_AIFSN >> 4) & 0x01;
 821
 822                        /* AIFS = AIFSN * slot time + SIFS - r2t phy delay */
 823                        AIFS = (pmlmeinfo->WMM_param.ac_param[i].ACI_AIFSN & 0x0f) * pmlmeinfo->slotTime + aSifsTime;
 824
 825                        ECWMin = (pmlmeinfo->WMM_param.ac_param[i].CW & 0x0f);
 826                        ECWMax = (pmlmeinfo->WMM_param.ac_param[i].CW & 0xf0) >> 4;
 827                        TXOP = le16_to_cpu(pmlmeinfo->WMM_param.ac_param[i].TXOP_limit);
 828
 829                        acParm = AIFS | (ECWMin << 8) | (ECWMax << 12) | (TXOP << 16);
 830
 831                        switch (ACI) {
 832                        case 0x0:
 833                                rtw_hal_set_hwreg(padapter, HW_VAR_AC_PARAM_BE, (u8 *)(&acParm));
 834                                acm_mask |= (ACM ? BIT(1):0);
 835                                edca[XMIT_BE_QUEUE] = acParm;
 836                                break;
 837
 838                        case 0x1:
 839                                rtw_hal_set_hwreg(padapter, HW_VAR_AC_PARAM_BK, (u8 *)(&acParm));
 840                                /* acm_mask |= (ACM? BIT(0):0); */
 841                                edca[XMIT_BK_QUEUE] = acParm;
 842                                break;
 843
 844                        case 0x2:
 845                                rtw_hal_set_hwreg(padapter, HW_VAR_AC_PARAM_VI, (u8 *)(&acParm));
 846                                acm_mask |= (ACM ? BIT(2):0);
 847                                edca[XMIT_VI_QUEUE] = acParm;
 848                                break;
 849
 850                        case 0x3:
 851                                rtw_hal_set_hwreg(padapter, HW_VAR_AC_PARAM_VO, (u8 *)(&acParm));
 852                                acm_mask |= (ACM ? BIT(3):0);
 853                                edca[XMIT_VO_QUEUE] = acParm;
 854                                break;
 855                        }
 856                }
 857
 858                if (padapter->registrypriv.acm_method == 1)
 859                        rtw_hal_set_hwreg(padapter, HW_VAR_ACM_CTRL, (u8 *)(&acm_mask));
 860                else
 861                        padapter->mlmepriv.acm_mask = acm_mask;
 862
 863                inx[0] = 0; inx[1] = 1; inx[2] = 2; inx[3] = 3;
 864
 865                if (pregpriv->wifi_spec == 1)
 866                        sort_wmm_ac_params(inx, edca);
 867
 868                for (i = 0; i < 4; i++)
 869                        pxmitpriv->wmm_para_seq[i] = inx[i];
 870        }
 871}
 872
 873static void bwmode_update_check(struct adapter *padapter, struct ndis_80211_var_ie *pIE)
 874{
 875        unsigned char  new_bwmode;
 876        unsigned char  new_ch_offset;
 877        struct HT_info_element   *pHT_info;
 878        struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
 879        struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
 880        struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
 881        struct registry_priv *pregistrypriv = &padapter->registrypriv;
 882        struct ht_priv *phtpriv = &pmlmepriv->htpriv;
 883        u8 cbw40_enable = 0;
 884
 885        if (!pIE)
 886                return;
 887
 888        if (phtpriv->ht_option == false)
 889                return;
 890
 891        if (pIE->length > sizeof(struct HT_info_element))
 892                return;
 893
 894        pHT_info = (struct HT_info_element *)pIE->data;
 895
 896        if (pmlmeext->cur_channel > 14) {
 897                if ((pregistrypriv->bw_mode & 0xf0) > 0)
 898                        cbw40_enable = 1;
 899        } else {
 900                if ((pregistrypriv->bw_mode & 0x0f) > 0)
 901                        cbw40_enable = 1;
 902        }
 903
 904        if ((pHT_info->infos[0] & BIT(2)) && cbw40_enable) {
 905                new_bwmode = CHANNEL_WIDTH_40;
 906
 907                switch (pHT_info->infos[0] & 0x3) {
 908                case 1:
 909                        new_ch_offset = HAL_PRIME_CHNL_OFFSET_LOWER;
 910                        break;
 911
 912                case 3:
 913                        new_ch_offset = HAL_PRIME_CHNL_OFFSET_UPPER;
 914                        break;
 915
 916                default:
 917                        new_bwmode = CHANNEL_WIDTH_20;
 918                        new_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
 919                        break;
 920                }
 921        } else {
 922                new_bwmode = CHANNEL_WIDTH_20;
 923                new_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
 924        }
 925
 926        if ((new_bwmode != pmlmeext->cur_bwmode) || (new_ch_offset != pmlmeext->cur_ch_offset)) {
 927                pmlmeinfo->bwmode_updated = true;
 928
 929                pmlmeext->cur_bwmode = new_bwmode;
 930                pmlmeext->cur_ch_offset = new_ch_offset;
 931
 932                /* update HT info also */
 933                HT_info_handler(padapter, pIE);
 934        } else {
 935                pmlmeinfo->bwmode_updated = false;
 936        }
 937
 938        if (true == pmlmeinfo->bwmode_updated) {
 939                struct sta_info *psta;
 940                struct wlan_bssid_ex    *cur_network = &(pmlmeinfo->network);
 941                struct sta_priv *pstapriv = &padapter->stapriv;
 942
 943                /* set_channel_bwmode(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode); */
 944
 945                /* update ap's stainfo */
 946                psta = rtw_get_stainfo(pstapriv, cur_network->mac_address);
 947                if (psta) {
 948                        struct ht_priv *phtpriv_sta = &psta->htpriv;
 949
 950                        if (phtpriv_sta->ht_option) {
 951                                /*  bwmode */
 952                                psta->bw_mode = pmlmeext->cur_bwmode;
 953                                phtpriv_sta->ch_offset = pmlmeext->cur_ch_offset;
 954                        } else {
 955                                psta->bw_mode = CHANNEL_WIDTH_20;
 956                                phtpriv_sta->ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
 957                        }
 958
 959                        rtw_dm_ra_mask_wk_cmd(padapter, (u8 *)psta);
 960                }
 961        }
 962}
 963
 964void HT_caps_handler(struct adapter *padapter, struct ndis_80211_var_ie *pIE)
 965{
 966        unsigned int    i;
 967        u8 max_AMPDU_len, min_MPDU_spacing;
 968        u8 cur_ldpc_cap = 0, cur_stbc_cap = 0;
 969        struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
 970        struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
 971        struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
 972        struct ht_priv *phtpriv = &pmlmepriv->htpriv;
 973
 974        if (!pIE)
 975                return;
 976
 977        if (phtpriv->ht_option == false)
 978                return;
 979
 980        pmlmeinfo->HT_caps_enable = 1;
 981
 982        for (i = 0; i < (pIE->length); i++) {
 983                if (i != 2) {
 984                        /* Commented by Albert 2010/07/12 */
 985                        /* Got the endian issue here. */
 986                        pmlmeinfo->HT_caps.u.HT_cap[i] &= (pIE->data[i]);
 987                } else {
 988                        /* modify from  fw by Thomas 2010/11/17 */
 989                        if ((pmlmeinfo->HT_caps.u.HT_cap_element.AMPDU_para & 0x3) > (pIE->data[i] & 0x3))
 990                                max_AMPDU_len = (pIE->data[i] & 0x3);
 991                        else
 992                                max_AMPDU_len = (pmlmeinfo->HT_caps.u.HT_cap_element.AMPDU_para & 0x3);
 993
 994                        if ((pmlmeinfo->HT_caps.u.HT_cap_element.AMPDU_para & 0x1c) > (pIE->data[i] & 0x1c))
 995                                min_MPDU_spacing = (pmlmeinfo->HT_caps.u.HT_cap_element.AMPDU_para & 0x1c);
 996                        else
 997                                min_MPDU_spacing = (pIE->data[i] & 0x1c);
 998
 999                        pmlmeinfo->HT_caps.u.HT_cap_element.AMPDU_para = max_AMPDU_len | min_MPDU_spacing;
1000                }
1001        }
1002
1003        /* update the MCS set */
1004        for (i = 0; i < 16; i++)
1005                pmlmeinfo->HT_caps.u.HT_cap_element.MCS_rate[i] &= pmlmeext->default_supported_mcs_set[i];
1006
1007        /* update the MCS rates */
1008        set_mcs_rate_by_mask(pmlmeinfo->HT_caps.u.HT_cap_element.MCS_rate, MCS_RATE_1R);
1009
1010        if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) {
1011                /*  Config STBC setting */
1012                if (TEST_FLAG(phtpriv->stbc_cap, STBC_HT_ENABLE_TX) &&
1013                    GET_HT_CAPABILITY_ELE_TX_STBC(pIE->data))
1014                        SET_FLAG(cur_stbc_cap, STBC_HT_ENABLE_TX);
1015
1016                phtpriv->stbc_cap = cur_stbc_cap;
1017        } else {
1018                /*  Config LDPC Coding Capability */
1019                if (TEST_FLAG(phtpriv->ldpc_cap, LDPC_HT_ENABLE_TX) &&
1020                    GET_HT_CAPABILITY_ELE_LDPC_CAP(pIE->data))
1021                        SET_FLAG(cur_ldpc_cap, (LDPC_HT_ENABLE_TX | LDPC_HT_CAP_TX));
1022
1023                phtpriv->ldpc_cap = cur_ldpc_cap;
1024
1025                /*  Config STBC setting */
1026                if (TEST_FLAG(phtpriv->stbc_cap, STBC_HT_ENABLE_TX) &&
1027                    GET_HT_CAPABILITY_ELE_RX_STBC(pIE->data))
1028                        SET_FLAG(cur_stbc_cap, (STBC_HT_ENABLE_TX | STBC_HT_CAP_TX));
1029
1030                phtpriv->stbc_cap = cur_stbc_cap;
1031        }
1032}
1033
1034void HT_info_handler(struct adapter *padapter, struct ndis_80211_var_ie *pIE)
1035{
1036        struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
1037        struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
1038        struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1039        struct ht_priv *phtpriv = &pmlmepriv->htpriv;
1040
1041        if (!pIE)
1042                return;
1043
1044        if (phtpriv->ht_option == false)
1045                return;
1046
1047        if (pIE->length > sizeof(struct HT_info_element))
1048                return;
1049
1050        pmlmeinfo->HT_info_enable = 1;
1051        memcpy(&(pmlmeinfo->HT_info), pIE->data, pIE->length);
1052}
1053
1054void HTOnAssocRsp(struct adapter *padapter)
1055{
1056        unsigned char max_AMPDU_len;
1057        unsigned char min_MPDU_spacing;
1058        /* struct registry_priv  *pregpriv = &padapter->registrypriv; */
1059        struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
1060        struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
1061
1062        if ((pmlmeinfo->HT_info_enable) && (pmlmeinfo->HT_caps_enable)) {
1063                pmlmeinfo->HT_enable = 1;
1064        } else {
1065                pmlmeinfo->HT_enable = 0;
1066                /* set_channel_bwmode(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode); */
1067                return;
1068        }
1069
1070        /* handle A-MPDU parameter field */
1071        /*
1072                AMPDU_para [1:0]:Max AMPDU Len => 0:8k , 1:16k, 2:32k, 3:64k
1073                AMPDU_para [4:2]:Min MPDU Start Spacing
1074        */
1075        max_AMPDU_len = pmlmeinfo->HT_caps.u.HT_cap_element.AMPDU_para & 0x03;
1076
1077        min_MPDU_spacing = (pmlmeinfo->HT_caps.u.HT_cap_element.AMPDU_para & 0x1c) >> 2;
1078
1079        rtw_hal_set_hwreg(padapter, HW_VAR_AMPDU_MIN_SPACE, (u8 *)(&min_MPDU_spacing));
1080
1081        rtw_hal_set_hwreg(padapter, HW_VAR_AMPDU_FACTOR, (u8 *)(&max_AMPDU_len));
1082}
1083
1084void ERP_IE_handler(struct adapter *padapter, struct ndis_80211_var_ie *pIE)
1085{
1086        struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
1087        struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
1088
1089        if (pIE->length > 1)
1090                return;
1091
1092        pmlmeinfo->ERP_enable = 1;
1093        memcpy(&(pmlmeinfo->ERP_IE), pIE->data, pIE->length);
1094}
1095
1096void VCS_update(struct adapter *padapter, struct sta_info *psta)
1097{
1098        struct registry_priv  *pregpriv = &padapter->registrypriv;
1099        struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
1100        struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
1101
1102        switch (pregpriv->vrtl_carrier_sense) {/* 0:off 1:on 2:auto */
1103        case 0: /* off */
1104                psta->rtsen = 0;
1105                psta->cts2self = 0;
1106                break;
1107
1108        case 1: /* on */
1109                if (pregpriv->vcs_type == 1) { /* 1:RTS/CTS 2:CTS to self */
1110                        psta->rtsen = 1;
1111                        psta->cts2self = 0;
1112                } else {
1113                        psta->rtsen = 0;
1114                        psta->cts2self = 1;
1115                }
1116                break;
1117
1118        case 2: /* auto */
1119        default:
1120                if ((pmlmeinfo->ERP_enable) && (pmlmeinfo->ERP_IE & BIT(1))) {
1121                        if (pregpriv->vcs_type == 1) {
1122                                psta->rtsen = 1;
1123                                psta->cts2self = 0;
1124                        } else {
1125                                psta->rtsen = 0;
1126                                psta->cts2self = 1;
1127                        }
1128                } else {
1129                        psta->rtsen = 0;
1130                        psta->cts2self = 0;
1131                }
1132                break;
1133        }
1134}
1135
1136void update_ldpc_stbc_cap(struct sta_info *psta)
1137{
1138        if (psta->htpriv.ht_option) {
1139                if (TEST_FLAG(psta->htpriv.ldpc_cap, LDPC_HT_ENABLE_TX))
1140                        psta->ldpc = 1;
1141
1142                if (TEST_FLAG(psta->htpriv.stbc_cap, STBC_HT_ENABLE_TX))
1143                        psta->stbc = 1;
1144        } else {
1145                psta->ldpc = 0;
1146                psta->stbc = 0;
1147        }
1148}
1149
1150int rtw_check_bcn_info(struct adapter *Adapter, u8 *pframe, u32 packet_len)
1151{
1152        unsigned int len;
1153        unsigned char *p;
1154        unsigned short  val16, subtype;
1155        struct wlan_network *cur_network = &(Adapter->mlmepriv.cur_network);
1156        /* u8 wpa_ie[255], rsn_ie[255]; */
1157        u16 wpa_len = 0, rsn_len = 0;
1158        u8 encryp_protocol = 0;
1159        struct wlan_bssid_ex *bssid;
1160        int group_cipher = 0, pairwise_cipher = 0, is_8021x = 0;
1161        unsigned char *pbuf;
1162        u32 wpa_ielen = 0;
1163        u8 *pbssid = GetAddr3Ptr(pframe);
1164        struct HT_info_element *pht_info = NULL;
1165        struct ieee80211_ht_cap *pht_cap = NULL;
1166        u32 bcn_channel;
1167        unsigned short  ht_cap_info;
1168        unsigned char ht_info_infos_0;
1169        struct mlme_priv *pmlmepriv = &Adapter->mlmepriv;
1170        int ssid_len;
1171
1172        if (is_client_associated_to_ap(Adapter) == false)
1173                return true;
1174
1175        len = packet_len - sizeof(struct ieee80211_hdr_3addr);
1176
1177        if (len > MAX_IE_SZ)
1178                return _FAIL;
1179
1180        if (memcmp(cur_network->network.mac_address, pbssid, 6))
1181                return true;
1182
1183        bssid = rtw_zmalloc(sizeof(struct wlan_bssid_ex));
1184        if (!bssid)
1185                return true;
1186
1187        if ((pmlmepriv->timeBcnInfoChkStart != 0) && (jiffies_to_msecs(jiffies - pmlmepriv->timeBcnInfoChkStart) > DISCONNECT_BY_CHK_BCN_FAIL_OBSERV_PERIOD_IN_MS)) {
1188                pmlmepriv->timeBcnInfoChkStart = 0;
1189                pmlmepriv->NumOfBcnInfoChkFail = 0;
1190        }
1191
1192        subtype = GetFrameSubType(pframe) >> 4;
1193
1194        if (subtype == WIFI_BEACON)
1195                bssid->reserved[0] = 1;
1196
1197        bssid->length = sizeof(struct wlan_bssid_ex) - MAX_IE_SZ + len;
1198
1199        /* below is to copy the information element */
1200        bssid->ie_length = len;
1201        memcpy(bssid->ies, (pframe + sizeof(struct ieee80211_hdr_3addr)), bssid->ie_length);
1202
1203        /* check bw and channel offset */
1204        /* parsing HT_CAP_IE */
1205        p = rtw_get_ie(bssid->ies + _FIXED_IE_LENGTH_, WLAN_EID_HT_CAPABILITY, &len, bssid->ie_length - _FIXED_IE_LENGTH_);
1206        if (p && len > 0) {
1207                pht_cap = (struct ieee80211_ht_cap *)(p + 2);
1208                ht_cap_info = le16_to_cpu(pht_cap->cap_info);
1209        } else {
1210                ht_cap_info = 0;
1211        }
1212        /* parsing HT_INFO_IE */
1213        p = rtw_get_ie(bssid->ies + _FIXED_IE_LENGTH_, WLAN_EID_HT_OPERATION, &len, bssid->ie_length - _FIXED_IE_LENGTH_);
1214        if (p && len > 0) {
1215                pht_info = (struct HT_info_element *)(p + 2);
1216                ht_info_infos_0 = pht_info->infos[0];
1217        } else {
1218                ht_info_infos_0 = 0;
1219        }
1220        if (ht_cap_info != cur_network->bcn_info.ht_cap_info ||
1221            ((ht_info_infos_0&0x03) != (cur_network->bcn_info.ht_info_infos_0&0x03))) {
1222                {
1223                        /* bcn_info_update */
1224                        cur_network->bcn_info.ht_cap_info = ht_cap_info;
1225                        cur_network->bcn_info.ht_info_infos_0 = ht_info_infos_0;
1226                        /* to do : need to check that whether modify related register of BB or not */
1227                }
1228                /* goto _mismatch; */
1229        }
1230
1231        /* Checking for channel */
1232        p = rtw_get_ie(bssid->ies + _FIXED_IE_LENGTH_, WLAN_EID_DS_PARAMS, &len, bssid->ie_length - _FIXED_IE_LENGTH_);
1233        if (p) {
1234                bcn_channel = *(p + 2);
1235        } else {/* In 5G, some ap do not have DSSET IE checking HT info for channel */
1236                rtw_get_ie(bssid->ies + _FIXED_IE_LENGTH_, WLAN_EID_HT_OPERATION,
1237                           &len, bssid->ie_length - _FIXED_IE_LENGTH_);
1238                if (pht_info)
1239                        bcn_channel = pht_info->primary_channel;
1240                else /* we don't find channel IE, so don't check it */
1241                        bcn_channel = Adapter->mlmeextpriv.cur_channel;
1242        }
1243
1244        if (bcn_channel != Adapter->mlmeextpriv.cur_channel)
1245                goto _mismatch;
1246
1247        /* checking SSID */
1248        ssid_len = 0;
1249        p = rtw_get_ie(bssid->ies + _FIXED_IE_LENGTH_, WLAN_EID_SSID, &len, bssid->ie_length - _FIXED_IE_LENGTH_);
1250        if (p) {
1251                ssid_len = *(p + 1);
1252                if (ssid_len > NDIS_802_11_LENGTH_SSID)
1253                        ssid_len = 0;
1254        }
1255        memcpy(bssid->ssid.ssid, (p + 2), ssid_len);
1256        bssid->ssid.ssid_length = ssid_len;
1257
1258        if (memcmp(bssid->ssid.ssid, cur_network->network.ssid.ssid, 32) ||
1259                        bssid->ssid.ssid_length != cur_network->network.ssid.ssid_length)
1260                if (bssid->ssid.ssid[0] != '\0' &&
1261                    bssid->ssid.ssid_length != 0) /* not hidden ssid */
1262                        goto _mismatch;
1263
1264        /* check encryption info */
1265        val16 = rtw_get_capability((struct wlan_bssid_ex *)bssid);
1266
1267        if (val16 & BIT(4))
1268                bssid->privacy = 1;
1269        else
1270                bssid->privacy = 0;
1271
1272        if (cur_network->network.privacy != bssid->privacy)
1273                goto _mismatch;
1274
1275        rtw_get_sec_ie(bssid->ies, bssid->ie_length, NULL, &rsn_len, NULL, &wpa_len);
1276
1277        if (rsn_len > 0)
1278                encryp_protocol = ENCRYP_PROTOCOL_WPA2;
1279        else if (wpa_len > 0)
1280                encryp_protocol = ENCRYP_PROTOCOL_WPA;
1281        else
1282                if (bssid->privacy)
1283                        encryp_protocol = ENCRYP_PROTOCOL_WEP;
1284
1285        if (cur_network->bcn_info.encryp_protocol != encryp_protocol)
1286                goto _mismatch;
1287
1288        if (encryp_protocol == ENCRYP_PROTOCOL_WPA || encryp_protocol == ENCRYP_PROTOCOL_WPA2) {
1289                pbuf = rtw_get_wpa_ie(&bssid->ies[12], &wpa_ielen, bssid->ie_length-12);
1290                if (pbuf && (wpa_ielen > 0)) {
1291                        rtw_parse_wpa_ie(pbuf, wpa_ielen + 2, &group_cipher,
1292                                         &pairwise_cipher, &is_8021x);
1293                } else {
1294                        pbuf = rtw_get_wpa2_ie(&bssid->ies[12], &wpa_ielen, bssid->ie_length-12);
1295
1296                        if (pbuf && (wpa_ielen > 0))
1297                                rtw_parse_wpa2_ie(pbuf, wpa_ielen + 2, &group_cipher,
1298                                                  &pairwise_cipher, &is_8021x);
1299                }
1300
1301                if (pairwise_cipher != cur_network->bcn_info.pairwise_cipher ||
1302                    group_cipher != cur_network->bcn_info.group_cipher)
1303                        goto _mismatch;
1304
1305                if (is_8021x != cur_network->bcn_info.is_8021x)
1306                        goto _mismatch;
1307        }
1308
1309        kfree(bssid);
1310        return _SUCCESS;
1311
1312_mismatch:
1313        kfree(bssid);
1314
1315        if (pmlmepriv->NumOfBcnInfoChkFail == 0)
1316                pmlmepriv->timeBcnInfoChkStart = jiffies;
1317
1318        pmlmepriv->NumOfBcnInfoChkFail++;
1319
1320        if ((pmlmepriv->timeBcnInfoChkStart != 0) && (jiffies_to_msecs(jiffies - pmlmepriv->timeBcnInfoChkStart) <= DISCONNECT_BY_CHK_BCN_FAIL_OBSERV_PERIOD_IN_MS)
1321                && (pmlmepriv->NumOfBcnInfoChkFail >= DISCONNECT_BY_CHK_BCN_FAIL_THRESHOLD)) {
1322                pmlmepriv->timeBcnInfoChkStart = 0;
1323                pmlmepriv->NumOfBcnInfoChkFail = 0;
1324                return _FAIL;
1325        }
1326
1327        return _SUCCESS;
1328}
1329
1330void update_beacon_info(struct adapter *padapter, u8 *pframe, uint pkt_len, struct sta_info *psta)
1331{
1332        unsigned int i;
1333        unsigned int len;
1334        struct ndis_80211_var_ie *pIE;
1335
1336        len = pkt_len - (_BEACON_IE_OFFSET_ + WLAN_HDR_A3_LEN);
1337
1338        for (i = 0; i < len;) {
1339                pIE = (struct ndis_80211_var_ie *)(pframe + (_BEACON_IE_OFFSET_ + WLAN_HDR_A3_LEN) + i);
1340
1341                switch (pIE->element_id) {
1342                case WLAN_EID_VENDOR_SPECIFIC:
1343                        /* to update WMM parameter set while receiving beacon */
1344                        if (!memcmp(pIE->data, WMM_PARA_OUI, 6) && pIE->length == WLAN_WMM_LEN) /* WMM */
1345                                if (WMM_param_handler(padapter, pIE))
1346                                        report_wmm_edca_update(padapter);
1347
1348                        break;
1349
1350                case WLAN_EID_HT_OPERATION:     /* HT info */
1351                        /* HT_info_handler(padapter, pIE); */
1352                        bwmode_update_check(padapter, pIE);
1353                        break;
1354
1355                case WLAN_EID_ERP_INFO:
1356                        ERP_IE_handler(padapter, pIE);
1357                        VCS_update(padapter, psta);
1358                        break;
1359
1360                default:
1361                        break;
1362                }
1363
1364                i += (pIE->length + 2);
1365        }
1366}
1367
1368unsigned int is_ap_in_tkip(struct adapter *padapter)
1369{
1370        u32 i;
1371        struct ndis_80211_var_ie *pIE;
1372        struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
1373        struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
1374        struct wlan_bssid_ex            *cur_network = &(pmlmeinfo->network);
1375
1376        if (rtw_get_capability((struct wlan_bssid_ex *)cur_network) & WLAN_CAPABILITY_PRIVACY) {
1377                for (i = sizeof(struct ndis_802_11_fix_ie); i < pmlmeinfo->network.ie_length;) {
1378                        pIE = (struct ndis_80211_var_ie *)(pmlmeinfo->network.ies + i);
1379
1380                        switch (pIE->element_id) {
1381                        case WLAN_EID_VENDOR_SPECIFIC:
1382                                if ((!memcmp(pIE->data, RTW_WPA_OUI, 4)) && (!memcmp((pIE->data + 12), WPA_TKIP_CIPHER, 4)))
1383                                        return true;
1384
1385                                break;
1386
1387                        case WLAN_EID_RSN:
1388                                if (!memcmp((pIE->data + 8), RSN_TKIP_CIPHER, 4))
1389                                        return true;
1390                                break;
1391
1392                        default:
1393                                break;
1394                        }
1395
1396                        i += (pIE->length + 2);
1397                }
1398
1399                return false;
1400        } else {
1401                return false;
1402        }
1403}
1404
1405int support_short_GI(struct adapter *padapter, struct HT_caps_element *pHT_caps, u8 bwmode)
1406{
1407        unsigned char bit_offset;
1408        struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
1409        struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
1410
1411        if (!(pmlmeinfo->HT_enable))
1412                return _FAIL;
1413
1414        bit_offset = (bwmode & CHANNEL_WIDTH_40) ? 6 : 5;
1415
1416        if (le16_to_cpu(pHT_caps->u.HT_cap_element.HT_caps_info) & (0x1 << bit_offset))
1417                return _SUCCESS;
1418        else
1419                return _FAIL;
1420}
1421
1422unsigned char get_highest_rate_idx(u32 mask)
1423{
1424        int i;
1425        unsigned char rate_idx = 0;
1426
1427        for (i = 31; i >= 0; i--) {
1428                if (mask & BIT(i)) {
1429                        rate_idx = i;
1430                        break;
1431                }
1432        }
1433
1434        return rate_idx;
1435}
1436
1437void Update_RA_Entry(struct adapter *padapter, struct sta_info *psta)
1438{
1439        rtw_hal_update_ra_mask(psta, 0);
1440}
1441
1442void set_sta_rate(struct adapter *padapter, struct sta_info *psta)
1443{
1444        /* rate adaptive */
1445        Update_RA_Entry(padapter, psta);
1446}
1447
1448static u32 get_realtek_assoc_AP_vender(struct ndis_80211_var_ie *pIE)
1449{
1450        u32 Vender = HT_IOT_PEER_REALTEK;
1451
1452        if (pIE->length >= 5) {
1453                if (pIE->data[4] == 1)
1454                        /* if (pIE->data[5] & RT_HT_CAP_USE_LONG_PREAMBLE) */
1455                        /* bssDesc->BssHT.RT2RT_HT_Mode |= RT_HT_CAP_USE_LONG_PREAMBLE; */
1456                        if (pIE->data[5] & RT_HT_CAP_USE_92SE)
1457                                /* bssDesc->BssHT.RT2RT_HT_Mode |= RT_HT_CAP_USE_92SE; */
1458                                Vender = HT_IOT_PEER_REALTEK_92SE;
1459
1460                if (pIE->data[5] & RT_HT_CAP_USE_SOFTAP)
1461                        Vender = HT_IOT_PEER_REALTEK_SOFTAP;
1462
1463                if (pIE->data[4] == 2) {
1464                        if (pIE->data[6] & RT_HT_CAP_USE_JAGUAR_BCUT)
1465                                Vender = HT_IOT_PEER_REALTEK_JAGUAR_BCUTAP;
1466
1467                        if (pIE->data[6] & RT_HT_CAP_USE_JAGUAR_CCUT)
1468                                Vender = HT_IOT_PEER_REALTEK_JAGUAR_CCUTAP;
1469                }
1470        }
1471
1472        return Vender;
1473}
1474
1475unsigned char check_assoc_AP(u8 *pframe, uint len)
1476{
1477        unsigned int    i;
1478        struct ndis_80211_var_ie *pIE;
1479
1480        for (i = sizeof(struct ndis_802_11_fix_ie); i < len;) {
1481                pIE = (struct ndis_80211_var_ie *)(pframe + i);
1482
1483                switch (pIE->element_id) {
1484                case WLAN_EID_VENDOR_SPECIFIC:
1485                        if ((!memcmp(pIE->data, ARTHEROS_OUI1, 3)) || (!memcmp(pIE->data, ARTHEROS_OUI2, 3)))
1486                                return HT_IOT_PEER_ATHEROS;
1487                        else if ((!memcmp(pIE->data, BROADCOM_OUI1, 3)) ||
1488                                 (!memcmp(pIE->data, BROADCOM_OUI2, 3)) ||
1489                                 (!memcmp(pIE->data, BROADCOM_OUI3, 3)))
1490                                return HT_IOT_PEER_BROADCOM;
1491                        else if (!memcmp(pIE->data, MARVELL_OUI, 3))
1492                                return HT_IOT_PEER_MARVELL;
1493                        else if (!memcmp(pIE->data, RALINK_OUI, 3))
1494                                return HT_IOT_PEER_RALINK;
1495                        else if (!memcmp(pIE->data, CISCO_OUI, 3))
1496                                return HT_IOT_PEER_CISCO;
1497                        else if (!memcmp(pIE->data, REALTEK_OUI, 3))
1498                                return get_realtek_assoc_AP_vender(pIE);
1499                        else if (!memcmp(pIE->data, AIRGOCAP_OUI, 3))
1500                                return HT_IOT_PEER_AIRGO;
1501                        else
1502                                break;
1503
1504                default:
1505                        break;
1506                }
1507
1508                i += (pIE->length + 2);
1509        }
1510
1511        return HT_IOT_PEER_UNKNOWN;
1512}
1513
1514void update_IOT_info(struct adapter *padapter)
1515{
1516        struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
1517        struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
1518
1519        switch (pmlmeinfo->assoc_AP_vendor) {
1520        case HT_IOT_PEER_MARVELL:
1521                pmlmeinfo->turboMode_cts2self = 1;
1522                pmlmeinfo->turboMode_rtsen = 0;
1523                break;
1524
1525        case HT_IOT_PEER_RALINK:
1526                pmlmeinfo->turboMode_cts2self = 0;
1527                pmlmeinfo->turboMode_rtsen = 1;
1528                /* disable high power */
1529                Switch_DM_Func(padapter, (~DYNAMIC_BB_DYNAMIC_TXPWR), false);
1530                break;
1531        case HT_IOT_PEER_REALTEK:
1532                /* rtw_write16(padapter, 0x4cc, 0xffff); */
1533                /* rtw_write16(padapter, 0x546, 0x01c0); */
1534                /* disable high power */
1535                Switch_DM_Func(padapter, (~DYNAMIC_BB_DYNAMIC_TXPWR), false);
1536                break;
1537        default:
1538                pmlmeinfo->turboMode_cts2self = 0;
1539                pmlmeinfo->turboMode_rtsen = 1;
1540                break;
1541        }
1542}
1543
1544void update_capinfo(struct adapter *Adapter, u16 updateCap)
1545{
1546        struct mlme_ext_priv *pmlmeext = &Adapter->mlmeextpriv;
1547        struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
1548        bool            ShortPreamble;
1549
1550        /*  Check preamble mode, 2005.01.06, by rcnjko. */
1551        /*  Mark to update preamble value forever, 2008.03.18 by lanhsin */
1552        /* if (pMgntInfo->RegPreambleMode == PREAMBLE_AUTO) */
1553        {
1554                if (updateCap & cShortPreamble) {
1555                        /*  Short Preamble */
1556                        if (pmlmeinfo->preamble_mode != PREAMBLE_SHORT) { /*  PREAMBLE_LONG or PREAMBLE_AUTO */
1557                                ShortPreamble = true;
1558                                pmlmeinfo->preamble_mode = PREAMBLE_SHORT;
1559                                rtw_hal_set_hwreg(Adapter, HW_VAR_ACK_PREAMBLE, (u8 *)&ShortPreamble);
1560                        }
1561                } else {
1562                        /*  Long Preamble */
1563                        if (pmlmeinfo->preamble_mode != PREAMBLE_LONG) { /*  PREAMBLE_SHORT or PREAMBLE_AUTO */
1564                                ShortPreamble = false;
1565                                pmlmeinfo->preamble_mode = PREAMBLE_LONG;
1566                                rtw_hal_set_hwreg(Adapter, HW_VAR_ACK_PREAMBLE, (u8 *)&ShortPreamble);
1567                        }
1568                }
1569        }
1570
1571        if (updateCap & cIBSS) {
1572                /* Filen: See 802.11-2007 p.91 */
1573                pmlmeinfo->slotTime = NON_SHORT_SLOT_TIME;
1574        } else {
1575                /* Filen: See 802.11-2007 p.90 */
1576                if (pmlmeext->cur_wireless_mode & (WIRELESS_11_24N)) {
1577                        pmlmeinfo->slotTime = SHORT_SLOT_TIME;
1578                } else if (pmlmeext->cur_wireless_mode & (WIRELESS_11G)) {
1579                        if ((updateCap & cShortSlotTime) /* && (!(pMgntInfo->pHTInfo->RT2RT_HT_Mode & RT_HT_CAP_USE_LONG_PREAMBLE)) */)
1580                                /*  Short Slot Time */
1581                                pmlmeinfo->slotTime = SHORT_SLOT_TIME;
1582                        else
1583                                /*  Long Slot Time */
1584                                pmlmeinfo->slotTime = NON_SHORT_SLOT_TIME;
1585                } else {
1586                        /* B Mode */
1587                        pmlmeinfo->slotTime = NON_SHORT_SLOT_TIME;
1588                }
1589        }
1590
1591        rtw_hal_set_hwreg(Adapter, HW_VAR_SLOT_TIME, &pmlmeinfo->slotTime);
1592}
1593
1594void update_wireless_mode(struct adapter *padapter)
1595{
1596        int network_type = 0;
1597        u32 SIFS_Timer;
1598        struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
1599        struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
1600        struct wlan_bssid_ex *cur_network = &(pmlmeinfo->network);
1601        unsigned char *rate = cur_network->supported_rates;
1602
1603        if ((pmlmeinfo->HT_info_enable) && (pmlmeinfo->HT_caps_enable))
1604                pmlmeinfo->HT_enable = 1;
1605
1606        if (pmlmeinfo->HT_enable)
1607                network_type = WIRELESS_11_24N;
1608
1609        if (rtw_is_cckratesonly_included(rate))
1610                network_type |= WIRELESS_11B;
1611        else if (rtw_is_cckrates_included(rate))
1612                network_type |= WIRELESS_11BG;
1613        else
1614                network_type |= WIRELESS_11G;
1615
1616        pmlmeext->cur_wireless_mode = network_type & padapter->registrypriv.wireless_mode;
1617
1618        SIFS_Timer = 0x0a0a0808; /* 0x0808 -> for CCK, 0x0a0a -> for OFDM */
1619                                                                                                        /* change this value if having IOT issues. */
1620
1621        padapter->HalFunc.SetHwRegHandler(padapter, HW_VAR_RESP_SIFS,  (u8 *)&SIFS_Timer);
1622
1623        padapter->HalFunc.SetHwRegHandler(padapter, HW_VAR_WIRELESS_MODE,  (u8 *)&(pmlmeext->cur_wireless_mode));
1624
1625        if (pmlmeext->cur_wireless_mode & WIRELESS_11B)
1626                update_mgnt_tx_rate(padapter, IEEE80211_CCK_RATE_1MB);
1627        else
1628                update_mgnt_tx_rate(padapter, IEEE80211_OFDM_RATE_6MB);
1629}
1630
1631void update_sta_basic_rate(struct sta_info *psta, u8 wireless_mode)
1632{
1633        if (is_supported_tx_cck(wireless_mode)) {
1634                /*  Only B, B/G, and B/G/N AP could use CCK rate */
1635                memcpy(psta->bssrateset, rtw_basic_rate_cck, 4);
1636                psta->bssratelen = 4;
1637        } else {
1638                memcpy(psta->bssrateset, rtw_basic_rate_ofdm, 3);
1639                psta->bssratelen = 3;
1640        }
1641}
1642
1643int update_sta_support_rate(struct adapter *padapter, u8 *pvar_ie, uint var_ie_len, int cam_idx)
1644{
1645        unsigned int    ie_len;
1646        struct ndis_80211_var_ie *pIE;
1647        int     supportRateNum = 0;
1648        struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
1649        struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
1650
1651        pIE = (struct ndis_80211_var_ie *)rtw_get_ie(pvar_ie, WLAN_EID_SUPP_RATES, &ie_len, var_ie_len);
1652        if (!pIE)
1653                return _FAIL;
1654        if (ie_len > sizeof(pmlmeinfo->FW_sta_info[cam_idx].SupportedRates))
1655                return _FAIL;
1656
1657        memcpy(pmlmeinfo->FW_sta_info[cam_idx].SupportedRates, pIE->data, ie_len);
1658        supportRateNum = ie_len;
1659
1660        pIE = (struct ndis_80211_var_ie *)rtw_get_ie(pvar_ie, WLAN_EID_EXT_SUPP_RATES, &ie_len, var_ie_len);
1661        if (pIE && (ie_len <= sizeof(pmlmeinfo->FW_sta_info[cam_idx].SupportedRates) - supportRateNum))
1662                memcpy((pmlmeinfo->FW_sta_info[cam_idx].SupportedRates + supportRateNum), pIE->data, ie_len);
1663
1664        return _SUCCESS;
1665}
1666
1667void process_addba_req(struct adapter *padapter, u8 *paddba_req, u8 *addr)
1668{
1669        struct sta_info *psta;
1670        u16 tid, param;
1671        struct recv_reorder_ctrl *preorder_ctrl;
1672        struct sta_priv *pstapriv = &padapter->stapriv;
1673        struct ADDBA_request *preq = (struct ADDBA_request *)paddba_req;
1674        struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
1675        struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
1676
1677        psta = rtw_get_stainfo(pstapriv, addr);
1678
1679        if (psta) {
1680                param = le16_to_cpu(preq->BA_para_set);
1681                tid = (param>>2)&0x0f;
1682
1683                preorder_ctrl = &psta->recvreorder_ctrl[tid];
1684
1685                preorder_ctrl->indicate_seq = 0xffff;
1686
1687                preorder_ctrl->enable = pmlmeinfo->accept_addba_req;
1688        }
1689}
1690
1691void update_TSF(struct mlme_ext_priv *pmlmeext, u8 *pframe, uint len)
1692{
1693        u8 *pIE;
1694        __le32 *pbuf;
1695
1696        pIE = pframe + sizeof(struct ieee80211_hdr_3addr);
1697        pbuf = (__le32 *)pIE;
1698
1699        pmlmeext->TSFValue = le32_to_cpu(*(pbuf+1));
1700
1701        pmlmeext->TSFValue = pmlmeext->TSFValue << 32;
1702
1703        pmlmeext->TSFValue |= le32_to_cpu(*pbuf);
1704}
1705
1706void correct_TSF(struct adapter *padapter, struct mlme_ext_priv *pmlmeext)
1707{
1708        rtw_hal_set_hwreg(padapter, HW_VAR_CORRECT_TSF, NULL);
1709}
1710
1711void adaptive_early_32k(struct mlme_ext_priv *pmlmeext, u8 *pframe, uint len)
1712{
1713        int i;
1714        u8 *pIE;
1715        __le32 *pbuf;
1716        u64 tsf = 0;
1717        u32 delay_ms;
1718        struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
1719
1720        pmlmeext->bcn_cnt++;
1721
1722        pIE = pframe + sizeof(struct ieee80211_hdr_3addr);
1723        pbuf = (__le32 *)pIE;
1724
1725        tsf = le32_to_cpu(*(pbuf+1));
1726        tsf = tsf << 32;
1727        tsf |= le32_to_cpu(*pbuf);
1728
1729        /* delay = (timestamp mod 1024*100)/1000 (unit: ms) */
1730        /* delay_ms = do_div(tsf, (pmlmeinfo->bcn_interval*1024))/1000; */
1731        delay_ms = do_div(tsf, (pmlmeinfo->bcn_interval*1024));
1732        delay_ms = delay_ms/1000;
1733
1734        if (delay_ms >= 8)
1735                pmlmeext->bcn_delay_cnt[8]++;
1736                /* pmlmeext->bcn_delay_ratio[8] = (pmlmeext->bcn_delay_cnt[8] * 100) /pmlmeext->bcn_cnt; */
1737        else
1738                pmlmeext->bcn_delay_cnt[delay_ms]++;
1739                /* pmlmeext->bcn_delay_ratio[delay_ms] = (pmlmeext->bcn_delay_cnt[delay_ms] * 100) /pmlmeext->bcn_cnt; */
1740
1741/*
1742
1743        for (i = 0; i<9; i++)
1744        {
1745                        pmlmeext->bcn_delay_cnt[i] , i, pmlmeext->bcn_delay_ratio[i]);
1746        }
1747*/
1748
1749        /* dump for  adaptive_early_32k */
1750        if (pmlmeext->bcn_cnt > 100 && (pmlmeext->adaptive_tsf_done == true)) {
1751                u8 ratio_20_delay, ratio_80_delay;
1752                u8 DrvBcnEarly, DrvBcnTimeOut;
1753
1754                ratio_20_delay = 0;
1755                ratio_80_delay = 0;
1756                DrvBcnEarly = 0xff;
1757                DrvBcnTimeOut = 0xff;
1758
1759                for (i = 0; i < 9; i++) {
1760                        pmlmeext->bcn_delay_ratio[i] = (pmlmeext->bcn_delay_cnt[i] * 100) / pmlmeext->bcn_cnt;
1761
1762                        ratio_20_delay += pmlmeext->bcn_delay_ratio[i];
1763                        ratio_80_delay += pmlmeext->bcn_delay_ratio[i];
1764
1765                        if (ratio_20_delay > 20 && DrvBcnEarly == 0xff)
1766                                DrvBcnEarly = i;
1767
1768                        if (ratio_80_delay > 80 && DrvBcnTimeOut == 0xff)
1769                                DrvBcnTimeOut = i;
1770
1771                        /* reset adaptive_early_32k cnt */
1772                        pmlmeext->bcn_delay_cnt[i] = 0;
1773                        pmlmeext->bcn_delay_ratio[i] = 0;
1774                }
1775
1776                pmlmeext->DrvBcnEarly = DrvBcnEarly;
1777                pmlmeext->DrvBcnTimeOut = DrvBcnTimeOut;
1778
1779                pmlmeext->bcn_cnt = 0;
1780        }
1781}
1782
1783void rtw_alloc_macid(struct adapter *padapter, struct sta_info *psta)
1784{
1785        int i;
1786        u8 bc_addr[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
1787        struct dvobj_priv *pdvobj = adapter_to_dvobj(padapter);
1788
1789        if (!memcmp(psta->hwaddr, bc_addr, ETH_ALEN))
1790                return;
1791
1792        if (!memcmp(psta->hwaddr, myid(&padapter->eeprompriv), ETH_ALEN)) {
1793                psta->mac_id = NUM_STA;
1794                return;
1795        }
1796
1797        spin_lock_bh(&pdvobj->lock);
1798        for (i = 0; i < NUM_STA; i++) {
1799                if (pdvobj->macid[i] == false) {
1800                        pdvobj->macid[i]  = true;
1801                        break;
1802                }
1803        }
1804        spin_unlock_bh(&pdvobj->lock);
1805
1806        if (i > (NUM_STA - 1))
1807                psta->mac_id = NUM_STA;
1808        else
1809                psta->mac_id = i;
1810}
1811
1812void rtw_release_macid(struct adapter *padapter, struct sta_info *psta)
1813{
1814        u8 bc_addr[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
1815        struct dvobj_priv *pdvobj = adapter_to_dvobj(padapter);
1816
1817        if (!memcmp(psta->hwaddr, bc_addr, ETH_ALEN))
1818                return;
1819
1820        if (!memcmp(psta->hwaddr, myid(&padapter->eeprompriv), ETH_ALEN))
1821                return;
1822
1823        spin_lock_bh(&pdvobj->lock);
1824        if (psta->mac_id < NUM_STA && psta->mac_id != 1) {
1825                if (pdvobj->macid[psta->mac_id] == true) {
1826                        pdvobj->macid[psta->mac_id] = false;
1827                        psta->mac_id = NUM_STA;
1828                }
1829        }
1830        spin_unlock_bh(&pdvobj->lock);
1831}
1832
1833/* For 8188E RA */
1834u8 rtw_search_max_mac_id(struct adapter *padapter)
1835{
1836        u8 max_mac_id = 0;
1837        struct dvobj_priv *pdvobj = adapter_to_dvobj(padapter);
1838        int i;
1839
1840        spin_lock_bh(&pdvobj->lock);
1841        for (i = (NUM_STA-1); i >= 0 ; i--) {
1842                if (pdvobj->macid[i] == true)
1843                        break;
1844        }
1845        max_mac_id = i;
1846        spin_unlock_bh(&pdvobj->lock);
1847
1848        return max_mac_id;
1849}
1850
1851struct adapter *dvobj_get_port0_adapter(struct dvobj_priv *dvobj)
1852{
1853        if (get_iface_type(dvobj->padapters[i]) != IFACE_PORT0)
1854                return NULL;
1855
1856        return dvobj->padapters;
1857}
1858