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