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