linux/drivers/staging/rtl8188eu/core/rtw_ap.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/******************************************************************************
   3 *
   4 * Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved.
   5 *
   6 ******************************************************************************/
   7#define _RTW_AP_C_
   8
   9#include <linux/ieee80211.h>
  10
  11#include <osdep_service.h>
  12#include <drv_types.h>
  13#include <wifi.h>
  14#include <ieee80211.h>
  15#include <asm/unaligned.h>
  16
  17#ifdef CONFIG_88EU_AP_MODE
  18
  19void init_mlme_ap_info(struct adapter *padapter)
  20{
  21        struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
  22        struct sta_priv *pstapriv = &padapter->stapriv;
  23        struct wlan_acl_pool *pacl_list = &pstapriv->acl_list;
  24
  25        spin_lock_init(&pmlmepriv->bcn_update_lock);
  26
  27        /* for ACL */
  28        _rtw_init_queue(&pacl_list->acl_node_q);
  29
  30        start_ap_mode(padapter);
  31}
  32
  33void free_mlme_ap_info(struct adapter *padapter)
  34{
  35        struct sta_info *psta = NULL;
  36        struct sta_priv *pstapriv = &padapter->stapriv;
  37        struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
  38        struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
  39        struct mlme_ext_info    *pmlmeinfo = &pmlmeext->mlmext_info;
  40
  41        pmlmepriv->update_bcn = false;
  42        pmlmeext->bstart_bss = false;
  43
  44        rtw_sta_flush(padapter);
  45
  46        pmlmeinfo->state = _HW_STATE_NOLINK_;
  47
  48        /* free_assoc_sta_resources */
  49        rtw_free_all_stainfo(padapter);
  50
  51        /* free bc/mc sta_info */
  52        psta = rtw_get_bcmc_stainfo(padapter);
  53        spin_lock_bh(&pstapriv->sta_hash_lock);
  54        rtw_free_stainfo(padapter, psta);
  55        spin_unlock_bh(&pstapriv->sta_hash_lock);
  56}
  57
  58static void update_BCNTIM(struct adapter *padapter)
  59{
  60        struct sta_priv *pstapriv = &padapter->stapriv;
  61        struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
  62        struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
  63        struct wlan_bssid_ex *pnetwork_mlmeext = &pmlmeinfo->network;
  64        unsigned char *pie = pnetwork_mlmeext->ies;
  65        u8 *p, *dst_ie, *premainder_ie = NULL;
  66        u8 *pbackup_remainder_ie = NULL;
  67        uint offset, tmp_len, tim_ielen, tim_ie_offset, remainder_ielen;
  68
  69        /* update TIM IE */
  70        p = rtw_get_ie(pie + _FIXED_IE_LENGTH_, WLAN_EID_TIM, &tim_ielen,
  71                       pnetwork_mlmeext->ie_length - _FIXED_IE_LENGTH_);
  72        if (p && tim_ielen > 0) {
  73                tim_ielen += 2;
  74                premainder_ie = p + tim_ielen;
  75                tim_ie_offset = (int)(p - pie);
  76                remainder_ielen = pnetwork_mlmeext->ie_length -
  77                                        tim_ie_offset - tim_ielen;
  78                /* append TIM IE from dst_ie offset */
  79                dst_ie = p;
  80        } else {
  81                tim_ielen = 0;
  82
  83                /* calculate head_len */
  84                offset = _FIXED_IE_LENGTH_;
  85                offset += pnetwork_mlmeext->ssid.ssid_length + 2;
  86
  87                /*  get supported rates len */
  88                p = rtw_get_ie(pie + _BEACON_IE_OFFSET_, WLAN_EID_SUPP_RATES,
  89                               &tmp_len, (pnetwork_mlmeext->ie_length -
  90                                          _BEACON_IE_OFFSET_));
  91                if (p)
  92                        offset += tmp_len + 2;
  93
  94                /* DS Parameter Set IE, len = 3 */
  95                offset += 3;
  96
  97                premainder_ie = pie + offset;
  98
  99                remainder_ielen = pnetwork_mlmeext->ie_length -
 100                                        offset - tim_ielen;
 101
 102                /* append TIM IE from offset */
 103                dst_ie = pie + offset;
 104        }
 105
 106        if (remainder_ielen > 0) {
 107                pbackup_remainder_ie = rtw_malloc(remainder_ielen);
 108                if (pbackup_remainder_ie && premainder_ie)
 109                        memcpy(pbackup_remainder_ie, premainder_ie,
 110                               remainder_ielen);
 111        }
 112        *dst_ie++ = WLAN_EID_TIM;
 113
 114        if ((pstapriv->tim_bitmap & 0xff00) && (pstapriv->tim_bitmap & 0x00fc))
 115                tim_ielen = 5;
 116        else
 117                tim_ielen = 4;
 118
 119        *dst_ie++ = tim_ielen;
 120
 121        *dst_ie++ = 0;/* DTIM count */
 122        *dst_ie++ = 1;/* DTIM period */
 123
 124        if (pstapriv->tim_bitmap & BIT(0))/* for bc/mc frames */
 125                *dst_ie++ = BIT(0);/* bitmap ctrl */
 126        else
 127                *dst_ie++ = 0;
 128
 129        if (tim_ielen == 4) {
 130                *dst_ie++ = pstapriv->tim_bitmap & 0xff;
 131        } else if (tim_ielen == 5) {
 132                put_unaligned_le16(pstapriv->tim_bitmap, dst_ie);
 133                dst_ie += 2;
 134        }
 135
 136        /* copy remainder IE */
 137        if (pbackup_remainder_ie) {
 138                memcpy(dst_ie, pbackup_remainder_ie, remainder_ielen);
 139
 140                kfree(pbackup_remainder_ie);
 141        }
 142        offset =  (uint)(dst_ie - pie);
 143        pnetwork_mlmeext->ie_length = offset + remainder_ielen;
 144
 145        set_tx_beacon_cmd(padapter);
 146}
 147
 148static u8 chk_sta_is_alive(struct sta_info *psta)
 149{
 150        u8 ret = false;
 151
 152        if ((psta->sta_stats.last_rx_data_pkts +
 153                        psta->sta_stats.last_rx_ctrl_pkts) ==
 154                        (psta->sta_stats.rx_data_pkts +
 155                        psta->sta_stats.rx_ctrl_pkts))
 156                ;
 157        else
 158                ret = true;
 159
 160        sta_update_last_rx_pkts(psta);
 161
 162        return ret;
 163}
 164
 165void expire_timeout_chk(struct adapter *padapter)
 166{
 167        struct list_head *phead;
 168        u8 updated = 0;
 169        struct sta_info *psta, *temp;
 170        struct sta_priv *pstapriv = &padapter->stapriv;
 171        u8 chk_alive_num = 0;
 172        char chk_alive_list[NUM_STA];
 173        int i;
 174
 175        spin_lock_bh(&pstapriv->auth_list_lock);
 176
 177        phead = &pstapriv->auth_list;
 178        /* check auth_queue */
 179        list_for_each_entry_safe(psta, temp, phead, auth_list) {
 180                if (psta->expire_to > 0) {
 181                        psta->expire_to--;
 182                        if (psta->expire_to == 0) {
 183                                list_del_init(&psta->auth_list);
 184                                pstapriv->auth_list_cnt--;
 185
 186                                spin_unlock_bh(&pstapriv->auth_list_lock);
 187
 188                                spin_lock_bh(&pstapriv->sta_hash_lock);
 189                                rtw_free_stainfo(padapter, psta);
 190                                spin_unlock_bh(&pstapriv->sta_hash_lock);
 191
 192                                spin_lock_bh(&pstapriv->auth_list_lock);
 193                        }
 194                }
 195        }
 196        spin_unlock_bh(&pstapriv->auth_list_lock);
 197
 198        psta = NULL;
 199
 200        spin_lock_bh(&pstapriv->asoc_list_lock);
 201
 202        phead = &pstapriv->asoc_list;
 203        /* check asoc_queue */
 204        list_for_each_entry_safe(psta, temp, phead, asoc_list) {
 205                if (chk_sta_is_alive(psta) || !psta->expire_to) {
 206                        psta->expire_to = pstapriv->expire_to;
 207                        psta->keep_alive_trycnt = 0;
 208                        psta->under_exist_checking = 0;
 209                } else {
 210                        psta->expire_to--;
 211                }
 212
 213                if (psta->expire_to <= 0) {
 214                        struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
 215
 216                        if (padapter->registrypriv.wifi_spec == 1) {
 217                                psta->expire_to = pstapriv->expire_to;
 218                                continue;
 219                        }
 220
 221                        if (psta->state & WIFI_SLEEP_STATE) {
 222                                if (!(psta->state & WIFI_STA_ALIVE_CHK_STATE)) {
 223                                        /* to check if alive by another methods
 224                                         * if station is at ps mode.
 225                                         */
 226                                        psta->expire_to = pstapriv->expire_to;
 227                                        psta->state |= WIFI_STA_ALIVE_CHK_STATE;
 228
 229                                        /* to update bcn with tim_bitmap
 230                                         * for this station
 231                                         */
 232                                        pstapriv->tim_bitmap |= BIT(psta->aid);
 233                                        update_beacon(padapter, WLAN_EID_TIM, NULL,
 234                                                      false);
 235
 236                                        if (!pmlmeext->active_keep_alive_check)
 237                                                continue;
 238                                }
 239                        }
 240                        if (pmlmeext->active_keep_alive_check) {
 241                                int stainfo_offset;
 242
 243                                stainfo_offset =
 244                                        rtw_stainfo_offset(pstapriv, psta);
 245                                if (stainfo_offset_valid(stainfo_offset))
 246                                        chk_alive_list[chk_alive_num++] =
 247                                                stainfo_offset;
 248                                continue;
 249                        }
 250
 251                        list_del_init(&psta->asoc_list);
 252                        pstapriv->asoc_list_cnt--;
 253
 254                        updated = ap_free_sta(padapter, psta, true,
 255                                              WLAN_REASON_DEAUTH_LEAVING);
 256                } else {
 257                        /* TODO: Aging mechanism to digest frames in sleep_q to avoid running out of xmitframe */
 258                        if (psta->sleepq_len > (NR_XMITFRAME / pstapriv->asoc_list_cnt) &&
 259                            padapter->xmitpriv.free_xmitframe_cnt < (NR_XMITFRAME / pstapriv->asoc_list_cnt / 2))
 260                                wakeup_sta_to_xmit(padapter, psta);
 261                }
 262        }
 263
 264        spin_unlock_bh(&pstapriv->asoc_list_lock);
 265
 266        if (chk_alive_num) {
 267                u8 backup_oper_channel = 0;
 268                struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
 269                /* switch to correct channel of current network  before issue keep-alive frames */
 270                if (rtw_get_oper_ch(padapter) != pmlmeext->cur_channel) {
 271                        backup_oper_channel = rtw_get_oper_ch(padapter);
 272                        SelectChannel(padapter, pmlmeext->cur_channel);
 273                }
 274
 275                /* issue null data to check sta alive*/
 276                for (i = 0; i < chk_alive_num; i++) {
 277                        int ret = _FAIL;
 278
 279                        psta = rtw_get_stainfo_by_offset(pstapriv,
 280                                                         chk_alive_list[i]);
 281
 282                        if (psta->state & WIFI_SLEEP_STATE) {
 283                                ret = issue_nulldata(padapter, psta->hwaddr,
 284                                                     0, 1, 50);
 285                        } else {
 286                                ret = issue_nulldata(padapter, psta->hwaddr,
 287                                                     0, 3, 50);
 288                        }
 289
 290                        psta->keep_alive_trycnt++;
 291                        if (ret == _SUCCESS) {
 292                                psta->expire_to = pstapriv->expire_to;
 293                                psta->keep_alive_trycnt = 0;
 294                                continue;
 295                        } else if (psta->keep_alive_trycnt <= 3) {
 296                                psta->expire_to = 1;
 297                                continue;
 298                        }
 299
 300                        psta->keep_alive_trycnt = 0;
 301
 302                        spin_lock_bh(&pstapriv->asoc_list_lock);
 303                        list_del_init(&psta->asoc_list);
 304                        pstapriv->asoc_list_cnt--;
 305                        updated = ap_free_sta(padapter, psta, true,
 306                                              WLAN_REASON_DEAUTH_LEAVING);
 307                        spin_unlock_bh(&pstapriv->asoc_list_lock);
 308                }
 309
 310                if (backup_oper_channel > 0) /* back to the original operation channel */
 311                        SelectChannel(padapter, backup_oper_channel);
 312        }
 313
 314        associated_clients_update(padapter, updated);
 315}
 316
 317void add_RATid(struct adapter *padapter, struct sta_info *psta, u8 rssi_level)
 318{
 319        int i;
 320        u32 init_rate = 0;
 321        unsigned char sta_band = 0, raid, shortGIrate = false;
 322        unsigned int tx_ra_bitmap = 0;
 323        struct ht_priv  *psta_ht = NULL;
 324
 325        if (psta)
 326                psta_ht = &psta->htpriv;
 327        else
 328                return;
 329
 330        if (!(psta->state & _FW_LINKED))
 331                return;
 332
 333        /* b/g mode ra_bitmap */
 334        for (i = 0; i < sizeof(psta->bssrateset); i++) {
 335                if (psta->bssrateset[i])
 336                        tx_ra_bitmap |= rtw_get_bit_value_from_ieee_value(psta->bssrateset[i] & 0x7f);
 337        }
 338        /* n mode ra_bitmap */
 339        if (psta_ht->ht_option) {
 340                for (i = 0; i < 8; i++)
 341                        if (psta_ht->ht_cap.mcs.rx_mask[0] & BIT(i))
 342                                tx_ra_bitmap |= BIT(i + 12);
 343
 344                /* max short GI rate */
 345                shortGIrate = psta_ht->sgi;
 346        }
 347
 348        if (tx_ra_bitmap & 0xffff000)
 349                sta_band |= WIRELESS_11_24N | WIRELESS_11G | WIRELESS_11B;
 350        else if (tx_ra_bitmap & 0xff0)
 351                sta_band |= WIRELESS_11G | WIRELESS_11B;
 352        else
 353                sta_band |= WIRELESS_11B;
 354
 355        psta->wireless_mode = sta_band;
 356
 357        raid = networktype_to_raid(sta_band);
 358        init_rate = get_highest_rate_idx(tx_ra_bitmap & 0x0fffffff) & 0x3f;
 359
 360        if (psta->aid < NUM_STA) {
 361                u8 arg = 0;
 362
 363                arg = psta->mac_id & 0x1f;
 364
 365                arg |= BIT(7);/* support entry 2~31 */
 366
 367                if (shortGIrate)
 368                        arg |= BIT(5);
 369
 370                tx_ra_bitmap |= ((raid << 28) & 0xf0000000);
 371
 372                /* bitmap[0:27] = tx_rate_bitmap */
 373                /* bitmap[28:31]= Rate Adaptive id */
 374                /* arg[0:4] = macid */
 375                /* arg[5] = Short GI */
 376                rtw_hal_add_ra_tid(padapter, tx_ra_bitmap, arg, rssi_level);
 377
 378                if (shortGIrate)
 379                        init_rate |= BIT(6);
 380
 381                /* set ra_id, init_rate */
 382                psta->raid = raid;
 383                psta->init_rate = init_rate;
 384
 385        }
 386}
 387
 388static void update_bmc_sta(struct adapter *padapter)
 389{
 390        u32 init_rate = 0;
 391        unsigned char   network_type, raid;
 392        int i, supportRateNum = 0;
 393        unsigned int tx_ra_bitmap = 0;
 394        struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
 395        struct wlan_bssid_ex *pcur_network = &pmlmepriv->cur_network.network;
 396        struct sta_info *psta = rtw_get_bcmc_stainfo(padapter);
 397
 398        if (psta) {
 399                psta->aid = 0;/* default set to 0 */
 400                psta->mac_id = psta->aid + 1;
 401
 402                psta->qos_option = 0;
 403                psta->htpriv.ht_option = false;
 404
 405                psta->ieee8021x_blocked = 0;
 406
 407                memset(&psta->sta_stats, 0, sizeof(struct stainfo_stats));
 408
 409                /* prepare for add_RATid */
 410                supportRateNum = rtw_get_rateset_len((u8 *)&pcur_network->SupportedRates);
 411                network_type = rtw_check_network_type((u8 *)&pcur_network->SupportedRates);
 412
 413                memcpy(psta->bssrateset, &pcur_network->SupportedRates,
 414                       supportRateNum);
 415                psta->bssratelen = supportRateNum;
 416
 417                /* b/g mode ra_bitmap */
 418                for (i = 0; i < supportRateNum; i++) {
 419                        if (psta->bssrateset[i])
 420                                tx_ra_bitmap |= rtw_get_bit_value_from_ieee_value(psta->bssrateset[i] & 0x7f);
 421                }
 422
 423                /* force to b mode */
 424                network_type = WIRELESS_11B;
 425                tx_ra_bitmap = 0xf;
 426
 427                raid = networktype_to_raid(network_type);
 428                init_rate = get_highest_rate_idx(tx_ra_bitmap & 0x0fffffff) &
 429                            0x3f;
 430
 431                /* ap mode */
 432                rtw_hal_set_odm_var(padapter, HAL_ODM_STA_INFO, psta, true);
 433
 434                {
 435                        u8 arg = 0;
 436
 437                        arg = psta->mac_id & 0x1f;
 438                        arg |= BIT(7);
 439                        tx_ra_bitmap |= ((raid << 28) & 0xf0000000);
 440
 441                        /* bitmap[0:27] = tx_rate_bitmap */
 442                        /* bitmap[28:31]= Rate Adaptive id */
 443                        /* arg[0:4] = macid */
 444                        /* arg[5] = Short GI */
 445                        rtw_hal_add_ra_tid(padapter, tx_ra_bitmap, arg, 0);
 446                }
 447                /* set ra_id, init_rate */
 448                psta->raid = raid;
 449                psta->init_rate = init_rate;
 450
 451                rtw_stassoc_hw_rpt(padapter, psta);
 452
 453                spin_lock_bh(&psta->lock);
 454                psta->state = _FW_LINKED;
 455                spin_unlock_bh(&psta->lock);
 456
 457        }
 458}
 459
 460/* notes: */
 461/* AID: 1~MAX for sta and 0 for bc/mc in ap/adhoc mode */
 462/* MAC_ID = AID+1 for sta in ap/adhoc mode */
 463/* MAC_ID = 1 for bc/mc for sta/ap/adhoc */
 464/* MAC_ID = 0 for bssid for sta/ap/adhoc */
 465/* CAM_ID = 0~3 for default key, cmd_id = macid + 3, macid = aid+1; */
 466
 467void update_sta_info_apmode(struct adapter *padapter, struct sta_info *psta)
 468{
 469        struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
 470        struct security_priv *psecuritypriv = &padapter->securitypriv;
 471        struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
 472        struct ht_priv  *phtpriv_ap = &pmlmepriv->htpriv;
 473        struct ht_priv  *phtpriv_sta = &psta->htpriv;
 474
 475        psta->mac_id = psta->aid + 1;
 476
 477        /* ap mode */
 478        rtw_hal_set_odm_var(padapter, HAL_ODM_STA_INFO, psta, true);
 479
 480        if (psecuritypriv->dot11AuthAlgrthm == dot11AuthAlgrthm_8021X)
 481                psta->ieee8021x_blocked = true;
 482        else
 483                psta->ieee8021x_blocked = false;
 484
 485        /* update sta's cap */
 486
 487        /* ERP */
 488        VCS_update(padapter, psta);
 489        /* HT related cap */
 490        if (phtpriv_sta->ht_option) {
 491                /* check if sta supports rx ampdu */
 492                phtpriv_sta->ampdu_enable = phtpriv_ap->ampdu_enable;
 493
 494                /* check if sta support s Short GI */
 495                if (le16_to_cpu(phtpriv_sta->ht_cap.cap_info &
 496                                phtpriv_ap->ht_cap.cap_info) &
 497                    (IEEE80211_HT_CAP_SGI_20 | IEEE80211_HT_CAP_SGI_40))
 498                        phtpriv_sta->sgi = true;
 499
 500                /*  bwmode */
 501                if (le16_to_cpu(phtpriv_sta->ht_cap.cap_info &
 502                                phtpriv_ap->ht_cap.cap_info) &
 503                    IEEE80211_HT_CAP_SUP_WIDTH_20_40) {
 504                        phtpriv_sta->bwmode = pmlmeext->cur_bwmode;
 505                        phtpriv_sta->ch_offset = pmlmeext->cur_ch_offset;
 506                }
 507                psta->qos_option = true;
 508        } else {
 509                phtpriv_sta->ampdu_enable = false;
 510                phtpriv_sta->sgi = false;
 511                phtpriv_sta->bwmode = HT_CHANNEL_WIDTH_20;
 512                phtpriv_sta->ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
 513        }
 514
 515        /* Rx AMPDU */
 516        send_delba(padapter, 0, psta->hwaddr);/*  recipient */
 517
 518        /* TX AMPDU */
 519        send_delba(padapter, 1, psta->hwaddr);/* originator */
 520        phtpriv_sta->agg_enable_bitmap = 0x0;/* reset */
 521        phtpriv_sta->candidate_tid_bitmap = 0x0;/* reset */
 522
 523        /* todo: init other variables */
 524
 525        memset(&psta->sta_stats, 0, sizeof(struct stainfo_stats));
 526
 527        spin_lock_bh(&psta->lock);
 528        psta->state |= _FW_LINKED;
 529        spin_unlock_bh(&psta->lock);
 530}
 531
 532static void update_hw_ht_param(struct adapter *padapter)
 533{
 534        u8 max_ampdu_len;
 535        u8 min_mpdu_spacing;
 536        struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
 537        struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
 538
 539        /* handle A-MPDU parameter field
 540         * ampdu_params_info [1:0]:Max AMPDU Len => 0:8k , 1:16k, 2:32k, 3:64k
 541         * ampdu_params_info [4:2]:Min MPDU Start Spacing
 542         */
 543        max_ampdu_len = pmlmeinfo->HT_caps.ampdu_params_info & 0x03;
 544        min_mpdu_spacing = (pmlmeinfo->HT_caps.ampdu_params_info & 0x1c) >> 2;
 545
 546        rtw_hal_set_hwreg(padapter, HW_VAR_AMPDU_MIN_SPACE, &min_mpdu_spacing);
 547        rtw_hal_set_hwreg(padapter, HW_VAR_AMPDU_FACTOR, &max_ampdu_len);
 548
 549        /* Config SM Power Save setting */
 550        pmlmeinfo->SM_PS = (le16_to_cpu(pmlmeinfo->HT_caps.cap_info) & 0x0C) >> 2;
 551}
 552
 553static void start_bss_network(struct adapter *padapter, u8 *pbuf)
 554{
 555        u8 *p;
 556        u8 val8, cur_channel, cur_bwmode, cur_ch_offset;
 557        u16 bcn_interval;
 558        u32     acparm;
 559        uint    ie_len;
 560        struct registry_priv     *pregpriv = &padapter->registrypriv;
 561        struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
 562        struct security_priv *psecuritypriv = &padapter->securitypriv;
 563        struct wlan_bssid_ex *pnetwork = &pmlmepriv->cur_network.network;
 564        struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
 565        struct mlme_ext_info    *pmlmeinfo = &pmlmeext->mlmext_info;
 566        struct wlan_bssid_ex *pnetwork_mlmeext = &pmlmeinfo->network;
 567        struct HT_info_element *pht_info = NULL;
 568
 569        bcn_interval = (u16)pnetwork->Configuration.BeaconPeriod;
 570        cur_channel = pnetwork->Configuration.DSConfig;
 571        cur_bwmode = HT_CHANNEL_WIDTH_20;
 572        cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
 573
 574        /* check if there is wps ie,
 575         * if there is wpsie in beacon, the hostapd will update
 576         * beacon twice when stating hostapd, and at first time the
 577         * security ie (RSN/WPA IE) will not include in beacon.
 578         */
 579        if (!rtw_get_wps_ie(pnetwork->ies + _FIXED_IE_LENGTH_, pnetwork->ie_length - _FIXED_IE_LENGTH_, NULL, NULL))
 580                pmlmeext->bstart_bss = true;
 581
 582        /* todo: update wmm, ht cap */
 583        if (pmlmepriv->qospriv.qos_option)
 584                pmlmeinfo->WMM_enable = true;
 585        if (pmlmepriv->htpriv.ht_option) {
 586                pmlmeinfo->WMM_enable = true;
 587                pmlmeinfo->HT_enable = true;
 588
 589                update_hw_ht_param(padapter);
 590        }
 591
 592        /* setting only at  first time */
 593        if (!pmlmepriv->cur_network.join_res) {
 594                /* WEP Key will be set before this function, do not
 595                 * clear CAM.
 596                 */
 597                if ((psecuritypriv->dot11PrivacyAlgrthm != _WEP40_) &&
 598                    (psecuritypriv->dot11PrivacyAlgrthm != _WEP104_))
 599                        flush_all_cam_entry(padapter);  /* clear CAM */
 600        }
 601
 602        /* set MSR to AP_Mode */
 603        Set_MSR(padapter, _HW_STATE_AP_);
 604
 605        /* Set BSSID REG */
 606        rtw_hal_set_hwreg(padapter, HW_VAR_BSSID, pnetwork->MacAddress);
 607
 608        /* Set EDCA param reg */
 609        acparm = 0x002F3217; /*  VO */
 610        rtw_hal_set_hwreg(padapter, HW_VAR_AC_PARAM_VO, (u8 *)(&acparm));
 611        acparm = 0x005E4317; /*  VI */
 612        rtw_hal_set_hwreg(padapter, HW_VAR_AC_PARAM_VI, (u8 *)(&acparm));
 613        acparm = 0x005ea42b;
 614        rtw_hal_set_hwreg(padapter, HW_VAR_AC_PARAM_BE, (u8 *)(&acparm));
 615        acparm = 0x0000A444; /*  BK */
 616        rtw_hal_set_hwreg(padapter, HW_VAR_AC_PARAM_BK, (u8 *)(&acparm));
 617
 618        /* Set Security */
 619        val8 = (psecuritypriv->dot11AuthAlgrthm == dot11AuthAlgrthm_8021X) ? 0xcc : 0xcf;
 620        rtw_hal_set_hwreg(padapter, HW_VAR_SEC_CFG, (u8 *)(&val8));
 621
 622        /* Beacon Control related register */
 623        rtw_hal_set_hwreg(padapter, HW_VAR_BEACON_INTERVAL,
 624                          (u8 *)(&bcn_interval));
 625
 626        UpdateBrateTbl(padapter, pnetwork->SupportedRates);
 627        rtw_hal_set_hwreg(padapter, HW_VAR_BASIC_RATE, pnetwork->SupportedRates);
 628
 629        if (!pmlmepriv->cur_network.join_res) { /* setting only at  first time */
 630                /* turn on all dynamic functions */
 631                Switch_DM_Func(padapter, DYNAMIC_ALL_FUNC_ENABLE, true);
 632        }
 633        /* set channel, bwmode */
 634        p = rtw_get_ie(pnetwork->ies + sizeof(struct ndis_802_11_fixed_ie),
 635                        WLAN_EID_HT_OPERATION, &ie_len,
 636                       pnetwork->ie_length -
 637                       sizeof(struct ndis_802_11_fixed_ie));
 638        if (p && ie_len) {
 639                pht_info = (struct HT_info_element *)(p + 2);
 640
 641                if ((pregpriv->cbw40_enable) &&  (pht_info->infos[0] & BIT(2))) {
 642                        /* switch to the 40M Hz mode */
 643                        cur_bwmode = HT_CHANNEL_WIDTH_40;
 644                        switch (pht_info->infos[0] & 0x3) {
 645                        case 1:
 646                                cur_ch_offset = HAL_PRIME_CHNL_OFFSET_LOWER;
 647                                break;
 648                        case 3:
 649                                cur_ch_offset = HAL_PRIME_CHNL_OFFSET_UPPER;
 650                                break;
 651                        default:
 652                                cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
 653                                break;
 654                        }
 655                }
 656        }
 657        /* TODO: need to judge the phy parameters on concurrent
 658         * mode for single phy
 659         */
 660        set_channel_bwmode(padapter, cur_channel, cur_ch_offset, cur_bwmode);
 661
 662        /*  */
 663        pmlmeext->cur_channel = cur_channel;
 664        pmlmeext->cur_bwmode = cur_bwmode;
 665        pmlmeext->cur_ch_offset = cur_ch_offset;
 666        pmlmeext->cur_wireless_mode = pmlmepriv->cur_network.network_type;
 667
 668        /* update cur_wireless_mode */
 669        update_wireless_mode(padapter);
 670
 671        /* update capability after cur_wireless_mode updated */
 672        update_capinfo(padapter, rtw_get_capability(pnetwork));
 673
 674        /* let pnetwork_mlmeext == pnetwork_mlme. */
 675        memcpy(pnetwork_mlmeext, pnetwork, pnetwork->Length);
 676
 677        if (pmlmeext->bstart_bss) {
 678                update_beacon(padapter, WLAN_EID_TIM, NULL, false);
 679
 680                /* issue beacon frame */
 681                send_beacon(padapter);
 682        }
 683
 684        /* update bc/mc sta_info */
 685        update_bmc_sta(padapter);
 686}
 687
 688int rtw_check_beacon_data(struct adapter *padapter, u8 *pbuf,  int len)
 689{
 690        int ret = _SUCCESS;
 691        u8 *p;
 692        u8 *pHT_caps_ie = NULL;
 693        u8 *pHT_info_ie = NULL;
 694        struct sta_info *psta = NULL;
 695        u16 cap, ht_cap = false;
 696        uint ie_len = 0;
 697        int group_cipher, pairwise_cipher;
 698        u8      channel, network_type, supportRate[NDIS_802_11_LENGTH_RATES_EX];
 699        int supportRateNum = 0;
 700        u8 OUI1[] = {0x00, 0x50, 0xf2, 0x01};
 701        u8 WMM_PARA_IE[] = {0x00, 0x50, 0xf2, 0x02, 0x01, 0x01};
 702        struct registry_priv *pregistrypriv = &padapter->registrypriv;
 703        struct security_priv *psecuritypriv = &padapter->securitypriv;
 704        struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
 705        struct wlan_bssid_ex *pbss_network = &pmlmepriv->cur_network.network;
 706        u8 *ie = pbss_network->ies;
 707
 708        /* SSID */
 709        /* Supported rates */
 710        /* DS Params */
 711        /* WLAN_EID_COUNTRY */
 712        /* ERP Information element */
 713        /* Extended supported rates */
 714        /* WPA/WPA2 */
 715        /* Wi-Fi Wireless Multimedia Extensions */
 716        /* ht_capab, ht_oper */
 717        /* WPS IE */
 718
 719        if (!check_fwstate(pmlmepriv, WIFI_AP_STATE))
 720                return _FAIL;
 721
 722        if (len < 0 || len > MAX_IE_SZ)
 723                return _FAIL;
 724
 725        pbss_network->ie_length = len;
 726
 727        memset(ie, 0, MAX_IE_SZ);
 728
 729        memcpy(ie, pbuf, pbss_network->ie_length);
 730
 731        if (pbss_network->InfrastructureMode != Ndis802_11APMode)
 732                return _FAIL;
 733
 734        pbss_network->Rssi = 0;
 735
 736        ether_addr_copy(pbss_network->MacAddress, myid(&padapter->eeprompriv));
 737
 738        /* beacon interval */
 739        p = rtw_get_beacon_interval_from_ie(ie);/* 8: TimeStamp, 2: Beacon Interval 2:Capability */
 740        pbss_network->Configuration.BeaconPeriod = get_unaligned_le16(p);
 741
 742        /* capability */
 743        cap = get_unaligned_le16(ie);
 744
 745        /* SSID */
 746        p = rtw_get_ie(ie + _BEACON_IE_OFFSET_, WLAN_EID_SSID, &ie_len,
 747                       pbss_network->ie_length - _BEACON_IE_OFFSET_);
 748        if (p && ie_len > 0) {
 749                ie_len = min_t(int, ie_len, sizeof(pbss_network->ssid.ssid));
 750                memset(&pbss_network->ssid, 0, sizeof(struct ndis_802_11_ssid));
 751                memcpy(pbss_network->ssid.ssid, p + 2, ie_len);
 752                pbss_network->ssid.ssid_length = ie_len;
 753        }
 754
 755        /* channel */
 756        channel = 0;
 757        pbss_network->Configuration.Length = 0;
 758        p = rtw_get_ie(ie + _BEACON_IE_OFFSET_, WLAN_EID_DS_PARAMS, &ie_len,
 759                       (pbss_network->ie_length - _BEACON_IE_OFFSET_));
 760        if (p && ie_len > 0)
 761                channel = *(p + 2);
 762
 763        pbss_network->Configuration.DSConfig = channel;
 764
 765        memset(supportRate, 0, NDIS_802_11_LENGTH_RATES_EX);
 766        /*  get supported rates */
 767        p = rtw_get_ie(ie + _BEACON_IE_OFFSET_, WLAN_EID_SUPP_RATES, &ie_len,
 768                       pbss_network->ie_length - _BEACON_IE_OFFSET_);
 769        if (p) {
 770                ie_len = min_t(int, ie_len, NDIS_802_11_LENGTH_RATES_EX);
 771                memcpy(supportRate, p + 2, ie_len);
 772                supportRateNum = ie_len;
 773        }
 774
 775        /* get ext_supported rates */
 776        p = rtw_get_ie(ie + _BEACON_IE_OFFSET_, WLAN_EID_EXT_SUPP_RATES,
 777                       &ie_len, pbss_network->ie_length - _BEACON_IE_OFFSET_);
 778        if (p) {
 779                ie_len = min_t(int, ie_len,
 780                               NDIS_802_11_LENGTH_RATES_EX - supportRateNum);
 781                memcpy(supportRate + supportRateNum, p + 2, ie_len);
 782                supportRateNum += ie_len;
 783        }
 784
 785        network_type = rtw_check_network_type(supportRate);
 786
 787        rtw_set_supported_rate(pbss_network->SupportedRates, network_type);
 788
 789        /* parsing ERP_IE */
 790        p = rtw_get_ie(ie + _BEACON_IE_OFFSET_, WLAN_EID_ERP_INFO, &ie_len,
 791                       pbss_network->ie_length - _BEACON_IE_OFFSET_);
 792        if (p && ie_len > 0)
 793                ERP_IE_handler(padapter, (struct ndis_802_11_var_ie *)p);
 794
 795        /* update privacy/security */
 796        if (cap & BIT(4))
 797                pbss_network->Privacy = 1;
 798        else
 799                pbss_network->Privacy = 0;
 800
 801        psecuritypriv->wpa_psk = 0;
 802
 803        /* wpa2 */
 804        group_cipher = 0;
 805        pairwise_cipher = 0;
 806        psecuritypriv->wpa2_group_cipher = _NO_PRIVACY_;
 807        psecuritypriv->wpa2_pairwise_cipher = _NO_PRIVACY_;
 808        p = rtw_get_ie(ie + _BEACON_IE_OFFSET_, WLAN_EID_RSN, &ie_len,
 809                       pbss_network->ie_length - _BEACON_IE_OFFSET_);
 810        if (p && ie_len > 0) {
 811                if (rtw_parse_wpa2_ie(p, ie_len + 2, &group_cipher, &pairwise_cipher, NULL) == _SUCCESS) {
 812                        psecuritypriv->dot11AuthAlgrthm = dot11AuthAlgrthm_8021X;
 813
 814                        psecuritypriv->dot8021xalg = 1;/* psk,  todo:802.1x */
 815                        psecuritypriv->wpa_psk |= BIT(1);
 816
 817                        psecuritypriv->wpa2_group_cipher = group_cipher;
 818                        psecuritypriv->wpa2_pairwise_cipher = pairwise_cipher;
 819                }
 820        }
 821        /* wpa */
 822        ie_len = 0;
 823        group_cipher = 0;
 824        pairwise_cipher = 0;
 825        psecuritypriv->wpa_group_cipher = _NO_PRIVACY_;
 826        psecuritypriv->wpa_pairwise_cipher = _NO_PRIVACY_;
 827        for (p = ie + _BEACON_IE_OFFSET_;; p += (ie_len + 2)) {
 828                p = rtw_get_ie(p, WLAN_EID_VENDOR_SPECIFIC, &ie_len,
 829                               pbss_network->ie_length - _BEACON_IE_OFFSET_ - (ie_len + 2));
 830                if ((p) && (!memcmp(p + 2, OUI1, 4))) {
 831                        if (rtw_parse_wpa_ie(p, ie_len + 2, &group_cipher,
 832                                             &pairwise_cipher, NULL) == _SUCCESS) {
 833                                psecuritypriv->dot11AuthAlgrthm = dot11AuthAlgrthm_8021X;
 834
 835                                psecuritypriv->dot8021xalg = 1;/* psk,  todo:802.1x */
 836
 837                                psecuritypriv->wpa_psk |= BIT(0);
 838
 839                                psecuritypriv->wpa_group_cipher = group_cipher;
 840                                psecuritypriv->wpa_pairwise_cipher = pairwise_cipher;
 841                        }
 842                        break;
 843                }
 844                if ((!p) || (ie_len == 0))
 845                        break;
 846        }
 847
 848        /* wmm */
 849        ie_len = 0;
 850        pmlmepriv->qospriv.qos_option = 0;
 851        if (pregistrypriv->wmm_enable) {
 852                for (p = ie + _BEACON_IE_OFFSET_;; p += (ie_len + 2)) {
 853                        p = rtw_get_ie(p, WLAN_EID_VENDOR_SPECIFIC, &ie_len,
 854                                       pbss_network->ie_length - _BEACON_IE_OFFSET_ - (ie_len + 2));
 855                        if ((p) && !memcmp(p + 2, WMM_PARA_IE, 6)) {
 856                                pmlmepriv->qospriv.qos_option = 1;
 857
 858                                /* QoS Info, support U-APSD */
 859                                *(p + 8) |= BIT(7);
 860
 861                                /* disable all ACM bits since the WMM
 862                                 * admission control is not supported
 863                                 */
 864                                *(p + 10) &= ~BIT(4); /* BE */
 865                                *(p + 14) &= ~BIT(4); /* BK */
 866                                *(p + 18) &= ~BIT(4); /* VI */
 867                                *(p + 22) &= ~BIT(4); /* VO */
 868                                break;
 869                        }
 870
 871                        if ((!p) || (ie_len == 0))
 872                                break;
 873                }
 874        }
 875        /* parsing HT_CAP_IE */
 876        p = rtw_get_ie(ie + _BEACON_IE_OFFSET_, WLAN_EID_HT_CAPABILITY, &ie_len,
 877                       pbss_network->ie_length - _BEACON_IE_OFFSET_);
 878        if (p && ie_len > 0) {
 879                struct ieee80211_ht_cap *pht_cap = (struct ieee80211_ht_cap *)(p + 2);
 880
 881                pHT_caps_ie = p;
 882                ht_cap = true;
 883                network_type |= WIRELESS_11_24N;
 884
 885                if ((psecuritypriv->wpa_pairwise_cipher & WPA_CIPHER_CCMP) ||
 886                    (psecuritypriv->wpa2_pairwise_cipher & WPA_CIPHER_CCMP))
 887                        pht_cap->ampdu_params_info |= (IEEE80211_HT_AMPDU_PARM_DENSITY & (0x07 << 2));
 888                else
 889                        pht_cap->ampdu_params_info |= (IEEE80211_HT_AMPDU_PARM_DENSITY & 0x00);
 890
 891                /* set  Max Rx AMPDU size  to 64K */
 892                pht_cap->ampdu_params_info |= (IEEE80211_HT_AMPDU_PARM_FACTOR & 0x03);
 893
 894                pht_cap->mcs.rx_mask[0] = 0xff;
 895                pht_cap->mcs.rx_mask[1] = 0x0;
 896                ie_len = min_t(int, ie_len, sizeof(pmlmepriv->htpriv.ht_cap));
 897                memcpy(&pmlmepriv->htpriv.ht_cap, p + 2, ie_len);
 898        }
 899
 900        /* parsing HT_INFO_IE */
 901        p = rtw_get_ie(ie + _BEACON_IE_OFFSET_, WLAN_EID_HT_OPERATION, &ie_len,
 902                       pbss_network->ie_length - _BEACON_IE_OFFSET_);
 903        if (p && ie_len > 0)
 904                pHT_info_ie = p;
 905        switch (network_type) {
 906        case WIRELESS_11B:
 907                pbss_network->NetworkTypeInUse = Ndis802_11DS;
 908                break;
 909        case WIRELESS_11G:
 910        case WIRELESS_11BG:
 911        case WIRELESS_11G_24N:
 912        case WIRELESS_11BG_24N:
 913                pbss_network->NetworkTypeInUse = Ndis802_11OFDM24;
 914                break;
 915        case WIRELESS_11A:
 916                pbss_network->NetworkTypeInUse = Ndis802_11OFDM5;
 917                break;
 918        default:
 919                pbss_network->NetworkTypeInUse = Ndis802_11OFDM24;
 920                break;
 921        }
 922
 923        pmlmepriv->cur_network.network_type = network_type;
 924
 925        pmlmepriv->htpriv.ht_option = false;
 926
 927        if ((psecuritypriv->wpa2_pairwise_cipher & WPA_CIPHER_TKIP) ||
 928            (psecuritypriv->wpa_pairwise_cipher & WPA_CIPHER_TKIP)) {
 929                /* todo: */
 930                /* ht_cap = false; */
 931        }
 932
 933        /* ht_cap */
 934        if (pregistrypriv->ht_enable && ht_cap) {
 935                pmlmepriv->htpriv.ht_option = true;
 936                pmlmepriv->qospriv.qos_option = 1;
 937
 938                if (pregistrypriv->ampdu_enable == 1)
 939                        pmlmepriv->htpriv.ampdu_enable = true;
 940                HT_caps_handler(padapter, (struct ndis_802_11_var_ie *)pHT_caps_ie);
 941
 942                HT_info_handler(padapter, (struct ndis_802_11_var_ie *)pHT_info_ie);
 943        }
 944
 945        pbss_network->Length = get_wlan_bssid_ex_sz(pbss_network);
 946
 947        /* issue beacon to start bss network */
 948        start_bss_network(padapter, (u8 *)pbss_network);
 949
 950        /* alloc sta_info for ap itself */
 951        psta = rtw_get_stainfo(&padapter->stapriv, pbss_network->MacAddress);
 952        if (!psta) {
 953                psta = rtw_alloc_stainfo(&padapter->stapriv, pbss_network->MacAddress);
 954                if (!psta)
 955                        return _FAIL;
 956        }
 957
 958        /* fix bug of flush_cam_entry at STOP AP mode */
 959        psta->state |= WIFI_AP_STATE;
 960        rtw_indicate_connect(padapter);
 961        pmlmepriv->cur_network.join_res = true;/* for check if already set beacon */
 962        return ret;
 963}
 964
 965void rtw_set_macaddr_acl(struct adapter *padapter, int mode)
 966{
 967        struct sta_priv *pstapriv = &padapter->stapriv;
 968        struct wlan_acl_pool *pacl_list = &pstapriv->acl_list;
 969
 970        pacl_list->mode = mode;
 971}
 972
 973int rtw_acl_add_sta(struct adapter *padapter, u8 *addr)
 974{
 975        struct list_head *plist, *phead;
 976        u8 added = false;
 977        int i, ret = 0;
 978        struct rtw_wlan_acl_node *paclnode;
 979        struct sta_priv *pstapriv = &padapter->stapriv;
 980        struct wlan_acl_pool *pacl_list = &pstapriv->acl_list;
 981        struct __queue *pacl_node_q = &pacl_list->acl_node_q;
 982
 983        if ((NUM_ACL - 1) < pacl_list->num)
 984                return -1;
 985
 986        spin_lock_bh(&pacl_node_q->lock);
 987
 988        phead = get_list_head(pacl_node_q);
 989        list_for_each(plist, phead) {
 990                paclnode = list_entry(plist, struct rtw_wlan_acl_node, list);
 991
 992                if (!memcmp(paclnode->addr, addr, ETH_ALEN)) {
 993                        if (paclnode->valid) {
 994                                added = true;
 995                                break;
 996                        }
 997                }
 998        }
 999
1000        spin_unlock_bh(&pacl_node_q->lock);
1001
1002        if (added)
1003                return ret;
1004
1005        spin_lock_bh(&pacl_node_q->lock);
1006
1007        for (i = 0; i < NUM_ACL; i++) {
1008                paclnode = &pacl_list->aclnode[i];
1009
1010                if (!paclnode->valid) {
1011                        INIT_LIST_HEAD(&paclnode->list);
1012
1013                        ether_addr_copy(paclnode->addr, addr);
1014
1015                        paclnode->valid = true;
1016
1017                        list_add_tail(&paclnode->list, get_list_head(pacl_node_q));
1018
1019                        pacl_list->num++;
1020
1021                        break;
1022                }
1023        }
1024
1025        spin_unlock_bh(&pacl_node_q->lock);
1026
1027        return ret;
1028}
1029
1030int rtw_acl_remove_sta(struct adapter *padapter, u8 *addr)
1031{
1032        struct list_head *phead;
1033        struct rtw_wlan_acl_node *paclnode, *temp;
1034        struct sta_priv *pstapriv = &padapter->stapriv;
1035        struct wlan_acl_pool *pacl_list = &pstapriv->acl_list;
1036        struct __queue *pacl_node_q = &pacl_list->acl_node_q;
1037
1038        spin_lock_bh(&pacl_node_q->lock);
1039
1040        phead = get_list_head(pacl_node_q);
1041        list_for_each_entry_safe(paclnode, temp, phead, list) {
1042                if (!memcmp(paclnode->addr, addr, ETH_ALEN)) {
1043                        if (paclnode->valid) {
1044                                paclnode->valid = false;
1045
1046                                list_del_init(&paclnode->list);
1047
1048                                pacl_list->num--;
1049                        }
1050                }
1051        }
1052
1053        spin_unlock_bh(&pacl_node_q->lock);
1054
1055        return 0;
1056}
1057
1058static void update_bcn_erpinfo_ie(struct adapter *padapter)
1059{
1060        struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1061        struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
1062        struct mlme_ext_info    *pmlmeinfo = &pmlmeext->mlmext_info;
1063        struct wlan_bssid_ex *pnetwork = &pmlmeinfo->network;
1064        unsigned char *p, *ie = pnetwork->ies;
1065        u32 len = 0;
1066
1067        if (!pmlmeinfo->ERP_enable)
1068                return;
1069
1070        /* parsing ERP_IE */
1071        p = rtw_get_ie(ie + _BEACON_IE_OFFSET_, WLAN_EID_ERP_INFO, &len,
1072                       (pnetwork->ie_length - _BEACON_IE_OFFSET_));
1073        if (p && len > 0) {
1074                struct ndis_802_11_var_ie *pIE = (struct ndis_802_11_var_ie *)p;
1075
1076                if (pmlmepriv->num_sta_non_erp == 1)
1077                        pIE->data[0] |= RTW_ERP_INFO_NON_ERP_PRESENT |
1078                                        RTW_ERP_INFO_USE_PROTECTION;
1079                else
1080                        pIE->data[0] &= ~(RTW_ERP_INFO_NON_ERP_PRESENT |
1081                                          RTW_ERP_INFO_USE_PROTECTION);
1082
1083                if (pmlmepriv->num_sta_no_short_preamble > 0)
1084                        pIE->data[0] |= RTW_ERP_INFO_BARKER_PREAMBLE_MODE;
1085                else
1086                        pIE->data[0] &= ~(RTW_ERP_INFO_BARKER_PREAMBLE_MODE);
1087
1088                ERP_IE_handler(padapter, pIE);
1089        }
1090}
1091
1092static void update_bcn_wps_ie(struct adapter *padapter)
1093{
1094        u8 *pwps_ie = NULL, *pwps_ie_src;
1095        u8 *premainder_ie, *pbackup_remainder_ie = NULL;
1096        uint wps_ielen = 0, wps_offset, remainder_ielen;
1097        struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1098        struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
1099        struct mlme_ext_info    *pmlmeinfo = &pmlmeext->mlmext_info;
1100        struct wlan_bssid_ex *pnetwork = &pmlmeinfo->network;
1101        unsigned char *ie = pnetwork->ies;
1102        u32 ielen = pnetwork->ie_length;
1103
1104        pwps_ie_src = pmlmepriv->wps_beacon_ie;
1105        if (!pwps_ie_src)
1106                return;
1107
1108        pwps_ie = rtw_get_wps_ie(ie + _FIXED_IE_LENGTH_,
1109                                 ielen - _FIXED_IE_LENGTH_, NULL, &wps_ielen);
1110
1111        if (!pwps_ie || wps_ielen == 0)
1112                return;
1113
1114        wps_offset = (uint)(pwps_ie - ie);
1115
1116        premainder_ie = pwps_ie + wps_ielen;
1117
1118        remainder_ielen = ielen - wps_offset - wps_ielen;
1119
1120        if (remainder_ielen > 0) {
1121                pbackup_remainder_ie = rtw_malloc(remainder_ielen);
1122                if (pbackup_remainder_ie)
1123                        memcpy(pbackup_remainder_ie, premainder_ie, remainder_ielen);
1124        }
1125
1126        wps_ielen = (uint)pwps_ie_src[1];/* to get ie data len */
1127        if (wps_offset + wps_ielen + 2 + remainder_ielen <= MAX_IE_SZ) {
1128                memcpy(pwps_ie, pwps_ie_src, wps_ielen + 2);
1129                pwps_ie += wps_ielen + 2;
1130
1131                if (pbackup_remainder_ie)
1132                        memcpy(pwps_ie, pbackup_remainder_ie, remainder_ielen);
1133
1134                /* update ie_length */
1135                pnetwork->ie_length = wps_offset + wps_ielen + 2 + remainder_ielen;
1136        }
1137
1138        kfree(pbackup_remainder_ie);
1139}
1140
1141static void update_bcn_vendor_spec_ie(struct adapter *padapter, u8 *oui)
1142{
1143
1144        if (!memcmp(WPS_OUI, oui, 4))
1145                update_bcn_wps_ie(padapter);
1146}
1147
1148void update_beacon(struct adapter *padapter, u8 ie_id, u8 *oui, u8 tx)
1149{
1150        struct mlme_priv *pmlmepriv;
1151        struct mlme_ext_priv    *pmlmeext;
1152
1153        if (!padapter)
1154                return;
1155
1156        pmlmepriv = &padapter->mlmepriv;
1157        pmlmeext = &padapter->mlmeextpriv;
1158
1159        if (!pmlmeext->bstart_bss)
1160                return;
1161
1162        spin_lock_bh(&pmlmepriv->bcn_update_lock);
1163
1164        switch (ie_id) {
1165        case WLAN_EID_TIM:
1166                update_BCNTIM(padapter);
1167                break;
1168        case WLAN_EID_ERP_INFO:
1169                update_bcn_erpinfo_ie(padapter);
1170                break;
1171        case WLAN_EID_VENDOR_SPECIFIC:
1172                update_bcn_vendor_spec_ie(padapter, oui);
1173                break;
1174        default:
1175                break;
1176        }
1177
1178        pmlmepriv->update_bcn = true;
1179
1180        spin_unlock_bh(&pmlmepriv->bcn_update_lock);
1181
1182        if (tx)
1183                set_tx_beacon_cmd(padapter);
1184}
1185
1186/*
1187 * op_mode
1188 * Set to 0 (HT pure) under the following conditions
1189 *      - all STAs in the BSS are 20/40 MHz HT in 20/40 MHz BSS or
1190 *      - all STAs in the BSS are 20 MHz HT in 20 MHz BSS
1191 * Set to 1 (HT non-member protection) if there may be non-HT STAs
1192 *        in both the primary and the secondary channel
1193 * Set to 2 if only HT STAs are associated in BSS,
1194 *        however and at least one 20 MHz HT STA is associated
1195 * Set to 3 (HT mixed mode) when one or more non-HT STAs are associated
1196 *        (currently non-GF HT station is considered as non-HT STA also)
1197 */
1198static int rtw_ht_operation_update(struct adapter *padapter)
1199{
1200        u16 cur_op_mode, new_op_mode;
1201        int op_mode_changes = 0;
1202        struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1203        struct ht_priv  *phtpriv_ap = &pmlmepriv->htpriv;
1204
1205        if (pmlmepriv->htpriv.ht_option)
1206                return 0;
1207
1208        if (!(pmlmepriv->ht_op_mode & HT_INFO_OPERATION_MODE_NON_GF_DEVS_PRESENT) &&
1209            pmlmepriv->num_sta_ht_no_gf) {
1210                pmlmepriv->ht_op_mode |=
1211                        HT_INFO_OPERATION_MODE_NON_GF_DEVS_PRESENT;
1212                op_mode_changes++;
1213        } else if ((pmlmepriv->ht_op_mode &
1214                   HT_INFO_OPERATION_MODE_NON_GF_DEVS_PRESENT) &&
1215                   pmlmepriv->num_sta_ht_no_gf == 0) {
1216                pmlmepriv->ht_op_mode &=
1217                        ~HT_INFO_OPERATION_MODE_NON_GF_DEVS_PRESENT;
1218                op_mode_changes++;
1219        }
1220
1221        if (!(pmlmepriv->ht_op_mode & HT_INFO_OPERATION_MODE_NON_HT_STA_PRESENT) &&
1222            (pmlmepriv->num_sta_no_ht || pmlmepriv->olbc_ht)) {
1223                pmlmepriv->ht_op_mode |= HT_INFO_OPERATION_MODE_NON_HT_STA_PRESENT;
1224                op_mode_changes++;
1225        } else if ((pmlmepriv->ht_op_mode &
1226                    HT_INFO_OPERATION_MODE_NON_HT_STA_PRESENT) &&
1227                   (pmlmepriv->num_sta_no_ht == 0 && !pmlmepriv->olbc_ht)) {
1228                pmlmepriv->ht_op_mode &=
1229                        ~HT_INFO_OPERATION_MODE_NON_HT_STA_PRESENT;
1230                op_mode_changes++;
1231        }
1232
1233        /* Note: currently we switch to the MIXED op mode if HT non-greenfield
1234         * station is associated. Probably it's a theoretical case, since
1235         * it looks like all known HT STAs support greenfield.
1236         */
1237        new_op_mode = 0;
1238        if (pmlmepriv->num_sta_no_ht ||
1239            (pmlmepriv->ht_op_mode & HT_INFO_OPERATION_MODE_NON_GF_DEVS_PRESENT))
1240                new_op_mode = OP_MODE_MIXED;
1241        else if ((le16_to_cpu(phtpriv_ap->ht_cap.cap_info) &
1242                  IEEE80211_HT_CAP_SUP_WIDTH_20_40) &&
1243                 pmlmepriv->num_sta_ht_20mhz)
1244                new_op_mode = OP_MODE_20MHZ_HT_STA_ASSOCED;
1245        else if (pmlmepriv->olbc_ht)
1246                new_op_mode = OP_MODE_MAY_BE_LEGACY_STAS;
1247        else
1248                new_op_mode = OP_MODE_PURE;
1249
1250        cur_op_mode = pmlmepriv->ht_op_mode & HT_INFO_OPERATION_MODE_OP_MODE_MASK;
1251        if (cur_op_mode != new_op_mode) {
1252                pmlmepriv->ht_op_mode &= ~HT_INFO_OPERATION_MODE_OP_MODE_MASK;
1253                pmlmepriv->ht_op_mode |= new_op_mode;
1254                op_mode_changes++;
1255        }
1256
1257        return op_mode_changes;
1258}
1259
1260void associated_clients_update(struct adapter *padapter, u8 updated)
1261{
1262        /* update associated stations cap. */
1263        if (updated) {
1264                struct list_head *phead, *plist;
1265                struct sta_info *psta = NULL;
1266                struct sta_priv *pstapriv = &padapter->stapriv;
1267
1268                spin_lock_bh(&pstapriv->asoc_list_lock);
1269
1270                phead = &pstapriv->asoc_list;
1271                /* check asoc_queue */
1272                list_for_each(plist, phead) {
1273                        psta = list_entry(plist, struct sta_info, asoc_list);
1274
1275                        VCS_update(padapter, psta);
1276                }
1277                spin_unlock_bh(&pstapriv->asoc_list_lock);
1278        }
1279}
1280
1281/* called > TSR LEVEL for USB or SDIO Interface*/
1282void bss_cap_update_on_sta_join(struct adapter *padapter, struct sta_info *psta)
1283{
1284        u8 beacon_updated = false;
1285        struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1286        struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
1287
1288        if (!(psta->flags & WLAN_STA_SHORT_PREAMBLE)) {
1289                if (!psta->no_short_preamble_set) {
1290                        psta->no_short_preamble_set = 1;
1291
1292                        pmlmepriv->num_sta_no_short_preamble++;
1293
1294                        if ((pmlmeext->cur_wireless_mode > WIRELESS_11B) &&
1295                            (pmlmepriv->num_sta_no_short_preamble == 1)) {
1296                                beacon_updated = true;
1297                                update_beacon(padapter, 0xFF, NULL, true);
1298                        }
1299                }
1300        } else {
1301                if (psta->no_short_preamble_set) {
1302                        psta->no_short_preamble_set = 0;
1303
1304                        pmlmepriv->num_sta_no_short_preamble--;
1305
1306                        if ((pmlmeext->cur_wireless_mode > WIRELESS_11B) &&
1307                            (pmlmepriv->num_sta_no_short_preamble == 0)) {
1308                                beacon_updated = true;
1309                                update_beacon(padapter, 0xFF, NULL, true);
1310                        }
1311                }
1312        }
1313
1314        if (psta->flags & WLAN_STA_NONERP) {
1315                if (!psta->nonerp_set) {
1316                        psta->nonerp_set = 1;
1317
1318                        pmlmepriv->num_sta_non_erp++;
1319
1320                        if (pmlmepriv->num_sta_non_erp == 1) {
1321                                beacon_updated = true;
1322                                update_beacon(padapter, WLAN_EID_ERP_INFO, NULL, true);
1323                        }
1324                }
1325        } else {
1326                if (psta->nonerp_set) {
1327                        psta->nonerp_set = 0;
1328
1329                        pmlmepriv->num_sta_non_erp--;
1330
1331                        if (pmlmepriv->num_sta_non_erp == 0) {
1332                                beacon_updated = true;
1333                                update_beacon(padapter, WLAN_EID_ERP_INFO, NULL, true);
1334                        }
1335                }
1336        }
1337
1338        if (!(psta->capability & WLAN_CAPABILITY_SHORT_SLOT_TIME)) {
1339                if (!psta->no_short_slot_time_set) {
1340                        psta->no_short_slot_time_set = 1;
1341
1342                        pmlmepriv->num_sta_no_short_slot_time++;
1343
1344                        if ((pmlmeext->cur_wireless_mode > WIRELESS_11B) &&
1345                            (pmlmepriv->num_sta_no_short_slot_time == 1)) {
1346                                beacon_updated = true;
1347                                update_beacon(padapter, 0xFF, NULL, true);
1348                        }
1349                }
1350        } else {
1351                if (psta->no_short_slot_time_set) {
1352                        psta->no_short_slot_time_set = 0;
1353
1354                        pmlmepriv->num_sta_no_short_slot_time--;
1355
1356                        if ((pmlmeext->cur_wireless_mode > WIRELESS_11B) &&
1357                            (pmlmepriv->num_sta_no_short_slot_time == 0)) {
1358                                beacon_updated = true;
1359                                update_beacon(padapter, 0xFF, NULL, true);
1360                        }
1361                }
1362        }
1363
1364        if (psta->flags & WLAN_STA_HT) {
1365                u16 ht_capab = le16_to_cpu(psta->htpriv.ht_cap.cap_info);
1366
1367                if (psta->no_ht_set) {
1368                        psta->no_ht_set = 0;
1369                        pmlmepriv->num_sta_no_ht--;
1370                }
1371
1372                if ((ht_capab & IEEE80211_HT_CAP_GRN_FLD) == 0) {
1373                        if (!psta->no_ht_gf_set) {
1374                                psta->no_ht_gf_set = 1;
1375                                pmlmepriv->num_sta_ht_no_gf++;
1376                        }
1377                }
1378
1379                if ((ht_capab & IEEE80211_HT_CAP_SUP_WIDTH_20_40) == 0) {
1380                        if (!psta->ht_20mhz_set) {
1381                                psta->ht_20mhz_set = 1;
1382                                pmlmepriv->num_sta_ht_20mhz++;
1383                        }
1384                }
1385        } else {
1386                if (!psta->no_ht_set) {
1387                        psta->no_ht_set = 1;
1388                        pmlmepriv->num_sta_no_ht++;
1389                }
1390        }
1391
1392        if (rtw_ht_operation_update(padapter) > 0) {
1393                update_beacon(padapter, WLAN_EID_HT_CAPABILITY, NULL, false);
1394                update_beacon(padapter, WLAN_EID_HT_OPERATION, NULL, true);
1395        }
1396
1397        /* update associated stations cap. */
1398        associated_clients_update(padapter,  beacon_updated);
1399}
1400
1401u8 bss_cap_update_on_sta_leave(struct adapter *padapter, struct sta_info *psta)
1402{
1403        u8 beacon_updated = false;
1404        struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1405        struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
1406
1407        if (!psta)
1408                return beacon_updated;
1409
1410        if (psta->no_short_preamble_set) {
1411                psta->no_short_preamble_set = 0;
1412                pmlmepriv->num_sta_no_short_preamble--;
1413                if (pmlmeext->cur_wireless_mode > WIRELESS_11B &&
1414                    pmlmepriv->num_sta_no_short_preamble == 0) {
1415                        beacon_updated = true;
1416                        update_beacon(padapter, 0xFF, NULL, true);
1417                }
1418        }
1419
1420        if (psta->nonerp_set) {
1421                psta->nonerp_set = 0;
1422                pmlmepriv->num_sta_non_erp--;
1423                if (pmlmepriv->num_sta_non_erp == 0) {
1424                        beacon_updated = true;
1425                        update_beacon(padapter, WLAN_EID_ERP_INFO, NULL, true);
1426                }
1427        }
1428
1429        if (psta->no_short_slot_time_set) {
1430                psta->no_short_slot_time_set = 0;
1431                pmlmepriv->num_sta_no_short_slot_time--;
1432                if (pmlmeext->cur_wireless_mode > WIRELESS_11B &&
1433                    pmlmepriv->num_sta_no_short_slot_time == 0) {
1434                        beacon_updated = true;
1435                        update_beacon(padapter, 0xFF, NULL, true);
1436                }
1437        }
1438
1439        if (psta->no_ht_gf_set) {
1440                psta->no_ht_gf_set = 0;
1441                pmlmepriv->num_sta_ht_no_gf--;
1442        }
1443
1444        if (psta->no_ht_set) {
1445                psta->no_ht_set = 0;
1446                pmlmepriv->num_sta_no_ht--;
1447        }
1448
1449        if (psta->ht_20mhz_set) {
1450                psta->ht_20mhz_set = 0;
1451                pmlmepriv->num_sta_ht_20mhz--;
1452        }
1453
1454        if (rtw_ht_operation_update(padapter) > 0) {
1455                update_beacon(padapter, WLAN_EID_HT_CAPABILITY, NULL, false);
1456                update_beacon(padapter, WLAN_EID_HT_OPERATION, NULL, true);
1457        }
1458
1459        /* update associated stations cap. */
1460
1461        return beacon_updated;
1462}
1463
1464u8 ap_free_sta(struct adapter *padapter, struct sta_info *psta,
1465               bool active, u16 reason)
1466{
1467        u8 beacon_updated = false;
1468        struct sta_priv *pstapriv = &padapter->stapriv;
1469
1470        if (!psta)
1471                return beacon_updated;
1472
1473        /* tear down Rx AMPDU */
1474        send_delba(padapter, 0, psta->hwaddr);/*  recipient */
1475
1476        /* tear down TX AMPDU */
1477        send_delba(padapter, 1, psta->hwaddr);/*  originator */
1478        psta->htpriv.agg_enable_bitmap = 0x0;/* reset */
1479        psta->htpriv.candidate_tid_bitmap = 0x0;/* reset */
1480
1481        if (active)
1482                issue_deauth(padapter, psta->hwaddr, reason);
1483
1484        /* clear cam entry / key */
1485        rtw_clearstakey_cmd(padapter, (u8 *)psta, (u8)(psta->mac_id + 3), true);
1486
1487        spin_lock_bh(&psta->lock);
1488        psta->state &= ~_FW_LINKED;
1489        spin_unlock_bh(&psta->lock);
1490
1491        rtw_indicate_sta_disassoc_event(padapter, psta);
1492
1493        report_del_sta_event(padapter, psta->hwaddr, reason);
1494
1495        beacon_updated = bss_cap_update_on_sta_leave(padapter, psta);
1496
1497        spin_lock_bh(&pstapriv->sta_hash_lock);
1498        rtw_free_stainfo(padapter, psta);
1499        spin_unlock_bh(&pstapriv->sta_hash_lock);
1500
1501        return beacon_updated;
1502}
1503
1504int rtw_sta_flush(struct adapter *padapter)
1505{
1506        struct list_head *phead;
1507        struct sta_info *psta, *temp;
1508        struct sta_priv *pstapriv = &padapter->stapriv;
1509        struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
1510        struct mlme_ext_info    *pmlmeinfo = &pmlmeext->mlmext_info;
1511        u8 bc_addr[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
1512
1513        if ((pmlmeinfo->state & 0x03) != WIFI_FW_AP_STATE)
1514                return 0;
1515
1516        spin_lock_bh(&pstapriv->asoc_list_lock);
1517        phead = &pstapriv->asoc_list;
1518        /* free sta asoc_queue */
1519        list_for_each_entry_safe(psta, temp, phead, asoc_list) {
1520                list_del_init(&psta->asoc_list);
1521                pstapriv->asoc_list_cnt--;
1522
1523                ap_free_sta(padapter, psta, true, WLAN_REASON_DEAUTH_LEAVING);
1524        }
1525        spin_unlock_bh(&pstapriv->asoc_list_lock);
1526
1527        issue_deauth(padapter, bc_addr, WLAN_REASON_DEAUTH_LEAVING);
1528
1529        associated_clients_update(padapter, true);
1530
1531        return 0;
1532}
1533
1534/* called > TSR LEVEL for USB or SDIO Interface*/
1535void sta_info_update(struct adapter *padapter, struct sta_info *psta)
1536{
1537        int flags = psta->flags;
1538        struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1539
1540        /* update wmm cap. */
1541        if (WLAN_STA_WME & flags)
1542                psta->qos_option = 1;
1543        else
1544                psta->qos_option = 0;
1545
1546        if (pmlmepriv->qospriv.qos_option == 0)
1547                psta->qos_option = 0;
1548
1549        /* update 802.11n ht cap. */
1550        if (WLAN_STA_HT & flags) {
1551                psta->htpriv.ht_option = true;
1552                psta->qos_option = 1;
1553        } else {
1554                psta->htpriv.ht_option = false;
1555        }
1556
1557        if (!pmlmepriv->htpriv.ht_option)
1558                psta->htpriv.ht_option = false;
1559
1560        update_sta_info_apmode(padapter, psta);
1561}
1562
1563/* called >= TSR LEVEL for USB or SDIO Interface*/
1564void ap_sta_info_defer_update(struct adapter *padapter, struct sta_info *psta)
1565{
1566        if (psta->state & _FW_LINKED) {
1567                /* add ratid */
1568                add_RATid(padapter, psta, 0);/* DM_RATR_STA_INIT */
1569        }
1570}
1571
1572void start_ap_mode(struct adapter *padapter)
1573{
1574        int i;
1575        struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1576        struct sta_priv *pstapriv = &padapter->stapriv;
1577        struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
1578        struct wlan_acl_pool *pacl_list = &pstapriv->acl_list;
1579
1580        pmlmepriv->update_bcn = false;
1581
1582        pmlmeext->bstart_bss = false;
1583
1584        pmlmepriv->num_sta_non_erp = 0;
1585
1586        pmlmepriv->num_sta_no_short_slot_time = 0;
1587
1588        pmlmepriv->num_sta_no_short_preamble = 0;
1589
1590        pmlmepriv->num_sta_ht_no_gf = 0;
1591        pmlmepriv->num_sta_no_ht = 0;
1592        pmlmepriv->num_sta_ht_20mhz = 0;
1593
1594        pmlmepriv->olbc = false;
1595
1596        pmlmepriv->olbc_ht = false;
1597
1598        pmlmepriv->ht_op_mode = 0;
1599
1600        for (i = 0; i < NUM_STA; i++)
1601                pstapriv->sta_aid[i] = NULL;
1602
1603        pmlmepriv->wps_beacon_ie = NULL;
1604        pmlmepriv->wps_probe_resp_ie = NULL;
1605        pmlmepriv->wps_assoc_resp_ie = NULL;
1606
1607        /* for ACL */
1608        INIT_LIST_HEAD(&pacl_list->acl_node_q.queue);
1609        pacl_list->num = 0;
1610        pacl_list->mode = 0;
1611        for (i = 0; i < NUM_ACL; i++) {
1612                INIT_LIST_HEAD(&pacl_list->aclnode[i].list);
1613                pacl_list->aclnode[i].valid = false;
1614        }
1615}
1616
1617void stop_ap_mode(struct adapter *padapter)
1618{
1619        struct rtw_wlan_acl_node *paclnode, *n;
1620        struct sta_info *psta = NULL;
1621        struct sta_priv *pstapriv = &padapter->stapriv;
1622        struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1623        struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
1624        struct wlan_acl_pool *pacl_list = &pstapriv->acl_list;
1625        struct __queue *pacl_node_q = &pacl_list->acl_node_q;
1626
1627        pmlmepriv->update_bcn = false;
1628        pmlmeext->bstart_bss = false;
1629
1630        /* reset and init security priv , this can refine with
1631         * rtw_reset_securitypriv
1632         */
1633        memset((unsigned char *)&padapter->securitypriv, 0, sizeof(struct security_priv));
1634        padapter->securitypriv.ndisauthtype = Ndis802_11AuthModeOpen;
1635        padapter->securitypriv.ndisencryptstatus = Ndis802_11WEPDisabled;
1636
1637        /* for ACL */
1638        spin_lock_bh(&pacl_node_q->lock);
1639        list_for_each_entry_safe(paclnode, n, &pacl_node_q->queue, list) {
1640                if (paclnode->valid) {
1641                        paclnode->valid = false;
1642
1643                        list_del_init(&paclnode->list);
1644
1645                        pacl_list->num--;
1646                }
1647        }
1648        spin_unlock_bh(&pacl_node_q->lock);
1649
1650        rtw_sta_flush(padapter);
1651
1652        /* free_assoc_sta_resources */
1653        rtw_free_all_stainfo(padapter);
1654
1655        psta = rtw_get_bcmc_stainfo(padapter);
1656        spin_lock_bh(&pstapriv->sta_hash_lock);
1657        rtw_free_stainfo(padapter, psta);
1658        spin_unlock_bh(&pstapriv->sta_hash_lock);
1659
1660        rtw_init_bcmc_stainfo(padapter);
1661
1662        rtw_free_mlme_priv_ie_data(pmlmepriv);
1663}
1664
1665#endif /* CONFIG_88EU_AP_MODE */
1666