linux/drivers/staging/rtl8188eu/core/rtw_mlme_ext.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_MLME_EXT_C_
   8
   9#include <linux/ieee80211.h>
  10#include <asm/unaligned.h>
  11
  12#include <osdep_service.h>
  13#include <drv_types.h>
  14#include <wifi.h>
  15#include <rtw_mlme_ext.h>
  16#include <wlan_bssdef.h>
  17#include <mlme_osdep.h>
  18#include <recv_osdep.h>
  19
  20static u8 null_addr[ETH_ALEN] = {0, 0, 0, 0, 0, 0};
  21
  22/**************************************************
  23OUI definitions for the vendor specific IE
  24***************************************************/
  25unsigned char   RTW_WPA_OUI[] = {0x00, 0x50, 0xf2, 0x01};
  26unsigned char WMM_OUI[] = {0x00, 0x50, 0xf2, 0x02};
  27unsigned char   WPS_OUI[] = {0x00, 0x50, 0xf2, 0x04};
  28unsigned char   P2P_OUI[] = {0x50, 0x6F, 0x9A, 0x09};
  29unsigned char   WFD_OUI[] = {0x50, 0x6F, 0x9A, 0x0A};
  30
  31unsigned char   WMM_INFO_OUI[] = {0x00, 0x50, 0xf2, 0x02, 0x00, 0x01};
  32unsigned char   WMM_PARA_OUI[] = {0x00, 0x50, 0xf2, 0x02, 0x01, 0x01};
  33
  34unsigned char WPA_TKIP_CIPHER[4] = {0x00, 0x50, 0xf2, 0x02};
  35unsigned char RSN_TKIP_CIPHER[4] = {0x00, 0x0f, 0xac, 0x02};
  36
  37extern unsigned char REALTEK_96B_IE[];
  38
  39/********************************************************
  40MCS rate definitions
  41*********************************************************/
  42const u8 MCS_rate_1R[16] = {
  43        0xff, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
  44        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
  45};
  46
  47/********************************************************
  48ChannelPlan definitions
  49*********************************************************/
  50static struct rt_channel_plan_2g RTW_ChannelPlan2G[RT_CHANNEL_DOMAIN_2G_MAX] = {
  51        {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13}, 13},              /*  0x00, RT_CHANNEL_DOMAIN_2G_WORLD , Passive scan CH 12, 13 */
  52        {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13}, 13},              /*  0x01, RT_CHANNEL_DOMAIN_2G_ETSI1 */
  53        {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}, 11},                      /*  0x02, RT_CHANNEL_DOMAIN_2G_FCC1 */
  54        {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14}, 14},  /*  0x03, RT_CHANNEL_DOMAIN_2G_MIKK1 */
  55        {{10, 11, 12, 13}, 4},                                  /*  0x04, RT_CHANNEL_DOMAIN_2G_ETSI2 */
  56        {{}, 0},                                                                        /*  0x05, RT_CHANNEL_DOMAIN_2G_NULL */
  57};
  58
  59static struct rt_channel_plan_map       RTW_ChannelPlanMap[RT_CHANNEL_DOMAIN_MAX] = {
  60        /*  0x00 ~ 0x1F , Old Define ===== */
  61        {0x02}, /* 0x00, RT_CHANNEL_DOMAIN_FCC */
  62        {0x02}, /* 0x01, RT_CHANNEL_DOMAIN_IC */
  63        {0x01}, /* 0x02, RT_CHANNEL_DOMAIN_ETSI */
  64        {0x01}, /* 0x03, RT_CHANNEL_DOMAIN_SPAIN */
  65        {0x01}, /* 0x04, RT_CHANNEL_DOMAIN_FRANCE */
  66        {0x03}, /* 0x05, RT_CHANNEL_DOMAIN_MKK */
  67        {0x03}, /* 0x06, RT_CHANNEL_DOMAIN_MKK1 */
  68        {0x01}, /* 0x07, RT_CHANNEL_DOMAIN_ISRAEL */
  69        {0x03}, /* 0x08, RT_CHANNEL_DOMAIN_TELEC */
  70        {0x03}, /* 0x09, RT_CHANNEL_DOMAIN_GLOBAL_DOAMIN */
  71        {0x00}, /* 0x0A, RT_CHANNEL_DOMAIN_WORLD_WIDE_13 */
  72        {0x02}, /* 0x0B, RT_CHANNEL_DOMAIN_TAIWAN */
  73        {0x01}, /* 0x0C, RT_CHANNEL_DOMAIN_CHINA */
  74        {0x02}, /* 0x0D, RT_CHANNEL_DOMAIN_SINGAPORE_INDIA_MEXICO */
  75        {0x02}, /* 0x0E, RT_CHANNEL_DOMAIN_KOREA */
  76        {0x02}, /* 0x0F, RT_CHANNEL_DOMAIN_TURKEY */
  77        {0x01}, /* 0x10, RT_CHANNEL_DOMAIN_JAPAN */
  78        {0x02}, /* 0x11, RT_CHANNEL_DOMAIN_FCC_NO_DFS */
  79        {0x01}, /* 0x12, RT_CHANNEL_DOMAIN_JAPAN_NO_DFS */
  80        {0x00}, /* 0x13, RT_CHANNEL_DOMAIN_WORLD_WIDE_5G */
  81        {0x02}, /* 0x14, RT_CHANNEL_DOMAIN_TAIWAN_NO_DFS */
  82        {0x00}, /* 0x15, RT_CHANNEL_DOMAIN_ETSI_NO_DFS */
  83        {0x00}, /* 0x16, RT_CHANNEL_DOMAIN_KOREA_NO_DFS */
  84        {0x03}, /* 0x17, RT_CHANNEL_DOMAIN_JAPAN_NO_DFS */
  85        {0x05}, /* 0x18, RT_CHANNEL_DOMAIN_PAKISTAN_NO_DFS */
  86        {0x02}, /* 0x19, RT_CHANNEL_DOMAIN_TAIWAN2_NO_DFS */
  87        {0x00}, /* 0x1A, */
  88        {0x00}, /* 0x1B, */
  89        {0x00}, /* 0x1C, */
  90        {0x00}, /* 0x1D, */
  91        {0x00}, /* 0x1E, */
  92        {0x05}, /* 0x1F, RT_CHANNEL_DOMAIN_WORLD_WIDE_ONLY_5G */
  93        /*  0x20 ~ 0x7F , New Define ===== */
  94        {0x00}, /* 0x20, RT_CHANNEL_DOMAIN_WORLD_NULL */
  95        {0x01}, /* 0x21, RT_CHANNEL_DOMAIN_ETSI1_NULL */
  96        {0x02}, /* 0x22, RT_CHANNEL_DOMAIN_FCC1_NULL */
  97        {0x03}, /* 0x23, RT_CHANNEL_DOMAIN_MKK1_NULL */
  98        {0x04}, /* 0x24, RT_CHANNEL_DOMAIN_ETSI2_NULL */
  99        {0x02}, /* 0x25, RT_CHANNEL_DOMAIN_FCC1_FCC1 */
 100        {0x00}, /* 0x26, RT_CHANNEL_DOMAIN_WORLD_ETSI1 */
 101        {0x03}, /* 0x27, RT_CHANNEL_DOMAIN_MKK1_MKK1 */
 102        {0x00}, /* 0x28, RT_CHANNEL_DOMAIN_WORLD_KCC1 */
 103        {0x00}, /* 0x29, RT_CHANNEL_DOMAIN_WORLD_FCC2 */
 104        {0x00}, /* 0x2A, */
 105        {0x00}, /* 0x2B, */
 106        {0x00}, /* 0x2C, */
 107        {0x00}, /* 0x2D, */
 108        {0x00}, /* 0x2E, */
 109        {0x00}, /* 0x2F, */
 110        {0x00}, /* 0x30, RT_CHANNEL_DOMAIN_WORLD_FCC3 */
 111        {0x00}, /* 0x31, RT_CHANNEL_DOMAIN_WORLD_FCC4 */
 112        {0x00}, /* 0x32, RT_CHANNEL_DOMAIN_WORLD_FCC5 */
 113        {0x00}, /* 0x33, RT_CHANNEL_DOMAIN_WORLD_FCC6 */
 114        {0x02}, /* 0x34, RT_CHANNEL_DOMAIN_FCC1_FCC7 */
 115        {0x00}, /* 0x35, RT_CHANNEL_DOMAIN_WORLD_ETSI2 */
 116        {0x00}, /* 0x36, RT_CHANNEL_DOMAIN_WORLD_ETSI3 */
 117        {0x03}, /* 0x37, RT_CHANNEL_DOMAIN_MKK1_MKK2 */
 118        {0x03}, /* 0x38, RT_CHANNEL_DOMAIN_MKK1_MKK3 */
 119        {0x02}, /* 0x39, RT_CHANNEL_DOMAIN_FCC1_NCC1 */
 120        {0x00}, /* 0x3A, */
 121        {0x00}, /* 0x3B, */
 122        {0x00}, /* 0x3C, */
 123        {0x00}, /* 0x3D, */
 124        {0x00}, /* 0x3E, */
 125        {0x00}, /* 0x3F, */
 126        {0x02}, /* 0x40, RT_CHANNEL_DOMAIN_FCC1_NCC2 */
 127        {0x03}, /* 0x41, RT_CHANNEL_DOMAIN_GLOBAL_DOAMIN_2G */
 128};
 129
 130static const struct rt_channel_plan_map RTW_CHANNEL_PLAN_MAP_REALTEK_DEFINE = {
 131        0x03
 132}; /* use the combination for max channel numbers */
 133
 134/*
 135 * Search the @param channel_num in given @param channel_set
 136 * @ch_set: the given channel set
 137 * @ch: the given channel number
 138 *
 139 * return the index of channel_num in channel_set, -1 if not found
 140 */
 141int rtw_ch_set_search_ch(struct rt_channel_info *ch_set, const u32 ch)
 142{
 143        int i;
 144
 145        for (i = 0; ch_set[i].ChannelNum != 0; i++) {
 146                if (ch == ch_set[i].ChannelNum)
 147                        break;
 148        }
 149
 150        if (i >= ch_set[i].ChannelNum)
 151                return -1;
 152        return i;
 153}
 154
 155struct xmit_frame *alloc_mgtxmitframe(struct xmit_priv *pxmitpriv)
 156{
 157        struct xmit_frame                       *pmgntframe;
 158        struct xmit_buf                         *pxmitbuf;
 159
 160        pmgntframe = rtw_alloc_xmitframe(pxmitpriv);
 161        if (!pmgntframe) {
 162                DBG_88E("%s, alloc xmitframe fail\n", __func__);
 163                return NULL;
 164        }
 165
 166        pxmitbuf = rtw_alloc_xmitbuf_ext(pxmitpriv);
 167        if (!pxmitbuf) {
 168                DBG_88E("%s, alloc xmitbuf fail\n", __func__);
 169                rtw_free_xmitframe(pxmitpriv, pmgntframe);
 170                return NULL;
 171        }
 172        pmgntframe->frame_tag = MGNT_FRAMETAG;
 173        pmgntframe->pxmitbuf = pxmitbuf;
 174        pmgntframe->buf_addr = pxmitbuf->pbuf;
 175        pxmitbuf->priv_data = pmgntframe;
 176        return pmgntframe;
 177}
 178
 179/****************************************************************************
 180
 181Following are some TX functions for WiFi MLME
 182
 183*****************************************************************************/
 184
 185void update_mgnt_tx_rate(struct adapter *padapter, u8 rate)
 186{
 187        struct mlme_ext_priv    *pmlmeext = &(padapter->mlmeextpriv);
 188
 189        pmlmeext->tx_rate = rate;
 190        DBG_88E("%s(): rate = %x\n", __func__, rate);
 191}
 192
 193void update_mgntframe_attrib(struct adapter *padapter, struct pkt_attrib *pattrib)
 194{
 195        struct mlme_ext_priv    *pmlmeext = &(padapter->mlmeextpriv);
 196
 197        memset((u8 *)(pattrib), 0, sizeof(struct pkt_attrib));
 198
 199        pattrib->hdrlen = 24;
 200        pattrib->nr_frags = 1;
 201        pattrib->priority = 7;
 202        pattrib->mac_id = 0;
 203        pattrib->qsel = 0x12;
 204
 205        pattrib->pktlen = 0;
 206
 207        if (pmlmeext->cur_wireless_mode & WIRELESS_11B)
 208                pattrib->raid = 6;/* b mode */
 209        else
 210                pattrib->raid = 5;/* a/g mode */
 211
 212        pattrib->encrypt = _NO_PRIVACY_;
 213        pattrib->bswenc = false;
 214
 215        pattrib->qos_en = false;
 216        pattrib->ht_en = false;
 217        pattrib->bwmode = HT_CHANNEL_WIDTH_20;
 218        pattrib->ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
 219        pattrib->sgi = false;
 220
 221        pattrib->seqnum = pmlmeext->mgnt_seq;
 222
 223        pattrib->retry_ctrl = true;
 224}
 225
 226static void dump_mgntframe(struct adapter *padapter,
 227                           struct xmit_frame *pmgntframe)
 228{
 229        if (padapter->bSurpriseRemoved || padapter->bDriverStopped)
 230                return;
 231
 232        rtw_hal_mgnt_xmit(padapter, pmgntframe);
 233}
 234
 235static s32 dump_mgntframe_and_wait(struct adapter *padapter,
 236                                   struct xmit_frame *pmgntframe,
 237                                   int timeout_ms)
 238{
 239        s32 ret = _FAIL;
 240        struct xmit_buf *pxmitbuf = pmgntframe->pxmitbuf;
 241        struct submit_ctx sctx;
 242
 243        if (padapter->bSurpriseRemoved || padapter->bDriverStopped)
 244                return ret;
 245
 246        rtw_sctx_init(&sctx, timeout_ms);
 247        pxmitbuf->sctx = &sctx;
 248
 249        ret = rtw_hal_mgnt_xmit(padapter, pmgntframe);
 250
 251        if (ret == _SUCCESS)
 252                ret = rtw_sctx_wait(&sctx);
 253
 254        return ret;
 255}
 256
 257static s32 dump_mgntframe_and_wait_ack(struct adapter *padapter,
 258                                       struct xmit_frame *pmgntframe)
 259{
 260        s32 ret = _FAIL;
 261        u32 timeout_ms = 500;/*   500ms */
 262        struct xmit_priv        *pxmitpriv = &padapter->xmitpriv;
 263
 264        if (padapter->bSurpriseRemoved || padapter->bDriverStopped)
 265                return -1;
 266
 267        if (mutex_lock_interruptible(&pxmitpriv->ack_tx_mutex))
 268                return _FAIL;
 269        pxmitpriv->ack_tx = true;
 270
 271        pmgntframe->ack_report = 1;
 272        if (rtw_hal_mgnt_xmit(padapter, pmgntframe) == _SUCCESS)
 273                ret = rtw_ack_tx_wait(pxmitpriv, timeout_ms);
 274
 275        pxmitpriv->ack_tx = false;
 276        mutex_unlock(&pxmitpriv->ack_tx_mutex);
 277
 278        return ret;
 279}
 280
 281static int update_hidden_ssid(u8 *ies, u32 ies_len, u8 hidden_ssid_mode)
 282{
 283        u8 *ssid_ie;
 284        uint ssid_len_ori;
 285        int len_diff = 0;
 286
 287        ssid_ie = rtw_get_ie(ies,  WLAN_EID_SSID, &ssid_len_ori, ies_len);
 288
 289        if (ssid_ie && ssid_len_ori > 0) {
 290                switch (hidden_ssid_mode) {
 291                case 1: {
 292                        u8 *next_ie = ssid_ie + 2 + ssid_len_ori;
 293                        u32 remain_len = 0;
 294
 295                        remain_len = ies_len - (next_ie - ies);
 296
 297                        ssid_ie[1] = 0;
 298                        memcpy(ssid_ie+2, next_ie, remain_len);
 299                        len_diff -= ssid_len_ori;
 300
 301                        break;
 302                }
 303                case 2:
 304                        memset(&ssid_ie[2], 0, ssid_len_ori);
 305                        break;
 306                default:
 307                        break;
 308                }
 309        }
 310
 311        return len_diff;
 312}
 313
 314static void issue_beacon(struct adapter *padapter, int timeout_ms)
 315{
 316        struct xmit_frame       *pmgntframe;
 317        struct pkt_attrib       *pattrib;
 318        unsigned char   *pframe;
 319        struct ieee80211_hdr *pwlanhdr;
 320        __le16 *fctrl;
 321        unsigned int    rate_len;
 322        struct xmit_priv        *pxmitpriv = &(padapter->xmitpriv);
 323        struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
 324        struct mlme_ext_priv    *pmlmeext = &(padapter->mlmeextpriv);
 325        struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
 326        struct wlan_bssid_ex            *cur_network = &(pmlmeinfo->network);
 327        u8      bc_addr[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
 328
 329        pmgntframe = alloc_mgtxmitframe(pxmitpriv);
 330        if (!pmgntframe) {
 331                DBG_88E("%s, alloc mgnt frame fail\n", __func__);
 332                return;
 333        }
 334#if defined(CONFIG_88EU_AP_MODE)
 335        spin_lock_bh(&pmlmepriv->bcn_update_lock);
 336#endif /* if defined (CONFIG_88EU_AP_MODE) */
 337
 338        /* update attribute */
 339        pattrib = &pmgntframe->attrib;
 340        update_mgntframe_attrib(padapter, pattrib);
 341        pattrib->qsel = 0x10;
 342
 343        memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
 344
 345        pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
 346        pwlanhdr = (struct ieee80211_hdr *)pframe;
 347
 348        fctrl = &pwlanhdr->frame_control;
 349        *(fctrl) = 0;
 350
 351        ether_addr_copy(pwlanhdr->addr1, bc_addr);
 352        ether_addr_copy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)));
 353        ether_addr_copy(pwlanhdr->addr3, cur_network->MacAddress);
 354
 355        SetSeqNum(pwlanhdr, 0/*pmlmeext->mgnt_seq*/);
 356        /* pmlmeext->mgnt_seq++; */
 357        SetFrameSubType(pframe, WIFI_BEACON);
 358
 359        pframe += sizeof(struct ieee80211_hdr_3addr);
 360        pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr);
 361
 362        if ((pmlmeinfo->state&0x03) == WIFI_FW_AP_STATE) {
 363                int len_diff;
 364                u8 *wps_ie;
 365                uint wps_ielen;
 366                u8 sr = 0;
 367
 368                memcpy(pframe, cur_network->ies, cur_network->ie_length);
 369                len_diff = update_hidden_ssid(
 370                        pframe+_BEACON_IE_OFFSET_
 371                        , cur_network->ie_length-_BEACON_IE_OFFSET_
 372                        , pmlmeinfo->hidden_ssid_mode
 373                        );
 374                pframe += (cur_network->ie_length+len_diff);
 375                pattrib->pktlen += (cur_network->ie_length+len_diff);
 376                wps_ie = rtw_get_wps_ie(pmgntframe->buf_addr+TXDESC_OFFSET+sizeof(struct ieee80211_hdr_3addr)+_BEACON_IE_OFFSET_,
 377                        pattrib->pktlen-sizeof(struct ieee80211_hdr_3addr)-_BEACON_IE_OFFSET_, NULL, &wps_ielen);
 378                if (wps_ie && wps_ielen > 0)
 379                        rtw_get_wps_attr_content(wps_ie,  wps_ielen, WPS_ATTR_SELECTED_REGISTRAR, (u8 *)(&sr), NULL);
 380                if (sr != 0)
 381                        set_fwstate(pmlmepriv, WIFI_UNDER_WPS);
 382                else
 383                        _clr_fwstate_(pmlmepriv, WIFI_UNDER_WPS);
 384
 385                goto _issue_bcn;
 386        }
 387
 388        /* below for ad-hoc mode */
 389
 390        /* timestamp will be inserted by hardware */
 391        pframe += 8;
 392        pattrib->pktlen += 8;
 393
 394        /*  beacon interval: 2 bytes */
 395
 396        memcpy(pframe, (unsigned char *)(rtw_get_beacon_interval_from_ie(cur_network->ies)), 2);
 397
 398        pframe += 2;
 399        pattrib->pktlen += 2;
 400
 401        /*  capability info: 2 bytes */
 402
 403        memcpy(pframe, (unsigned char *)(rtw_get_capability_from_ie(cur_network->ies)), 2);
 404
 405        pframe += 2;
 406        pattrib->pktlen += 2;
 407
 408        /*  SSID */
 409        pframe = rtw_set_ie(pframe, _SSID_IE_, cur_network->Ssid.SsidLength, cur_network->Ssid.Ssid, &pattrib->pktlen);
 410
 411        /*  supported rates... */
 412        rate_len = rtw_get_rateset_len(cur_network->SupportedRates);
 413        pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_, min_t(unsigned int, rate_len, 8), cur_network->SupportedRates, &pattrib->pktlen);
 414
 415        /*  DS parameter set */
 416        pframe = rtw_set_ie(pframe, _DSSET_IE_, 1, (unsigned char *)&(cur_network->Configuration.DSConfig), &pattrib->pktlen);
 417
 418        {
 419                u8 erpinfo = 0;
 420                u32 ATIMWindow;
 421                /*  IBSS Parameter Set... */
 422                ATIMWindow = 0;
 423                pframe = rtw_set_ie(pframe, _IBSS_PARA_IE_, 2, (unsigned char *)(&ATIMWindow), &pattrib->pktlen);
 424
 425                /* ERP IE */
 426                pframe = rtw_set_ie(pframe, _ERPINFO_IE_, 1, &erpinfo, &pattrib->pktlen);
 427        }
 428
 429        /*  EXTERNDED SUPPORTED RATE */
 430        if (rate_len > 8)
 431                pframe = rtw_set_ie(pframe, _EXT_SUPPORTEDRATES_IE_, (rate_len - 8), (cur_network->SupportedRates + 8), &pattrib->pktlen);
 432        /* todo:HT for adhoc */
 433_issue_bcn:
 434
 435#if defined(CONFIG_88EU_AP_MODE)
 436        pmlmepriv->update_bcn = false;
 437
 438        spin_unlock_bh(&pmlmepriv->bcn_update_lock);
 439#endif /* if defined (CONFIG_88EU_AP_MODE) */
 440
 441        if ((pattrib->pktlen + TXDESC_SIZE) > 512) {
 442                DBG_88E("beacon frame too large\n");
 443                return;
 444        }
 445
 446        pattrib->last_txcmdsz = pattrib->pktlen;
 447
 448        /* DBG_88E("issue bcn_sz=%d\n", pattrib->last_txcmdsz); */
 449        if (timeout_ms > 0)
 450                dump_mgntframe_and_wait(padapter, pmgntframe, timeout_ms);
 451        else
 452                dump_mgntframe(padapter, pmgntframe);
 453}
 454
 455static void issue_probersp(struct adapter *padapter, unsigned char *da)
 456{
 457        struct xmit_frame                       *pmgntframe;
 458        struct pkt_attrib                       *pattrib;
 459        unsigned char                                   *pframe;
 460        struct ieee80211_hdr *pwlanhdr;
 461        __le16 *fctrl;
 462        unsigned char                                   *mac, *bssid;
 463        struct xmit_priv        *pxmitpriv = &(padapter->xmitpriv);
 464#if defined(CONFIG_88EU_AP_MODE)
 465        u8 *pwps_ie;
 466        uint wps_ielen;
 467        struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
 468#endif /* if defined (CONFIG_88EU_AP_MODE) */
 469        struct mlme_ext_priv    *pmlmeext = &(padapter->mlmeextpriv);
 470        struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
 471        struct wlan_bssid_ex            *cur_network = &(pmlmeinfo->network);
 472        unsigned int    rate_len;
 473
 474        pmgntframe = alloc_mgtxmitframe(pxmitpriv);
 475        if (!pmgntframe) {
 476                DBG_88E("%s, alloc mgnt frame fail\n", __func__);
 477                return;
 478        }
 479
 480        /* update attribute */
 481        pattrib = &pmgntframe->attrib;
 482        update_mgntframe_attrib(padapter, pattrib);
 483
 484        memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
 485
 486        pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
 487        pwlanhdr = (struct ieee80211_hdr *)pframe;
 488
 489        mac = myid(&(padapter->eeprompriv));
 490        bssid = cur_network->MacAddress;
 491
 492        fctrl = &pwlanhdr->frame_control;
 493        *(fctrl) = 0;
 494        ether_addr_copy(pwlanhdr->addr1, da);
 495        ether_addr_copy(pwlanhdr->addr2, mac);
 496        ether_addr_copy(pwlanhdr->addr3, bssid);
 497
 498        SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
 499        pmlmeext->mgnt_seq++;
 500        SetFrameSubType(fctrl, WIFI_PROBERSP);
 501
 502        pattrib->hdrlen = sizeof(struct ieee80211_hdr_3addr);
 503        pattrib->pktlen = pattrib->hdrlen;
 504        pframe += pattrib->hdrlen;
 505
 506        if (cur_network->ie_length > MAX_IE_SZ)
 507                return;
 508
 509#if defined(CONFIG_88EU_AP_MODE)
 510        if ((pmlmeinfo->state&0x03) == WIFI_FW_AP_STATE) {
 511                pwps_ie = rtw_get_wps_ie(cur_network->ies+_FIXED_IE_LENGTH_, cur_network->ie_length-_FIXED_IE_LENGTH_, NULL, &wps_ielen);
 512
 513                /* inerset & update wps_probe_resp_ie */
 514                if ((pmlmepriv->wps_probe_resp_ie != NULL) && pwps_ie && (wps_ielen > 0)) {
 515                        uint wps_offset, remainder_ielen;
 516                        u8 *premainder_ie;
 517
 518                        wps_offset = (uint)(pwps_ie - cur_network->ies);
 519
 520                        premainder_ie = pwps_ie + wps_ielen;
 521
 522                        remainder_ielen = cur_network->ie_length - wps_offset - wps_ielen;
 523
 524                        memcpy(pframe, cur_network->ies, wps_offset);
 525                        pframe += wps_offset;
 526                        pattrib->pktlen += wps_offset;
 527
 528                        wps_ielen = (uint)pmlmepriv->wps_probe_resp_ie[1];/* to get ie data len */
 529                        if ((wps_offset+wps_ielen+2) <= MAX_IE_SZ) {
 530                                memcpy(pframe, pmlmepriv->wps_probe_resp_ie, wps_ielen+2);
 531                                pframe += wps_ielen+2;
 532                                pattrib->pktlen += wps_ielen+2;
 533                        }
 534
 535                        if ((wps_offset+wps_ielen+2+remainder_ielen) <= MAX_IE_SZ) {
 536                                memcpy(pframe, premainder_ie, remainder_ielen);
 537                                pframe += remainder_ielen;
 538                                pattrib->pktlen += remainder_ielen;
 539                        }
 540                } else {
 541                        memcpy(pframe, cur_network->ies, cur_network->ie_length);
 542                        pframe += cur_network->ie_length;
 543                        pattrib->pktlen += cur_network->ie_length;
 544                }
 545        } else
 546#endif
 547        {
 548                /* timestamp will be inserted by hardware */
 549                pframe += 8;
 550                pattrib->pktlen += 8;
 551
 552                /*  beacon interval: 2 bytes */
 553
 554                memcpy(pframe, (unsigned char *)(rtw_get_beacon_interval_from_ie(cur_network->ies)), 2);
 555
 556                pframe += 2;
 557                pattrib->pktlen += 2;
 558
 559                /*  capability info: 2 bytes */
 560
 561                memcpy(pframe, (unsigned char *)(rtw_get_capability_from_ie(cur_network->ies)), 2);
 562
 563                pframe += 2;
 564                pattrib->pktlen += 2;
 565
 566                /* below for ad-hoc mode */
 567
 568                /*  SSID */
 569                pframe = rtw_set_ie(pframe, _SSID_IE_, cur_network->Ssid.SsidLength, cur_network->Ssid.Ssid, &pattrib->pktlen);
 570
 571                /*  supported rates... */
 572                rate_len = rtw_get_rateset_len(cur_network->SupportedRates);
 573                pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_, min_t(unsigned int, rate_len, 8), cur_network->SupportedRates, &pattrib->pktlen);
 574
 575                /*  DS parameter set */
 576                pframe = rtw_set_ie(pframe, _DSSET_IE_, 1, (unsigned char *)&(cur_network->Configuration.DSConfig), &pattrib->pktlen);
 577
 578                if ((pmlmeinfo->state&0x03) == WIFI_FW_ADHOC_STATE) {
 579                        u8 erpinfo = 0;
 580                        u32 ATIMWindow;
 581                        /*  IBSS Parameter Set... */
 582                        /* ATIMWindow = cur->Configuration.ATIMWindow; */
 583                        ATIMWindow = 0;
 584                        pframe = rtw_set_ie(pframe, _IBSS_PARA_IE_, 2, (unsigned char *)(&ATIMWindow), &pattrib->pktlen);
 585
 586                        /* ERP IE */
 587                        pframe = rtw_set_ie(pframe, _ERPINFO_IE_, 1, &erpinfo, &pattrib->pktlen);
 588                }
 589
 590                /*  EXTERNDED SUPPORTED RATE */
 591                if (rate_len > 8)
 592                        pframe = rtw_set_ie(pframe, _EXT_SUPPORTEDRATES_IE_, (rate_len - 8), (cur_network->SupportedRates + 8), &pattrib->pktlen);
 593                /* todo:HT for adhoc */
 594        }
 595
 596        pattrib->last_txcmdsz = pattrib->pktlen;
 597
 598        dump_mgntframe(padapter, pmgntframe);
 599}
 600
 601static int issue_probereq(struct adapter *padapter,
 602                          struct ndis_802_11_ssid *pssid, u8 *da,
 603                          bool wait_ack)
 604{
 605        int ret = _FAIL;
 606        struct xmit_frame               *pmgntframe;
 607        struct pkt_attrib               *pattrib;
 608        unsigned char                   *pframe;
 609        struct ieee80211_hdr *pwlanhdr;
 610        __le16 *fctrl;
 611        unsigned char                   *mac;
 612        unsigned char                   bssrate[NumRates];
 613        struct xmit_priv                *pxmitpriv = &(padapter->xmitpriv);
 614        struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
 615        struct mlme_ext_priv    *pmlmeext = &(padapter->mlmeextpriv);
 616        int     bssrate_len = 0;
 617        u8      bc_addr[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
 618
 619        RT_TRACE(_module_rtl871x_mlme_c_, _drv_notice_, ("+%s\n", __func__));
 620
 621        pmgntframe = alloc_mgtxmitframe(pxmitpriv);
 622        if (!pmgntframe)
 623                goto exit;
 624
 625        /* update attribute */
 626        pattrib = &pmgntframe->attrib;
 627        update_mgntframe_attrib(padapter, pattrib);
 628
 629        memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
 630
 631        pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
 632        pwlanhdr = (struct ieee80211_hdr *)pframe;
 633
 634        mac = myid(&(padapter->eeprompriv));
 635
 636        fctrl = &pwlanhdr->frame_control;
 637        *(fctrl) = 0;
 638
 639        if (da) {
 640                /*      unicast probe request frame */
 641                ether_addr_copy(pwlanhdr->addr1, da);
 642                ether_addr_copy(pwlanhdr->addr3, da);
 643        } else {
 644                /*      broadcast probe request frame */
 645                ether_addr_copy(pwlanhdr->addr1, bc_addr);
 646                ether_addr_copy(pwlanhdr->addr3, bc_addr);
 647        }
 648
 649        ether_addr_copy(pwlanhdr->addr2, mac);
 650
 651        SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
 652        pmlmeext->mgnt_seq++;
 653        SetFrameSubType(pframe, WIFI_PROBEREQ);
 654
 655        pframe += sizeof(struct ieee80211_hdr_3addr);
 656        pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr);
 657
 658        if (pssid)
 659                pframe = rtw_set_ie(pframe, _SSID_IE_, pssid->SsidLength, pssid->Ssid, &(pattrib->pktlen));
 660        else
 661                pframe = rtw_set_ie(pframe, _SSID_IE_, 0, NULL, &(pattrib->pktlen));
 662
 663        get_rate_set(padapter, bssrate, &bssrate_len);
 664
 665        if (bssrate_len > 8) {
 666                pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_, 8, bssrate, &(pattrib->pktlen));
 667                pframe = rtw_set_ie(pframe, _EXT_SUPPORTEDRATES_IE_, (bssrate_len - 8), (bssrate + 8), &(pattrib->pktlen));
 668        } else {
 669                pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_, bssrate_len, bssrate, &(pattrib->pktlen));
 670        }
 671
 672        /* add wps_ie for wps2.0 */
 673        if (pmlmepriv->wps_probe_req_ie_len > 0 && pmlmepriv->wps_probe_req_ie) {
 674                memcpy(pframe, pmlmepriv->wps_probe_req_ie, pmlmepriv->wps_probe_req_ie_len);
 675                pframe += pmlmepriv->wps_probe_req_ie_len;
 676                pattrib->pktlen += pmlmepriv->wps_probe_req_ie_len;
 677        }
 678
 679        pattrib->last_txcmdsz = pattrib->pktlen;
 680
 681        RT_TRACE(_module_rtl871x_mlme_c_, _drv_notice_,
 682                 ("issuing probe_req, tx_len=%d\n", pattrib->last_txcmdsz));
 683
 684        if (wait_ack) {
 685                ret = dump_mgntframe_and_wait_ack(padapter, pmgntframe);
 686        } else {
 687                dump_mgntframe(padapter, pmgntframe);
 688                ret = _SUCCESS;
 689        }
 690
 691exit:
 692        return ret;
 693}
 694
 695static int issue_probereq_ex(struct adapter *padapter,
 696                             struct ndis_802_11_ssid *pssid, u8 *da,
 697                             int try_cnt, int wait_ms)
 698{
 699        int ret;
 700        int i = 0;
 701        unsigned long start = jiffies;
 702
 703        do {
 704                ret = issue_probereq(padapter, pssid, da, wait_ms > 0);
 705
 706                i++;
 707
 708                if (padapter->bDriverStopped || padapter->bSurpriseRemoved)
 709                        break;
 710
 711                if (i < try_cnt && wait_ms > 0 && ret == _FAIL)
 712                        msleep(wait_ms);
 713
 714        } while ((i < try_cnt) && ((ret == _FAIL) || (wait_ms == 0)));
 715
 716        if (ret != _FAIL) {
 717                ret = _SUCCESS;
 718                goto exit;
 719        }
 720
 721        if (try_cnt && wait_ms) {
 722                if (da)
 723                        DBG_88E(FUNC_ADPT_FMT" to %pM, ch:%u%s, %d/%d in %u ms\n",
 724                                FUNC_ADPT_ARG(padapter), da, rtw_get_oper_ch(padapter),
 725                                ret == _SUCCESS ? ", acked" : "", i, try_cnt,
 726                                jiffies_to_msecs(jiffies - start));
 727                else
 728                        DBG_88E(FUNC_ADPT_FMT", ch:%u%s, %d/%d in %u ms\n",
 729                                FUNC_ADPT_ARG(padapter), rtw_get_oper_ch(padapter),
 730                                ret == _SUCCESS ? ", acked" : "", i, try_cnt,
 731                                jiffies_to_msecs(jiffies - start));
 732        }
 733exit:
 734        return ret;
 735}
 736
 737/*  if psta == NULL, indicate we are station(client) now... */
 738static void issue_auth(struct adapter *padapter, struct sta_info *psta,
 739                       unsigned short status)
 740{
 741        struct xmit_frame *pmgntframe;
 742        struct pkt_attrib *pattrib;
 743        unsigned char *pframe;
 744        struct ieee80211_hdr *pwlanhdr;
 745        __le16 *fctrl;
 746        unsigned int val32;
 747        u16 val16;
 748#ifdef CONFIG_88EU_AP_MODE
 749        __le16 le_val16;
 750#endif
 751        int use_shared_key = 0;
 752        struct xmit_priv *pxmitpriv = &(padapter->xmitpriv);
 753        struct mlme_ext_priv    *pmlmeext = &(padapter->mlmeextpriv);
 754        struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
 755        struct wlan_bssid_ex    *pnetwork = &(pmlmeinfo->network);
 756
 757        pmgntframe = alloc_mgtxmitframe(pxmitpriv);
 758        if (pmgntframe == NULL)
 759                return;
 760
 761        /* update attribute */
 762        pattrib = &pmgntframe->attrib;
 763        update_mgntframe_attrib(padapter, pattrib);
 764
 765        memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
 766
 767        pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
 768        pwlanhdr = (struct ieee80211_hdr *)pframe;
 769
 770        fctrl = &pwlanhdr->frame_control;
 771        *(fctrl) = 0;
 772
 773        SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
 774        pmlmeext->mgnt_seq++;
 775        SetFrameSubType(pframe, WIFI_AUTH);
 776
 777        pframe += sizeof(struct ieee80211_hdr_3addr);
 778        pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr);
 779
 780        if (psta) {/*  for AP mode */
 781#ifdef CONFIG_88EU_AP_MODE
 782
 783                ether_addr_copy(pwlanhdr->addr1, psta->hwaddr);
 784                ether_addr_copy(pwlanhdr->addr2,
 785                                myid(&(padapter->eeprompriv)));
 786                ether_addr_copy(pwlanhdr->addr3,
 787                                myid(&(padapter->eeprompriv)));
 788
 789                /*  setting auth algo number */
 790                val16 = (u16)psta->authalg;
 791
 792                if (status != _STATS_SUCCESSFUL_)
 793                        val16 = 0;
 794
 795                if (val16) {
 796                        le_val16 = cpu_to_le16(val16);
 797                        use_shared_key = 1;
 798                } else {
 799                        le_val16 = 0;
 800                }
 801
 802                pframe = rtw_set_fixed_ie(pframe, _AUTH_ALGM_NUM_, &le_val16,
 803                                          &pattrib->pktlen);
 804
 805                /*  setting auth seq number */
 806                val16 = (u16)psta->auth_seq;
 807                le_val16 = cpu_to_le16(val16);
 808                pframe = rtw_set_fixed_ie(pframe, _AUTH_SEQ_NUM_, &le_val16,
 809                                          &pattrib->pktlen);
 810
 811                /*  setting status code... */
 812                val16 = status;
 813                le_val16 = cpu_to_le16(val16);
 814                pframe = rtw_set_fixed_ie(pframe, _STATUS_CODE_,
 815                                          &le_val16, &pattrib->pktlen);
 816
 817                /*  added challenging text... */
 818                if ((psta->auth_seq == 2) && (psta->state & WIFI_FW_AUTH_STATE) && (use_shared_key == 1))
 819                        pframe = rtw_set_ie(pframe, _CHLGETXT_IE_, 128, psta->chg_txt, &(pattrib->pktlen));
 820#endif
 821        } else {
 822                __le32 le_tmp32;
 823                __le16 le_tmp16;
 824
 825                ether_addr_copy(pwlanhdr->addr1, pnetwork->MacAddress);
 826                ether_addr_copy(pwlanhdr->addr2, myid(&padapter->eeprompriv));
 827                ether_addr_copy(pwlanhdr->addr3, pnetwork->MacAddress);
 828
 829                /*  setting auth algo number */
 830                val16 = (pmlmeinfo->auth_algo == dot11AuthAlgrthm_Shared) ? 1 : 0;/*  0:OPEN System, 1:Shared key */
 831                if (val16)
 832                        use_shared_key = 1;
 833
 834                /* setting IV for auth seq #3 */
 835                if ((pmlmeinfo->auth_seq == 3) && (pmlmeinfo->state & WIFI_FW_AUTH_STATE) && (use_shared_key == 1)) {
 836                        val32 = (pmlmeinfo->iv++) | (pmlmeinfo->key_index << 30);
 837                        le_tmp32 = cpu_to_le32(val32);
 838                        pframe = rtw_set_fixed_ie(pframe, 4, &le_tmp32,
 839                                                  &pattrib->pktlen);
 840
 841                        pattrib->iv_len = 4;
 842                }
 843
 844                le_tmp16 = cpu_to_le16(val16);
 845                pframe = rtw_set_fixed_ie(pframe, _AUTH_ALGM_NUM_, &le_tmp16,
 846                                          &pattrib->pktlen);
 847
 848                /*  setting auth seq number */
 849                val16 = pmlmeinfo->auth_seq;
 850                le_tmp16 = cpu_to_le16(val16);
 851                pframe = rtw_set_fixed_ie(pframe, _AUTH_SEQ_NUM_, &le_tmp16,
 852                                          &pattrib->pktlen);
 853
 854                /*  setting status code... */
 855                le_tmp16 = cpu_to_le16(status);
 856                pframe = rtw_set_fixed_ie(pframe, _STATUS_CODE_, &le_tmp16,
 857                                          &pattrib->pktlen);
 858
 859                /*  then checking to see if sending challenging text... */
 860                if ((pmlmeinfo->auth_seq == 3) && (pmlmeinfo->state & WIFI_FW_AUTH_STATE) && (use_shared_key == 1)) {
 861                        pframe = rtw_set_ie(pframe, _CHLGETXT_IE_, 128, pmlmeinfo->chg_txt, &(pattrib->pktlen));
 862
 863                        SetPrivacy(fctrl);
 864
 865                        pattrib->hdrlen = sizeof(struct ieee80211_hdr_3addr);
 866
 867                        pattrib->encrypt = _WEP40_;
 868
 869                        pattrib->icv_len = 4;
 870
 871                        pattrib->pktlen += pattrib->icv_len;
 872                }
 873        }
 874
 875        pattrib->last_txcmdsz = pattrib->pktlen;
 876
 877        rtw_wep_encrypt(padapter, (u8 *)pmgntframe);
 878        DBG_88E("%s\n", __func__);
 879        dump_mgntframe(padapter, pmgntframe);
 880}
 881
 882#ifdef CONFIG_88EU_AP_MODE
 883static void issue_asocrsp(struct adapter *padapter, unsigned short status,
 884                          struct sta_info *pstat, int pkt_type)
 885{
 886        struct xmit_frame       *pmgntframe;
 887        struct ieee80211_hdr *pwlanhdr;
 888        struct pkt_attrib *pattrib;
 889        unsigned char   *pbuf, *pframe;
 890        unsigned short val;
 891        __le16 *fctrl;
 892        struct xmit_priv *pxmitpriv = &(padapter->xmitpriv);
 893        struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
 894        struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
 895        struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
 896        struct wlan_bssid_ex *pnetwork = &(pmlmeinfo->network);
 897        u8 *ie = pnetwork->ies;
 898        __le16 lestatus, leval;
 899
 900        DBG_88E("%s\n", __func__);
 901
 902        pmgntframe = alloc_mgtxmitframe(pxmitpriv);
 903        if (!pmgntframe)
 904                return;
 905
 906        /* update attribute */
 907        pattrib = &pmgntframe->attrib;
 908        update_mgntframe_attrib(padapter, pattrib);
 909
 910        memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
 911
 912        pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
 913        pwlanhdr = (struct ieee80211_hdr *)pframe;
 914
 915        fctrl = &pwlanhdr->frame_control;
 916        *(fctrl) = 0;
 917
 918        ether_addr_copy((void *)GetAddr1Ptr(pwlanhdr), pstat->hwaddr);
 919        ether_addr_copy((void *)GetAddr2Ptr(pwlanhdr),
 920                        myid(&(padapter->eeprompriv)));
 921        ether_addr_copy((void *)GetAddr3Ptr(pwlanhdr), pnetwork->MacAddress);
 922
 923        SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
 924        pmlmeext->mgnt_seq++;
 925        if ((pkt_type == WIFI_ASSOCRSP) || (pkt_type == WIFI_REASSOCRSP))
 926                SetFrameSubType(pwlanhdr, pkt_type);
 927        else
 928                return;
 929
 930        pattrib->hdrlen = sizeof(struct ieee80211_hdr_3addr);
 931        pattrib->pktlen += pattrib->hdrlen;
 932        pframe += pattrib->hdrlen;
 933
 934        /* capability */
 935        val = *(unsigned short *)rtw_get_capability_from_ie(ie);
 936
 937        pframe = rtw_set_fixed_ie(pframe, _CAPABILITY_, &val, &pattrib->pktlen);
 938
 939        lestatus = cpu_to_le16(status);
 940        pframe = rtw_set_fixed_ie(pframe, _STATUS_CODE_, &lestatus,
 941                                  &pattrib->pktlen);
 942
 943        leval = cpu_to_le16(pstat->aid | BIT(14) | BIT(15));
 944        pframe = rtw_set_fixed_ie(pframe, _ASOC_ID_, &leval, &pattrib->pktlen);
 945
 946        if (pstat->bssratelen <= 8) {
 947                pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_, pstat->bssratelen, pstat->bssrateset, &(pattrib->pktlen));
 948        } else {
 949                pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_, 8, pstat->bssrateset, &(pattrib->pktlen));
 950                pframe = rtw_set_ie(pframe, _EXT_SUPPORTEDRATES_IE_, (pstat->bssratelen-8), pstat->bssrateset+8, &(pattrib->pktlen));
 951        }
 952
 953        if ((pstat->flags & WLAN_STA_HT) && (pmlmepriv->htpriv.ht_option)) {
 954                uint ie_len = 0;
 955
 956                /* FILL HT CAP INFO IE */
 957                pbuf = rtw_get_ie(ie + _BEACON_IE_OFFSET_, _HT_CAPABILITY_IE_, &ie_len, (pnetwork->ie_length - _BEACON_IE_OFFSET_));
 958                if (pbuf && ie_len > 0) {
 959                        memcpy(pframe, pbuf, ie_len+2);
 960                        pframe += (ie_len+2);
 961                        pattrib->pktlen += (ie_len+2);
 962                }
 963
 964                /* FILL HT ADD INFO IE */
 965                pbuf = rtw_get_ie(ie + _BEACON_IE_OFFSET_, _HT_ADD_INFO_IE_, &ie_len, (pnetwork->ie_length - _BEACON_IE_OFFSET_));
 966                if (pbuf && ie_len > 0) {
 967                        memcpy(pframe, pbuf, ie_len+2);
 968                        pframe += (ie_len+2);
 969                        pattrib->pktlen += (ie_len+2);
 970                }
 971        }
 972
 973        /* FILL WMM IE */
 974        if ((pstat->flags & WLAN_STA_WME) && (pmlmepriv->qospriv.qos_option)) {
 975                uint ie_len = 0;
 976                unsigned char WMM_PARA_IE[] = {0x00, 0x50, 0xf2, 0x02, 0x01, 0x01};
 977
 978                for (pbuf = ie + _BEACON_IE_OFFSET_;; pbuf += (ie_len + 2)) {
 979                        pbuf = rtw_get_ie(pbuf, _VENDOR_SPECIFIC_IE_, &ie_len, (pnetwork->ie_length - _BEACON_IE_OFFSET_ - (ie_len + 2)));
 980                        if (pbuf && !memcmp(pbuf+2, WMM_PARA_IE, 6)) {
 981                                memcpy(pframe, pbuf, ie_len+2);
 982                                pframe += (ie_len+2);
 983                                pattrib->pktlen += (ie_len+2);
 984                                break;
 985                        }
 986
 987                        if ((pbuf == NULL) || (ie_len == 0))
 988                                break;
 989                }
 990        }
 991
 992        if (pmlmeinfo->assoc_AP_vendor == HT_IOT_PEER_REALTEK)
 993                pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, 6, REALTEK_96B_IE, &(pattrib->pktlen));
 994
 995        /* add WPS IE ie for wps 2.0 */
 996        if (pmlmepriv->wps_assoc_resp_ie && pmlmepriv->wps_assoc_resp_ie_len > 0) {
 997                memcpy(pframe, pmlmepriv->wps_assoc_resp_ie, pmlmepriv->wps_assoc_resp_ie_len);
 998
 999                pframe += pmlmepriv->wps_assoc_resp_ie_len;
1000                pattrib->pktlen += pmlmepriv->wps_assoc_resp_ie_len;
1001        }
1002
1003        pattrib->last_txcmdsz = pattrib->pktlen;
1004        dump_mgntframe(padapter, pmgntframe);
1005}
1006#endif /* CONFIG_88EU_AP_MODE */
1007
1008static void issue_assocreq(struct adapter *padapter)
1009{
1010        int ret = _FAIL;
1011        struct xmit_frame       *pmgntframe;
1012        struct pkt_attrib       *pattrib;
1013        unsigned char           *pframe, *p;
1014        struct ieee80211_hdr *pwlanhdr;
1015        __le16 *fctrl;
1016        unsigned int    i, j, ie_len, index = 0;
1017        unsigned char bssrate[NumRates], sta_bssrate[NumRates];
1018        struct ndis_802_11_var_ie *pIE;
1019        struct registry_priv    *pregpriv = &padapter->registrypriv;
1020        struct xmit_priv                *pxmitpriv = &(padapter->xmitpriv);
1021        struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
1022        struct mlme_ext_priv    *pmlmeext = &(padapter->mlmeextpriv);
1023        struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
1024        int     bssrate_len = 0, sta_bssrate_len = 0;
1025        struct wlan_bssid_ex    *pnetwork = &(pmlmeinfo->network);
1026
1027        pmgntframe = alloc_mgtxmitframe(pxmitpriv);
1028        if (!pmgntframe)
1029                goto exit;
1030
1031        /* update attribute */
1032        pattrib = &pmgntframe->attrib;
1033        update_mgntframe_attrib(padapter, pattrib);
1034
1035        memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
1036        pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
1037        pwlanhdr = (struct ieee80211_hdr *)pframe;
1038
1039        fctrl = &pwlanhdr->frame_control;
1040        *(fctrl) = 0;
1041        ether_addr_copy(pwlanhdr->addr1, pnetwork->MacAddress);
1042        ether_addr_copy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)));
1043        ether_addr_copy(pwlanhdr->addr3, pnetwork->MacAddress);
1044
1045        SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
1046        pmlmeext->mgnt_seq++;
1047        SetFrameSubType(pframe, WIFI_ASSOCREQ);
1048
1049        pframe += sizeof(struct ieee80211_hdr_3addr);
1050        pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr);
1051
1052        /* caps */
1053
1054        memcpy(pframe, rtw_get_capability_from_ie(pmlmeinfo->network.ies), 2);
1055
1056        pframe += 2;
1057        pattrib->pktlen += 2;
1058
1059        /* listen interval */
1060        /* todo: listen interval for power saving */
1061        put_unaligned_le16(3, pframe);
1062        pframe += 2;
1063        pattrib->pktlen += 2;
1064
1065        /* SSID */
1066        pframe = rtw_set_ie(pframe, _SSID_IE_,  pmlmeinfo->network.Ssid.SsidLength, pmlmeinfo->network.Ssid.Ssid, &(pattrib->pktlen));
1067
1068        /* supported rate & extended supported rate */
1069
1070        /*  Check if the AP's supported rates are also supported by STA. */
1071        get_rate_set(padapter, sta_bssrate, &sta_bssrate_len);
1072
1073        if (pmlmeext->cur_channel == 14)/*  for JAPAN, channel 14 can only uses B Mode(CCK) */
1074                sta_bssrate_len = 4;
1075
1076        for (i = 0; i < NDIS_802_11_LENGTH_RATES_EX; i++) {
1077                if (pmlmeinfo->network.SupportedRates[i] == 0)
1078                        break;
1079                DBG_88E("network.SupportedRates[%d]=%02X\n", i, pmlmeinfo->network.SupportedRates[i]);
1080        }
1081
1082        for (i = 0; i < NDIS_802_11_LENGTH_RATES_EX; i++) {
1083                if (pmlmeinfo->network.SupportedRates[i] == 0)
1084                        break;
1085
1086                /*  Check if the AP's supported rates are also supported by STA. */
1087                for (j = 0; j < sta_bssrate_len; j++) {
1088                        /*  Avoid the proprietary data rate (22Mbps) of Handlink WSG-4000 AP */
1089                        if ((pmlmeinfo->network.SupportedRates[i]|IEEE80211_BASIC_RATE_MASK)
1090                                        == (sta_bssrate[j]|IEEE80211_BASIC_RATE_MASK))
1091                                break;
1092                }
1093
1094                if (j == sta_bssrate_len) {
1095                        /*  the rate is not supported by STA */
1096                        DBG_88E("%s(): the rate[%d]=%02X is not supported by STA!\n", __func__, i, pmlmeinfo->network.SupportedRates[i]);
1097                } else {
1098                        /*  the rate is supported by STA */
1099                        bssrate[index++] = pmlmeinfo->network.SupportedRates[i];
1100                }
1101        }
1102
1103        bssrate_len = index;
1104        DBG_88E("bssrate_len=%d\n", bssrate_len);
1105
1106        if (bssrate_len == 0) {
1107                rtw_free_xmitbuf(pxmitpriv, pmgntframe->pxmitbuf);
1108                rtw_free_xmitframe(pxmitpriv, pmgntframe);
1109                goto exit; /* don't connect to AP if no joint supported rate */
1110        }
1111
1112        if (bssrate_len > 8) {
1113                pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_, 8, bssrate, &(pattrib->pktlen));
1114                pframe = rtw_set_ie(pframe, _EXT_SUPPORTEDRATES_IE_, (bssrate_len - 8), (bssrate + 8), &(pattrib->pktlen));
1115        } else {
1116                pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_, bssrate_len, bssrate, &(pattrib->pktlen));
1117        }
1118
1119        /* RSN */
1120        p = rtw_get_ie((pmlmeinfo->network.ies + sizeof(struct ndis_802_11_fixed_ie)), _RSN_IE_2_, &ie_len, (pmlmeinfo->network.ie_length - sizeof(struct ndis_802_11_fixed_ie)));
1121        if (p)
1122                pframe = rtw_set_ie(pframe, _RSN_IE_2_, ie_len, (p + 2), &(pattrib->pktlen));
1123
1124        /* HT caps */
1125        if (padapter->mlmepriv.htpriv.ht_option) {
1126                p = rtw_get_ie((pmlmeinfo->network.ies + sizeof(struct ndis_802_11_fixed_ie)), _HT_CAPABILITY_IE_, &ie_len, (pmlmeinfo->network.ie_length - sizeof(struct ndis_802_11_fixed_ie)));
1127                if ((p != NULL) && (!(is_ap_in_tkip(padapter)))) {
1128                        memcpy(&pmlmeinfo->HT_caps, p + 2, sizeof(struct ieee80211_ht_cap));
1129
1130                        /* to disable 40M Hz support while gd_bw_40MHz_en = 0 */
1131                        if (pregpriv->cbw40_enable == 0)
1132                                pmlmeinfo->HT_caps.cap_info &= cpu_to_le16(~(BIT(6) | BIT(1)));
1133                        else
1134                                pmlmeinfo->HT_caps.cap_info |= cpu_to_le16(BIT(1));
1135
1136                        /* todo: disable SM power save mode */
1137                        pmlmeinfo->HT_caps.cap_info |= cpu_to_le16(0x000c);
1138
1139                        if (pregpriv->rx_stbc)
1140                                pmlmeinfo->HT_caps.cap_info |= cpu_to_le16(0x0100);/* RX STBC One spatial stream */
1141                        memcpy((u8 *)&pmlmeinfo->HT_caps.mcs, MCS_rate_1R, 16);
1142                        pframe = rtw_set_ie(pframe, _HT_CAPABILITY_IE_, ie_len, (u8 *)(&(pmlmeinfo->HT_caps)), &(pattrib->pktlen));
1143                }
1144        }
1145
1146        /* vendor specific IE, such as WPA, WMM, WPS */
1147        for (i = sizeof(struct ndis_802_11_fixed_ie); i < pmlmeinfo->network.ie_length; i += (pIE->Length + 2)) {
1148                pIE = (struct ndis_802_11_var_ie *)(pmlmeinfo->network.ies + i);
1149
1150                switch (pIE->ElementID) {
1151                case _VENDOR_SPECIFIC_IE_:
1152                        if ((!memcmp(pIE->data, RTW_WPA_OUI, 4)) ||
1153                            (!memcmp(pIE->data, WMM_OUI, 4)) ||
1154                            (!memcmp(pIE->data, WPS_OUI, 4))) {
1155                                if (!padapter->registrypriv.wifi_spec) {
1156                                        /* Commented by Kurt 20110629 */
1157                                        /* In some older APs, WPS handshake */
1158                                        /* would be fail if we append vender extensions informations to AP */
1159                                        if (!memcmp(pIE->data, WPS_OUI, 4))
1160                                                pIE->Length = 14;
1161                                }
1162                                pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, pIE->Length, pIE->data, &(pattrib->pktlen));
1163                        }
1164                        break;
1165                default:
1166                        break;
1167                }
1168        }
1169
1170        if (pmlmeinfo->assoc_AP_vendor == HT_IOT_PEER_REALTEK)
1171                pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, 6, REALTEK_96B_IE, &(pattrib->pktlen));
1172
1173        pattrib->last_txcmdsz = pattrib->pktlen;
1174        dump_mgntframe(padapter, pmgntframe);
1175
1176        ret = _SUCCESS;
1177
1178exit:
1179        if (ret == _SUCCESS)
1180                rtw_buf_update(&pmlmepriv->assoc_req, &pmlmepriv->assoc_req_len, (u8 *)pwlanhdr, pattrib->pktlen);
1181        else
1182                rtw_buf_free(&pmlmepriv->assoc_req, &pmlmepriv->assoc_req_len);
1183}
1184
1185/* when wait_ack is true, this function should be called at process context */
1186static int _issue_nulldata(struct adapter *padapter, unsigned char *da,
1187                           unsigned int power_mode, bool wait_ack)
1188{
1189        int ret = _FAIL;
1190        struct xmit_frame                       *pmgntframe;
1191        struct pkt_attrib                       *pattrib;
1192        unsigned char                                   *pframe;
1193        struct ieee80211_hdr *pwlanhdr;
1194        __le16 *fctrl;
1195        struct xmit_priv        *pxmitpriv;
1196        struct mlme_ext_priv    *pmlmeext;
1197        struct mlme_ext_info    *pmlmeinfo;
1198        struct wlan_bssid_ex    *pnetwork;
1199
1200        if (!padapter)
1201                goto exit;
1202
1203        pxmitpriv = &(padapter->xmitpriv);
1204        pmlmeext = &(padapter->mlmeextpriv);
1205        pmlmeinfo = &(pmlmeext->mlmext_info);
1206        pnetwork = &(pmlmeinfo->network);
1207
1208        pmgntframe = alloc_mgtxmitframe(pxmitpriv);
1209        if (!pmgntframe)
1210                goto exit;
1211
1212        /* update attribute */
1213        pattrib = &pmgntframe->attrib;
1214        update_mgntframe_attrib(padapter, pattrib);
1215        pattrib->retry_ctrl = false;
1216
1217        memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
1218
1219        pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
1220        pwlanhdr = (struct ieee80211_hdr *)pframe;
1221
1222        fctrl = &pwlanhdr->frame_control;
1223        *(fctrl) = 0;
1224
1225        if ((pmlmeinfo->state&0x03) == WIFI_FW_AP_STATE)
1226                SetFrDs(fctrl);
1227        else if ((pmlmeinfo->state&0x03) == WIFI_FW_STATION_STATE)
1228                SetToDs(fctrl);
1229
1230        if (power_mode)
1231                SetPwrMgt(fctrl);
1232
1233        ether_addr_copy(pwlanhdr->addr1, da);
1234        ether_addr_copy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)));
1235        ether_addr_copy(pwlanhdr->addr3, pnetwork->MacAddress);
1236
1237        SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
1238        pmlmeext->mgnt_seq++;
1239        SetFrameSubType(pframe, WIFI_DATA_NULL);
1240
1241        pframe += sizeof(struct ieee80211_hdr_3addr);
1242        pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr);
1243
1244        pattrib->last_txcmdsz = pattrib->pktlen;
1245
1246        if (wait_ack) {
1247                ret = dump_mgntframe_and_wait_ack(padapter, pmgntframe);
1248        } else {
1249                dump_mgntframe(padapter, pmgntframe);
1250                ret = _SUCCESS;
1251        }
1252
1253exit:
1254        return ret;
1255}
1256
1257/* when wait_ms > 0 , this function should be called at process context */
1258/* da == NULL for station mode */
1259int issue_nulldata(struct adapter *padapter, unsigned char *da,
1260                   unsigned int power_mode, int try_cnt, int wait_ms)
1261{
1262        int ret;
1263        int i = 0;
1264        unsigned long start = jiffies;
1265        struct mlme_ext_priv    *pmlmeext = &(padapter->mlmeextpriv);
1266        struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
1267        struct wlan_bssid_ex    *pnetwork = &(pmlmeinfo->network);
1268
1269        /* da == NULL, assume it's null data for sta to ap*/
1270        if (da == NULL)
1271                da = pnetwork->MacAddress;
1272
1273        do {
1274                ret = _issue_nulldata(padapter, da, power_mode, wait_ms > 0);
1275
1276                i++;
1277
1278                if (padapter->bDriverStopped || padapter->bSurpriseRemoved)
1279                        break;
1280
1281                if (i < try_cnt && wait_ms > 0 && ret == _FAIL)
1282                        msleep(wait_ms);
1283        } while ((i < try_cnt) && ((ret == _FAIL) || (wait_ms == 0)));
1284
1285        if (ret != _FAIL) {
1286                ret = _SUCCESS;
1287                goto exit;
1288        }
1289
1290        if (try_cnt && wait_ms) {
1291                if (da)
1292                        DBG_88E(FUNC_ADPT_FMT" to %pM, ch:%u%s, %d/%d in %u ms\n",
1293                                FUNC_ADPT_ARG(padapter), da, rtw_get_oper_ch(padapter),
1294                                ret == _SUCCESS ? ", acked" : "", i, try_cnt,
1295                                jiffies_to_msecs(jiffies - start));
1296                else
1297                        DBG_88E(FUNC_ADPT_FMT", ch:%u%s, %d/%d in %u ms\n",
1298                                FUNC_ADPT_ARG(padapter), rtw_get_oper_ch(padapter),
1299                                ret == _SUCCESS ? ", acked" : "", i, try_cnt,
1300                                jiffies_to_msecs(jiffies - start));
1301        }
1302exit:
1303        return ret;
1304}
1305
1306/* when wait_ack is true, this function should be called at process context */
1307static int _issue_qos_nulldata(struct adapter *padapter, unsigned char *da,
1308                               u16 tid, bool wait_ack)
1309{
1310        int ret = _FAIL;
1311        struct xmit_frame                       *pmgntframe;
1312        struct pkt_attrib                       *pattrib;
1313        unsigned char                                   *pframe;
1314        struct ieee80211_hdr *pwlanhdr;
1315        __le16 *fctrl;
1316        unsigned short *qc;
1317        struct xmit_priv                        *pxmitpriv = &(padapter->xmitpriv);
1318        struct mlme_ext_priv    *pmlmeext = &(padapter->mlmeextpriv);
1319        struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
1320        struct wlan_bssid_ex    *pnetwork = &(pmlmeinfo->network);
1321
1322        DBG_88E("%s\n", __func__);
1323
1324        pmgntframe = alloc_mgtxmitframe(pxmitpriv);
1325        if (!pmgntframe)
1326                goto exit;
1327
1328        /* update attribute */
1329        pattrib = &pmgntframe->attrib;
1330        update_mgntframe_attrib(padapter, pattrib);
1331
1332        pattrib->hdrlen += 2;
1333        pattrib->qos_en = true;
1334        pattrib->eosp = 1;
1335        pattrib->ack_policy = 0;
1336        pattrib->mdata = 0;
1337
1338        memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
1339
1340        pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
1341        pwlanhdr = (struct ieee80211_hdr *)pframe;
1342
1343        fctrl = &pwlanhdr->frame_control;
1344        *(fctrl) = 0;
1345
1346        if ((pmlmeinfo->state&0x03) == WIFI_FW_AP_STATE)
1347                SetFrDs(fctrl);
1348        else if ((pmlmeinfo->state&0x03) == WIFI_FW_STATION_STATE)
1349                SetToDs(fctrl);
1350
1351        if (pattrib->mdata)
1352                SetMData(fctrl);
1353
1354        qc = (unsigned short *)(pframe + pattrib->hdrlen - 2);
1355
1356        SetPriority(qc, tid);
1357
1358        SetEOSP(qc, pattrib->eosp);
1359
1360        SetAckpolicy(qc, pattrib->ack_policy);
1361
1362        ether_addr_copy(pwlanhdr->addr1, da);
1363        ether_addr_copy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)));
1364        ether_addr_copy(pwlanhdr->addr3, pnetwork->MacAddress);
1365
1366        SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
1367        pmlmeext->mgnt_seq++;
1368        SetFrameSubType(pframe, WIFI_QOS_DATA_NULL);
1369
1370        pframe += sizeof(struct ieee80211_qos_hdr);
1371        pattrib->pktlen = sizeof(struct ieee80211_qos_hdr);
1372
1373        pattrib->last_txcmdsz = pattrib->pktlen;
1374
1375        if (wait_ack) {
1376                ret = dump_mgntframe_and_wait_ack(padapter, pmgntframe);
1377        } else {
1378                dump_mgntframe(padapter, pmgntframe);
1379                ret = _SUCCESS;
1380        }
1381
1382exit:
1383        return ret;
1384}
1385
1386/* when wait_ms > 0 , this function should be called at process context */
1387/* da == NULL for station mode */
1388int issue_qos_nulldata(struct adapter *padapter, unsigned char *da,
1389                       u16 tid, int try_cnt, int wait_ms)
1390{
1391        int ret;
1392        int i = 0;
1393        unsigned long start = jiffies;
1394        struct mlme_ext_priv    *pmlmeext = &(padapter->mlmeextpriv);
1395        struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
1396        struct wlan_bssid_ex    *pnetwork = &(pmlmeinfo->network);
1397
1398        /* da == NULL, assume it's null data for sta to ap*/
1399        if (da == NULL)
1400                da = pnetwork->MacAddress;
1401
1402        do {
1403                ret = _issue_qos_nulldata(padapter, da, tid, wait_ms > 0);
1404
1405                i++;
1406
1407                if (padapter->bDriverStopped || padapter->bSurpriseRemoved)
1408                        break;
1409
1410                if (i < try_cnt && wait_ms > 0 && ret == _FAIL)
1411                        msleep(wait_ms);
1412        } while ((i < try_cnt) && ((ret == _FAIL) || (wait_ms == 0)));
1413
1414        if (ret != _FAIL) {
1415                ret = _SUCCESS;
1416                goto exit;
1417        }
1418
1419        if (try_cnt && wait_ms) {
1420                if (da)
1421                        DBG_88E(FUNC_ADPT_FMT" to %pM, ch:%u%s, %d/%d in %u ms\n",
1422                                FUNC_ADPT_ARG(padapter), da, rtw_get_oper_ch(padapter),
1423                                ret == _SUCCESS ? ", acked" : "", i, try_cnt,
1424                                jiffies_to_msecs(jiffies - start));
1425                else
1426                        DBG_88E(FUNC_ADPT_FMT", ch:%u%s, %d/%d in %u ms\n",
1427                                FUNC_ADPT_ARG(padapter), rtw_get_oper_ch(padapter),
1428                                ret == _SUCCESS ? ", acked" : "", i, try_cnt,
1429                                jiffies_to_msecs(jiffies - start));
1430        }
1431exit:
1432        return ret;
1433}
1434
1435static int _issue_deauth(struct adapter *padapter, unsigned char *da,
1436                         unsigned short reason, bool wait_ack)
1437{
1438        struct xmit_frame                       *pmgntframe;
1439        struct pkt_attrib                       *pattrib;
1440        unsigned char                                   *pframe;
1441        struct ieee80211_hdr *pwlanhdr;
1442        __le16 *fctrl;
1443        struct xmit_priv                        *pxmitpriv = &(padapter->xmitpriv);
1444        struct mlme_ext_priv    *pmlmeext = &(padapter->mlmeextpriv);
1445        struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
1446        struct wlan_bssid_ex    *pnetwork = &(pmlmeinfo->network);
1447        int ret = _FAIL;
1448        __le16 le_tmp;
1449
1450        pmgntframe = alloc_mgtxmitframe(pxmitpriv);
1451        if (pmgntframe == NULL)
1452                goto exit;
1453
1454        /* update attribute */
1455        pattrib = &pmgntframe->attrib;
1456        update_mgntframe_attrib(padapter, pattrib);
1457        pattrib->retry_ctrl = false;
1458
1459        memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
1460
1461        pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
1462        pwlanhdr = (struct ieee80211_hdr *)pframe;
1463
1464        fctrl = &pwlanhdr->frame_control;
1465        *(fctrl) = 0;
1466
1467        ether_addr_copy(pwlanhdr->addr1, da);
1468        ether_addr_copy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)));
1469        ether_addr_copy(pwlanhdr->addr3, pnetwork->MacAddress);
1470
1471        SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
1472        pmlmeext->mgnt_seq++;
1473        SetFrameSubType(pframe, WIFI_DEAUTH);
1474
1475        pframe += sizeof(struct ieee80211_hdr_3addr);
1476        pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr);
1477
1478        le_tmp = cpu_to_le16(reason);
1479        pframe = rtw_set_fixed_ie(pframe, _RSON_CODE_, &le_tmp,
1480                                  &pattrib->pktlen);
1481
1482        pattrib->last_txcmdsz = pattrib->pktlen;
1483
1484        if (wait_ack) {
1485                ret = dump_mgntframe_and_wait_ack(padapter, pmgntframe);
1486        } else {
1487                dump_mgntframe(padapter, pmgntframe);
1488                ret = _SUCCESS;
1489        }
1490
1491exit:
1492        return ret;
1493}
1494
1495int issue_deauth(struct adapter *padapter, unsigned char *da,
1496                 unsigned short reason)
1497{
1498        DBG_88E("%s to %pM\n", __func__, da);
1499        return _issue_deauth(padapter, da, reason, false);
1500}
1501
1502static int issue_deauth_ex(struct adapter *padapter, u8 *da,
1503                           unsigned short reason, int try_cnt,
1504                           int wait_ms)
1505{
1506        int ret;
1507        int i = 0;
1508        unsigned long start = jiffies;
1509
1510        do {
1511                ret = _issue_deauth(padapter, da, reason, wait_ms > 0);
1512
1513                i++;
1514
1515                if (padapter->bDriverStopped || padapter->bSurpriseRemoved)
1516                        break;
1517
1518                if (i < try_cnt && wait_ms > 0 && ret == _FAIL)
1519                        mdelay(wait_ms);
1520        } while ((i < try_cnt) && ((ret == _FAIL) || (wait_ms == 0)));
1521
1522        if (ret != _FAIL) {
1523                ret = _SUCCESS;
1524                goto exit;
1525        }
1526
1527        if (try_cnt && wait_ms) {
1528                if (da)
1529                        DBG_88E(FUNC_ADPT_FMT" to %pM, ch:%u%s, %d/%d in %u ms\n",
1530                                FUNC_ADPT_ARG(padapter), da, rtw_get_oper_ch(padapter),
1531                                ret == _SUCCESS ? ", acked" : "", i, try_cnt,
1532                                jiffies_to_msecs(jiffies - start));
1533                else
1534                        DBG_88E(FUNC_ADPT_FMT", ch:%u%s, %d/%d in %u ms\n",
1535                                FUNC_ADPT_ARG(padapter), rtw_get_oper_ch(padapter),
1536                                ret == _SUCCESS ? ", acked" : "", i, try_cnt,
1537                                jiffies_to_msecs(jiffies - start));
1538        }
1539exit:
1540        return ret;
1541}
1542
1543static void issue_action_BA(struct adapter *padapter, unsigned char *raddr,
1544                            unsigned char action, unsigned short status)
1545{
1546        u8 category = RTW_WLAN_CATEGORY_BACK;
1547        u16 start_seq;
1548        u16 BA_para_set;
1549        u16 reason_code;
1550        u16 BA_timeout_value;
1551        __le16  le_tmp;
1552        u16 BA_starting_seqctrl = 0;
1553        enum ht_cap_ampdu_factor max_rx_ampdu_factor;
1554        struct xmit_frame *pmgntframe;
1555        struct pkt_attrib *pattrib;
1556        u8 *pframe;
1557        struct ieee80211_hdr *pwlanhdr;
1558        __le16 *fctrl;
1559        struct xmit_priv *pxmitpriv = &(padapter->xmitpriv);
1560        struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
1561        struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
1562        struct sta_info *psta;
1563        struct sta_priv *pstapriv = &padapter->stapriv;
1564        struct registry_priv *pregpriv = &padapter->registrypriv;
1565        struct wlan_bssid_ex    *pnetwork = &(pmlmeinfo->network);
1566
1567        DBG_88E("%s, category=%d, action=%d, status=%d\n", __func__, category, action, status);
1568
1569        pmgntframe = alloc_mgtxmitframe(pxmitpriv);
1570        if (!pmgntframe)
1571                return;
1572
1573        /* update attribute */
1574        pattrib = &pmgntframe->attrib;
1575        update_mgntframe_attrib(padapter, pattrib);
1576
1577        memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
1578
1579        pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
1580        pwlanhdr = (struct ieee80211_hdr *)pframe;
1581
1582        fctrl = &pwlanhdr->frame_control;
1583        *(fctrl) = 0;
1584
1585        ether_addr_copy(pwlanhdr->addr1, raddr);
1586        ether_addr_copy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)));
1587        ether_addr_copy(pwlanhdr->addr3, pnetwork->MacAddress);
1588
1589        SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
1590        pmlmeext->mgnt_seq++;
1591        SetFrameSubType(pframe, WIFI_ACTION);
1592
1593        pframe += sizeof(struct ieee80211_hdr_3addr);
1594        pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr);
1595
1596        pframe = rtw_set_fixed_ie(pframe, 1, &(category), &(pattrib->pktlen));
1597        pframe = rtw_set_fixed_ie(pframe, 1, &(action), &(pattrib->pktlen));
1598
1599        if (category == 3) {
1600                switch (action) {
1601                case 0: /* ADDBA req */
1602                        do {
1603                                pmlmeinfo->dialogToken++;
1604                        } while (pmlmeinfo->dialogToken == 0);
1605                        pframe = rtw_set_fixed_ie(pframe, 1, &(pmlmeinfo->dialogToken), &(pattrib->pktlen));
1606
1607                        BA_para_set = 0x1002 | ((status & 0xf) << 2); /* immediate ack & 64 buffer size */
1608                        le_tmp = cpu_to_le16(BA_para_set);
1609                        pframe = rtw_set_fixed_ie(pframe, 2, &(le_tmp),
1610                                                  &pattrib->pktlen);
1611
1612                        BA_timeout_value = 5000;/*  5ms */
1613                        le_tmp = cpu_to_le16(BA_timeout_value);
1614                        pframe = rtw_set_fixed_ie(pframe, 2, &(le_tmp),
1615                                                  &pattrib->pktlen);
1616
1617                        psta = rtw_get_stainfo(pstapriv, raddr);
1618                        if (psta) {
1619                                start_seq = (psta->sta_xmitpriv.txseq_tid[status & 0x07]&0xfff) + 1;
1620
1621                                DBG_88E("BA_starting_seqctrl=%d for TID=%d\n", start_seq, status & 0x07);
1622
1623                                psta->BA_starting_seqctrl[status & 0x07] = start_seq;
1624
1625                                BA_starting_seqctrl = start_seq << 4;
1626                        }
1627                        le_tmp = cpu_to_le16(BA_starting_seqctrl);
1628                        pframe = rtw_set_fixed_ie(pframe, 2, &(le_tmp),
1629                                                  &pattrib->pktlen);
1630                        break;
1631                case 1: /* ADDBA rsp */
1632                {
1633                        struct ADDBA_request *ADDBA_req = &pmlmeinfo->ADDBA_req;
1634
1635                        pframe = rtw_set_fixed_ie(pframe, 1,
1636                                                  &ADDBA_req->dialog_token,
1637                                                  &pattrib->pktlen);
1638                        pframe = rtw_set_fixed_ie(pframe, 2, &status,
1639                                                  &pattrib->pktlen);
1640
1641                        BA_para_set = le16_to_cpu(ADDBA_req->BA_para_set) &
1642                                      0x3f;
1643                        rtw_hal_get_def_var(padapter, HW_VAR_MAX_RX_AMPDU_FACTOR, &max_rx_ampdu_factor);
1644                        switch (max_rx_ampdu_factor) {
1645                        case MAX_AMPDU_FACTOR_64K:
1646                                BA_para_set |= 0x1000; /* 64 buffer size */
1647                                break;
1648                        case MAX_AMPDU_FACTOR_32K:
1649                                BA_para_set |= 0x0800; /* 32 buffer size */
1650                                break;
1651                        case MAX_AMPDU_FACTOR_16K:
1652                                BA_para_set |= 0x0400; /* 16 buffer size */
1653                                break;
1654                        case MAX_AMPDU_FACTOR_8K:
1655                                BA_para_set |= 0x0200; /* 8 buffer size */
1656                                break;
1657                        default:
1658                                BA_para_set |= 0x1000; /* 64 buffer size */
1659                                break;
1660                        }
1661
1662                        if (pregpriv->ampdu_amsdu == 0)/* disabled */
1663                                BA_para_set = BA_para_set & ~BIT(0);
1664                        else if (pregpriv->ampdu_amsdu == 1)/* enabled */
1665                                BA_para_set = BA_para_set | BIT(0);
1666                        le_tmp = cpu_to_le16(BA_para_set);
1667
1668                        pframe = rtw_set_fixed_ie(pframe, 2, &(le_tmp),
1669                                                  &pattrib->pktlen);
1670                        pframe = rtw_set_fixed_ie(pframe, 2,
1671                                                  &ADDBA_req->BA_timeout_value,
1672                                                  &pattrib->pktlen);
1673                        break;
1674                }
1675                case 2:/* DELBA */
1676                        BA_para_set = (status & 0x1F) << 3;
1677                        le_tmp = cpu_to_le16(BA_para_set);
1678                        pframe = rtw_set_fixed_ie(pframe, 2, &(le_tmp),
1679                                                  &pattrib->pktlen);
1680
1681                        reason_code = 37;/* Requested from peer STA as it does not want to use the mechanism */
1682                        le_tmp = cpu_to_le16(reason_code);
1683                        pframe = rtw_set_fixed_ie(pframe, 2, &(le_tmp),
1684                                                  &pattrib->pktlen);
1685                        break;
1686                default:
1687                        break;
1688                }
1689        }
1690
1691        pattrib->last_txcmdsz = pattrib->pktlen;
1692
1693        dump_mgntframe(padapter, pmgntframe);
1694}
1695
1696static void issue_action_BSSCoexistPacket(struct adapter *padapter)
1697{
1698        struct list_head *plist, *phead;
1699        unsigned char category, action;
1700        struct xmit_frame                       *pmgntframe;
1701        struct pkt_attrib                       *pattrib;
1702        unsigned char                           *pframe;
1703        struct ieee80211_hdr *pwlanhdr;
1704        __le16 *fctrl;
1705        struct  wlan_network    *pnetwork = NULL;
1706        struct xmit_priv                        *pxmitpriv = &(padapter->xmitpriv);
1707        struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1708        struct mlme_ext_priv    *pmlmeext = &(padapter->mlmeextpriv);
1709        struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
1710        struct __queue *queue   = &(pmlmepriv->scanned_queue);
1711        u8 InfoContent[16] = {0};
1712        u8 ICS[8][15];
1713        struct wlan_bssid_ex  *cur_network   = &(pmlmeinfo->network);
1714
1715        if ((pmlmepriv->num_FortyMHzIntolerant == 0) || (pmlmepriv->num_sta_no_ht == 0))
1716                return;
1717
1718        if (pmlmeinfo->bwmode_updated)
1719                return;
1720
1721        DBG_88E("%s\n", __func__);
1722
1723        category = RTW_WLAN_CATEGORY_PUBLIC;
1724        action = ACT_PUBLIC_BSSCOEXIST;
1725
1726        pmgntframe = alloc_mgtxmitframe(pxmitpriv);
1727        if (!pmgntframe)
1728                return;
1729
1730        /* update attribute */
1731        pattrib = &pmgntframe->attrib;
1732        update_mgntframe_attrib(padapter, pattrib);
1733
1734        memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
1735
1736        pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
1737        pwlanhdr = (struct ieee80211_hdr *)pframe;
1738
1739        fctrl = &pwlanhdr->frame_control;
1740        *(fctrl) = 0;
1741
1742        ether_addr_copy(pwlanhdr->addr1, cur_network->MacAddress);
1743        ether_addr_copy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)));
1744        ether_addr_copy(pwlanhdr->addr3, cur_network->MacAddress);
1745
1746        SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
1747        pmlmeext->mgnt_seq++;
1748        SetFrameSubType(pframe, WIFI_ACTION);
1749
1750        pframe += sizeof(struct ieee80211_hdr_3addr);
1751        pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr);
1752
1753        pframe = rtw_set_fixed_ie(pframe, 1, &(category), &(pattrib->pktlen));
1754        pframe = rtw_set_fixed_ie(pframe, 1, &(action), &(pattrib->pktlen));
1755
1756        /*  */
1757        if (pmlmepriv->num_FortyMHzIntolerant > 0) {
1758                u8 iedata = 0;
1759
1760                iedata |= BIT(2);/* 20 MHz BSS Width Request */
1761
1762                pframe = rtw_set_ie(pframe, EID_BSSCoexistence,  1, &iedata, &(pattrib->pktlen));
1763        }
1764
1765        /*  */
1766        memset(ICS, 0, sizeof(ICS));
1767        if (pmlmepriv->num_sta_no_ht > 0) {
1768                int i;
1769
1770                spin_lock_bh(&(pmlmepriv->scanned_queue.lock));
1771
1772                phead = get_list_head(queue);
1773                plist = phead->next;
1774
1775                while (phead != plist) {
1776                        uint len;
1777                        u8 *p;
1778                        struct wlan_bssid_ex *pbss_network;
1779
1780                        pnetwork = container_of(plist, struct wlan_network, list);
1781
1782                        plist = plist->next;
1783
1784                        pbss_network = (struct wlan_bssid_ex *)&pnetwork->network;
1785
1786                        p = rtw_get_ie(pbss_network->ies + _FIXED_IE_LENGTH_, _HT_CAPABILITY_IE_, &len, pbss_network->ie_length - _FIXED_IE_LENGTH_);
1787                        if ((p == NULL) || (len == 0)) { /* non-HT */
1788                                if ((pbss_network->Configuration.DSConfig <= 0) || (pbss_network->Configuration.DSConfig > 14))
1789                                        continue;
1790
1791                                ICS[0][pbss_network->Configuration.DSConfig] = 1;
1792
1793                                if (ICS[0][0] == 0)
1794                                        ICS[0][0] = 1;
1795                        }
1796                }
1797                spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
1798
1799                for (i = 0; i < 8; i++) {
1800                        if (ICS[i][0] == 1) {
1801                                int j, k = 0;
1802
1803                                InfoContent[k] = i;
1804                                /* SET_BSS_INTOLERANT_ELE_REG_CLASS(InfoContent, i); */
1805                                k++;
1806
1807                                for (j = 1; j <= 14; j++) {
1808                                        if (ICS[i][j] == 1) {
1809                                                if (k < 16) {
1810                                                        InfoContent[k] = j; /* channel number */
1811                                                        /* SET_BSS_INTOLERANT_ELE_CHANNEL(InfoContent+k, j); */
1812                                                        k++;
1813                                                }
1814                                        }
1815                                }
1816
1817                                pframe = rtw_set_ie(pframe, EID_BSSIntolerantChlReport, k, InfoContent, &(pattrib->pktlen));
1818                        }
1819                }
1820        }
1821
1822        pattrib->last_txcmdsz = pattrib->pktlen;
1823
1824        dump_mgntframe(padapter, pmgntframe);
1825}
1826
1827unsigned int send_delba(struct adapter *padapter, u8 initiator, u8 *addr)
1828{
1829        struct sta_priv *pstapriv = &padapter->stapriv;
1830        struct sta_info *psta = NULL;
1831        /* struct recv_reorder_ctrl *preorder_ctrl; */
1832        struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
1833        struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
1834        u16 tid;
1835
1836        if ((pmlmeinfo->state&0x03) != WIFI_FW_AP_STATE)
1837                if (!(pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS))
1838                        return _SUCCESS;
1839
1840        psta = rtw_get_stainfo(pstapriv, addr);
1841        if (psta == NULL)
1842                return _SUCCESS;
1843
1844        if (initiator == 0) { /*  recipient */
1845                for (tid = 0; tid < MAXTID; tid++) {
1846                        if (psta->recvreorder_ctrl[tid].enable) {
1847                                DBG_88E("rx agg disable tid(%d)\n", tid);
1848                                issue_action_BA(padapter, addr, RTW_WLAN_ACTION_DELBA, (((tid << 1) | initiator)&0x1F));
1849                                psta->recvreorder_ctrl[tid].enable = false;
1850                                psta->recvreorder_ctrl[tid].indicate_seq = 0xffff;
1851                        }
1852                }
1853        } else if (initiator == 1) { /*  originator */
1854                for (tid = 0; tid < MAXTID; tid++) {
1855                        if (psta->htpriv.agg_enable_bitmap & BIT(tid)) {
1856                                DBG_88E("tx agg disable tid(%d)\n", tid);
1857                                issue_action_BA(padapter, addr, RTW_WLAN_ACTION_DELBA, (((tid << 1) | initiator)&0x1F));
1858                                psta->htpriv.agg_enable_bitmap &= ~BIT(tid);
1859                                psta->htpriv.candidate_tid_bitmap &= ~BIT(tid);
1860                        }
1861                }
1862        }
1863
1864        return _SUCCESS;
1865}
1866
1867unsigned int send_beacon(struct adapter *padapter)
1868{
1869        u8 bxmitok = false;
1870        int     issue = 0;
1871        int poll = 0;
1872
1873        unsigned long start = jiffies;
1874
1875        rtw_hal_set_hwreg(padapter, HW_VAR_BCN_VALID, NULL);
1876        do {
1877                issue_beacon(padapter, 100);
1878                issue++;
1879                do {
1880                        yield();
1881                        rtw_hal_get_hwreg(padapter, HW_VAR_BCN_VALID, (u8 *)(&bxmitok));
1882                        poll++;
1883                } while ((poll%10) != 0 && !bxmitok && !padapter->bSurpriseRemoved && !padapter->bDriverStopped);
1884        } while (!bxmitok && issue < 100 && !padapter->bSurpriseRemoved && !padapter->bDriverStopped);
1885
1886        if (padapter->bSurpriseRemoved || padapter->bDriverStopped)
1887                return _FAIL;
1888        if (!bxmitok) {
1889                DBG_88E("%s fail! %u ms\n", __func__,
1890                        jiffies_to_msecs(jiffies - start));
1891                return _FAIL;
1892        } else {
1893                u32 passing_time = jiffies_to_msecs(jiffies - start);
1894
1895                if (passing_time > 100 || issue > 3)
1896                        DBG_88E("%s success, issue:%d, poll:%d, %u ms\n",
1897                                __func__, issue, poll,
1898                                jiffies_to_msecs(jiffies - start));
1899                return _SUCCESS;
1900        }
1901}
1902
1903/****************************************************************************
1904
1905Following are some utility functions for WiFi MLME
1906
1907*****************************************************************************/
1908
1909static void site_survey(struct adapter *padapter)
1910{
1911        unsigned char           survey_channel = 0, val8;
1912        enum rt_scan_type ScanType = SCAN_PASSIVE;
1913        struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
1914        struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
1915        u32 initialgain = 0;
1916        struct rtw_ieee80211_channel *ch;
1917
1918        if (pmlmeext->sitesurvey_res.channel_idx < pmlmeext->sitesurvey_res.ch_num) {
1919                ch = &pmlmeext->sitesurvey_res.ch[pmlmeext->sitesurvey_res.channel_idx];
1920                survey_channel = ch->hw_value;
1921                ScanType = (ch->flags & RTW_IEEE80211_CHAN_PASSIVE_SCAN) ? SCAN_PASSIVE : SCAN_ACTIVE;
1922        }
1923
1924        if (survey_channel != 0) {
1925                /* PAUSE 4-AC Queue when site_survey */
1926                /* rtw_hal_get_hwreg(padapter, HW_VAR_TXPAUSE, (u8 *)(&val8)); */
1927                /* val8 |= 0x0f; */
1928                /* rtw_hal_set_hwreg(padapter, HW_VAR_TXPAUSE, (u8 *)(&val8)); */
1929                if (pmlmeext->sitesurvey_res.channel_idx == 0)
1930                        set_channel_bwmode(padapter, survey_channel, HAL_PRIME_CHNL_OFFSET_DONT_CARE, HT_CHANNEL_WIDTH_20);
1931                else
1932                        SelectChannel(padapter, survey_channel);
1933
1934                if (ScanType == SCAN_ACTIVE) { /* obey the channel plan setting... */
1935                        int i;
1936
1937                        for (i = 0; i < RTW_SSID_SCAN_AMOUNT; i++) {
1938                                if (pmlmeext->sitesurvey_res.ssid[i].SsidLength) {
1939                                        /* todo: to issue two probe req??? */
1940                                        issue_probereq(padapter,
1941                                        &(pmlmeext->sitesurvey_res.ssid[i]),
1942                                                                NULL, false);
1943                                        /* msleep(SURVEY_TO>>1); */
1944                                        issue_probereq(padapter,
1945                                        &(pmlmeext->sitesurvey_res.ssid[i]),
1946                                                                NULL, false);
1947                                }
1948                        }
1949
1950                        if (pmlmeext->sitesurvey_res.scan_mode == SCAN_ACTIVE) {
1951                                /* todo: to issue two probe req??? */
1952                                issue_probereq(padapter, NULL, NULL, false);
1953                                /* msleep(SURVEY_TO>>1); */
1954                                issue_probereq(padapter, NULL, NULL, false);
1955                        }
1956
1957                        if (pmlmeext->sitesurvey_res.scan_mode == SCAN_ACTIVE) {
1958                                /* todo: to issue two probe req??? */
1959                                issue_probereq(padapter, NULL, NULL, false);
1960                                /* msleep(SURVEY_TO>>1); */
1961                                issue_probereq(padapter, NULL, NULL, false);
1962                        }
1963                }
1964
1965                set_survey_timer(pmlmeext, pmlmeext->chan_scan_time);
1966        } else {
1967                /*  20100721:Interrupt scan operation here. */
1968                /*  For SW antenna diversity before link, it needs to switch to another antenna and scan again. */
1969                /*  It compares the scan result and select better one to do connection. */
1970                if (rtw_hal_antdiv_before_linked(padapter)) {
1971                        pmlmeext->sitesurvey_res.bss_cnt = 0;
1972                        pmlmeext->sitesurvey_res.channel_idx = -1;
1973                        pmlmeext->chan_scan_time = SURVEY_TO / 2;
1974                        set_survey_timer(pmlmeext, pmlmeext->chan_scan_time);
1975                        return;
1976                }
1977
1978                pmlmeext->sitesurvey_res.state = SCAN_COMPLETE;
1979
1980                /* switch back to the original channel */
1981
1982                set_channel_bwmode(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode);
1983
1984                /* flush 4-AC Queue after site_survey */
1985                /* val8 = 0; */
1986                /* rtw_hal_set_hwreg(padapter, HW_VAR_TXPAUSE, (u8 *)(&val8)); */
1987
1988                /* config MSR */
1989                Set_MSR(padapter, (pmlmeinfo->state & 0x3));
1990
1991                initialgain = 0xff; /* restore RX GAIN */
1992                rtw_hal_set_hwreg(padapter, HW_VAR_INITIAL_GAIN, (u8 *)(&initialgain));
1993                /* turn on dynamic functions */
1994                Restore_DM_Func_Flag(padapter);
1995                /* Switch_DM_Func(padapter, DYNAMIC_ALL_FUNC_ENABLE, true); */
1996
1997                if (is_client_associated_to_ap(padapter))
1998                        issue_nulldata(padapter, NULL, 0, 3, 500);
1999
2000                val8 = 0; /* survey done */
2001                rtw_hal_set_hwreg(padapter, HW_VAR_MLME_SITESURVEY, (u8 *)(&val8));
2002
2003                report_surveydone_event(padapter);
2004
2005                pmlmeext->chan_scan_time = SURVEY_TO;
2006                pmlmeext->sitesurvey_res.state = SCAN_DISABLE;
2007
2008                issue_action_BSSCoexistPacket(padapter);
2009                issue_action_BSSCoexistPacket(padapter);
2010                issue_action_BSSCoexistPacket(padapter);
2011        }
2012}
2013
2014/* collect bss info from Beacon and Probe request/response frames. */
2015static u8 collect_bss_info(struct adapter *padapter,
2016                           struct recv_frame *precv_frame,
2017                           struct wlan_bssid_ex *bssid)
2018{
2019        int     i;
2020        u32     len;
2021        u8 *p;
2022        u16 val16, subtype;
2023        u8 *pframe = precv_frame->pkt->data;
2024        u32 packet_len = precv_frame->pkt->len;
2025        u8 ie_offset;
2026        struct registry_priv    *pregistrypriv = &padapter->registrypriv;
2027        struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
2028        struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
2029
2030        len = packet_len - sizeof(struct ieee80211_hdr_3addr);
2031
2032        if (len > MAX_IE_SZ)
2033                return _FAIL;
2034
2035        memset(bssid, 0, sizeof(struct wlan_bssid_ex));
2036
2037        subtype = GetFrameSubType(pframe);
2038
2039        if (subtype == WIFI_BEACON) {
2040                bssid->Reserved[0] = 1;
2041                ie_offset = _BEACON_IE_OFFSET_;
2042        } else {
2043                /*  FIXME : more type */
2044                if (subtype == WIFI_PROBEREQ) {
2045                        ie_offset = _PROBEREQ_IE_OFFSET_;
2046                        bssid->Reserved[0] = 2;
2047                } else if (subtype == WIFI_PROBERSP) {
2048                        ie_offset = _PROBERSP_IE_OFFSET_;
2049                        bssid->Reserved[0] = 3;
2050                } else {
2051                        bssid->Reserved[0] = 0;
2052                        ie_offset = _FIXED_IE_LENGTH_;
2053                }
2054        }
2055
2056        bssid->Length = sizeof(struct wlan_bssid_ex) - MAX_IE_SZ + len;
2057
2058        /* below is to copy the information element */
2059        bssid->ie_length = len;
2060        memcpy(bssid->ies, (pframe + sizeof(struct ieee80211_hdr_3addr)), bssid->ie_length);
2061
2062        /* get the signal strength in dBM.raw data */
2063        bssid->Rssi = precv_frame->attrib.phy_info.recvpower;
2064        bssid->PhyInfo.SignalQuality = precv_frame->attrib.phy_info.SignalQuality;/* in percentage */
2065        bssid->PhyInfo.SignalStrength = precv_frame->attrib.phy_info.SignalStrength;/* in percentage */
2066        rtw_hal_get_def_var(padapter, HAL_DEF_CURRENT_ANTENNA,  &bssid->PhyInfo.Optimum_antenna);
2067
2068        /*  checking SSID */
2069        p = rtw_get_ie(bssid->ies + ie_offset, _SSID_IE_, &len, bssid->ie_length - ie_offset);
2070        if (!p) {
2071                DBG_88E("marc: cannot find SSID for survey event\n");
2072                return _FAIL;
2073        }
2074
2075        if (len) {
2076                if (len > NDIS_802_11_LENGTH_SSID) {
2077                        DBG_88E("%s()-%d: IE too long (%d) for survey event\n", __func__, __LINE__, len);
2078                        return _FAIL;
2079                }
2080                memcpy(bssid->Ssid.Ssid, (p + 2), len);
2081                bssid->Ssid.SsidLength = len;
2082        } else {
2083                bssid->Ssid.SsidLength = 0;
2084        }
2085
2086        memset(bssid->SupportedRates, 0, NDIS_802_11_LENGTH_RATES_EX);
2087
2088        /* checking rate info... */
2089        i = 0;
2090        p = rtw_get_ie(bssid->ies + ie_offset, _SUPPORTEDRATES_IE_, &len, bssid->ie_length - ie_offset);
2091        if (p != NULL) {
2092                if (len > NDIS_802_11_LENGTH_RATES_EX) {
2093                        DBG_88E("%s()-%d: IE too long (%d) for survey event\n", __func__, __LINE__, len);
2094                        return _FAIL;
2095                }
2096                memcpy(bssid->SupportedRates, (p + 2), len);
2097                i = len;
2098        }
2099
2100        p = rtw_get_ie(bssid->ies + ie_offset, _EXT_SUPPORTEDRATES_IE_, &len, bssid->ie_length - ie_offset);
2101        if (p) {
2102                if (len > (NDIS_802_11_LENGTH_RATES_EX-i)) {
2103                        DBG_88E("%s()-%d: IE too long (%d) for survey event\n", __func__, __LINE__, len);
2104                        return _FAIL;
2105                }
2106                memcpy(bssid->SupportedRates + i, (p + 2), len);
2107        }
2108
2109        /* todo: */
2110        bssid->NetworkTypeInUse = Ndis802_11OFDM24;
2111
2112        if (bssid->ie_length < 12)
2113                return _FAIL;
2114
2115        /*  Checking for DSConfig */
2116        p = rtw_get_ie(bssid->ies + ie_offset, _DSSET_IE_, &len, bssid->ie_length - ie_offset);
2117
2118        bssid->Configuration.DSConfig = 0;
2119        bssid->Configuration.Length = 0;
2120
2121        if (p) {
2122                bssid->Configuration.DSConfig = *(p + 2);
2123        } else {/*  In 5G, some ap do not have DSSET IE */
2124                /*  checking HT info for channel */
2125                p = rtw_get_ie(bssid->ies + ie_offset, _HT_ADD_INFO_IE_, &len, bssid->ie_length - ie_offset);
2126                if (p) {
2127                        struct HT_info_element *HT_info = (struct HT_info_element *)(p + 2);
2128
2129                        bssid->Configuration.DSConfig = HT_info->primary_channel;
2130                } else { /*  use current channel */
2131                        bssid->Configuration.DSConfig = rtw_get_oper_ch(padapter);
2132                }
2133        }
2134
2135        if (subtype == WIFI_PROBEREQ) {
2136                /*  FIXME */
2137                bssid->InfrastructureMode = Ndis802_11Infrastructure;
2138                ether_addr_copy(bssid->MacAddress, GetAddr2Ptr(pframe));
2139                bssid->Privacy = 1;
2140                return _SUCCESS;
2141        }
2142
2143        bssid->Configuration.BeaconPeriod =
2144                get_unaligned_le16(rtw_get_beacon_interval_from_ie(bssid->ies));
2145
2146        val16 = rtw_get_capability((struct wlan_bssid_ex *)bssid);
2147
2148        if (val16 & BIT(0)) {
2149                bssid->InfrastructureMode = Ndis802_11Infrastructure;
2150                ether_addr_copy(bssid->MacAddress, GetAddr2Ptr(pframe));
2151        } else {
2152                bssid->InfrastructureMode = Ndis802_11IBSS;
2153                ether_addr_copy(bssid->MacAddress, GetAddr3Ptr(pframe));
2154        }
2155
2156        if (val16 & BIT(4))
2157                bssid->Privacy = 1;
2158        else
2159                bssid->Privacy = 0;
2160
2161        bssid->Configuration.ATIMWindow = 0;
2162
2163        /* 20/40 BSS Coexistence check */
2164        if ((pregistrypriv->wifi_spec == 1) && (!pmlmeinfo->bwmode_updated)) {
2165                struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
2166
2167                p = rtw_get_ie(bssid->ies + ie_offset, _HT_CAPABILITY_IE_, &len, bssid->ie_length - ie_offset);
2168                if (p && len > 0) {
2169                        struct ieee80211_ht_cap *pHT_caps =
2170                                (struct ieee80211_ht_cap *)(p + 2);
2171
2172                        if (le16_to_cpu(pHT_caps->cap_info) & BIT(14))
2173                                pmlmepriv->num_FortyMHzIntolerant++;
2174                } else {
2175                        pmlmepriv->num_sta_no_ht++;
2176                }
2177        }
2178
2179        /*  mark bss info receiving from nearby channel as SignalQuality 101 */
2180        if (bssid->Configuration.DSConfig != rtw_get_oper_ch(padapter))
2181                bssid->PhyInfo.SignalQuality = 101;
2182        return _SUCCESS;
2183}
2184
2185static void start_create_ibss(struct adapter *padapter)
2186{
2187        unsigned short  caps;
2188        u8 val8;
2189        u8 join_type;
2190        struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
2191        struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
2192        struct wlan_bssid_ex *pnetwork = (struct wlan_bssid_ex *)(&(pmlmeinfo->network));
2193
2194        pmlmeext->cur_channel = (u8)pnetwork->Configuration.DSConfig;
2195        pmlmeinfo->bcn_interval = get_beacon_interval(pnetwork);
2196
2197        /* update wireless mode */
2198        update_wireless_mode(padapter);
2199
2200        /* update capability */
2201        caps = rtw_get_capability((struct wlan_bssid_ex *)pnetwork);
2202        update_capinfo(padapter, caps);
2203        if (caps&cap_IBSS) {/* adhoc master */
2204                val8 = 0xcf;
2205                rtw_hal_set_hwreg(padapter, HW_VAR_SEC_CFG, (u8 *)(&val8));
2206
2207                /* switch channel */
2208                /* SelectChannel(padapter, pmlmeext->cur_channel, HAL_PRIME_CHNL_OFFSET_DONT_CARE); */
2209                set_channel_bwmode(padapter, pmlmeext->cur_channel, HAL_PRIME_CHNL_OFFSET_DONT_CARE, HT_CHANNEL_WIDTH_20);
2210
2211                beacon_timing_control(padapter);
2212
2213                /* set msr to WIFI_FW_ADHOC_STATE */
2214                pmlmeinfo->state = WIFI_FW_ADHOC_STATE;
2215                Set_MSR(padapter, (pmlmeinfo->state & 0x3));
2216
2217                /* issue beacon */
2218                if (send_beacon(padapter) == _FAIL) {
2219                        RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("issuing beacon frame fail....\n"));
2220
2221                        report_join_res(padapter, -1);
2222                        pmlmeinfo->state = WIFI_FW_NULL_STATE;
2223                } else {
2224                        rtw_hal_set_hwreg(padapter, HW_VAR_BSSID, padapter->registrypriv.dev_network.MacAddress);
2225                        join_type = 0;
2226                        rtw_hal_set_hwreg(padapter, HW_VAR_MLME_JOIN, (u8 *)(&join_type));
2227
2228                        report_join_res(padapter, 1);
2229                        pmlmeinfo->state |= WIFI_FW_ASSOC_SUCCESS;
2230                }
2231        } else {
2232                DBG_88E("%s, invalid cap:%x\n", __func__, caps);
2233                return;
2234        }
2235}
2236
2237static void start_clnt_join(struct adapter *padapter)
2238{
2239        unsigned short  caps;
2240        u8 val8;
2241        struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
2242        struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
2243        struct wlan_bssid_ex *pnetwork = (struct wlan_bssid_ex *)(&(pmlmeinfo->network));
2244        int beacon_timeout;
2245
2246        pmlmeext->cur_channel = (u8)pnetwork->Configuration.DSConfig;
2247        pmlmeinfo->bcn_interval = get_beacon_interval(pnetwork);
2248
2249        /* update wireless mode */
2250        update_wireless_mode(padapter);
2251
2252        /* update capability */
2253        caps = rtw_get_capability((struct wlan_bssid_ex *)pnetwork);
2254        update_capinfo(padapter, caps);
2255        if (caps&cap_ESS) {
2256                Set_MSR(padapter, WIFI_FW_STATION_STATE);
2257
2258                val8 = (pmlmeinfo->auth_algo == dot11AuthAlgrthm_8021X) ? 0xcc : 0xcf;
2259
2260                rtw_hal_set_hwreg(padapter, HW_VAR_SEC_CFG, (u8 *)(&val8));
2261
2262                /* switch channel */
2263                set_channel_bwmode(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode);
2264
2265                /* here wait for receiving the beacon to start auth */
2266                /* and enable a timer */
2267                beacon_timeout = decide_wait_for_beacon_timeout(pmlmeinfo->bcn_interval);
2268                set_link_timer(pmlmeext, beacon_timeout);
2269                mod_timer(&padapter->mlmepriv.assoc_timer, jiffies +
2270                          msecs_to_jiffies((REAUTH_TO * REAUTH_LIMIT) + (REASSOC_TO * REASSOC_LIMIT) + beacon_timeout));
2271
2272                pmlmeinfo->state = WIFI_FW_AUTH_NULL | WIFI_FW_STATION_STATE;
2273        } else if (caps&cap_IBSS) { /* adhoc client */
2274                Set_MSR(padapter, WIFI_FW_ADHOC_STATE);
2275
2276                val8 = 0xcf;
2277                rtw_hal_set_hwreg(padapter, HW_VAR_SEC_CFG, (u8 *)(&val8));
2278
2279                /* switch channel */
2280                set_channel_bwmode(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode);
2281
2282                beacon_timing_control(padapter);
2283
2284                pmlmeinfo->state = WIFI_FW_ADHOC_STATE;
2285
2286                report_join_res(padapter, 1);
2287        } else {
2288                return;
2289        }
2290}
2291
2292static void start_clnt_auth(struct adapter *padapter)
2293{
2294        struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
2295        struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
2296
2297        del_timer_sync(&pmlmeext->link_timer);
2298
2299        pmlmeinfo->state &= (~WIFI_FW_AUTH_NULL);
2300        pmlmeinfo->state |= WIFI_FW_AUTH_STATE;
2301
2302        pmlmeinfo->auth_seq = 1;
2303        pmlmeinfo->reauth_count = 0;
2304        pmlmeinfo->reassoc_count = 0;
2305        pmlmeinfo->link_count = 0;
2306        pmlmeext->retry = 0;
2307
2308        /*  Because of AP's not receiving deauth before */
2309        /*  AP may: 1)not response auth or 2)deauth us after link is complete */
2310        /*  issue deauth before issuing auth to deal with the situation */
2311        /*      Commented by Albert 2012/07/21 */
2312        /*      For the Win8 P2P connection, it will be hard to have a successful connection if this Wi-Fi doesn't connect to it. */
2313        issue_deauth(padapter, (&(pmlmeinfo->network))->MacAddress, WLAN_REASON_DEAUTH_LEAVING);
2314
2315        DBG_88E_LEVEL(_drv_info_, "start auth\n");
2316        issue_auth(padapter, NULL, 0);
2317
2318        set_link_timer(pmlmeext, REAUTH_TO);
2319}
2320
2321static void start_clnt_assoc(struct adapter *padapter)
2322{
2323        struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
2324        struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
2325
2326        del_timer_sync(&pmlmeext->link_timer);
2327
2328        pmlmeinfo->state &= (~(WIFI_FW_AUTH_NULL | WIFI_FW_AUTH_STATE));
2329        pmlmeinfo->state |= (WIFI_FW_AUTH_SUCCESS | WIFI_FW_ASSOC_STATE);
2330
2331        issue_assocreq(padapter);
2332
2333        set_link_timer(pmlmeext, REASSOC_TO);
2334}
2335
2336static unsigned int receive_disconnect(struct adapter *padapter,
2337                                       unsigned char *MacAddr,
2338                                       unsigned short reason)
2339{
2340        struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
2341        struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
2342        struct wlan_bssid_ex    *pnetwork = &(pmlmeinfo->network);
2343
2344        /* check A3 */
2345        if (memcmp(MacAddr, pnetwork->MacAddress, ETH_ALEN))
2346                return _SUCCESS;
2347
2348        DBG_88E("%s\n", __func__);
2349
2350        if ((pmlmeinfo->state&0x03) == WIFI_FW_STATION_STATE) {
2351                if (pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS) {
2352                        pmlmeinfo->state = WIFI_FW_NULL_STATE;
2353                        report_del_sta_event(padapter, MacAddr, reason);
2354                } else if (pmlmeinfo->state & WIFI_FW_LINKING_STATE) {
2355                        pmlmeinfo->state = WIFI_FW_NULL_STATE;
2356                        report_join_res(padapter, -2);
2357                }
2358        }
2359        return _SUCCESS;
2360}
2361
2362static void process_80211d(struct adapter *padapter, struct wlan_bssid_ex *bssid)
2363{
2364        struct registry_priv *pregistrypriv;
2365        struct mlme_ext_priv *pmlmeext;
2366        struct rt_channel_info *chplan_new;
2367        u8 channel;
2368        u8 i;
2369
2370        pregistrypriv = &padapter->registrypriv;
2371        pmlmeext = &padapter->mlmeextpriv;
2372
2373        /*  Adjust channel plan by AP Country IE */
2374        if (pregistrypriv->enable80211d &&
2375            (!pmlmeext->update_channel_plan_by_ap_done)) {
2376                u8 *ie, *p;
2377                u32 len;
2378                struct rt_channel_plan chplan_ap;
2379                struct rt_channel_info chplan_sta[MAX_CHANNEL_NUM];
2380                u8 country[4];
2381                u8 fcn; /*  first channel number */
2382                u8 noc; /*  number of channel */
2383                u8 j, k;
2384
2385                ie = rtw_get_ie(bssid->ies + _FIXED_IE_LENGTH_, _COUNTRY_IE_, &len, bssid->ie_length - _FIXED_IE_LENGTH_);
2386                if (!ie)
2387                        return;
2388                if (len < 6)
2389                        return;
2390                ie += 2;
2391                p = ie;
2392                ie += len;
2393
2394                memset(country, 0, 4);
2395                memcpy(country, p, 3);
2396                p += 3;
2397                RT_TRACE(_module_rtl871x_mlme_c_, _drv_notice_,
2398                         ("%s: 802.11d country =%s\n", __func__, country));
2399
2400                i = 0;
2401                while ((ie - p) >= 3) {
2402                        fcn = *(p++);
2403                        noc = *(p++);
2404                        p++;
2405
2406                        for (j = 0; j < noc; j++) {
2407                                channel = fcn + j;
2408
2409                                chplan_ap.Channel[i++] = channel;
2410                        }
2411                }
2412                chplan_ap.Len = i;
2413
2414                memcpy(chplan_sta, pmlmeext->channel_set, sizeof(chplan_sta));
2415
2416                memset(pmlmeext->channel_set, 0, sizeof(pmlmeext->channel_set));
2417                chplan_new = pmlmeext->channel_set;
2418
2419                i = 0;
2420                j = 0;
2421                k = 0;
2422                if (pregistrypriv->wireless_mode & WIRELESS_11G) {
2423                        do {
2424                                if ((i == MAX_CHANNEL_NUM) ||
2425                                    (chplan_sta[i].ChannelNum == 0) ||
2426                                    (chplan_sta[i].ChannelNum > 14))
2427                                        break;
2428
2429                                if ((j == chplan_ap.Len) || (chplan_ap.Channel[j] > 14))
2430                                        break;
2431
2432                                if (chplan_sta[i].ChannelNum == chplan_ap.Channel[j]) {
2433                                        chplan_new[k].ChannelNum = chplan_ap.Channel[j];
2434                                        chplan_new[k].ScanType = SCAN_ACTIVE;
2435                                        i++;
2436                                        j++;
2437                                        k++;
2438                                } else if (chplan_sta[i].ChannelNum < chplan_ap.Channel[j]) {
2439                                        chplan_new[k].ChannelNum = chplan_sta[i].ChannelNum;
2440                                        chplan_new[k].ScanType = SCAN_PASSIVE;
2441                                        i++;
2442                                        k++;
2443                                } else if (chplan_sta[i].ChannelNum > chplan_ap.Channel[j]) {
2444                                        chplan_new[k].ChannelNum = chplan_ap.Channel[j];
2445                                        chplan_new[k].ScanType = SCAN_ACTIVE;
2446                                        j++;
2447                                        k++;
2448                                }
2449                        } while (1);
2450
2451                        /*  change AP not support channel to Passive scan */
2452                        while ((i < MAX_CHANNEL_NUM) &&
2453                               (chplan_sta[i].ChannelNum != 0) &&
2454                               (chplan_sta[i].ChannelNum <= 14)) {
2455                                chplan_new[k].ChannelNum = chplan_sta[i].ChannelNum;
2456                                chplan_new[k].ScanType = SCAN_PASSIVE;
2457                                i++;
2458                                k++;
2459                        }
2460
2461                        /*  add channel AP supported */
2462                        while ((j < chplan_ap.Len) && (chplan_ap.Channel[j] <= 14)) {
2463                                chplan_new[k].ChannelNum = chplan_ap.Channel[j];
2464                                chplan_new[k].ScanType = SCAN_ACTIVE;
2465                                j++;
2466                                k++;
2467                        }
2468                } else {
2469                        /*  keep original STA 2.4G channel plan */
2470                        while ((i < MAX_CHANNEL_NUM) &&
2471                               (chplan_sta[i].ChannelNum != 0) &&
2472                               (chplan_sta[i].ChannelNum <= 14)) {
2473                                chplan_new[k].ChannelNum = chplan_sta[i].ChannelNum;
2474                                chplan_new[k].ScanType = chplan_sta[i].ScanType;
2475                                i++;
2476                                k++;
2477                        }
2478
2479                        /*  skip AP 2.4G channel plan */
2480                        while ((j < chplan_ap.Len) && (chplan_ap.Channel[j] <= 14))
2481                                j++;
2482                }
2483
2484                pmlmeext->update_channel_plan_by_ap_done = 1;
2485        }
2486
2487        /*  If channel is used by AP, set channel scan type to active */
2488        channel = bssid->Configuration.DSConfig;
2489        chplan_new = pmlmeext->channel_set;
2490        i = 0;
2491        while ((i < MAX_CHANNEL_NUM) && (chplan_new[i].ChannelNum != 0)) {
2492                if (chplan_new[i].ChannelNum == channel) {
2493                        if (chplan_new[i].ScanType == SCAN_PASSIVE) {
2494                                chplan_new[i].ScanType = SCAN_ACTIVE;
2495                                RT_TRACE(_module_rtl871x_mlme_c_, _drv_notice_,
2496                                         ("%s: change channel %d scan type from passive to active\n",
2497                                         __func__, channel));
2498                        }
2499                        break;
2500                }
2501                i++;
2502        }
2503}
2504
2505/****************************************************************************
2506
2507Following are the callback functions for each subtype of the management frames
2508
2509*****************************************************************************/
2510
2511static unsigned int OnProbeReq(struct adapter *padapter,
2512                               struct recv_frame *precv_frame)
2513{
2514        unsigned int    ielen;
2515        unsigned char   *p;
2516        struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
2517        struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
2518        struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
2519        struct wlan_bssid_ex *cur = &(pmlmeinfo->network);
2520        u8 *pframe = precv_frame->pkt->data;
2521        uint len = precv_frame->pkt->len;
2522
2523        if (check_fwstate(pmlmepriv, WIFI_STATION_STATE))
2524                return _SUCCESS;
2525
2526        if (!check_fwstate(pmlmepriv, _FW_LINKED) &&
2527            !check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE|WIFI_AP_STATE))
2528                return _SUCCESS;
2529
2530        p = rtw_get_ie(pframe + WLAN_HDR_A3_LEN + _PROBEREQ_IE_OFFSET_, _SSID_IE_, &ielen,
2531                        len - WLAN_HDR_A3_LEN - _PROBEREQ_IE_OFFSET_);
2532
2533        /* check (wildcard) SSID */
2534        if (p) {
2535                if ((ielen != 0 && memcmp((void *)(p+2), (void *)cur->Ssid.Ssid, cur->Ssid.SsidLength)) ||
2536                    (ielen == 0 && pmlmeinfo->hidden_ssid_mode))
2537                        return _SUCCESS;
2538
2539                if (check_fwstate(pmlmepriv, _FW_LINKED) &&
2540                    pmlmepriv->cur_network.join_res)
2541                        issue_probersp(padapter, get_sa(pframe));
2542        }
2543        return _SUCCESS;
2544}
2545
2546static unsigned int OnProbeRsp(struct adapter *padapter,
2547                               struct recv_frame *precv_frame)
2548{
2549        struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
2550
2551        if (pmlmeext->sitesurvey_res.state == SCAN_PROCESS) {
2552                report_survey_event(padapter, precv_frame);
2553                return _SUCCESS;
2554        }
2555
2556        return _SUCCESS;
2557}
2558
2559static unsigned int OnBeacon(struct adapter *padapter,
2560                             struct recv_frame *precv_frame)
2561{
2562        int cam_idx;
2563        struct sta_info *psta;
2564        struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
2565        struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
2566        struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
2567        struct sta_priv *pstapriv = &padapter->stapriv;
2568        u8 *pframe = precv_frame->pkt->data;
2569        uint len = precv_frame->pkt->len;
2570        struct wlan_bssid_ex *pbss;
2571        int ret = _SUCCESS;
2572        struct wlan_bssid_ex *pnetwork = &(pmlmeinfo->network);
2573
2574        if (pmlmeext->sitesurvey_res.state == SCAN_PROCESS) {
2575                report_survey_event(padapter, precv_frame);
2576                return _SUCCESS;
2577        }
2578
2579        if (!memcmp(GetAddr3Ptr(pframe), pnetwork->MacAddress, ETH_ALEN)) {
2580                if (pmlmeinfo->state & WIFI_FW_AUTH_NULL) {
2581                        /* we should update current network before auth, or some IE is wrong */
2582                        pbss = (struct wlan_bssid_ex *)rtw_malloc(sizeof(struct wlan_bssid_ex));
2583                        if (pbss) {
2584                                if (collect_bss_info(padapter, precv_frame, pbss) == _SUCCESS) {
2585                                        update_network(&(pmlmepriv->cur_network.network), pbss, padapter, true);
2586                                        rtw_get_bcn_info(&(pmlmepriv->cur_network));
2587                                }
2588                                kfree(pbss);
2589                        }
2590
2591                        /* check the vendor of the assoc AP */
2592                        pmlmeinfo->assoc_AP_vendor = check_assoc_AP(pframe+sizeof(struct ieee80211_hdr_3addr), len-sizeof(struct ieee80211_hdr_3addr));
2593
2594                        /* update TSF Value */
2595                        update_TSF(pmlmeext, pframe, len);
2596
2597                        /* start auth */
2598                        start_clnt_auth(padapter);
2599
2600                        return _SUCCESS;
2601                }
2602
2603                if (((pmlmeinfo->state&0x03) == WIFI_FW_STATION_STATE) && (pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS)) {
2604                        psta = rtw_get_stainfo(pstapriv, GetAddr2Ptr(pframe));
2605                        if (psta != NULL) {
2606                                ret = rtw_check_bcn_info(padapter, pframe, len);
2607                                if (!ret) {
2608                                                DBG_88E_LEVEL(_drv_info_, "ap has changed, disconnect now\n ");
2609                                                receive_disconnect(padapter, pmlmeinfo->network.MacAddress, 65535);
2610                                                return _SUCCESS;
2611                                }
2612                                /* update WMM, ERP in the beacon */
2613                                /* todo: the timer is used instead of the number of the beacon received */
2614                                if ((sta_rx_pkts(psta) & 0xf) == 0)
2615                                        update_beacon_info(padapter, pframe, len, psta);
2616                        }
2617                } else if ((pmlmeinfo->state&0x03) == WIFI_FW_ADHOC_STATE) {
2618                        psta = rtw_get_stainfo(pstapriv, GetAddr2Ptr(pframe));
2619                        if (psta != NULL) {
2620                                /* update WMM, ERP in the beacon */
2621                                /* todo: the timer is used instead of the number of the beacon received */
2622                                if ((sta_rx_pkts(psta) & 0xf) == 0)
2623                                        update_beacon_info(padapter, pframe, len, psta);
2624                        } else {
2625                                /* allocate a new CAM entry for IBSS station */
2626                                cam_idx = allocate_fw_sta_entry(padapter);
2627                                if (cam_idx == NUM_STA)
2628                                        goto _END_ONBEACON_;
2629
2630                                /* get supported rate */
2631                                if (update_sta_support_rate(padapter, (pframe + WLAN_HDR_A3_LEN + _BEACON_IE_OFFSET_), (len - WLAN_HDR_A3_LEN - _BEACON_IE_OFFSET_), cam_idx) == _FAIL) {
2632                                        pmlmeinfo->FW_sta_info[cam_idx].status = 0;
2633                                        goto _END_ONBEACON_;
2634                                }
2635
2636                                /* update TSF Value */
2637                                update_TSF(pmlmeext, pframe, len);
2638
2639                                /* report sta add event */
2640                                report_add_sta_event(padapter, GetAddr2Ptr(pframe), cam_idx);
2641                        }
2642                }
2643        }
2644
2645_END_ONBEACON_:
2646
2647        return _SUCCESS;
2648}
2649
2650#ifdef CONFIG_88EU_AP_MODE
2651static unsigned int OnAuth(struct adapter *padapter,
2652                           struct recv_frame *precv_frame)
2653{
2654        unsigned int    auth_mode, ie_len;
2655        u16 seq;
2656        unsigned char   *sa, *p;
2657        u16 algorithm;
2658        int     status;
2659        static struct sta_info stat;
2660        struct  sta_info        *pstat = NULL;
2661        struct  sta_priv *pstapriv = &padapter->stapriv;
2662        struct security_priv *psecuritypriv = &padapter->securitypriv;
2663        struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
2664        struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
2665        u8 *pframe = precv_frame->pkt->data;
2666        uint len = precv_frame->pkt->len;
2667
2668        if ((pmlmeinfo->state&0x03) != WIFI_FW_AP_STATE)
2669                return _FAIL;
2670
2671        DBG_88E("+%s\n", __func__);
2672
2673        sa = GetAddr2Ptr(pframe);
2674
2675        auth_mode = psecuritypriv->dot11AuthAlgrthm;
2676        seq = le16_to_cpu(*(__le16 *)((size_t)pframe + WLAN_HDR_A3_LEN + 2));
2677        algorithm = le16_to_cpu(*(__le16 *)((size_t)pframe + WLAN_HDR_A3_LEN));
2678
2679        DBG_88E("auth alg=%x, seq=%X\n", algorithm, seq);
2680
2681        if (auth_mode == 2 && psecuritypriv->dot11PrivacyAlgrthm != _WEP40_ &&
2682            psecuritypriv->dot11PrivacyAlgrthm != _WEP104_)
2683                auth_mode = 0;
2684
2685        if ((algorithm > 0 && auth_mode == 0) ||        /*  rx a shared-key auth but shared not enabled */
2686            (algorithm == 0 && auth_mode == 1)) {       /*  rx a open-system auth but shared-key is enabled */
2687                DBG_88E("auth rejected due to bad alg [alg=%d, auth_mib=%d] %02X%02X%02X%02X%02X%02X\n",
2688                        algorithm, auth_mode, sa[0], sa[1], sa[2], sa[3], sa[4], sa[5]);
2689
2690                status = _STATS_NO_SUPP_ALG_;
2691
2692                goto auth_fail;
2693        }
2694
2695        if (!rtw_access_ctrl(padapter, sa)) {
2696                status = _STATS_UNABLE_HANDLE_STA_;
2697                goto auth_fail;
2698        }
2699
2700        pstat = rtw_get_stainfo(pstapriv, sa);
2701        if (!pstat) {
2702                /*  allocate a new one */
2703                DBG_88E("going to alloc stainfo for sa=%pM\n", sa);
2704                pstat = rtw_alloc_stainfo(pstapriv, sa);
2705                if (!pstat) {
2706                        DBG_88E(" Exceed the upper limit of supported clients...\n");
2707                        status = _STATS_UNABLE_HANDLE_STA_;
2708                        goto auth_fail;
2709                }
2710
2711                pstat->state = WIFI_FW_AUTH_NULL;
2712                pstat->auth_seq = 0;
2713        } else {
2714                spin_lock_bh(&pstapriv->asoc_list_lock);
2715                if (!list_empty(&pstat->asoc_list)) {
2716                        list_del_init(&pstat->asoc_list);
2717                        pstapriv->asoc_list_cnt--;
2718                }
2719                spin_unlock_bh(&pstapriv->asoc_list_lock);
2720
2721                if (seq == 1) {
2722                        /* TODO: STA re_auth and auth timeout */
2723                }
2724        }
2725
2726        spin_lock_bh(&pstapriv->auth_list_lock);
2727        if (list_empty(&pstat->auth_list)) {
2728                list_add_tail(&pstat->auth_list, &pstapriv->auth_list);
2729                pstapriv->auth_list_cnt++;
2730        }
2731        spin_unlock_bh(&pstapriv->auth_list_lock);
2732
2733        if (pstat->auth_seq == 0)
2734                pstat->expire_to = pstapriv->auth_to;
2735
2736        if ((pstat->auth_seq + 1) != seq) {
2737                DBG_88E("(1)auth rejected because out of seq [rx_seq=%d, exp_seq=%d]!\n",
2738                        seq, pstat->auth_seq+1);
2739                status = _STATS_OUT_OF_AUTH_SEQ_;
2740                goto auth_fail;
2741        }
2742
2743        if (algorithm == 0 && (auth_mode == 0 || auth_mode == 2)) {
2744                if (seq == 1) {
2745                        pstat->state &= ~WIFI_FW_AUTH_NULL;
2746                        pstat->state |= WIFI_FW_AUTH_SUCCESS;
2747                        pstat->expire_to = pstapriv->assoc_to;
2748                        pstat->authalg = algorithm;
2749                } else {
2750                        DBG_88E("(2)auth rejected because out of seq [rx_seq=%d, exp_seq=%d]!\n",
2751                                seq, pstat->auth_seq+1);
2752                        status = _STATS_OUT_OF_AUTH_SEQ_;
2753                        goto auth_fail;
2754                }
2755        } else { /*  shared system or auto authentication */
2756                if (seq == 1) {
2757                        /* prepare for the challenging txt... */
2758
2759                        pstat->state &= ~WIFI_FW_AUTH_NULL;
2760                        pstat->state |= WIFI_FW_AUTH_STATE;
2761                        pstat->authalg = algorithm;
2762                        pstat->auth_seq = 2;
2763                } else if (seq == 3) {
2764                        /* checking for challenging txt... */
2765                        DBG_88E("checking for challenging txt...\n");
2766
2767                        p = rtw_get_ie(pframe + WLAN_HDR_A3_LEN + 4 + _AUTH_IE_OFFSET_, _CHLGETXT_IE_, &ie_len,
2768                                        len - WLAN_HDR_A3_LEN - _AUTH_IE_OFFSET_ - 4);
2769
2770                        if ((p == NULL) || (ie_len <= 0)) {
2771                                DBG_88E("auth rejected because challenge failure!(1)\n");
2772                                status = _STATS_CHALLENGE_FAIL_;
2773                                goto auth_fail;
2774                        }
2775
2776                        if (!memcmp((void *)(p + 2), pstat->chg_txt, 128)) {
2777                                pstat->state &= (~WIFI_FW_AUTH_STATE);
2778                                pstat->state |= WIFI_FW_AUTH_SUCCESS;
2779                                /*  challenging txt is correct... */
2780                                pstat->expire_to =  pstapriv->assoc_to;
2781                        } else {
2782                                DBG_88E("auth rejected because challenge failure!\n");
2783                                status = _STATS_CHALLENGE_FAIL_;
2784                                goto auth_fail;
2785                        }
2786                } else {
2787                        DBG_88E("(3)auth rejected because out of seq [rx_seq=%d, exp_seq=%d]!\n",
2788                                seq, pstat->auth_seq+1);
2789                        status = _STATS_OUT_OF_AUTH_SEQ_;
2790                        goto auth_fail;
2791                }
2792        }
2793
2794        /*  Now, we are going to issue_auth... */
2795        pstat->auth_seq = seq + 1;
2796
2797        issue_auth(padapter, pstat, (unsigned short)(_STATS_SUCCESSFUL_));
2798
2799        if (pstat->state & WIFI_FW_AUTH_SUCCESS)
2800                pstat->auth_seq = 0;
2801
2802        return _SUCCESS;
2803
2804auth_fail:
2805
2806        if (pstat)
2807                rtw_free_stainfo(padapter, pstat);
2808
2809        pstat = &stat;
2810        memset((char *)pstat, '\0', sizeof(stat));
2811        pstat->auth_seq = 2;
2812        memcpy(pstat->hwaddr, sa, 6);
2813
2814        issue_auth(padapter, pstat, (unsigned short)status);
2815
2816        return _FAIL;
2817}
2818#endif /* CONFIG_88EU_AP_MODE */
2819
2820static unsigned int OnAuthClient(struct adapter *padapter,
2821                                 struct recv_frame *precv_frame)
2822{
2823        unsigned int    seq, len, status, offset;
2824        unsigned char   *p;
2825        unsigned int    go2asoc = 0;
2826        struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
2827        struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
2828        u8 *pframe = precv_frame->pkt->data;
2829        uint pkt_len = precv_frame->pkt->len;
2830
2831        DBG_88E("%s\n", __func__);
2832
2833        /* check A1 matches or not */
2834        if (memcmp(myid(&(padapter->eeprompriv)), get_da(pframe), ETH_ALEN))
2835                return _SUCCESS;
2836
2837        if (!(pmlmeinfo->state & WIFI_FW_AUTH_STATE))
2838                return _SUCCESS;
2839
2840        offset = (GetPrivacy(pframe)) ? 4 : 0;
2841
2842        seq     = le16_to_cpu(*(__le16 *)((size_t)pframe + WLAN_HDR_A3_LEN + offset + 2));
2843        status  = le16_to_cpu(*(__le16 *)((size_t)pframe + WLAN_HDR_A3_LEN + offset + 4));
2844
2845        if (status != 0) {
2846                DBG_88E("clnt auth fail, status: %d\n", status);
2847                if (status == 13) { /*  pmlmeinfo->auth_algo == dot11AuthAlgrthm_Auto) */
2848                        if (pmlmeinfo->auth_algo == dot11AuthAlgrthm_Shared)
2849                                pmlmeinfo->auth_algo = dot11AuthAlgrthm_Open;
2850                        else
2851                                pmlmeinfo->auth_algo = dot11AuthAlgrthm_Shared;
2852                }
2853
2854                set_link_timer(pmlmeext, 1);
2855                goto authclnt_fail;
2856        }
2857
2858        if (seq == 2) {
2859                if (pmlmeinfo->auth_algo == dot11AuthAlgrthm_Shared) {
2860                        /*  legendary shared system */
2861                        p = rtw_get_ie(pframe + WLAN_HDR_A3_LEN + _AUTH_IE_OFFSET_, _CHLGETXT_IE_, &len,
2862                                pkt_len - WLAN_HDR_A3_LEN - _AUTH_IE_OFFSET_);
2863
2864                        if (p == NULL)
2865                                goto authclnt_fail;
2866
2867                        memcpy((void *)(pmlmeinfo->chg_txt), (void *)(p + 2), len);
2868                        pmlmeinfo->auth_seq = 3;
2869                        issue_auth(padapter, NULL, 0);
2870                        set_link_timer(pmlmeext, REAUTH_TO);
2871
2872                        return _SUCCESS;
2873                } else {
2874                        /*  open system */
2875                        go2asoc = 1;
2876                }
2877        } else if (seq == 4) {
2878                if (pmlmeinfo->auth_algo == dot11AuthAlgrthm_Shared)
2879                        go2asoc = 1;
2880                else
2881                        goto authclnt_fail;
2882        } else {
2883                /*  this is also illegal */
2884                goto authclnt_fail;
2885        }
2886
2887        if (go2asoc) {
2888                DBG_88E_LEVEL(_drv_info_, "auth success, start assoc\n");
2889                start_clnt_assoc(padapter);
2890                return _SUCCESS;
2891        }
2892authclnt_fail:
2893        return _FAIL;
2894}
2895
2896static unsigned int OnAssocReq(struct adapter *padapter,
2897                               struct recv_frame *precv_frame)
2898{
2899#ifdef CONFIG_88EU_AP_MODE
2900        u16 capab_info;
2901        struct rtw_ieee802_11_elems elems;
2902        struct sta_info *pstat;
2903        unsigned char           reassoc, *p, *pos, *wpa_ie;
2904        unsigned char WMM_IE[] = {0x00, 0x50, 0xf2, 0x02, 0x00, 0x01};
2905        int             i, wpa_ie_len, left;
2906        unsigned char           supportRate[16];
2907        int                                     supportRateNum;
2908        unsigned short          status = _STATS_SUCCESSFUL_;
2909        unsigned short          frame_type, ie_offset = 0;
2910        struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
2911        struct security_priv *psecuritypriv = &padapter->securitypriv;
2912        struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
2913        struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
2914        struct wlan_bssid_ex *cur = &(pmlmeinfo->network);
2915        struct sta_priv *pstapriv = &padapter->stapriv;
2916        u8 *pframe = precv_frame->pkt->data;
2917        uint ie_len, pkt_len = precv_frame->pkt->len;
2918
2919        if ((pmlmeinfo->state&0x03) != WIFI_FW_AP_STATE)
2920                return _FAIL;
2921
2922        frame_type = GetFrameSubType(pframe);
2923        if (frame_type == WIFI_ASSOCREQ) {
2924                reassoc = 0;
2925                ie_offset = _ASOCREQ_IE_OFFSET_;
2926        } else { /*  WIFI_REASSOCREQ */
2927                reassoc = 1;
2928                ie_offset = _REASOCREQ_IE_OFFSET_;
2929        }
2930
2931        if (pkt_len < IEEE80211_3ADDR_LEN + ie_offset) {
2932                DBG_88E("handle_assoc(reassoc=%d) - too short payload (len=%lu)"
2933                       "\n", reassoc, (unsigned long)pkt_len);
2934                return _FAIL;
2935        }
2936
2937        pstat = rtw_get_stainfo(pstapriv, GetAddr2Ptr(pframe));
2938        if (!pstat) {
2939                status = _RSON_CLS2_;
2940                goto asoc_class2_error;
2941        }
2942
2943        capab_info = get_unaligned_le16(pframe + WLAN_HDR_A3_LEN);
2944
2945        left = pkt_len - (IEEE80211_3ADDR_LEN + ie_offset);
2946        pos = pframe + (IEEE80211_3ADDR_LEN + ie_offset);
2947
2948        DBG_88E("%s\n", __func__);
2949
2950        /*  check if this stat has been successfully authenticated/assocated */
2951        if (!((pstat->state) & WIFI_FW_AUTH_SUCCESS)) {
2952                if (!((pstat->state) & WIFI_FW_ASSOC_SUCCESS)) {
2953                        status = _RSON_CLS2_;
2954                        goto asoc_class2_error;
2955                } else {
2956                        pstat->state &= (~WIFI_FW_ASSOC_SUCCESS);
2957                        pstat->state |= WIFI_FW_ASSOC_STATE;
2958                }
2959        } else {
2960                pstat->state &= (~WIFI_FW_AUTH_SUCCESS);
2961                pstat->state |= WIFI_FW_ASSOC_STATE;
2962        }
2963        pstat->capability = capab_info;
2964        /* now parse all ieee802_11 ie to point to elems */
2965        if (rtw_ieee802_11_parse_elems(pos, left, &elems, 1) == ParseFailed ||
2966            !elems.ssid) {
2967                DBG_88E("STA %pM sent invalid association request\n",
2968                        pstat->hwaddr);
2969                status = _STATS_FAILURE_;
2970                goto OnAssocReqFail;
2971        }
2972
2973        /*  now we should check all the fields... */
2974        /*  checking SSID */
2975        p = rtw_get_ie(pframe + WLAN_HDR_A3_LEN + ie_offset, _SSID_IE_, &ie_len,
2976                pkt_len - WLAN_HDR_A3_LEN - ie_offset);
2977
2978        if (!p || ie_len == 0) {
2979                /*  broadcast ssid, however it is not allowed in assocreq */
2980                status = _STATS_FAILURE_;
2981                goto OnAssocReqFail;
2982        } else {
2983                /*  check if ssid match */
2984                if (memcmp((void *)(p+2), cur->Ssid.Ssid, cur->Ssid.SsidLength))
2985                        status = _STATS_FAILURE_;
2986
2987                if (ie_len != cur->Ssid.SsidLength)
2988                        status = _STATS_FAILURE_;
2989        }
2990
2991        if (_STATS_SUCCESSFUL_ != status)
2992                goto OnAssocReqFail;
2993
2994        /*  check if the supported rate is ok */
2995        p = rtw_get_ie(pframe + WLAN_HDR_A3_LEN + ie_offset, _SUPPORTEDRATES_IE_, &ie_len, pkt_len - WLAN_HDR_A3_LEN - ie_offset);
2996        if (p == NULL) {
2997                DBG_88E("Rx a sta assoc-req which supported rate is empty!\n");
2998                /*  use our own rate set as statoin used */
2999                /* memcpy(supportRate, AP_BSSRATE, AP_BSSRATE_LEN); */
3000                /* supportRateNum = AP_BSSRATE_LEN; */
3001
3002                status = _STATS_FAILURE_;
3003                goto OnAssocReqFail;
3004        } else {
3005                memcpy(supportRate, p+2, ie_len);
3006                supportRateNum = ie_len;
3007
3008                p = rtw_get_ie(pframe + WLAN_HDR_A3_LEN + ie_offset, _EXT_SUPPORTEDRATES_IE_, &ie_len,
3009                                pkt_len - WLAN_HDR_A3_LEN - ie_offset);
3010                if (p !=  NULL) {
3011                        if (supportRateNum <= sizeof(supportRate)) {
3012                                memcpy(supportRate+supportRateNum, p+2, ie_len);
3013                                supportRateNum += ie_len;
3014                        }
3015                }
3016        }
3017
3018        /* todo: mask supportRate between AP & STA -> move to update raid */
3019        /* get_matched_rate(pmlmeext, supportRate, &supportRateNum, 0); */
3020
3021        /* update station supportRate */
3022        pstat->bssratelen = supportRateNum;
3023        memcpy(pstat->bssrateset, supportRate, supportRateNum);
3024        UpdateBrateTblForSoftAP(pstat->bssrateset, pstat->bssratelen);
3025
3026        /* check RSN/WPA/WPS */
3027        pstat->dot8021xalg = 0;
3028        pstat->wpa_psk = 0;
3029        pstat->wpa_group_cipher = 0;
3030        pstat->wpa2_group_cipher = 0;
3031        pstat->wpa_pairwise_cipher = 0;
3032        pstat->wpa2_pairwise_cipher = 0;
3033        memset(pstat->wpa_ie, 0, sizeof(pstat->wpa_ie));
3034        if ((psecuritypriv->wpa_psk & BIT(1)) && elems.rsn_ie) {
3035                int group_cipher = 0, pairwise_cipher = 0;
3036
3037                wpa_ie = elems.rsn_ie;
3038                wpa_ie_len = elems.rsn_ie_len;
3039
3040                if (rtw_parse_wpa2_ie(wpa_ie-2, wpa_ie_len+2, &group_cipher, &pairwise_cipher, NULL) == _SUCCESS) {
3041                        pstat->dot8021xalg = 1;/* psk,  todo:802.1x */
3042                        pstat->wpa_psk |= BIT(1);
3043
3044                        pstat->wpa2_group_cipher = group_cipher&psecuritypriv->wpa2_group_cipher;
3045                        pstat->wpa2_pairwise_cipher = pairwise_cipher&psecuritypriv->wpa2_pairwise_cipher;
3046
3047                        if (!pstat->wpa2_group_cipher)
3048                                status = WLAN_STATUS_INVALID_GROUP_CIPHER;
3049
3050                        if (!pstat->wpa2_pairwise_cipher)
3051                                status = WLAN_STATUS_INVALID_PAIRWISE_CIPHER;
3052                } else {
3053                        status = WLAN_STATUS_INVALID_IE;
3054                }
3055        } else if ((psecuritypriv->wpa_psk & BIT(0)) && elems.wpa_ie) {
3056                int group_cipher = 0, pairwise_cipher = 0;
3057
3058                wpa_ie = elems.wpa_ie;
3059                wpa_ie_len = elems.wpa_ie_len;
3060
3061                if (rtw_parse_wpa_ie(wpa_ie-2, wpa_ie_len+2, &group_cipher, &pairwise_cipher, NULL) == _SUCCESS) {
3062                        pstat->dot8021xalg = 1;/* psk,  todo:802.1x */
3063                        pstat->wpa_psk |= BIT(0);
3064
3065                        pstat->wpa_group_cipher = group_cipher&psecuritypriv->wpa_group_cipher;
3066                        pstat->wpa_pairwise_cipher = pairwise_cipher&psecuritypriv->wpa_pairwise_cipher;
3067
3068                        if (!pstat->wpa_group_cipher)
3069                                status = WLAN_STATUS_INVALID_GROUP_CIPHER;
3070
3071                        if (!pstat->wpa_pairwise_cipher)
3072                                status = WLAN_STATUS_INVALID_PAIRWISE_CIPHER;
3073                } else {
3074                        status = WLAN_STATUS_INVALID_IE;
3075                }
3076        } else {
3077                wpa_ie = NULL;
3078                wpa_ie_len = 0;
3079        }
3080
3081        if (_STATS_SUCCESSFUL_ != status)
3082                goto OnAssocReqFail;
3083
3084        pstat->flags &= ~(WLAN_STA_WPS | WLAN_STA_MAYBE_WPS);
3085        if (!wpa_ie) {
3086                if (elems.wps_ie) {
3087                        DBG_88E("STA included WPS IE in "
3088                                   "(Re)Association Request - assume WPS is "
3089                                   "used\n");
3090                        pstat->flags |= WLAN_STA_WPS;
3091                        /* wpabuf_free(sta->wps_ie); */
3092                        /* sta->wps_ie = wpabuf_alloc_copy(elems.wps_ie + 4, */
3093                        /*                              elems.wps_ie_len - 4); */
3094                } else {
3095                        DBG_88E("STA did not include WPA/RSN IE "
3096                                   "in (Re)Association Request - possible WPS "
3097                                   "use\n");
3098                        pstat->flags |= WLAN_STA_MAYBE_WPS;
3099                }
3100
3101                /*  AP support WPA/RSN, and sta is going to do WPS, but AP is not ready */
3102                /*  that the selected registrar of AP is _FLASE */
3103                if ((psecuritypriv->wpa_psk > 0) && (pstat->flags & (WLAN_STA_WPS|WLAN_STA_MAYBE_WPS))) {
3104                        if (pmlmepriv->wps_beacon_ie) {
3105                                u8 selected_registrar = 0;
3106
3107                                rtw_get_wps_attr_content(pmlmepriv->wps_beacon_ie, pmlmepriv->wps_beacon_ie_len, WPS_ATTR_SELECTED_REGISTRAR, &selected_registrar, NULL);
3108
3109                                if (!selected_registrar) {
3110                                        DBG_88E("selected_registrar is false , or AP is not ready to do WPS\n");
3111
3112                                        status = _STATS_UNABLE_HANDLE_STA_;
3113
3114                                        goto OnAssocReqFail;
3115                                }
3116                        }
3117                }
3118        } else {
3119                int copy_len;
3120
3121                if (psecuritypriv->wpa_psk == 0) {
3122                        DBG_88E("STA %pM: WPA/RSN IE in association "
3123                        "request, but AP don't support WPA/RSN\n", pstat->hwaddr);
3124
3125                        status = WLAN_STATUS_INVALID_IE;
3126
3127                        goto OnAssocReqFail;
3128                }
3129
3130                if (elems.wps_ie) {
3131                        DBG_88E("STA included WPS IE in "
3132                                   "(Re)Association Request - WPS is "
3133                                   "used\n");
3134                        pstat->flags |= WLAN_STA_WPS;
3135                        copy_len = 0;
3136                } else {
3137                        copy_len = min_t(int, wpa_ie_len + 2, sizeof(pstat->wpa_ie));
3138                }
3139                if (copy_len > 0)
3140                        memcpy(pstat->wpa_ie, wpa_ie-2, copy_len);
3141        }
3142        /*  check if there is WMM IE & support WWM-PS */
3143        pstat->flags &= ~WLAN_STA_WME;
3144        pstat->qos_option = 0;
3145        pstat->qos_info = 0;
3146        pstat->has_legacy_ac = true;
3147        pstat->uapsd_vo = 0;
3148        pstat->uapsd_vi = 0;
3149        pstat->uapsd_be = 0;
3150        pstat->uapsd_bk = 0;
3151        if (pmlmepriv->qospriv.qos_option) {
3152                p = pframe + WLAN_HDR_A3_LEN + ie_offset; ie_len = 0;
3153                for (;;) {
3154                        p = rtw_get_ie(p, _VENDOR_SPECIFIC_IE_, &ie_len, pkt_len - WLAN_HDR_A3_LEN - ie_offset);
3155                        if (p != NULL) {
3156                                if (!memcmp(p+2, WMM_IE, 6)) {
3157                                        pstat->flags |= WLAN_STA_WME;
3158
3159                                        pstat->qos_option = 1;
3160                                        pstat->qos_info = *(p+8);
3161
3162                                        pstat->max_sp_len = (pstat->qos_info>>5)&0x3;
3163
3164                                        if ((pstat->qos_info&0xf) != 0xf)
3165                                                pstat->has_legacy_ac = true;
3166                                        else
3167                                                pstat->has_legacy_ac = false;
3168
3169                                        if (pstat->qos_info&0xf) {
3170                                                if (pstat->qos_info&BIT(0))
3171                                                        pstat->uapsd_vo = BIT(0)|BIT(1);
3172                                                else
3173                                                        pstat->uapsd_vo = 0;
3174
3175                                                if (pstat->qos_info&BIT(1))
3176                                                        pstat->uapsd_vi = BIT(0)|BIT(1);
3177                                                else
3178                                                        pstat->uapsd_vi = 0;
3179
3180                                                if (pstat->qos_info&BIT(2))
3181                                                        pstat->uapsd_bk = BIT(0)|BIT(1);
3182                                                else
3183                                                        pstat->uapsd_bk = 0;
3184
3185                                                if (pstat->qos_info&BIT(3))
3186                                                        pstat->uapsd_be = BIT(0)|BIT(1);
3187                                                else
3188                                                        pstat->uapsd_be = 0;
3189                                        }
3190                                        break;
3191                                }
3192                        } else {
3193                                break;
3194                        }
3195                        p = p + ie_len + 2;
3196                }
3197        }
3198
3199        /* save HT capabilities in the sta object */
3200        memset(&pstat->htpriv.ht_cap, 0, sizeof(struct ieee80211_ht_cap));
3201        if (elems.ht_capabilities &&
3202            elems.ht_capabilities_len >= sizeof(struct ieee80211_ht_cap)) {
3203                pstat->flags |= WLAN_STA_HT;
3204
3205                pstat->flags |= WLAN_STA_WME;
3206
3207                memcpy(&pstat->htpriv.ht_cap,
3208                       elems.ht_capabilities, sizeof(struct ieee80211_ht_cap));
3209        } else {
3210                pstat->flags &= ~WLAN_STA_HT;
3211        }
3212        if ((!pmlmepriv->htpriv.ht_option) && (pstat->flags&WLAN_STA_HT)) {
3213                status = _STATS_FAILURE_;
3214                goto OnAssocReqFail;
3215        }
3216
3217        if ((pstat->flags & WLAN_STA_HT) &&
3218            ((pstat->wpa2_pairwise_cipher&WPA_CIPHER_TKIP) ||
3219            (pstat->wpa_pairwise_cipher&WPA_CIPHER_TKIP))) {
3220                DBG_88E("HT: %pM tried to "
3221                        "use TKIP with HT association\n", pstat->hwaddr);
3222
3223                /* status = WLAN_STATUS_CIPHER_REJECTED_PER_POLICY; */
3224                /* goto OnAssocReqFail; */
3225        }
3226
3227        pstat->flags |= WLAN_STA_NONERP;
3228        for (i = 0; i < pstat->bssratelen; i++) {
3229                if ((pstat->bssrateset[i] & 0x7f) > 22) {
3230                        pstat->flags &= ~WLAN_STA_NONERP;
3231                        break;
3232                }
3233        }
3234
3235        if (pstat->capability & WLAN_CAPABILITY_SHORT_PREAMBLE)
3236                pstat->flags |= WLAN_STA_SHORT_PREAMBLE;
3237        else
3238                pstat->flags &= ~WLAN_STA_SHORT_PREAMBLE;
3239
3240        if (status != _STATS_SUCCESSFUL_)
3241                goto OnAssocReqFail;
3242
3243        /* TODO: identify_proprietary_vendor_ie(); */
3244        /*  Realtek proprietary IE */
3245        /*  identify if this is Broadcom sta */
3246        /*  identify if this is ralink sta */
3247        /*  Customer proprietary IE */
3248
3249        /* get a unique AID */
3250        if (pstat->aid > 0) {
3251                DBG_88E("  old AID %d\n", pstat->aid);
3252        } else {
3253                for (pstat->aid = 1; pstat->aid <= NUM_STA; pstat->aid++)
3254                        if (pstapriv->sta_aid[pstat->aid - 1] == NULL)
3255                                break;
3256
3257                /* if (pstat->aid > NUM_STA) { */
3258                if (pstat->aid > pstapriv->max_num_sta) {
3259                        pstat->aid = 0;
3260
3261                        DBG_88E("  no room for more AIDs\n");
3262
3263                        status = WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA;
3264
3265                        goto OnAssocReqFail;
3266                } else {
3267                        pstapriv->sta_aid[pstat->aid - 1] = pstat;
3268                        DBG_88E("allocate new AID=(%d)\n", pstat->aid);
3269                }
3270        }
3271
3272        pstat->state &= (~WIFI_FW_ASSOC_STATE);
3273        pstat->state |= WIFI_FW_ASSOC_SUCCESS;
3274
3275        spin_lock_bh(&pstapriv->auth_list_lock);
3276        if (!list_empty(&pstat->auth_list)) {
3277                list_del_init(&pstat->auth_list);
3278                pstapriv->auth_list_cnt--;
3279        }
3280        spin_unlock_bh(&pstapriv->auth_list_lock);
3281
3282        spin_lock_bh(&pstapriv->asoc_list_lock);
3283        if (list_empty(&pstat->asoc_list)) {
3284                pstat->expire_to = pstapriv->expire_to;
3285                list_add_tail(&pstat->asoc_list, &pstapriv->asoc_list);
3286                pstapriv->asoc_list_cnt++;
3287        }
3288        spin_unlock_bh(&pstapriv->asoc_list_lock);
3289
3290        /*  now the station is qualified to join our BSS... */
3291        if ((pstat->state & WIFI_FW_ASSOC_SUCCESS) && (_STATS_SUCCESSFUL_ == status)) {
3292                /* 1 bss_cap_update & sta_info_update */
3293                bss_cap_update_on_sta_join(padapter, pstat);
3294                sta_info_update(padapter, pstat);
3295
3296                /* issue assoc rsp before notify station join event. */
3297                if (frame_type == WIFI_ASSOCREQ)
3298                        issue_asocrsp(padapter, status, pstat, WIFI_ASSOCRSP);
3299                else
3300                        issue_asocrsp(padapter, status, pstat, WIFI_REASSOCRSP);
3301
3302                /* 2 - report to upper layer */
3303                DBG_88E("indicate_sta_join_event to upper layer - hostapd\n");
3304                rtw_indicate_sta_assoc_event(padapter, pstat);
3305
3306                /* 3-(1) report sta add event */
3307                report_add_sta_event(padapter, pstat->hwaddr, pstat->aid);
3308        }
3309
3310        return _SUCCESS;
3311
3312asoc_class2_error:
3313
3314        issue_deauth(padapter, (void *)GetAddr2Ptr(pframe), status);
3315
3316        return _FAIL;
3317
3318OnAssocReqFail:
3319
3320        pstat->aid = 0;
3321        if (frame_type == WIFI_ASSOCREQ)
3322                issue_asocrsp(padapter, status, pstat, WIFI_ASSOCRSP);
3323        else
3324                issue_asocrsp(padapter, status, pstat, WIFI_REASSOCRSP);
3325
3326#endif /* CONFIG_88EU_AP_MODE */
3327
3328        return _FAIL;
3329}
3330
3331static unsigned int OnAssocRsp(struct adapter *padapter,
3332                               struct recv_frame *precv_frame)
3333{
3334        uint i;
3335        int res;
3336        unsigned short  status;
3337        struct ndis_802_11_var_ie *pIE;
3338        struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
3339        struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
3340        struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
3341        /* struct wlan_bssid_ex *cur_network = &(pmlmeinfo->network); */
3342        u8 *pframe = precv_frame->pkt->data;
3343        uint pkt_len = precv_frame->pkt->len;
3344
3345        DBG_88E("%s\n", __func__);
3346
3347        /* check A1 matches or not */
3348        if (memcmp(myid(&(padapter->eeprompriv)), get_da(pframe), ETH_ALEN))
3349                return _SUCCESS;
3350
3351        if (!(pmlmeinfo->state & (WIFI_FW_AUTH_SUCCESS | WIFI_FW_ASSOC_STATE)))
3352                return _SUCCESS;
3353
3354        if (pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS)
3355                return _SUCCESS;
3356
3357        del_timer_sync(&pmlmeext->link_timer);
3358
3359        /* status */
3360        status = le16_to_cpu(*(__le16 *)(pframe + WLAN_HDR_A3_LEN + 2));
3361        if (status > 0) {
3362                DBG_88E("assoc reject, status code: %d\n", status);
3363                pmlmeinfo->state = WIFI_FW_NULL_STATE;
3364                res = -4;
3365                goto report_assoc_result;
3366        }
3367
3368        /* get capabilities */
3369        pmlmeinfo->capability = le16_to_cpu(*(__le16 *)(pframe + WLAN_HDR_A3_LEN));
3370
3371        /* set slot time */
3372        pmlmeinfo->slotTime = (pmlmeinfo->capability & BIT(10)) ? 9 : 20;
3373
3374        /* AID */
3375        pmlmeinfo->aid = (int)(le16_to_cpu(*(__le16 *)(pframe + WLAN_HDR_A3_LEN + 4))&0x3fff);
3376        res = pmlmeinfo->aid;
3377
3378        /* following are moved to join event callback function */
3379        /* to handle HT, WMM, rate adaptive, update MAC reg */
3380        /* for not to handle the synchronous IO in the tasklet */
3381        for (i = 6 + WLAN_HDR_A3_LEN; i < pkt_len;) {
3382                pIE = (struct ndis_802_11_var_ie *)(pframe + i);
3383
3384                switch (pIE->ElementID) {
3385                case _VENDOR_SPECIFIC_IE_:
3386                        if (!memcmp(pIE->data, WMM_PARA_OUI, 6)) /* WMM */
3387                                WMM_param_handler(padapter, pIE);
3388                        break;
3389                case _HT_CAPABILITY_IE_:        /* HT caps */
3390                        HT_caps_handler(padapter, pIE);
3391                        break;
3392                case _HT_EXTRA_INFO_IE_:        /* HT info */
3393                        HT_info_handler(padapter, pIE);
3394                        break;
3395                case _ERPINFO_IE_:
3396                        ERP_IE_handler(padapter, pIE);
3397                default:
3398                        break;
3399                }
3400
3401                i += (pIE->Length + 2);
3402        }
3403
3404        pmlmeinfo->state &= (~WIFI_FW_ASSOC_STATE);
3405        pmlmeinfo->state |= WIFI_FW_ASSOC_SUCCESS;
3406
3407        UpdateBrateTbl(padapter, pmlmeinfo->network.SupportedRates);
3408
3409report_assoc_result:
3410        if (res > 0)
3411                rtw_buf_update(&pmlmepriv->assoc_rsp, &pmlmepriv->assoc_rsp_len, pframe, pkt_len);
3412        else
3413                rtw_buf_free(&pmlmepriv->assoc_rsp, &pmlmepriv->assoc_rsp_len);
3414
3415        report_join_res(padapter, res);
3416
3417        return _SUCCESS;
3418}
3419
3420static unsigned int OnDeAuth(struct adapter *padapter,
3421                             struct recv_frame *precv_frame)
3422{
3423        unsigned short  reason;
3424        struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
3425        struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
3426        struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
3427        u8 *pframe = precv_frame->pkt->data;
3428        struct wlan_bssid_ex *pnetwork = &(pmlmeinfo->network);
3429
3430        /* check A3 */
3431        if (memcmp(GetAddr3Ptr(pframe), pnetwork->MacAddress, ETH_ALEN))
3432                return _SUCCESS;
3433
3434        reason = le16_to_cpu(*(__le16 *)(pframe + WLAN_HDR_A3_LEN));
3435
3436        DBG_88E("%s Reason code(%d)\n", __func__, reason);
3437
3438#ifdef CONFIG_88EU_AP_MODE
3439        if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) {
3440                struct sta_info *psta;
3441                struct sta_priv *pstapriv = &padapter->stapriv;
3442
3443                DBG_88E_LEVEL(_drv_always_, "ap recv deauth reason code(%d) sta:%pM\n",
3444                              reason, GetAddr2Ptr(pframe));
3445
3446                psta = rtw_get_stainfo(pstapriv, GetAddr2Ptr(pframe));
3447                if (psta) {
3448                        u8 updated = 0;
3449
3450                        spin_lock_bh(&pstapriv->asoc_list_lock);
3451                        if (!list_empty(&psta->asoc_list)) {
3452                                list_del_init(&psta->asoc_list);
3453                                pstapriv->asoc_list_cnt--;
3454                                updated = ap_free_sta(padapter, psta, false, reason);
3455                        }
3456                        spin_unlock_bh(&pstapriv->asoc_list_lock);
3457
3458                        associated_clients_update(padapter, updated);
3459                }
3460
3461                return _SUCCESS;
3462        } else
3463#endif
3464        {
3465                DBG_88E_LEVEL(_drv_always_, "sta recv deauth reason code(%d) sta:%pM\n",
3466                              reason, GetAddr3Ptr(pframe));
3467
3468                receive_disconnect(padapter, GetAddr3Ptr(pframe), reason);
3469        }
3470        pmlmepriv->LinkDetectInfo.bBusyTraffic = false;
3471        return _SUCCESS;
3472}
3473
3474static unsigned int OnDisassoc(struct adapter *padapter,
3475                               struct recv_frame *precv_frame)
3476{
3477        u16 reason;
3478        struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
3479        struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
3480        struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
3481        u8 *pframe = precv_frame->pkt->data;
3482        struct wlan_bssid_ex *pnetwork = &(pmlmeinfo->network);
3483
3484        /* check A3 */
3485        if (memcmp(GetAddr3Ptr(pframe), pnetwork->MacAddress, ETH_ALEN))
3486                return _SUCCESS;
3487
3488        reason = le16_to_cpu(*(__le16 *)(pframe + WLAN_HDR_A3_LEN));
3489
3490        DBG_88E("%s Reason code(%d)\n", __func__, reason);
3491
3492#ifdef CONFIG_88EU_AP_MODE
3493        if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) {
3494                struct sta_info *psta;
3495                struct sta_priv *pstapriv = &padapter->stapriv;
3496
3497                DBG_88E_LEVEL(_drv_always_, "ap recv disassoc reason code(%d) sta:%pM\n",
3498                              reason, GetAddr2Ptr(pframe));
3499
3500                psta = rtw_get_stainfo(pstapriv, GetAddr2Ptr(pframe));
3501                if (psta) {
3502                        u8 updated = 0;
3503
3504                        spin_lock_bh(&pstapriv->asoc_list_lock);
3505                        if (!list_empty(&psta->asoc_list)) {
3506                                list_del_init(&psta->asoc_list);
3507                                pstapriv->asoc_list_cnt--;
3508                                updated = ap_free_sta(padapter, psta, false, reason);
3509                        }
3510                        spin_unlock_bh(&pstapriv->asoc_list_lock);
3511
3512                        associated_clients_update(padapter, updated);
3513                }
3514
3515                return _SUCCESS;
3516        } else
3517#endif
3518        {
3519                DBG_88E_LEVEL(_drv_always_, "ap recv disassoc reason code(%d) sta:%pM\n",
3520                              reason, GetAddr3Ptr(pframe));
3521
3522                receive_disconnect(padapter, GetAddr3Ptr(pframe), reason);
3523        }
3524        pmlmepriv->LinkDetectInfo.bBusyTraffic = false;
3525        return _SUCCESS;
3526}
3527
3528static unsigned int OnAtim(struct adapter *padapter,
3529                           struct recv_frame *precv_frame)
3530{
3531        DBG_88E("%s\n", __func__);
3532        return _SUCCESS;
3533}
3534
3535static unsigned int on_action_spct(struct adapter *padapter,
3536                                   struct recv_frame *precv_frame)
3537{
3538        struct sta_info *psta = NULL;
3539        struct sta_priv *pstapriv = &padapter->stapriv;
3540        u8 *pframe = precv_frame->pkt->data;
3541        u8 *frame_body = pframe + sizeof(struct ieee80211_hdr_3addr);
3542        u8 category;
3543        u8 action;
3544
3545        DBG_88E(FUNC_NDEV_FMT"\n", FUNC_NDEV_ARG(padapter->pnetdev));
3546
3547        psta = rtw_get_stainfo(pstapriv, GetAddr2Ptr(pframe));
3548
3549        if (!psta)
3550                goto exit;
3551
3552        category = frame_body[0];
3553        if (category != RTW_WLAN_CATEGORY_SPECTRUM_MGMT)
3554                goto exit;
3555
3556        action = frame_body[1];
3557        switch (action) {
3558        case RTW_WLAN_ACTION_SPCT_MSR_REQ:
3559        case RTW_WLAN_ACTION_SPCT_MSR_RPRT:
3560        case RTW_WLAN_ACTION_SPCT_TPC_REQ:
3561        case RTW_WLAN_ACTION_SPCT_TPC_RPRT:
3562                break;
3563        case RTW_WLAN_ACTION_SPCT_CHL_SWITCH:
3564                break;
3565        default:
3566                break;
3567        }
3568
3569exit:
3570        return _FAIL;
3571}
3572
3573static unsigned int OnAction_qos(struct adapter *padapter,
3574                                 struct recv_frame *precv_frame)
3575{
3576        return _SUCCESS;
3577}
3578
3579static unsigned int OnAction_dls(struct adapter *padapter,
3580                                 struct recv_frame *precv_frame)
3581{
3582        return _SUCCESS;
3583}
3584
3585static unsigned int OnAction_back(struct adapter *padapter,
3586                                  struct recv_frame *precv_frame)
3587{
3588        u8 *addr;
3589        struct sta_info *psta = NULL;
3590        struct recv_reorder_ctrl *preorder_ctrl;
3591        unsigned char           *frame_body;
3592        unsigned char           category, action;
3593        unsigned short  tid, status, reason_code = 0;
3594        struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
3595        struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
3596        u8 *pframe = precv_frame->pkt->data;
3597        struct sta_priv *pstapriv = &padapter->stapriv;
3598        /* check RA matches or not */
3599        if (memcmp(myid(&(padapter->eeprompriv)), GetAddr1Ptr(pframe),
3600                   ETH_ALEN))/* for if1, sta/ap mode */
3601                return _SUCCESS;
3602
3603        DBG_88E("%s\n", __func__);
3604
3605        if ((pmlmeinfo->state&0x03) != WIFI_FW_AP_STATE)
3606                if (!(pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS))
3607                        return _SUCCESS;
3608
3609        addr = GetAddr2Ptr(pframe);
3610        psta = rtw_get_stainfo(pstapriv, addr);
3611
3612        if (!psta)
3613                return _SUCCESS;
3614
3615        frame_body = (unsigned char *)(pframe + sizeof(struct ieee80211_hdr_3addr));
3616
3617        category = frame_body[0];
3618        if (category == RTW_WLAN_CATEGORY_BACK) { /*  representing Block Ack */
3619                if (!pmlmeinfo->HT_enable)
3620                        return _SUCCESS;
3621                action = frame_body[1];
3622                DBG_88E("%s, action=%d\n", __func__, action);
3623                switch (action) {
3624                case RTW_WLAN_ACTION_ADDBA_REQ: /* ADDBA request */
3625                        memcpy(&(pmlmeinfo->ADDBA_req), &(frame_body[2]), sizeof(struct ADDBA_request));
3626                        process_addba_req(padapter, (u8 *)&(pmlmeinfo->ADDBA_req), addr);
3627
3628                        /* 37 = reject ADDBA Req */
3629                        issue_action_BA(padapter, addr,
3630                                        RTW_WLAN_ACTION_ADDBA_RESP,
3631                                        pmlmeinfo->accept_addba_req ? 0 : 37);
3632                        break;
3633                case RTW_WLAN_ACTION_ADDBA_RESP: /* ADDBA response */
3634                        status = get_unaligned_le16(&frame_body[3]);
3635                        tid = (frame_body[5] >> 2) & 0x7;
3636                        if (status == 0) {      /* successful */
3637                                DBG_88E("agg_enable for TID=%d\n", tid);
3638                                psta->htpriv.agg_enable_bitmap |= 1 << tid;
3639                                psta->htpriv.candidate_tid_bitmap &= ~BIT(tid);
3640                        } else {
3641                                psta->htpriv.agg_enable_bitmap &= ~BIT(tid);
3642                        }
3643                        break;
3644                case RTW_WLAN_ACTION_DELBA: /* DELBA */
3645                        if ((frame_body[3] & BIT(3)) == 0) {
3646                                psta->htpriv.agg_enable_bitmap &= ~(1 << ((frame_body[3] >> 4) & 0xf));
3647                                psta->htpriv.candidate_tid_bitmap &= ~(1 << ((frame_body[3] >> 4) & 0xf));
3648                                reason_code = get_unaligned_le16(&frame_body[4]);
3649                        } else if ((frame_body[3] & BIT(3)) == BIT(3)) {
3650                                tid = (frame_body[3] >> 4) & 0x0F;
3651                                preorder_ctrl =  &psta->recvreorder_ctrl[tid];
3652                                preorder_ctrl->enable = false;
3653                                preorder_ctrl->indicate_seq = 0xffff;
3654                        }
3655                        DBG_88E("%s(): DELBA: %x(%x)\n", __func__, pmlmeinfo->agg_enable_bitmap, reason_code);
3656                        /* todo: how to notify the host while receiving DELETE BA */
3657                        break;
3658                default:
3659                        break;
3660                }
3661        }
3662        return _SUCCESS;
3663}
3664
3665static s32 rtw_action_public_decache(struct recv_frame *recv_frame, s32 token)
3666{
3667        struct adapter *adapter = recv_frame->adapter;
3668        struct mlme_ext_priv *mlmeext = &(adapter->mlmeextpriv);
3669        u8 *frame = recv_frame->pkt->data;
3670        u16 seq_ctrl = ((recv_frame->attrib.seq_num&0xffff) << 4) |
3671                (recv_frame->attrib.frag_num & 0xf);
3672
3673        if (GetRetry(frame)) {
3674                if (token >= 0) {
3675                        if ((seq_ctrl == mlmeext->action_public_rxseq) && (token == mlmeext->action_public_dialog_token)) {
3676                                DBG_88E(FUNC_ADPT_FMT" seq_ctrl = 0x%x, rxseq = 0x%x, token:%d\n",
3677                                        FUNC_ADPT_ARG(adapter), seq_ctrl, mlmeext->action_public_rxseq, token);
3678                                return _FAIL;
3679                        }
3680                } else {
3681                        if (seq_ctrl == mlmeext->action_public_rxseq) {
3682                                DBG_88E(FUNC_ADPT_FMT" seq_ctrl = 0x%x, rxseq = 0x%x\n",
3683                                        FUNC_ADPT_ARG(adapter), seq_ctrl, mlmeext->action_public_rxseq);
3684                                return _FAIL;
3685                        }
3686                }
3687        }
3688
3689        mlmeext->action_public_rxseq = seq_ctrl;
3690
3691        if (token >= 0)
3692                mlmeext->action_public_dialog_token = token;
3693
3694        return _SUCCESS;
3695}
3696
3697static unsigned int on_action_public_p2p(struct recv_frame *precv_frame)
3698{
3699        u8 *pframe = precv_frame->pkt->data;
3700        u8 *frame_body;
3701        u8 dialogToken = 0;
3702
3703        frame_body = (unsigned char *)(pframe + sizeof(struct ieee80211_hdr_3addr));
3704        dialogToken = frame_body[7];
3705
3706        if (rtw_action_public_decache(precv_frame, dialogToken) == _FAIL)
3707                return _FAIL;
3708
3709        return _SUCCESS;
3710}
3711
3712static unsigned int on_action_public_vendor(struct recv_frame *precv_frame)
3713{
3714        unsigned int ret = _FAIL;
3715        u8 *pframe = precv_frame->pkt->data;
3716        u8 *frame_body = pframe + sizeof(struct ieee80211_hdr_3addr);
3717
3718        if (!memcmp(frame_body + 2, P2P_OUI, 4))
3719                ret = on_action_public_p2p(precv_frame);
3720
3721        return ret;
3722}
3723
3724static unsigned int on_action_public_default(struct recv_frame *precv_frame,
3725                                             u8 action)
3726{
3727        unsigned int ret = _FAIL;
3728        u8 *pframe = precv_frame->pkt->data;
3729        u8 *frame_body = pframe + sizeof(struct ieee80211_hdr_3addr);
3730        u8 token;
3731
3732        token = frame_body[2];
3733
3734        if (rtw_action_public_decache(precv_frame, token) == _FAIL)
3735                goto exit;
3736
3737        ret = _SUCCESS;
3738
3739exit:
3740        return ret;
3741}
3742
3743static unsigned int on_action_public(struct adapter *padapter,
3744                                     struct recv_frame *precv_frame)
3745{
3746        unsigned int ret = _FAIL;
3747        u8 *pframe = precv_frame->pkt->data;
3748        u8 *frame_body = pframe + sizeof(struct ieee80211_hdr_3addr);
3749        u8 category, action;
3750
3751        /* check RA matches or not */
3752        if (memcmp(myid(&(padapter->eeprompriv)), GetAddr1Ptr(pframe), ETH_ALEN))
3753                goto exit;
3754
3755        category = frame_body[0];
3756        if (category != RTW_WLAN_CATEGORY_PUBLIC)
3757                goto exit;
3758
3759        action = frame_body[1];
3760        switch (action) {
3761        case ACT_PUBLIC_VENDOR:
3762                ret = on_action_public_vendor(precv_frame);
3763                break;
3764        default:
3765                ret = on_action_public_default(precv_frame, action);
3766                break;
3767        }
3768
3769exit:
3770        return ret;
3771}
3772
3773static unsigned int OnAction_ht(struct adapter *padapter,
3774                                struct recv_frame *precv_frame)
3775{
3776        return _SUCCESS;
3777}
3778
3779static unsigned int OnAction_wmm(struct adapter *padapter,
3780                                 struct recv_frame *precv_frame)
3781{
3782        return _SUCCESS;
3783}
3784
3785static unsigned int OnAction_p2p(struct adapter *padapter,
3786                                 struct recv_frame *precv_frame)
3787{
3788        return _SUCCESS;
3789}
3790
3791static unsigned int DoReserved(struct adapter *padapter,
3792                               struct recv_frame *precv_frame)
3793{
3794        return _SUCCESS;
3795}
3796
3797static struct action_handler OnAction_tbl[] = {
3798        {RTW_WLAN_CATEGORY_SPECTRUM_MGMT,        "ACTION_SPECTRUM_MGMT", on_action_spct},
3799        {RTW_WLAN_CATEGORY_QOS, "ACTION_QOS", &OnAction_qos},
3800        {RTW_WLAN_CATEGORY_DLS, "ACTION_DLS", &OnAction_dls},
3801        {RTW_WLAN_CATEGORY_BACK, "ACTION_BACK", &OnAction_back},
3802        {RTW_WLAN_CATEGORY_PUBLIC, "ACTION_PUBLIC", on_action_public},
3803        {RTW_WLAN_CATEGORY_RADIO_MEASUREMENT, "ACTION_RADIO_MEASUREMENT", &DoReserved},
3804        {RTW_WLAN_CATEGORY_FT, "ACTION_FT",     &DoReserved},
3805        {RTW_WLAN_CATEGORY_HT,  "ACTION_HT",    &OnAction_ht},
3806        {RTW_WLAN_CATEGORY_SA_QUERY, "ACTION_SA_QUERY", &DoReserved},
3807        {RTW_WLAN_CATEGORY_WMM, "ACTION_WMM", &OnAction_wmm},
3808        {RTW_WLAN_CATEGORY_P2P, "ACTION_P2P", &OnAction_p2p},
3809};
3810
3811static unsigned int OnAction(struct adapter *padapter,
3812                             struct recv_frame *precv_frame)
3813{
3814        int i;
3815        unsigned char   category;
3816        struct action_handler *ptable;
3817        unsigned char   *frame_body;
3818        u8 *pframe = precv_frame->pkt->data;
3819
3820        frame_body = (unsigned char *)(pframe + sizeof(struct ieee80211_hdr_3addr));
3821
3822        category = frame_body[0];
3823
3824        for (i = 0; i < ARRAY_SIZE(OnAction_tbl); i++) {
3825                ptable = &OnAction_tbl[i];
3826                if (category == ptable->num)
3827                        ptable->func(padapter, precv_frame);
3828        }
3829        return _SUCCESS;
3830}
3831
3832/****************************************************************************
3833
3834Following are the initialization functions for WiFi MLME
3835
3836*****************************************************************************/
3837
3838static struct mlme_handler mlme_sta_tbl[] = {
3839        {WIFI_ASSOCREQ,   "OnAssocReq",   &OnAssocReq},
3840        {WIFI_ASSOCRSP,   "OnAssocRsp",   &OnAssocRsp},
3841        {WIFI_REASSOCREQ, "OnReAssocReq", &OnAssocReq},
3842        {WIFI_REASSOCRSP, "OnReAssocRsp", &OnAssocRsp},
3843        {WIFI_PROBEREQ,   "OnProbeReq",   &OnProbeReq},
3844        {WIFI_PROBERSP,   "OnProbeRsp",   &OnProbeRsp},
3845        {0,               "DoReserved",   &DoReserved},
3846        {0,               "DoReserved",   &DoReserved},
3847        {WIFI_BEACON,     "OnBeacon",     &OnBeacon},
3848        {WIFI_ATIM,       "OnATIM",       &OnAtim},
3849        {WIFI_DISASSOC,   "OnDisassoc",   &OnDisassoc},
3850        {WIFI_AUTH,       "OnAuth",       &OnAuthClient},
3851        {WIFI_DEAUTH,     "OnDeAuth",     &OnDeAuth},
3852        {WIFI_ACTION,     "OnAction",     &OnAction},
3853};
3854
3855int init_hw_mlme_ext(struct adapter *padapter)
3856{
3857        struct  mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
3858
3859        set_channel_bwmode(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode);
3860        return _SUCCESS;
3861}
3862
3863static void init_mlme_ext_priv_value(struct adapter *padapter)
3864{
3865        struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
3866        struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
3867        unsigned char   mixed_datarate[NumRates] = {
3868                _1M_RATE_, _2M_RATE_, _5M_RATE_, _11M_RATE_, _6M_RATE_,
3869                _9M_RATE_, _12M_RATE_, _18M_RATE_, _24M_RATE_, _36M_RATE_,
3870                 _48M_RATE_, _54M_RATE_, 0xff
3871        };
3872        unsigned char   mixed_basicrate[NumRates] = {
3873                _1M_RATE_, _2M_RATE_, _5M_RATE_, _11M_RATE_, _6M_RATE_,
3874                _12M_RATE_, _24M_RATE_, 0xff,
3875        };
3876
3877        atomic_set(&pmlmeext->event_seq, 0);
3878        pmlmeext->mgnt_seq = 0;/* reset to zero when disconnect at client mode */
3879
3880        pmlmeext->cur_channel = padapter->registrypriv.channel;
3881        pmlmeext->cur_bwmode = HT_CHANNEL_WIDTH_20;
3882        pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
3883        pmlmeext->oper_channel = pmlmeext->cur_channel;
3884        pmlmeext->oper_bwmode = pmlmeext->cur_bwmode;
3885        pmlmeext->oper_ch_offset = pmlmeext->cur_ch_offset;
3886        pmlmeext->retry = 0;
3887
3888        pmlmeext->cur_wireless_mode = padapter->registrypriv.wireless_mode;
3889
3890        memcpy(pmlmeext->datarate, mixed_datarate, NumRates);
3891        memcpy(pmlmeext->basicrate, mixed_basicrate, NumRates);
3892
3893        pmlmeext->tx_rate = IEEE80211_CCK_RATE_1MB;
3894
3895        pmlmeext->sitesurvey_res.state = SCAN_DISABLE;
3896        pmlmeext->sitesurvey_res.channel_idx = 0;
3897        pmlmeext->sitesurvey_res.bss_cnt = 0;
3898        pmlmeext->scan_abort = false;
3899
3900        pmlmeinfo->state = WIFI_FW_NULL_STATE;
3901        pmlmeinfo->reauth_count = 0;
3902        pmlmeinfo->reassoc_count = 0;
3903        pmlmeinfo->link_count = 0;
3904        pmlmeinfo->auth_seq = 0;
3905        pmlmeinfo->auth_algo = dot11AuthAlgrthm_Open;
3906        pmlmeinfo->key_index = 0;
3907        pmlmeinfo->iv = 0;
3908
3909        pmlmeinfo->enc_algo = _NO_PRIVACY_;
3910        pmlmeinfo->authModeToggle = 0;
3911
3912        memset(pmlmeinfo->chg_txt, 0, 128);
3913
3914        pmlmeinfo->slotTime = SHORT_SLOT_TIME;
3915        pmlmeinfo->preamble_mode = PREAMBLE_AUTO;
3916
3917        pmlmeinfo->dialogToken = 0;
3918
3919        pmlmeext->action_public_rxseq = 0xffff;
3920        pmlmeext->action_public_dialog_token = 0xff;
3921}
3922
3923static int has_channel(struct rt_channel_info *channel_set,
3924                                           u8 chanset_size,
3925                                           u8 chan)
3926{
3927        int i;
3928
3929        for (i = 0; i < chanset_size; i++) {
3930                if (channel_set[i].ChannelNum == chan)
3931                        return 1;
3932        }
3933        return 0;
3934}
3935
3936static void init_channel_list(struct adapter *padapter,
3937                              struct rt_channel_info *channel_set,
3938                              u8 chanset_size,
3939                              struct p2p_channels *channel_list)
3940{
3941        struct p2p_oper_class_map op_class[] = {
3942                { IEEE80211G,  81,   1,  13,  1, BW20 },
3943                { IEEE80211G,  82,  14,  14,  1, BW20 },
3944                { -1, 0, 0, 0, 0, BW20 }
3945        };
3946
3947        int cla, op;
3948
3949        cla = 0;
3950
3951        for (op = 0; op_class[op].op_class; op++) {
3952                u8 ch;
3953                struct p2p_oper_class_map *o = &op_class[op];
3954                struct p2p_reg_class *reg = NULL;
3955
3956                for (ch = o->min_chan; ch <= o->max_chan; ch += o->inc) {
3957                        if (!has_channel(channel_set, chanset_size, ch))
3958                                continue;
3959
3960                        if (!padapter->registrypriv.ht_enable && o->inc == 8)
3961                                continue;
3962
3963                        if ((0 == (padapter->registrypriv.cbw40_enable & BIT(1))) &&
3964                            ((o->bw == BW40MINUS) || (o->bw == BW40PLUS)))
3965                                continue;
3966
3967                        if (reg == NULL) {
3968                                reg = &channel_list->reg_class[cla];
3969                                cla++;
3970                                reg->reg_class = o->op_class;
3971                                reg->channels = 0;
3972                        }
3973                        reg->channel[reg->channels] = ch;
3974                        reg->channels++;
3975                }
3976        }
3977        channel_list->reg_classes = cla;
3978}
3979
3980static u8 init_channel_set(struct adapter *padapter, u8 ChannelPlan,
3981                           struct rt_channel_info *channel_set)
3982{
3983        u8 index, chanset_size = 0;
3984        u8 b2_4GBand = false;
3985        u8 Index2G = 0;
3986
3987        memset(channel_set, 0, sizeof(struct rt_channel_info) * MAX_CHANNEL_NUM);
3988
3989        if (ChannelPlan >= RT_CHANNEL_DOMAIN_MAX && ChannelPlan != RT_CHANNEL_DOMAIN_REALTEK_DEFINE) {
3990                DBG_88E("ChannelPlan ID %x error !!!!!\n", ChannelPlan);
3991                return chanset_size;
3992        }
3993
3994        if (padapter->registrypriv.wireless_mode & WIRELESS_11G) {
3995                b2_4GBand = true;
3996                if (ChannelPlan == RT_CHANNEL_DOMAIN_REALTEK_DEFINE)
3997                        Index2G = RTW_CHANNEL_PLAN_MAP_REALTEK_DEFINE.Index2G;
3998                else
3999                        Index2G = RTW_ChannelPlanMap[ChannelPlan].Index2G;
4000        }
4001
4002        if (b2_4GBand) {
4003                for (index = 0; index < RTW_ChannelPlan2G[Index2G].Len; index++) {
4004                        channel_set[chanset_size].ChannelNum = RTW_ChannelPlan2G[Index2G].Channel[index];
4005
4006                        if ((ChannelPlan == RT_CHANNEL_DOMAIN_GLOBAL_DOAMIN) ||/* Channel 1~11 is active, and 12~14 is passive */
4007                            (ChannelPlan == RT_CHANNEL_DOMAIN_GLOBAL_DOAMIN_2G)) {
4008                                if (channel_set[chanset_size].ChannelNum >= 1 && channel_set[chanset_size].ChannelNum <= 11)
4009                                        channel_set[chanset_size].ScanType = SCAN_ACTIVE;
4010                                else if ((channel_set[chanset_size].ChannelNum  >= 12 && channel_set[chanset_size].ChannelNum  <= 14))
4011                                        channel_set[chanset_size].ScanType  = SCAN_PASSIVE;
4012                        } else if (ChannelPlan == RT_CHANNEL_DOMAIN_WORLD_WIDE_13 ||
4013                                   Index2G == RT_CHANNEL_DOMAIN_2G_WORLD) {/*  channel 12~13, passive scan */
4014                                if (channel_set[chanset_size].ChannelNum <= 11)
4015                                        channel_set[chanset_size].ScanType = SCAN_ACTIVE;
4016                                else
4017                                        channel_set[chanset_size].ScanType = SCAN_PASSIVE;
4018                        } else {
4019                                channel_set[chanset_size].ScanType = SCAN_ACTIVE;
4020                        }
4021
4022                        chanset_size++;
4023                }
4024        }
4025        return chanset_size;
4026}
4027
4028int     init_mlme_ext_priv(struct adapter *padapter)
4029{
4030        struct registry_priv *pregistrypriv = &padapter->registrypriv;
4031        struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
4032        struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
4033        struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
4034
4035        pmlmeext->padapter = padapter;
4036
4037        init_mlme_ext_priv_value(padapter);
4038        pmlmeinfo->accept_addba_req = pregistrypriv->accept_addba_req;
4039
4040        init_mlme_ext_timer(padapter);
4041
4042#ifdef CONFIG_88EU_AP_MODE
4043        init_mlme_ap_info(padapter);
4044#endif
4045
4046        pmlmeext->max_chan_nums = init_channel_set(padapter, pmlmepriv->ChannelPlan, pmlmeext->channel_set);
4047        init_channel_list(padapter, pmlmeext->channel_set, pmlmeext->max_chan_nums, &pmlmeext->channel_list);
4048
4049        pmlmeext->chan_scan_time = SURVEY_TO;
4050        pmlmeext->mlmeext_init = true;
4051
4052        pmlmeext->active_keep_alive_check = true;
4053
4054        return _SUCCESS;
4055}
4056
4057void free_mlme_ext_priv(struct mlme_ext_priv *pmlmeext)
4058{
4059        struct adapter *padapter = pmlmeext->padapter;
4060
4061        if (!padapter)
4062                return;
4063
4064        if (padapter->bDriverStopped) {
4065                del_timer_sync(&pmlmeext->survey_timer);
4066                del_timer_sync(&pmlmeext->link_timer);
4067        }
4068}
4069
4070static void _mgt_dispatcher(struct adapter *padapter,
4071                            struct mlme_handler *ptable,
4072                            struct recv_frame *precv_frame)
4073{
4074        u8 bc_addr[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
4075        u8 *pframe = precv_frame->pkt->data;
4076
4077        if (ptable->func) {
4078                /* receive the frames that ra(a1) is my address or ra(a1) is bc address. */
4079                if (memcmp(GetAddr1Ptr(pframe), myid(&padapter->eeprompriv), ETH_ALEN) &&
4080                    memcmp(GetAddr1Ptr(pframe), bc_addr, ETH_ALEN))
4081                        return;
4082                ptable->func(padapter, precv_frame);
4083        }
4084}
4085
4086void mgt_dispatcher(struct adapter *padapter, struct recv_frame *precv_frame)
4087{
4088        int index;
4089        struct mlme_handler *ptable;
4090#ifdef CONFIG_88EU_AP_MODE
4091        struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
4092#endif /* CONFIG_88EU_AP_MODE */
4093        u8 bc_addr[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
4094        u8 *pframe = precv_frame->pkt->data;
4095        struct sta_info *psta = rtw_get_stainfo(&padapter->stapriv, GetAddr2Ptr(pframe));
4096
4097        RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_,
4098                 ("+%s: type(0x%x) subtype(0x%x)\n", __func__,
4099                  (unsigned int)GetFrameType(pframe),
4100                  (unsigned int)GetFrameSubType(pframe)));
4101
4102        if (GetFrameType(pframe) != WIFI_MGT_TYPE) {
4103                RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_,
4104                         ("%s: type(0x%x) error!\n", __func__,
4105                          (unsigned int)GetFrameType(pframe)));
4106                return;
4107        }
4108
4109        /* receive the frames that ra(a1) is my address or ra(a1) is bc address. */
4110        if (memcmp(GetAddr1Ptr(pframe), myid(&padapter->eeprompriv), ETH_ALEN) &&
4111            memcmp(GetAddr1Ptr(pframe), bc_addr, ETH_ALEN))
4112                return;
4113
4114        ptable = mlme_sta_tbl;
4115
4116        index = GetFrameSubType(pframe) >> 4;
4117
4118        if (index > 13) {
4119                RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("Currently we do not support reserved sub-fr-type=%d\n", index));
4120                return;
4121        }
4122        ptable += index;
4123
4124        if (psta) {
4125                if (GetRetry(pframe)) {
4126                        if (precv_frame->attrib.seq_num ==
4127                            psta->RxMgmtFrameSeqNum) {
4128                                /* drop the duplicate management frame */
4129                                DBG_88E("Drop duplicate management frame with seq_num=%d.\n",
4130                                        precv_frame->attrib.seq_num);
4131                                return;
4132                        }
4133                }
4134                psta->RxMgmtFrameSeqNum = precv_frame->attrib.seq_num;
4135        }
4136
4137#ifdef CONFIG_88EU_AP_MODE
4138        switch (GetFrameSubType(pframe)) {
4139        case WIFI_AUTH:
4140                if (check_fwstate(pmlmepriv, WIFI_AP_STATE))
4141                        ptable->func = &OnAuth;
4142                else
4143                        ptable->func = &OnAuthClient;
4144                /* fall through */
4145        case WIFI_ASSOCREQ:
4146        case WIFI_REASSOCREQ:
4147        case WIFI_PROBEREQ:
4148        case WIFI_BEACON:
4149        case WIFI_ACTION:
4150                _mgt_dispatcher(padapter, ptable, precv_frame);
4151                break;
4152        default:
4153                _mgt_dispatcher(padapter, ptable, precv_frame);
4154                break;
4155        }
4156#else
4157        _mgt_dispatcher(padapter, ptable, precv_frame);
4158#endif
4159}
4160
4161/****************************************************************************
4162
4163Following are the functions to report events
4164
4165*****************************************************************************/
4166
4167void report_survey_event(struct adapter *padapter,
4168                         struct recv_frame *precv_frame)
4169{
4170        struct cmd_obj *pcmd_obj;
4171        u8 *pevtcmd;
4172        u32 cmdsz;
4173        struct survey_event     *psurvey_evt;
4174        struct C2HEvent_Header *pc2h_evt_hdr;
4175        struct mlme_ext_priv *pmlmeext;
4176        struct cmd_priv *pcmdpriv;
4177
4178        if (!padapter)
4179                return;
4180
4181        pmlmeext = &padapter->mlmeextpriv;
4182        pcmdpriv = &padapter->cmdpriv;
4183
4184        pcmd_obj = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC);
4185        if (!pcmd_obj)
4186                return;
4187
4188        cmdsz = sizeof(struct survey_event) + sizeof(struct C2HEvent_Header);
4189        pevtcmd = kzalloc(cmdsz, GFP_ATOMIC);
4190        if (!pevtcmd) {
4191                kfree(pcmd_obj);
4192                return;
4193        }
4194
4195        INIT_LIST_HEAD(&pcmd_obj->list);
4196
4197        pcmd_obj->cmdcode = _Set_MLME_EVT_CMD_;
4198        pcmd_obj->cmdsz = cmdsz;
4199        pcmd_obj->parmbuf = pevtcmd;
4200
4201        pcmd_obj->rsp = NULL;
4202        pcmd_obj->rspsz  = 0;
4203
4204        pc2h_evt_hdr = (struct C2HEvent_Header *)(pevtcmd);
4205        pc2h_evt_hdr->len = sizeof(struct survey_event);
4206        pc2h_evt_hdr->ID = _Survey_EVT_;
4207        pc2h_evt_hdr->seq = atomic_inc_return(&pmlmeext->event_seq);
4208
4209        psurvey_evt = (struct survey_event *)(pevtcmd + sizeof(struct C2HEvent_Header));
4210
4211        if (collect_bss_info(padapter, precv_frame, (struct wlan_bssid_ex *)&psurvey_evt->bss) == _FAIL) {
4212                kfree(pcmd_obj);
4213                kfree(pevtcmd);
4214                return;
4215        }
4216
4217        process_80211d(padapter, &psurvey_evt->bss);
4218
4219        rtw_enqueue_cmd(pcmdpriv, pcmd_obj);
4220
4221        pmlmeext->sitesurvey_res.bss_cnt++;
4222}
4223
4224void report_surveydone_event(struct adapter *padapter)
4225{
4226        struct cmd_obj *pcmd_obj;
4227        u8 *pevtcmd;
4228        u32 cmdsz;
4229        struct surveydone_event *psurveydone_evt;
4230        struct C2HEvent_Header  *pc2h_evt_hdr;
4231        struct mlme_ext_priv            *pmlmeext = &padapter->mlmeextpriv;
4232        struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
4233
4234        pcmd_obj = kzalloc(sizeof(struct cmd_obj), GFP_KERNEL);
4235        if (!pcmd_obj)
4236                return;
4237
4238        cmdsz = sizeof(struct surveydone_event) + sizeof(struct C2HEvent_Header);
4239        pevtcmd = kzalloc(cmdsz, GFP_KERNEL);
4240        if (!pevtcmd) {
4241                kfree(pcmd_obj);
4242                return;
4243        }
4244
4245        INIT_LIST_HEAD(&pcmd_obj->list);
4246
4247        pcmd_obj->cmdcode = _Set_MLME_EVT_CMD_;
4248        pcmd_obj->cmdsz = cmdsz;
4249        pcmd_obj->parmbuf = pevtcmd;
4250
4251        pcmd_obj->rsp = NULL;
4252        pcmd_obj->rspsz  = 0;
4253
4254        pc2h_evt_hdr = (struct C2HEvent_Header *)(pevtcmd);
4255        pc2h_evt_hdr->len = sizeof(struct surveydone_event);
4256        pc2h_evt_hdr->ID = _SurveyDone_EVT_;
4257        pc2h_evt_hdr->seq = atomic_inc_return(&pmlmeext->event_seq);
4258
4259        psurveydone_evt = (struct surveydone_event *)(pevtcmd + sizeof(struct C2HEvent_Header));
4260        psurveydone_evt->bss_cnt = pmlmeext->sitesurvey_res.bss_cnt;
4261
4262        DBG_88E("survey done event(%x)\n", psurveydone_evt->bss_cnt);
4263
4264        rtw_enqueue_cmd(pcmdpriv, pcmd_obj);
4265}
4266
4267void report_join_res(struct adapter *padapter, int res)
4268{
4269        struct cmd_obj *pcmd_obj;
4270        u8 *pevtcmd;
4271        u32 cmdsz;
4272        struct joinbss_event            *pjoinbss_evt;
4273        struct C2HEvent_Header  *pc2h_evt_hdr;
4274        struct mlme_ext_priv            *pmlmeext = &padapter->mlmeextpriv;
4275        struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
4276        struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
4277
4278        pcmd_obj = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC);
4279        if (!pcmd_obj)
4280                return;
4281
4282        cmdsz = sizeof(struct joinbss_event) + sizeof(struct C2HEvent_Header);
4283        pevtcmd = kzalloc(cmdsz, GFP_ATOMIC);
4284        if (!pevtcmd) {
4285                kfree(pcmd_obj);
4286                return;
4287        }
4288
4289        INIT_LIST_HEAD(&pcmd_obj->list);
4290
4291        pcmd_obj->cmdcode = _Set_MLME_EVT_CMD_;
4292        pcmd_obj->cmdsz = cmdsz;
4293        pcmd_obj->parmbuf = pevtcmd;
4294
4295        pcmd_obj->rsp = NULL;
4296        pcmd_obj->rspsz  = 0;
4297
4298        pc2h_evt_hdr = (struct C2HEvent_Header *)(pevtcmd);
4299        pc2h_evt_hdr->len = sizeof(struct joinbss_event);
4300        pc2h_evt_hdr->ID = _JoinBss_EVT_;
4301        pc2h_evt_hdr->seq = atomic_inc_return(&pmlmeext->event_seq);
4302
4303        pjoinbss_evt = (struct joinbss_event *)(pevtcmd + sizeof(struct C2HEvent_Header));
4304        memcpy((unsigned char *)(&(pjoinbss_evt->network.network)), &(pmlmeinfo->network), sizeof(struct wlan_bssid_ex));
4305        pjoinbss_evt->network.join_res  = res;
4306        pjoinbss_evt->network.aid = res;
4307
4308        DBG_88E("%s(%d)\n", __func__, res);
4309
4310        rtw_joinbss_event_prehandle(padapter, (u8 *)&pjoinbss_evt->network);
4311
4312        rtw_enqueue_cmd(pcmdpriv, pcmd_obj);
4313}
4314
4315void report_del_sta_event(struct adapter *padapter, unsigned char *MacAddr,
4316                          unsigned short reason)
4317{
4318        struct cmd_obj *pcmd_obj;
4319        u8 *pevtcmd;
4320        u32 cmdsz;
4321        struct sta_info *psta;
4322        int     mac_id;
4323        struct stadel_event                     *pdel_sta_evt;
4324        struct C2HEvent_Header  *pc2h_evt_hdr;
4325        struct mlme_ext_priv            *pmlmeext = &padapter->mlmeextpriv;
4326        struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
4327
4328        pcmd_obj = kzalloc(sizeof(struct cmd_obj), GFP_KERNEL);
4329        if (!pcmd_obj)
4330                return;
4331
4332        cmdsz = sizeof(struct stadel_event) + sizeof(struct C2HEvent_Header);
4333        pevtcmd = kzalloc(cmdsz, GFP_KERNEL);
4334        if (!pevtcmd) {
4335                kfree(pcmd_obj);
4336                return;
4337        }
4338
4339        INIT_LIST_HEAD(&pcmd_obj->list);
4340
4341        pcmd_obj->cmdcode = _Set_MLME_EVT_CMD_;
4342        pcmd_obj->cmdsz = cmdsz;
4343        pcmd_obj->parmbuf = pevtcmd;
4344
4345        pcmd_obj->rsp = NULL;
4346        pcmd_obj->rspsz  = 0;
4347
4348        pc2h_evt_hdr = (struct C2HEvent_Header *)(pevtcmd);
4349        pc2h_evt_hdr->len = sizeof(struct stadel_event);
4350        pc2h_evt_hdr->ID = _DelSTA_EVT_;
4351        pc2h_evt_hdr->seq = atomic_inc_return(&pmlmeext->event_seq);
4352
4353        pdel_sta_evt = (struct stadel_event *)(pevtcmd + sizeof(struct C2HEvent_Header));
4354        ether_addr_copy((unsigned char *)(&(pdel_sta_evt->macaddr)), MacAddr);
4355        memcpy((unsigned char *)(pdel_sta_evt->rsvd), (unsigned char *)(&reason), 2);
4356
4357        psta = rtw_get_stainfo(&padapter->stapriv, MacAddr);
4358        if (psta)
4359                mac_id = (int)psta->mac_id;
4360        else
4361                mac_id = -1;
4362
4363        pdel_sta_evt->mac_id = mac_id;
4364
4365        DBG_88E("%s: delete STA, mac_id =%d\n", __func__, mac_id);
4366
4367        rtw_enqueue_cmd(pcmdpriv, pcmd_obj);
4368}
4369
4370void report_add_sta_event(struct adapter *padapter, unsigned char *MacAddr,
4371                          int cam_idx)
4372{
4373        struct cmd_obj *pcmd_obj;
4374        u8 *pevtcmd;
4375        u32 cmdsz;
4376        struct stassoc_event            *padd_sta_evt;
4377        struct C2HEvent_Header  *pc2h_evt_hdr;
4378        struct mlme_ext_priv            *pmlmeext = &padapter->mlmeextpriv;
4379        struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
4380
4381        pcmd_obj = kzalloc(sizeof(struct cmd_obj), GFP_KERNEL);
4382        if (!pcmd_obj)
4383                return;
4384
4385        cmdsz = sizeof(struct stassoc_event) + sizeof(struct C2HEvent_Header);
4386        pevtcmd = kzalloc(cmdsz, GFP_KERNEL);
4387        if (!pevtcmd) {
4388                kfree(pcmd_obj);
4389                return;
4390        }
4391
4392        INIT_LIST_HEAD(&pcmd_obj->list);
4393
4394        pcmd_obj->cmdcode = _Set_MLME_EVT_CMD_;
4395        pcmd_obj->cmdsz = cmdsz;
4396        pcmd_obj->parmbuf = pevtcmd;
4397
4398        pcmd_obj->rsp = NULL;
4399        pcmd_obj->rspsz  = 0;
4400
4401        pc2h_evt_hdr = (struct C2HEvent_Header *)(pevtcmd);
4402        pc2h_evt_hdr->len = sizeof(struct stassoc_event);
4403        pc2h_evt_hdr->ID = _AddSTA_EVT_;
4404        pc2h_evt_hdr->seq = atomic_inc_return(&pmlmeext->event_seq);
4405
4406        padd_sta_evt = (struct stassoc_event *)(pevtcmd + sizeof(struct C2HEvent_Header));
4407        ether_addr_copy((unsigned char *)(&(padd_sta_evt->macaddr)), MacAddr);
4408        padd_sta_evt->cam_id = cam_idx;
4409
4410        DBG_88E("%s: add STA\n", __func__);
4411
4412        rtw_enqueue_cmd(pcmdpriv, pcmd_obj);
4413}
4414
4415/****************************************************************************
4416
4417Following are the event callback functions
4418
4419*****************************************************************************/
4420
4421/* for sta/adhoc mode */
4422void update_sta_info(struct adapter *padapter, struct sta_info *psta)
4423{
4424        struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
4425        struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
4426        struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
4427
4428        /* ERP */
4429        VCS_update(padapter, psta);
4430
4431        /* HT */
4432        if (pmlmepriv->htpriv.ht_option) {
4433                psta->htpriv.ht_option = true;
4434
4435                psta->htpriv.ampdu_enable = pmlmepriv->htpriv.ampdu_enable;
4436
4437                if (support_short_GI(padapter, &pmlmeinfo->HT_caps))
4438                        psta->htpriv.sgi = true;
4439
4440                psta->qos_option = true;
4441        } else {
4442                psta->htpriv.ht_option = false;
4443
4444                psta->htpriv.ampdu_enable = false;
4445
4446                psta->htpriv.sgi = false;
4447                psta->qos_option = false;
4448        }
4449        psta->htpriv.bwmode = pmlmeext->cur_bwmode;
4450        psta->htpriv.ch_offset = pmlmeext->cur_ch_offset;
4451
4452        psta->htpriv.agg_enable_bitmap = 0x0;/* reset */
4453        psta->htpriv.candidate_tid_bitmap = 0x0;/* reset */
4454
4455        /* QoS */
4456        if (pmlmepriv->qospriv.qos_option)
4457                psta->qos_option = true;
4458
4459        psta->state = _FW_LINKED;
4460}
4461
4462void mlmeext_joinbss_event_callback(struct adapter *padapter, int join_res)
4463{
4464        struct sta_info         *psta, *psta_bmc;
4465        struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
4466        struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
4467        struct wlan_bssid_ex *cur_network = &(pmlmeinfo->network);
4468        struct sta_priv         *pstapriv = &padapter->stapriv;
4469        u8 join_type;
4470        u16 media_status;
4471
4472        if (join_res < 0) {
4473                join_type = 1;
4474                rtw_hal_set_hwreg(padapter, HW_VAR_MLME_JOIN, (u8 *)(&join_type));
4475                rtw_hal_set_hwreg(padapter, HW_VAR_BSSID, null_addr);
4476
4477                /* restore to initial setting. */
4478                update_tx_basic_rate(padapter, padapter->registrypriv.wireless_mode);
4479
4480                goto exit_mlmeext_joinbss_event_callback;
4481        }
4482
4483        if ((pmlmeinfo->state&0x03) == WIFI_FW_ADHOC_STATE) {
4484                /* for bc/mc */
4485                psta_bmc = rtw_get_bcmc_stainfo(padapter);
4486                if (psta_bmc) {
4487                        pmlmeinfo->FW_sta_info[psta_bmc->mac_id].psta = psta_bmc;
4488                        update_bmc_sta_support_rate(padapter, psta_bmc->mac_id);
4489                        Update_RA_Entry(padapter, psta_bmc->mac_id);
4490                }
4491        }
4492
4493        /* turn on dynamic functions */
4494        Switch_DM_Func(padapter, DYNAMIC_ALL_FUNC_ENABLE, true);
4495
4496        /*  update IOT-related issue */
4497        update_IOT_info(padapter);
4498
4499        rtw_hal_set_hwreg(padapter, HW_VAR_BASIC_RATE, cur_network->SupportedRates);
4500
4501        /* BCN interval */
4502        rtw_hal_set_hwreg(padapter, HW_VAR_BEACON_INTERVAL, (u8 *)(&pmlmeinfo->bcn_interval));
4503
4504        /* update capability */
4505        update_capinfo(padapter, pmlmeinfo->capability);
4506
4507        /* WMM, Update EDCA param */
4508        WMMOnAssocRsp(padapter);
4509
4510        /* HT */
4511        HTOnAssocRsp(padapter);
4512
4513        set_channel_bwmode(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode);
4514
4515        psta = rtw_get_stainfo(pstapriv, cur_network->MacAddress);
4516        if (psta) { /* only for infra. mode */
4517                pmlmeinfo->FW_sta_info[psta->mac_id].psta = psta;
4518
4519                psta->wireless_mode = pmlmeext->cur_wireless_mode;
4520
4521                /* set per sta rate after updating HT cap. */
4522                set_sta_rate(padapter, psta);
4523                rtw_hal_set_hwreg(padapter, HW_VAR_TX_RPT_MAX_MACID, (u8 *)&psta->mac_id);
4524                media_status = (psta->mac_id<<8)|1; /*   MACID|OPMODE: 1 means connect */
4525                rtw_hal_set_hwreg(padapter, HW_VAR_H2C_MEDIA_STATUS_RPT, (u8 *)&media_status);
4526        }
4527
4528        join_type = 2;
4529        rtw_hal_set_hwreg(padapter, HW_VAR_MLME_JOIN, (u8 *)(&join_type));
4530
4531        if ((pmlmeinfo->state&0x03) == WIFI_FW_STATION_STATE) {
4532                /*  correcting TSF */
4533                correct_TSF(padapter, pmlmeext);
4534        }
4535        rtw_lps_ctrl_wk_cmd(padapter, LPS_CTRL_CONNECT, 0);
4536
4537exit_mlmeext_joinbss_event_callback:
4538
4539        DBG_88E("=>%s\n", __func__);
4540}
4541
4542void mlmeext_sta_add_event_callback(struct adapter *padapter, struct sta_info *psta)
4543{
4544        struct mlme_ext_priv    *pmlmeext = &(padapter->mlmeextpriv);
4545        struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
4546        u8 join_type;
4547
4548        DBG_88E("%s\n", __func__);
4549
4550        if ((pmlmeinfo->state&0x03) == WIFI_FW_ADHOC_STATE) {
4551                if (pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS) {/* adhoc master or sta_count>1 */
4552                        /* nothing to do */
4553                } else { /* adhoc client */
4554                        /*  correcting TSF */
4555                        correct_TSF(padapter, pmlmeext);
4556
4557                        /* start beacon */
4558                        if (send_beacon(padapter) == _FAIL) {
4559                                pmlmeinfo->FW_sta_info[psta->mac_id].status = 0;
4560                                pmlmeinfo->state ^= WIFI_FW_ADHOC_STATE;
4561                                return;
4562                        }
4563                        pmlmeinfo->state |= WIFI_FW_ASSOC_SUCCESS;
4564                }
4565
4566                join_type = 2;
4567                rtw_hal_set_hwreg(padapter, HW_VAR_MLME_JOIN, (u8 *)(&join_type));
4568        }
4569
4570        pmlmeinfo->FW_sta_info[psta->mac_id].psta = psta;
4571
4572        /* rate radaptive */
4573        Update_RA_Entry(padapter, psta->mac_id);
4574
4575        /* update adhoc sta_info */
4576        update_sta_info(padapter, psta);
4577}
4578
4579void mlmeext_sta_del_event_callback(struct adapter *padapter)
4580{
4581        struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
4582        struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
4583
4584        if (is_client_associated_to_ap(padapter) || is_IBSS_empty(padapter)) {
4585                rtw_hal_set_hwreg(padapter, HW_VAR_MLME_DISCONNECT, NULL);
4586                rtw_hal_set_hwreg(padapter, HW_VAR_BSSID, null_addr);
4587
4588                /* restore to initial setting. */
4589                update_tx_basic_rate(padapter, padapter->registrypriv.wireless_mode);
4590
4591                /* switch to the 20M Hz mode after disconnect */
4592                pmlmeext->cur_bwmode = HT_CHANNEL_WIDTH_20;
4593                pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
4594
4595                /* SelectChannel(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset); */
4596                set_channel_bwmode(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode);
4597
4598                flush_all_cam_entry(padapter);
4599
4600                pmlmeinfo->state = WIFI_FW_NULL_STATE;
4601
4602                /* set MSR to no link state -> infra. mode */
4603                Set_MSR(padapter, _HW_STATE_STATION_);
4604
4605                del_timer_sync(&pmlmeext->link_timer);
4606        }
4607}
4608
4609/****************************************************************************
4610
4611Following are the functions for the timer handlers
4612
4613*****************************************************************************/
4614
4615static u8 chk_ap_is_alive(struct adapter *padapter, struct sta_info *psta)
4616{
4617        u8 ret = false;
4618
4619        if ((sta_rx_data_pkts(psta) == sta_last_rx_data_pkts(psta)) &&
4620            sta_rx_beacon_pkts(psta) == sta_last_rx_beacon_pkts(psta) &&
4621            sta_rx_probersp_pkts(psta) == sta_last_rx_probersp_pkts(psta))
4622                ret = false;
4623        else
4624                ret = true;
4625
4626        sta_update_last_rx_pkts(psta);
4627
4628        return ret;
4629}
4630
4631void linked_status_chk(struct adapter *padapter)
4632{
4633        u32     i;
4634        struct sta_info         *psta;
4635        struct xmit_priv                *pxmitpriv = &(padapter->xmitpriv);
4636        struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
4637        struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
4638        struct sta_priv         *pstapriv = &padapter->stapriv;
4639
4640        if (is_client_associated_to_ap(padapter)) {
4641                /* linked infrastructure client mode */
4642
4643                int tx_chk = _SUCCESS, rx_chk = _SUCCESS;
4644                int rx_chk_limit;
4645
4646                rx_chk_limit = 4;
4647                psta = rtw_get_stainfo(pstapriv, pmlmeinfo->network.MacAddress);
4648                if (psta) {
4649                        bool is_p2p_enable = false;
4650
4651                        if (!chk_ap_is_alive(padapter, psta))
4652                                rx_chk = _FAIL;
4653
4654                        if (pxmitpriv->last_tx_pkts == pxmitpriv->tx_pkts)
4655                                tx_chk = _FAIL;
4656
4657                        if (pmlmeext->active_keep_alive_check && (rx_chk == _FAIL || tx_chk == _FAIL)) {
4658                                u8 backup_oper_channel = 0;
4659
4660                                /* switch to correct channel of current network  before issue keep-alive frames */
4661                                if (rtw_get_oper_ch(padapter) != pmlmeext->cur_channel) {
4662                                        backup_oper_channel = rtw_get_oper_ch(padapter);
4663                                        SelectChannel(padapter, pmlmeext->cur_channel);
4664                                }
4665
4666                                if (rx_chk != _SUCCESS)
4667                                        issue_probereq_ex(padapter, &pmlmeinfo->network.Ssid, psta->hwaddr, 3, 1);
4668
4669                                if ((tx_chk != _SUCCESS && pmlmeinfo->link_count++ == 0xf) || rx_chk != _SUCCESS) {
4670                                        tx_chk = issue_nulldata(padapter, psta->hwaddr, 0, 3, 1);
4671                                        /* if tx acked and p2p disabled, set rx_chk _SUCCESS to reset retry count */
4672                                        if (tx_chk == _SUCCESS && !is_p2p_enable)
4673                                                rx_chk = _SUCCESS;
4674                                }
4675
4676                                /* back to the original operation channel */
4677                                if (backup_oper_channel > 0)
4678                                        SelectChannel(padapter, backup_oper_channel);
4679                        } else {
4680                                if (rx_chk != _SUCCESS) {
4681                                        if (pmlmeext->retry == 0) {
4682                                                issue_probereq(padapter,
4683                                                &pmlmeinfo->network.Ssid,
4684                                                pmlmeinfo->network.MacAddress,
4685                                                                        false);
4686                                                issue_probereq(padapter,
4687                                                &pmlmeinfo->network.Ssid,
4688                                                pmlmeinfo->network.MacAddress,
4689                                                                        false);
4690                                                issue_probereq(padapter,
4691                                                &pmlmeinfo->network.Ssid,
4692                                                pmlmeinfo->network.MacAddress,
4693                                                                        false);
4694                                        }
4695                                }
4696
4697                                if (tx_chk != _SUCCESS && pmlmeinfo->link_count++ == 0xf)
4698                                        tx_chk = issue_nulldata(padapter, NULL, 0, 1, 0);
4699                        }
4700
4701                        if (rx_chk == _FAIL) {
4702                                pmlmeext->retry++;
4703                                if (pmlmeext->retry > rx_chk_limit) {
4704                                        DBG_88E_LEVEL(_drv_always_, FUNC_ADPT_FMT" disconnect or roaming\n",
4705                                                      FUNC_ADPT_ARG(padapter));
4706                                        receive_disconnect(padapter, pmlmeinfo->network.MacAddress,
4707                                                           WLAN_REASON_EXPIRATION_CHK);
4708                                        return;
4709                                }
4710                        } else {
4711                                pmlmeext->retry = 0;
4712                        }
4713
4714                        if (tx_chk == _FAIL) {
4715                                pmlmeinfo->link_count &= 0xf;
4716                        } else {
4717                                pxmitpriv->last_tx_pkts = pxmitpriv->tx_pkts;
4718                                pmlmeinfo->link_count = 0;
4719                        }
4720                } /* end of if ((psta = rtw_get_stainfo(pstapriv, passoc_res->network.MacAddress)) != NULL) */
4721        } else if (is_client_associated_to_ibss(padapter)) {
4722                /* linked IBSS mode */
4723                /* for each assoc list entry to check the rx pkt counter */
4724                for (i = IBSS_START_MAC_ID; i < NUM_STA; i++) {
4725                        if (pmlmeinfo->FW_sta_info[i].status == 1) {
4726                                psta = pmlmeinfo->FW_sta_info[i].psta;
4727
4728                                if (!psta)
4729                                        continue;
4730                                if (pmlmeinfo->FW_sta_info[i].rx_pkt == sta_rx_pkts(psta)) {
4731                                        if (pmlmeinfo->FW_sta_info[i].retry < 3) {
4732                                                pmlmeinfo->FW_sta_info[i].retry++;
4733                                        } else {
4734                                                pmlmeinfo->FW_sta_info[i].retry = 0;
4735                                                pmlmeinfo->FW_sta_info[i].status = 0;
4736                                                report_del_sta_event(padapter, psta->hwaddr
4737                                                        , 65535/*  indicate disconnect caused by no rx */
4738                                        );
4739                                        }
4740                                } else {
4741                                        pmlmeinfo->FW_sta_info[i].retry = 0;
4742                                        pmlmeinfo->FW_sta_info[i].rx_pkt = (u32)sta_rx_pkts(psta);
4743                                }
4744                        }
4745                }
4746        }
4747}
4748
4749void survey_timer_hdl(struct timer_list *t)
4750{
4751        struct adapter *padapter = from_timer(padapter, t,
4752                                              mlmeextpriv.survey_timer);
4753        struct cmd_obj  *ph2c;
4754        struct sitesurvey_parm  *psurveyPara;
4755        struct cmd_priv                                 *pcmdpriv = &padapter->cmdpriv;
4756        struct mlme_ext_priv            *pmlmeext = &padapter->mlmeextpriv;
4757
4758        /* issue rtw_sitesurvey_cmd */
4759        if (pmlmeext->sitesurvey_res.state > SCAN_START) {
4760                if (pmlmeext->sitesurvey_res.state ==  SCAN_PROCESS)
4761                        pmlmeext->sitesurvey_res.channel_idx++;
4762
4763                if (pmlmeext->scan_abort) {
4764                        pmlmeext->sitesurvey_res.channel_idx = pmlmeext->sitesurvey_res.ch_num;
4765                        DBG_88E("%s idx:%d\n", __func__
4766                                , pmlmeext->sitesurvey_res.channel_idx);
4767
4768                        pmlmeext->scan_abort = false;/* reset */
4769                }
4770
4771                ph2c = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC);
4772                if (!ph2c)
4773                        goto exit_survey_timer_hdl;
4774
4775                psurveyPara = kzalloc(sizeof(struct sitesurvey_parm), GFP_ATOMIC);
4776                if (!psurveyPara) {
4777                        kfree(ph2c);
4778                        goto exit_survey_timer_hdl;
4779                }
4780
4781                init_h2fwcmd_w_parm_no_rsp(ph2c, psurveyPara, _SiteSurvey_CMD_);
4782                rtw_enqueue_cmd(pcmdpriv, ph2c);
4783        }
4784
4785exit_survey_timer_hdl:
4786        return;
4787}
4788
4789void link_timer_hdl(struct timer_list *t)
4790{
4791        struct adapter *padapter = from_timer(padapter, t,
4792                                            mlmeextpriv.link_timer);
4793        struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
4794        struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
4795
4796        if (pmlmeinfo->state & WIFI_FW_AUTH_NULL) {
4797                DBG_88E("%s:no beacon while connecting\n", __func__);
4798                pmlmeinfo->state = WIFI_FW_NULL_STATE;
4799                report_join_res(padapter, -3);
4800        } else if (pmlmeinfo->state & WIFI_FW_AUTH_STATE) {
4801                /* re-auth timer */
4802                if (++pmlmeinfo->reauth_count > REAUTH_LIMIT) {
4803                        pmlmeinfo->state = 0;
4804                        report_join_res(padapter, -1);
4805                        return;
4806                }
4807
4808                DBG_88E("%s: auth timeout and try again\n", __func__);
4809                pmlmeinfo->auth_seq = 1;
4810                issue_auth(padapter, NULL, 0);
4811                set_link_timer(pmlmeext, REAUTH_TO);
4812        } else if (pmlmeinfo->state & WIFI_FW_ASSOC_STATE) {
4813                /* re-assoc timer */
4814                if (++pmlmeinfo->reassoc_count > REASSOC_LIMIT) {
4815                        pmlmeinfo->state = WIFI_FW_NULL_STATE;
4816                        report_join_res(padapter, -2);
4817                        return;
4818                }
4819
4820                DBG_88E("%s: assoc timeout and try again\n", __func__);
4821                issue_assocreq(padapter);
4822                set_link_timer(pmlmeext, REASSOC_TO);
4823        }
4824}
4825
4826void addba_timer_hdl(struct timer_list *t)
4827{
4828        struct sta_info *psta = from_timer(psta, t, addba_retry_timer);
4829        struct ht_priv  *phtpriv;
4830
4831        if (!psta)
4832                return;
4833
4834        phtpriv = &psta->htpriv;
4835
4836        if ((phtpriv->ht_option) && (phtpriv->ampdu_enable)) {
4837                if (phtpriv->candidate_tid_bitmap)
4838                        phtpriv->candidate_tid_bitmap = 0x0;
4839        }
4840}
4841
4842u8 setopmode_hdl(struct adapter *padapter, u8 *pbuf)
4843{
4844        u8 type;
4845        struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
4846        struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
4847        struct setopmode_parm *psetop = (struct setopmode_parm *)pbuf;
4848
4849        if (psetop->mode == Ndis802_11APMode) {
4850                pmlmeinfo->state = WIFI_FW_AP_STATE;
4851                type = _HW_STATE_AP_;
4852        } else if (psetop->mode == Ndis802_11Infrastructure) {
4853                pmlmeinfo->state &= ~(BIT(0)|BIT(1));/*  clear state */
4854                pmlmeinfo->state |= WIFI_FW_STATION_STATE;/* set to     STATION_STATE */
4855                type = _HW_STATE_STATION_;
4856        } else if (psetop->mode == Ndis802_11IBSS) {
4857                type = _HW_STATE_ADHOC_;
4858        } else {
4859                type = _HW_STATE_NOLINK_;
4860        }
4861
4862        rtw_hal_set_hwreg(padapter, HW_VAR_SET_OPMODE, (u8 *)(&type));
4863        /* Set_NETYPE0_MSR(padapter, type); */
4864
4865        return H2C_SUCCESS;
4866}
4867
4868u8 createbss_hdl(struct adapter *padapter, u8 *pbuf)
4869{
4870        struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
4871        struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
4872        struct wlan_bssid_ex *pnetwork = (struct wlan_bssid_ex *)(&(pmlmeinfo->network));
4873        struct wlan_bssid_ex *pparm = (struct wlan_bssid_ex *)pbuf;
4874        /* u32  initialgain; */
4875
4876        if (pparm->InfrastructureMode == Ndis802_11APMode) {
4877#ifdef CONFIG_88EU_AP_MODE
4878
4879                if (pmlmeinfo->state == WIFI_FW_AP_STATE) {
4880                        /* todo: */
4881                        return H2C_SUCCESS;
4882                }
4883#endif
4884        }
4885
4886        /* below is for ad-hoc master */
4887        if (pparm->InfrastructureMode == Ndis802_11IBSS) {
4888                rtw_joinbss_reset(padapter);
4889
4890                pmlmeext->cur_bwmode = HT_CHANNEL_WIDTH_20;
4891                pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
4892                pmlmeinfo->ERP_enable = 0;
4893                pmlmeinfo->WMM_enable = 0;
4894                pmlmeinfo->HT_enable = 0;
4895                pmlmeinfo->HT_caps_enable = 0;
4896                pmlmeinfo->HT_info_enable = 0;
4897                pmlmeinfo->agg_enable_bitmap = 0;
4898                pmlmeinfo->candidate_tid_bitmap = 0;
4899
4900                /* disable dynamic functions, such as high power, DIG */
4901                Save_DM_Func_Flag(padapter);
4902                Switch_DM_Func(padapter, DYNAMIC_FUNC_DISABLE, false);
4903
4904                /* config the initial gain under linking, need to write the BB registers */
4905                /* initialgain = 0x1E; */
4906                /* rtw_hal_set_hwreg(padapter, HW_VAR_INITIAL_GAIN, (u8 *)(&initialgain)); */
4907
4908                /* cancel link timer */
4909                del_timer_sync(&pmlmeext->link_timer);
4910
4911                /* clear CAM */
4912                flush_all_cam_entry(padapter);
4913
4914                memcpy(pnetwork, pbuf, offsetof(struct wlan_bssid_ex, ie_length));
4915                pnetwork->ie_length = ((struct wlan_bssid_ex *)pbuf)->ie_length;
4916
4917                if (pnetwork->ie_length > MAX_IE_SZ)/* Check pbuf->ie_length */
4918                        return H2C_PARAMETERS_ERROR;
4919
4920                memcpy(pnetwork->ies, ((struct wlan_bssid_ex *)pbuf)->ies, pnetwork->ie_length);
4921
4922                start_create_ibss(padapter);
4923        }
4924
4925        return H2C_SUCCESS;
4926}
4927
4928u8 join_cmd_hdl(struct adapter *padapter, u8 *pbuf)
4929{
4930        u8 join_type;
4931        struct ndis_802_11_var_ie *pIE;
4932        struct registry_priv    *pregpriv = &padapter->registrypriv;
4933        struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
4934        struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
4935        struct wlan_bssid_ex *pnetwork = (struct wlan_bssid_ex *)(&(pmlmeinfo->network));
4936        struct wlan_bssid_ex *pparm = (struct wlan_bssid_ex *)pbuf;
4937        u32 i;
4938
4939        /* check already connecting to AP or not */
4940        if (pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS) {
4941                if (pmlmeinfo->state & WIFI_FW_STATION_STATE)
4942                        issue_deauth_ex(padapter, pnetwork->MacAddress, WLAN_REASON_DEAUTH_LEAVING, 5, 100);
4943
4944                pmlmeinfo->state = WIFI_FW_NULL_STATE;
4945
4946                /* clear CAM */
4947                flush_all_cam_entry(padapter);
4948
4949                del_timer_sync(&pmlmeext->link_timer);
4950
4951                /* set MSR to nolink -> infra. mode */
4952                Set_MSR(padapter, _HW_STATE_STATION_);
4953
4954                rtw_hal_set_hwreg(padapter, HW_VAR_MLME_DISCONNECT, NULL);
4955        }
4956
4957        rtw_antenna_select_cmd(padapter, pparm->PhyInfo.Optimum_antenna, false);
4958
4959        rtw_joinbss_reset(padapter);
4960
4961        pmlmeext->cur_bwmode = HT_CHANNEL_WIDTH_20;
4962        pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
4963        pmlmeinfo->ERP_enable = 0;
4964        pmlmeinfo->WMM_enable = 0;
4965        pmlmeinfo->HT_enable = 0;
4966        pmlmeinfo->HT_caps_enable = 0;
4967        pmlmeinfo->HT_info_enable = 0;
4968        pmlmeinfo->agg_enable_bitmap = 0;
4969        pmlmeinfo->candidate_tid_bitmap = 0;
4970        pmlmeinfo->bwmode_updated = false;
4971
4972        memcpy(pnetwork, pbuf, offsetof(struct wlan_bssid_ex, ie_length));
4973        pnetwork->ie_length = ((struct wlan_bssid_ex *)pbuf)->ie_length;
4974
4975        if (pnetwork->ie_length > MAX_IE_SZ)/* Check pbuf->ie_length */
4976                return H2C_PARAMETERS_ERROR;
4977
4978        memcpy(pnetwork->ies, ((struct wlan_bssid_ex *)pbuf)->ies, pnetwork->ie_length);
4979
4980        /* Check AP vendor to move rtw_joinbss_cmd() */
4981
4982        for (i = sizeof(struct ndis_802_11_fixed_ie); i < pnetwork->ie_length;) {
4983                pIE = (struct ndis_802_11_var_ie *)(pnetwork->ies + i);
4984
4985                switch (pIE->ElementID) {
4986                case _VENDOR_SPECIFIC_IE_:/* Get WMM IE. */
4987                        if (!memcmp(pIE->data, WMM_OUI, 4))
4988                                pmlmeinfo->WMM_enable = 1;
4989                        break;
4990                case _HT_CAPABILITY_IE_:        /* Get HT Cap IE. */
4991                        pmlmeinfo->HT_caps_enable = 1;
4992                        break;
4993                case _HT_EXTRA_INFO_IE_:        /* Get HT Info IE. */
4994                        pmlmeinfo->HT_info_enable = 1;
4995
4996                        /* spec case only for cisco's ap because cisco's ap issue assoc rsp using mcs rate @40MHz or @20MHz */
4997                        {
4998                                struct HT_info_element *pht_info = (struct HT_info_element *)(pIE->data);
4999
5000                                if ((pregpriv->cbw40_enable) &&  (pht_info->infos[0] & BIT(2))) {
5001                                        /* switch to the 40M Hz mode according to the AP */
5002                                        pmlmeext->cur_bwmode = HT_CHANNEL_WIDTH_40;
5003                                        switch (pht_info->infos[0] & 0x3) {
5004                                        case 1:
5005                                                pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_LOWER;
5006                                                break;
5007                                        case 3:
5008                                                pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_UPPER;
5009                                                break;
5010                                        default:
5011                                                pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
5012                                                break;
5013                                }
5014
5015                                        DBG_88E("set ch/bw before connected\n");
5016                                }
5017                        }
5018                        break;
5019                default:
5020                        break;
5021                }
5022
5023                i += (pIE->Length + 2);
5024        }
5025        /* disable dynamic functions, such as high power, DIG */
5026
5027        /* config the initial gain under linking, need to write the BB registers */
5028
5029        rtw_hal_set_hwreg(padapter, HW_VAR_BSSID, pmlmeinfo->network.MacAddress);
5030        join_type = 0;
5031        rtw_hal_set_hwreg(padapter, HW_VAR_MLME_JOIN, (u8 *)(&join_type));
5032
5033        /* cancel link timer */
5034        del_timer_sync(&pmlmeext->link_timer);
5035
5036        start_clnt_join(padapter);
5037
5038        return H2C_SUCCESS;
5039}
5040
5041u8 disconnect_hdl(struct adapter *padapter, unsigned char *pbuf)
5042{
5043        struct disconnect_parm *param = (struct disconnect_parm *)pbuf;
5044        struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
5045        struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
5046        struct wlan_bssid_ex *pnetwork = (struct wlan_bssid_ex *)(&(pmlmeinfo->network));
5047        u8 val8;
5048
5049        if (is_client_associated_to_ap(padapter))
5050                issue_deauth_ex(padapter, pnetwork->MacAddress, WLAN_REASON_DEAUTH_LEAVING, param->deauth_timeout_ms/100, 100);
5051
5052        rtw_hal_set_hwreg(padapter, HW_VAR_MLME_DISCONNECT, NULL);
5053        rtw_hal_set_hwreg(padapter, HW_VAR_BSSID, null_addr);
5054
5055        /* restore to initial setting. */
5056        update_tx_basic_rate(padapter, padapter->registrypriv.wireless_mode);
5057
5058        if (((pmlmeinfo->state&0x03) == WIFI_FW_ADHOC_STATE) || ((pmlmeinfo->state&0x03) == WIFI_FW_AP_STATE)) {
5059                /* Stop BCN */
5060                val8 = 0;
5061                rtw_hal_set_hwreg(padapter, HW_VAR_BCN_FUNC, (u8 *)(&val8));
5062        }
5063
5064        /* set MSR to no link state -> infra. mode */
5065        Set_MSR(padapter, _HW_STATE_STATION_);
5066
5067        pmlmeinfo->state = WIFI_FW_NULL_STATE;
5068
5069        /* switch to the 20M Hz mode after disconnect */
5070        pmlmeext->cur_bwmode = HT_CHANNEL_WIDTH_20;
5071        pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
5072
5073        set_channel_bwmode(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode);
5074
5075        flush_all_cam_entry(padapter);
5076
5077        del_timer_sync(&pmlmeext->link_timer);
5078
5079        rtw_free_uc_swdec_pending_queue(padapter);
5080
5081        return  H2C_SUCCESS;
5082}
5083
5084static int rtw_scan_ch_decision(struct adapter *padapter,
5085                                struct rtw_ieee80211_channel *out,
5086                                u32 out_num,
5087                                struct rtw_ieee80211_channel *in, u32 in_num)
5088{
5089        int i, j;
5090        int set_idx;
5091        struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
5092
5093        /* clear out first */
5094        memset(out, 0, sizeof(struct rtw_ieee80211_channel)*out_num);
5095
5096        /* acquire channels from in */
5097        j = 0;
5098        for (i = 0; i < in_num; i++) {
5099                set_idx = rtw_ch_set_search_ch(pmlmeext->channel_set, in[i].hw_value);
5100                if (in[i].hw_value && !(in[i].flags & RTW_IEEE80211_CHAN_DISABLED) &&
5101                    set_idx >= 0) {
5102                        out[j] = in[i];
5103
5104                        if (pmlmeext->channel_set[set_idx].ScanType == SCAN_PASSIVE)
5105                                out[j].flags &= RTW_IEEE80211_CHAN_PASSIVE_SCAN;
5106
5107                        j++;
5108                }
5109                if (j >= out_num)
5110                        break;
5111        }
5112
5113        /* if out is empty, use channel_set as default */
5114        if (j == 0) {
5115                for (i = 0; i < pmlmeext->max_chan_nums; i++) {
5116                        out[i].hw_value = pmlmeext->channel_set[i].ChannelNum;
5117
5118                        if (pmlmeext->channel_set[i].ScanType == SCAN_PASSIVE)
5119                                out[i].flags &= RTW_IEEE80211_CHAN_PASSIVE_SCAN;
5120
5121                        j++;
5122                }
5123        }
5124
5125        return j;
5126}
5127
5128u8 sitesurvey_cmd_hdl(struct adapter *padapter, u8 *pbuf)
5129{
5130        struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
5131        struct sitesurvey_parm  *pparm = (struct sitesurvey_parm *)pbuf;
5132        u8 bdelayscan = false;
5133        u8 val8;
5134        u32     initialgain;
5135        u32     i;
5136
5137        if (pmlmeext->sitesurvey_res.state == SCAN_DISABLE) {
5138                /* for first time sitesurvey_cmd */
5139                rtw_hal_set_hwreg(padapter, HW_VAR_CHECK_TXBUF, NULL);
5140
5141                pmlmeext->sitesurvey_res.state = SCAN_START;
5142                pmlmeext->sitesurvey_res.bss_cnt = 0;
5143                pmlmeext->sitesurvey_res.channel_idx = 0;
5144
5145                for (i = 0; i < RTW_SSID_SCAN_AMOUNT; i++) {
5146                        if (pparm->ssid[i].SsidLength) {
5147                                memcpy(pmlmeext->sitesurvey_res.ssid[i].Ssid, pparm->ssid[i].Ssid, IW_ESSID_MAX_SIZE);
5148                                pmlmeext->sitesurvey_res.ssid[i].SsidLength = pparm->ssid[i].SsidLength;
5149                        } else {
5150                                pmlmeext->sitesurvey_res.ssid[i].SsidLength = 0;
5151                        }
5152                }
5153
5154                pmlmeext->sitesurvey_res.ch_num = rtw_scan_ch_decision(padapter
5155                        , pmlmeext->sitesurvey_res.ch, RTW_CHANNEL_SCAN_AMOUNT
5156                        , pparm->ch, pparm->ch_num
5157        );
5158
5159                pmlmeext->sitesurvey_res.scan_mode = pparm->scan_mode;
5160
5161                /* issue null data if associating to the AP */
5162                if (is_client_associated_to_ap(padapter)) {
5163                        pmlmeext->sitesurvey_res.state = SCAN_TXNULL;
5164
5165                        issue_nulldata(padapter, NULL, 1, 3, 500);
5166
5167                        bdelayscan = true;
5168                }
5169                if (bdelayscan) {
5170                        /* delay 50ms to protect nulldata(1). */
5171                        set_survey_timer(pmlmeext, 50);
5172                        return H2C_SUCCESS;
5173                }
5174        }
5175
5176        if ((pmlmeext->sitesurvey_res.state == SCAN_START) || (pmlmeext->sitesurvey_res.state == SCAN_TXNULL)) {
5177                /* disable dynamic functions, such as high power, DIG */
5178                Save_DM_Func_Flag(padapter);
5179                Switch_DM_Func(padapter, DYNAMIC_FUNC_DISABLE, false);
5180
5181                /* config the initial gain under scanning, need to write the BB registers */
5182                initialgain = 0x1E;
5183
5184                rtw_hal_set_hwreg(padapter, HW_VAR_INITIAL_GAIN, (u8 *)(&initialgain));
5185
5186                /* set MSR to no link state */
5187                Set_MSR(padapter, _HW_STATE_NOLINK_);
5188
5189                val8 = 1; /* under site survey */
5190                rtw_hal_set_hwreg(padapter, HW_VAR_MLME_SITESURVEY, (u8 *)(&val8));
5191
5192                pmlmeext->sitesurvey_res.state = SCAN_PROCESS;
5193        }
5194
5195        site_survey(padapter);
5196
5197        return H2C_SUCCESS;
5198}
5199
5200u8 setauth_hdl(struct adapter *padapter, unsigned char *pbuf)
5201{
5202        struct setauth_parm             *pparm = (struct setauth_parm *)pbuf;
5203        struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
5204        struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
5205
5206        if (pparm->mode < 4)
5207                pmlmeinfo->auth_algo = pparm->mode;
5208        return  H2C_SUCCESS;
5209}
5210
5211u8 setkey_hdl(struct adapter *padapter, u8 *pbuf)
5212{
5213        unsigned short                          ctrl;
5214        struct setkey_parm              *pparm = (struct setkey_parm *)pbuf;
5215        struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
5216        struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
5217        unsigned char                                   null_sta[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
5218
5219        /* main tx key for wep. */
5220        if (pparm->set_tx)
5221                pmlmeinfo->key_index = pparm->keyid;
5222
5223        /* write cam */
5224        ctrl = BIT(15) | ((pparm->algorithm) << 2) | pparm->keyid;
5225
5226        DBG_88E_LEVEL(_drv_info_, "set group key to hw: alg:%d(WEP40-1 WEP104-5 TKIP-2 AES-4) "
5227                        "keyid:%d\n", pparm->algorithm, pparm->keyid);
5228        write_cam(padapter, pparm->keyid, ctrl, null_sta, pparm->key);
5229
5230        return H2C_SUCCESS;
5231}
5232
5233u8 set_stakey_hdl(struct adapter *padapter, u8 *pbuf)
5234{
5235        u16 ctrl = 0;
5236        u8 cam_id;/* cam_entry */
5237        struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
5238        struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
5239        struct set_stakey_parm  *pparm = (struct set_stakey_parm *)pbuf;
5240
5241        /* cam_entry: */
5242        /* 0~3 for default key */
5243
5244        /* for concurrent mode (ap+sta): */
5245        /* default key is disable, using sw encrypt/decrypt */
5246        /* cam_entry = 4 for sta mode (macid = 0) */
5247        /* cam_entry(macid+3) = 5 ~ N for ap mode (aid = 1~N, macid = 2 ~N) */
5248
5249        /* for concurrent mode (sta+sta): */
5250        /* default key is disable, using sw encrypt/decrypt */
5251        /* cam_entry = 4 mapping to macid = 0 */
5252        /* cam_entry = 5 mapping to macid = 2 */
5253
5254        cam_id = 4;
5255
5256        DBG_88E_LEVEL(_drv_info_, "set pairwise key to hw: alg:%d(WEP40-1 WEP104-5 TKIP-2 AES-4) camid:%d\n",
5257                      pparm->algorithm, cam_id);
5258        if ((pmlmeinfo->state&0x03) == WIFI_FW_AP_STATE) {
5259                struct sta_info *psta;
5260                struct sta_priv *pstapriv = &padapter->stapriv;
5261
5262                if (pparm->algorithm == _NO_PRIVACY_)   /*  clear cam entry */ {
5263                        clear_cam_entry(padapter, pparm->id);
5264                        return H2C_SUCCESS_RSP;
5265                }
5266
5267                psta = rtw_get_stainfo(pstapriv, pparm->addr);
5268                if (psta) {
5269                        ctrl = BIT(15) | ((pparm->algorithm) << 2);
5270
5271                        DBG_88E("r871x_set_stakey_hdl(): enc_algorithm=%d\n", pparm->algorithm);
5272
5273                        if ((psta->mac_id < 1) || (psta->mac_id > (NUM_STA-4))) {
5274                                DBG_88E("r871x_set_stakey_hdl():set_stakey failed, mac_id(aid)=%d\n", psta->mac_id);
5275                                return H2C_REJECTED;
5276                        }
5277
5278                        cam_id = psta->mac_id + 3;/* 0~3 for default key, cmd_id = macid + 3, macid = aid+1; */
5279
5280                        DBG_88E("Write CAM, mac_addr =%pM, cam_entry=%d\n",
5281                                pparm->addr, cam_id);
5282
5283                        write_cam(padapter, cam_id, ctrl, pparm->addr, pparm->key);
5284
5285                        return H2C_SUCCESS_RSP;
5286                } else {
5287                        DBG_88E("r871x_set_stakey_hdl(): sta has been free\n");
5288                        return H2C_REJECTED;
5289                }
5290        }
5291
5292        /* below for sta mode */
5293
5294        if (pparm->algorithm == _NO_PRIVACY_) { /*  clear cam entry */
5295                clear_cam_entry(padapter, pparm->id);
5296                return H2C_SUCCESS;
5297        }
5298        ctrl = BIT(15) | ((pparm->algorithm) << 2);
5299        write_cam(padapter, cam_id, ctrl, pparm->addr, pparm->key);
5300        pmlmeinfo->enc_algo = pparm->algorithm;
5301        return H2C_SUCCESS;
5302}
5303
5304u8 add_ba_hdl(struct adapter *padapter, unsigned char *pbuf)
5305{
5306        struct addBaReq_parm    *pparm = (struct addBaReq_parm *)pbuf;
5307        struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
5308        struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
5309
5310        struct sta_info *psta = rtw_get_stainfo(&padapter->stapriv, pparm->addr);
5311
5312        if (!psta)
5313                return  H2C_SUCCESS;
5314
5315        if (((pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS) && (pmlmeinfo->HT_enable)) ||
5316            ((pmlmeinfo->state&0x03) == WIFI_FW_AP_STATE)) {
5317                issue_action_BA(padapter, pparm->addr, RTW_WLAN_ACTION_ADDBA_REQ, (u16)pparm->tid);
5318                mod_timer(&psta->addba_retry_timer,
5319                          jiffies + msecs_to_jiffies(ADDBA_TO));
5320        } else {
5321                psta->htpriv.candidate_tid_bitmap &= ~BIT(pparm->tid);
5322        }
5323        return  H2C_SUCCESS;
5324}
5325
5326u8 set_tx_beacon_cmd(struct adapter *padapter)
5327{
5328        struct cmd_obj  *ph2c;
5329        struct wlan_bssid_ex    *ptxBeacon_parm;
5330        struct cmd_priv *pcmdpriv = &(padapter->cmdpriv);
5331        struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
5332        struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
5333        u8 res = _SUCCESS;
5334        int len_diff = 0;
5335
5336        ph2c = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC);
5337        if (!ph2c) {
5338                res = _FAIL;
5339                goto exit;
5340        }
5341
5342        ptxBeacon_parm = kmemdup(&(pmlmeinfo->network),
5343                                sizeof(struct wlan_bssid_ex), GFP_ATOMIC);
5344        if (ptxBeacon_parm == NULL) {
5345                kfree(ph2c);
5346                res = _FAIL;
5347                goto exit;
5348        }
5349
5350        len_diff = update_hidden_ssid(ptxBeacon_parm->ies+_BEACON_IE_OFFSET_,
5351                                      ptxBeacon_parm->ie_length-_BEACON_IE_OFFSET_,
5352                                      pmlmeinfo->hidden_ssid_mode);
5353        ptxBeacon_parm->ie_length += len_diff;
5354
5355        init_h2fwcmd_w_parm_no_rsp(ph2c, ptxBeacon_parm, _TX_Beacon_CMD_);
5356
5357        res = rtw_enqueue_cmd(pcmdpriv, ph2c);
5358
5359exit:
5360        return res;
5361}
5362
5363u8 mlme_evt_hdl(struct adapter *padapter, unsigned char *pbuf)
5364{
5365        u8 evt_code;
5366        u16 evt_sz;
5367        uint    *peventbuf;
5368        void (*event_callback)(struct adapter *dev, u8 *pbuf);
5369
5370        peventbuf = (uint *)pbuf;
5371        evt_sz = (u16)(*peventbuf&0xffff);
5372        evt_code = (u8)((*peventbuf>>16)&0xff);
5373
5374        /*  checking if event code is valid */
5375        if (evt_code >= MAX_C2HEVT) {
5376                RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_, ("\nEvent Code(%d) mismatch!\n", evt_code));
5377                goto _abort_event_;
5378        }
5379
5380        /*  checking if event size match the event parm size */
5381        if ((wlanevents[evt_code].parmsize != 0) &&
5382            (wlanevents[evt_code].parmsize != evt_sz)) {
5383                RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_,
5384                         ("\nEvent(%d) Parm Size mismatch (%d vs %d)!\n",
5385                         evt_code, wlanevents[evt_code].parmsize, evt_sz));
5386                goto _abort_event_;
5387        }
5388
5389        peventbuf += 2;
5390
5391        if (peventbuf) {
5392                event_callback = wlanevents[evt_code].event_callback;
5393                event_callback(padapter, (u8 *)peventbuf);
5394        }
5395
5396_abort_event_:
5397        return H2C_SUCCESS;
5398}
5399
5400u8 tx_beacon_hdl(struct adapter *padapter, unsigned char *pbuf)
5401{
5402        if (send_beacon(padapter) == _FAIL) {
5403                DBG_88E("issue_beacon, fail!\n");
5404                return H2C_PARAMETERS_ERROR;
5405        }
5406#ifdef CONFIG_88EU_AP_MODE
5407        else { /* tx bc/mc frames after update TIM */
5408                struct sta_info *psta_bmc;
5409                struct list_head *xmitframe_plist, *xmitframe_phead;
5410                struct xmit_frame *pxmitframe = NULL;
5411                struct sta_priv  *pstapriv = &padapter->stapriv;
5412
5413                /* for BC/MC Frames */
5414                psta_bmc = rtw_get_bcmc_stainfo(padapter);
5415                if (!psta_bmc)
5416                        return H2C_SUCCESS;
5417
5418                if ((pstapriv->tim_bitmap&BIT(0)) && (psta_bmc->sleepq_len > 0)) {
5419                        msleep(10);/*  10ms, ATIM(HIQ) Windows */
5420                        spin_lock_bh(&psta_bmc->sleep_q.lock);
5421
5422                        xmitframe_phead = get_list_head(&psta_bmc->sleep_q);
5423                        xmitframe_plist = xmitframe_phead->next;
5424
5425                        while (xmitframe_phead != xmitframe_plist) {
5426                                pxmitframe = container_of(xmitframe_plist, struct xmit_frame, list);
5427
5428                                xmitframe_plist = xmitframe_plist->next;
5429
5430                                list_del_init(&pxmitframe->list);
5431
5432                                psta_bmc->sleepq_len--;
5433                                if (psta_bmc->sleepq_len > 0)
5434                                        pxmitframe->attrib.mdata = 1;
5435                                else
5436                                        pxmitframe->attrib.mdata = 0;
5437
5438                                pxmitframe->attrib.triggered = 1;
5439
5440                                pxmitframe->attrib.qsel = 0x11;/* HIQ */
5441
5442                                spin_unlock_bh(&psta_bmc->sleep_q.lock);
5443                                if (rtw_hal_xmit(padapter, pxmitframe))
5444                                        rtw_os_xmit_complete(padapter, pxmitframe);
5445                                spin_lock_bh(&psta_bmc->sleep_q.lock);
5446                        }
5447                        spin_unlock_bh(&psta_bmc->sleep_q.lock);
5448                }
5449        }
5450#endif
5451        return H2C_SUCCESS;
5452}
5453
5454u8 set_ch_hdl(struct adapter *padapter, u8 *pbuf)
5455{
5456        struct set_ch_parm *set_ch_parm;
5457        struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
5458
5459        if (!pbuf)
5460                return H2C_PARAMETERS_ERROR;
5461
5462        set_ch_parm = (struct set_ch_parm *)pbuf;
5463
5464        DBG_88E(FUNC_NDEV_FMT" ch:%u, bw:%u, ch_offset:%u\n",
5465                FUNC_NDEV_ARG(padapter->pnetdev),
5466                set_ch_parm->ch, set_ch_parm->bw, set_ch_parm->ch_offset);
5467
5468        pmlmeext->cur_channel = set_ch_parm->ch;
5469        pmlmeext->cur_ch_offset = set_ch_parm->ch_offset;
5470        pmlmeext->cur_bwmode = set_ch_parm->bw;
5471
5472        set_channel_bwmode(padapter, set_ch_parm->ch, set_ch_parm->ch_offset, set_ch_parm->bw);
5473
5474        return  H2C_SUCCESS;
5475}
5476
5477u8 set_chplan_hdl(struct adapter *padapter, unsigned char *pbuf)
5478{
5479        struct SetChannelPlan_param *setChannelPlan_param;
5480        struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
5481
5482        if (!pbuf)
5483                return H2C_PARAMETERS_ERROR;
5484
5485        setChannelPlan_param = (struct SetChannelPlan_param *)pbuf;
5486
5487        pmlmeext->max_chan_nums = init_channel_set(padapter, setChannelPlan_param->channel_plan, pmlmeext->channel_set);
5488        init_channel_list(padapter, pmlmeext->channel_set, pmlmeext->max_chan_nums, &pmlmeext->channel_list);
5489
5490        return  H2C_SUCCESS;
5491}
5492