linux/drivers/staging/rtl8188eu/core/rtw_cmd.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/******************************************************************************
   3 *
   4 * Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved.
   5 *
   6 ******************************************************************************/
   7
   8#include <osdep_service.h>
   9#include <drv_types.h>
  10#include <recv_osdep.h>
  11#include <mlme_osdep.h>
  12#include <rtw_mlme_ext.h>
  13
  14static struct cmd_hdl wlancmds[] = {
  15        {sizeof(struct wlan_bssid_ex), join_cmd_hdl},
  16        {sizeof(struct disconnect_parm), disconnect_hdl},
  17        {sizeof(struct wlan_bssid_ex), createbss_hdl},
  18        {sizeof(struct setopmode_parm), setopmode_hdl},
  19        {sizeof(struct sitesurvey_parm), sitesurvey_cmd_hdl},
  20        {sizeof(struct setauth_parm), setauth_hdl},
  21        {sizeof(struct setkey_parm), setkey_hdl},
  22        {sizeof(struct set_stakey_parm), set_stakey_hdl},
  23        {sizeof(struct set_assocsta_parm), NULL},
  24        {sizeof(struct addBaReq_parm), add_ba_hdl},
  25        {sizeof(struct set_ch_parm), set_ch_hdl},
  26        {sizeof(struct wlan_bssid_ex), tx_beacon_hdl},
  27        {0, mlme_evt_hdl},
  28        {0, rtw_drvextra_cmd_hdl},
  29        {sizeof(struct SetChannelPlan_param), set_chplan_hdl}
  30};
  31
  32static struct _cmd_callback rtw_cmd_callback[] = {
  33        {_JoinBss_CMD_, &rtw_joinbss_cmd_callback},
  34        {_DisConnect_CMD_, &rtw_disassoc_cmd_callback},
  35        {_CreateBss_CMD_, &rtw_createbss_cmd_callback},
  36        {_SetOpMode_CMD_, NULL},
  37        {_SiteSurvey_CMD_, &rtw_survey_cmd_callback},
  38        {_SetAuth_CMD_, NULL},
  39        {_SetKey_CMD_, NULL},
  40        {_SetStaKey_CMD_, NULL},
  41        {_SetAssocSta_CMD_, &rtw_setassocsta_cmdrsp_callback},
  42        {_AddBAReq_CMD_, NULL},
  43        {_SetChannel_CMD_, NULL},
  44        {_TX_Beacon_CMD_, NULL},
  45        {_Set_MLME_EVT_CMD_, NULL},
  46        {_Set_Drv_Extra_CMD_, NULL},
  47        {_SetChannelPlan_CMD_, NULL},
  48};
  49
  50/*
  51 * Caller and the rtw_cmd_thread can protect cmd_q by spin_lock.
  52 * No irqsave is necessary.
  53 */
  54
  55void rtw_init_cmd_priv(struct cmd_priv *pcmdpriv)
  56{
  57        init_completion(&pcmdpriv->cmd_queue_comp);
  58
  59        _rtw_init_queue(&pcmdpriv->cmd_queue);
  60}
  61
  62/*
  63 * Calling Context:
  64 *
  65 * rtw_enqueue_cmd can only be called between kernel thread,
  66 * since only spin_lock is used.
  67 *
  68 * ISR/Call-Back functions can't call this sub-function.
  69 */
  70
  71static int _rtw_enqueue_cmd(struct __queue *queue, struct cmd_obj *obj)
  72{
  73        unsigned long irqL;
  74
  75        spin_lock_irqsave(&queue->lock, irqL);
  76
  77        list_add_tail(&obj->list, &queue->queue);
  78
  79        spin_unlock_irqrestore(&queue->lock, irqL);
  80
  81        return _SUCCESS;
  82}
  83
  84struct cmd_obj *rtw_dequeue_cmd(struct __queue *queue)
  85{
  86        unsigned long irqL;
  87        struct cmd_obj *obj;
  88
  89        spin_lock_irqsave(&queue->lock, irqL);
  90        obj = list_first_entry_or_null(&queue->queue, struct cmd_obj, list);
  91        if (obj)
  92                list_del_init(&obj->list);
  93        spin_unlock_irqrestore(&queue->lock, irqL);
  94
  95        return obj;
  96}
  97
  98static int rtw_cmd_filter(struct cmd_priv *pcmdpriv, struct cmd_obj *cmd_obj)
  99{
 100        struct adapter *padapter = container_of(pcmdpriv, struct adapter, cmdpriv);
 101        u8 bAllow = false; /* set to true to allow enqueuing cmd when hw_init_completed is false */
 102
 103        /* To decide allow or not */
 104        if ((padapter->pwrctrlpriv.bHWPwrPindetect) &&
 105            (!padapter->registrypriv.usbss_enable)) {
 106                if (cmd_obj->cmdcode == _Set_Drv_Extra_CMD_) {
 107                        struct drvextra_cmd_parm        *pdrvextra_cmd_parm = (struct drvextra_cmd_parm *)cmd_obj->parmbuf;
 108
 109                        if (pdrvextra_cmd_parm->ec_id == POWER_SAVING_CTRL_WK_CID)
 110                                bAllow = true;
 111                }
 112        }
 113
 114        if (cmd_obj->cmdcode == _SetChannelPlan_CMD_)
 115                bAllow = true;
 116
 117        if ((!padapter->hw_init_completed && !bAllow) ||
 118            !padapter->cmdThread) /* com_thread not running */
 119                return _FAIL;
 120        return _SUCCESS;
 121}
 122
 123u32 rtw_enqueue_cmd(struct cmd_priv *pcmdpriv, struct cmd_obj *cmd_obj)
 124{
 125        int res = _FAIL;
 126        struct adapter *padapter = container_of(pcmdpriv, struct adapter, cmdpriv);
 127
 128        if (!cmd_obj)
 129                goto exit;
 130
 131        cmd_obj->padapter = padapter;
 132
 133        res = rtw_cmd_filter(pcmdpriv, cmd_obj);
 134        if (res == _FAIL) {
 135                rtw_free_cmd_obj(cmd_obj);
 136                goto exit;
 137        }
 138
 139        res = _rtw_enqueue_cmd(&pcmdpriv->cmd_queue, cmd_obj);
 140
 141        if (res == _SUCCESS)
 142                complete(&pcmdpriv->cmd_queue_comp);
 143
 144exit:
 145
 146        return res;
 147}
 148
 149void rtw_free_cmd_obj(struct cmd_obj *pcmd)
 150{
 151        if ((pcmd->cmdcode != _JoinBss_CMD_) && (pcmd->cmdcode != _CreateBss_CMD_)) {
 152                /* free parmbuf in cmd_obj */
 153                kfree(pcmd->parmbuf);
 154        }
 155
 156        if (pcmd->rsp) {
 157                if (pcmd->rspsz != 0) {
 158                        /* free rsp in cmd_obj */
 159                        kfree(pcmd->rsp);
 160                }
 161        }
 162
 163        /* free cmd_obj */
 164        kfree(pcmd);
 165}
 166
 167int rtw_cmd_thread(void *context)
 168{
 169        u8 ret;
 170        struct cmd_obj *pcmd;
 171        u8 (*cmd_hdl)(struct adapter *padapter, u8 *pbuf);
 172        void (*pcmd_callback)(struct adapter *dev, struct cmd_obj *pcmd);
 173        struct adapter *padapter = context;
 174        struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
 175
 176        allow_signal(SIGTERM);
 177
 178        do {
 179                if (padapter->bDriverStopped || padapter->bSurpriseRemoved)
 180                        break;
 181
 182                pcmd = rtw_dequeue_cmd(&pcmdpriv->cmd_queue);
 183                if (!pcmd) {
 184                        /* The queue is empty. Wait until someone enqueues a command. */
 185                        if (wait_for_completion_interruptible(&pcmdpriv->cmd_queue_comp))
 186                                break;
 187
 188                        continue;
 189                }
 190
 191                if (rtw_cmd_filter(pcmdpriv, pcmd) == _FAIL) {
 192                        pcmd->res = H2C_DROPPED;
 193                } else {
 194                        if (pcmd->cmdcode < ARRAY_SIZE(wlancmds)) {
 195                                cmd_hdl = wlancmds[pcmd->cmdcode].h2cfuns;
 196
 197                                if (cmd_hdl) {
 198                                        ret = cmd_hdl(pcmd->padapter, pcmd->parmbuf);
 199                                        pcmd->res = ret;
 200                                }
 201                        } else {
 202                                pcmd->res = H2C_PARAMETERS_ERROR;
 203                        }
 204                }
 205
 206                /* call callback function for post-processed */
 207                if (pcmd->cmdcode < ARRAY_SIZE(rtw_cmd_callback)) {
 208                        pcmd_callback = rtw_cmd_callback[pcmd->cmdcode].callback;
 209                        if (pcmd_callback) {
 210                                /* todo: !!! fill rsp_buf to pcmd->rsp if (pcmd->rsp!= NULL) */
 211                                pcmd_callback(pcmd->padapter, pcmd);
 212                        }
 213                }
 214                rtw_free_cmd_obj(pcmd);
 215
 216                if (signal_pending(current))
 217                        flush_signals(current);
 218        } while (!kthread_should_stop());
 219
 220        /*  free all cmd_obj resources */
 221        while ((pcmd = rtw_dequeue_cmd(&pcmdpriv->cmd_queue)))
 222                rtw_free_cmd_obj(pcmd);
 223
 224        padapter->cmdThread = NULL;
 225        return 0;
 226}
 227
 228/*
 229 * rtw_sitesurvey_cmd(~)
 230 * ### NOTE:#### (!!!!)
 231 * MUST TAKE CARE THAT BEFORE CALLING THIS FUNC, YOU SHOULD HAVE
 232 * LOCKED pmlmepriv->lock
 233 */
 234u8 rtw_sitesurvey_cmd(struct adapter  *padapter, struct ndis_802_11_ssid *ssid, int ssid_num,
 235                      struct rtw_ieee80211_channel *ch, int ch_num)
 236{
 237        u8 res = _FAIL;
 238        struct cmd_obj          *ph2c;
 239        struct sitesurvey_parm  *psurveyPara;
 240        struct cmd_priv         *pcmdpriv = &padapter->cmdpriv;
 241        struct mlme_priv        *pmlmepriv = &padapter->mlmepriv;
 242
 243        if (check_fwstate(pmlmepriv, _FW_LINKED))
 244                rtw_lps_ctrl_wk_cmd(padapter, LPS_CTRL_SCAN, 1);
 245
 246        ph2c = kzalloc(sizeof(*ph2c), GFP_ATOMIC);
 247        if (!ph2c)
 248                return _FAIL;
 249
 250        psurveyPara = kzalloc(sizeof(*psurveyPara), GFP_ATOMIC);
 251        if (!psurveyPara) {
 252                kfree(ph2c);
 253                return _FAIL;
 254        }
 255
 256        rtw_free_network_queue(padapter, false);
 257
 258        init_h2fwcmd_w_parm_no_rsp(ph2c, psurveyPara, _SiteSurvey_CMD_);
 259
 260        psurveyPara->scan_mode = pmlmepriv->scan_mode;
 261
 262        /* prepare ssid list */
 263        if (ssid) {
 264                int i;
 265
 266                for (i = 0; i < ssid_num && i < RTW_SSID_SCAN_AMOUNT; i++) {
 267                        if (ssid[i].ssid_length) {
 268                                memcpy(&psurveyPara->ssid[i], &ssid[i],
 269                                       sizeof(struct ndis_802_11_ssid));
 270                                psurveyPara->ssid_num++;
 271                        }
 272                }
 273        }
 274
 275        /* prepare channel list */
 276        if (ch) {
 277                int i;
 278
 279                for (i = 0; i < ch_num && i < RTW_CHANNEL_SCAN_AMOUNT; i++) {
 280                        if (ch[i].hw_value && !(ch[i].flags & RTW_IEEE80211_CHAN_DISABLED)) {
 281                                memcpy(&psurveyPara->ch[i], &ch[i],
 282                                       sizeof(struct rtw_ieee80211_channel));
 283                                psurveyPara->ch_num++;
 284                        }
 285                }
 286        }
 287
 288        set_fwstate(pmlmepriv, _FW_UNDER_SURVEY);
 289
 290        res = rtw_enqueue_cmd(pcmdpriv, ph2c);
 291
 292        if (res == _SUCCESS) {
 293                mod_timer(&pmlmepriv->scan_to_timer,
 294                          jiffies + msecs_to_jiffies(SCANNING_TIMEOUT));
 295
 296                led_control_8188eu(padapter, LED_CTL_SITE_SURVEY);
 297
 298                pmlmepriv->scan_interval = SCAN_INTERVAL;/*  30*2 sec = 60sec */
 299        } else {
 300                _clr_fwstate_(pmlmepriv, _FW_UNDER_SURVEY);
 301        }
 302
 303        return res;
 304}
 305
 306void rtw_readtssi_cmdrsp_callback(struct adapter *padapter,  struct cmd_obj *pcmd)
 307{
 308        kfree(pcmd->parmbuf);
 309        kfree(pcmd);
 310}
 311
 312u8 rtw_createbss_cmd(struct adapter  *padapter)
 313{
 314        struct cmd_obj *pcmd;
 315        struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
 316        struct wlan_bssid_ex *pdev_network = &padapter->registrypriv.dev_network;
 317        u8      res = _SUCCESS;
 318
 319        led_control_8188eu(padapter, LED_CTL_START_TO_LINK);
 320
 321        pcmd = kzalloc(sizeof(*pcmd), GFP_ATOMIC);
 322        if (!pcmd) {
 323                res = _FAIL;
 324                goto exit;
 325        }
 326
 327        INIT_LIST_HEAD(&pcmd->list);
 328        pcmd->cmdcode = _CreateBss_CMD_;
 329        pcmd->parmbuf = (unsigned char *)pdev_network;
 330        pcmd->cmdsz = get_wlan_bssid_ex_sz(pdev_network);
 331        pcmd->rsp = NULL;
 332        pcmd->rspsz = 0;
 333        pdev_network->Length = pcmd->cmdsz;
 334        res = rtw_enqueue_cmd(pcmdpriv, pcmd);
 335exit:
 336
 337        return res;
 338}
 339
 340u8 rtw_joinbss_cmd(struct adapter  *padapter, struct wlan_network *pnetwork)
 341{
 342        u8      res = _SUCCESS;
 343        uint    t_len = 0;
 344        struct wlan_bssid_ex            *psecnetwork;
 345        struct cmd_obj          *pcmd;
 346        struct cmd_priv         *pcmdpriv = &padapter->cmdpriv;
 347        struct mlme_priv        *pmlmepriv = &padapter->mlmepriv;
 348        struct qos_priv         *pqospriv = &pmlmepriv->qospriv;
 349        struct security_priv    *psecuritypriv = &padapter->securitypriv;
 350        struct registry_priv    *pregistrypriv = &padapter->registrypriv;
 351        struct ht_priv          *phtpriv = &pmlmepriv->htpriv;
 352        enum ndis_802_11_network_infra ndis_network_mode = pnetwork->network.InfrastructureMode;
 353        struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
 354        struct mlme_ext_info    *pmlmeinfo = &pmlmeext->mlmext_info;
 355
 356        led_control_8188eu(padapter, LED_CTL_START_TO_LINK);
 357
 358        pcmd = kzalloc(sizeof(*pcmd), GFP_ATOMIC);
 359        if (!pcmd) {
 360                res = _FAIL;
 361                goto exit;
 362        }
 363        /* for ies is fix buf size */
 364        t_len = sizeof(struct wlan_bssid_ex);
 365
 366        /* for hidden ap to set fw_state here */
 367        if (!check_fwstate(pmlmepriv, WIFI_STATION_STATE | WIFI_ADHOC_STATE)) {
 368                switch (ndis_network_mode) {
 369                case Ndis802_11IBSS:
 370                        set_fwstate(pmlmepriv, WIFI_ADHOC_STATE);
 371                        break;
 372                case Ndis802_11Infrastructure:
 373                        set_fwstate(pmlmepriv, WIFI_STATION_STATE);
 374                        break;
 375                case Ndis802_11APMode:
 376                case Ndis802_11AutoUnknown:
 377                case Ndis802_11InfrastructureMax:
 378                        break;
 379                }
 380        }
 381
 382        psecnetwork = &psecuritypriv->sec_bss;
 383        if (!psecnetwork) {
 384                kfree(pcmd);
 385
 386                res = _FAIL;
 387
 388                goto exit;
 389        }
 390
 391        memset(psecnetwork, 0, t_len);
 392
 393        memcpy(psecnetwork, &pnetwork->network, get_wlan_bssid_ex_sz(&pnetwork->network));
 394
 395        psecuritypriv->authenticator_ie[0] = (unsigned char)psecnetwork->ie_length;
 396
 397        if (psecnetwork->ie_length - 12 < 255)
 398                memcpy(&psecuritypriv->authenticator_ie[1], &psecnetwork->ies[12],
 399                       psecnetwork->ie_length - 12);
 400        else
 401                memcpy(&psecuritypriv->authenticator_ie[1], &psecnetwork->ies[12], 255);
 402
 403        psecnetwork->ie_length = 0;
 404        /*  Added by Albert 2009/02/18 */
 405        /*  If the driver wants to use the bssid to create the connection. */
 406        /*  If not,  we have to copy the connecting AP's MAC address to it so that */
 407        /*  the driver just has the bssid information for PMKIDList searching. */
 408
 409        if (!pmlmepriv->assoc_by_bssid)
 410                memcpy(&pmlmepriv->assoc_bssid[0], &pnetwork->network.MacAddress[0], ETH_ALEN);
 411
 412        psecnetwork->ie_length = rtw_restruct_sec_ie(padapter, &pnetwork->network.ies[0],
 413                                                     &psecnetwork->ies[0],
 414                                                     pnetwork->network.ie_length);
 415
 416        pqospriv->qos_option = 0;
 417
 418        if (pregistrypriv->wmm_enable) {
 419                u32 tmp_len;
 420
 421                tmp_len = rtw_restruct_wmm_ie(padapter, &pnetwork->network.ies[0],
 422                                              &psecnetwork->ies[0],
 423                                              pnetwork->network.ie_length,
 424                                              psecnetwork->ie_length);
 425
 426                if (psecnetwork->ie_length != tmp_len) {
 427                        psecnetwork->ie_length = tmp_len;
 428                        pqospriv->qos_option = 1; /* There is WMM IE in this corresp. beacon */
 429                } else {
 430                        pqospriv->qos_option = 0;/* There is no WMM IE in this corresp. beacon */
 431                }
 432        }
 433
 434        phtpriv->ht_option = false;
 435        if (pregistrypriv->ht_enable) {
 436                /*
 437                 * Added by Albert 2010/06/23
 438                 * For the WEP mode, we will use the bg mode to do
 439                 * the connection to avoid some IOT issue.
 440                 * Especially for Realtek 8192u SoftAP.
 441                 */
 442                if ((padapter->securitypriv.dot11PrivacyAlgrthm != _WEP40_) &&
 443                    (padapter->securitypriv.dot11PrivacyAlgrthm != _WEP104_) &&
 444                    (padapter->securitypriv.dot11PrivacyAlgrthm != _TKIP_)) {
 445                        /* rtw_restructure_ht_ie */
 446                        rtw_restructure_ht_ie(padapter, &pnetwork->network.ies[0],
 447                                              &psecnetwork->ies[0],
 448                                              pnetwork->network.ie_length, &psecnetwork->ie_length);
 449                }
 450        }
 451
 452        pmlmeinfo->assoc_AP_vendor = check_assoc_AP(pnetwork->network.ies, pnetwork->network.ie_length);
 453
 454        if (pmlmeinfo->assoc_AP_vendor == HT_IOT_PEER_TENDA)
 455                padapter->pwrctrlpriv.smart_ps = 0;
 456        else
 457                padapter->pwrctrlpriv.smart_ps = padapter->registrypriv.smart_ps;
 458
 459        pcmd->cmdsz = get_wlan_bssid_ex_sz(psecnetwork);/* get cmdsz before endian conversion */
 460
 461        INIT_LIST_HEAD(&pcmd->list);
 462        pcmd->cmdcode = _JoinBss_CMD_;
 463        pcmd->parmbuf = (unsigned char *)psecnetwork;
 464        pcmd->rsp = NULL;
 465        pcmd->rspsz = 0;
 466
 467        res = rtw_enqueue_cmd(pcmdpriv, pcmd);
 468
 469exit:
 470
 471        return res;
 472}
 473
 474u8 rtw_disassoc_cmd(struct adapter *padapter, u32 deauth_timeout_ms, bool enqueue) /* for sta_mode */
 475{
 476        struct cmd_obj *cmdobj = NULL;
 477        struct disconnect_parm *param = NULL;
 478        struct cmd_priv *cmdpriv = &padapter->cmdpriv;
 479        u8 res = _SUCCESS;
 480
 481        /* prepare cmd parameter */
 482        param = kzalloc(sizeof(*param), GFP_ATOMIC);
 483        if (!param) {
 484                res = _FAIL;
 485                goto exit;
 486        }
 487        param->deauth_timeout_ms = deauth_timeout_ms;
 488
 489        if (enqueue) {
 490                /* need enqueue, prepare cmd_obj and enqueue */
 491                cmdobj = kzalloc(sizeof(*cmdobj), GFP_ATOMIC);
 492                if (!cmdobj) {
 493                        res = _FAIL;
 494                        kfree(param);
 495                        goto exit;
 496                }
 497                init_h2fwcmd_w_parm_no_rsp(cmdobj, param, _DisConnect_CMD_);
 498                res = rtw_enqueue_cmd(cmdpriv, cmdobj);
 499        } else {
 500                /* no need to enqueue, do the cmd hdl directly and free cmd parameter */
 501                if (disconnect_hdl(padapter, (u8 *)param) != H2C_SUCCESS)
 502                        res = _FAIL;
 503                kfree(param);
 504        }
 505
 506exit:
 507
 508        return res;
 509}
 510
 511u8 rtw_setopmode_cmd(struct adapter  *padapter, enum ndis_802_11_network_infra networktype)
 512{
 513        struct  cmd_obj *ph2c;
 514        struct  setopmode_parm *psetop;
 515
 516        struct  cmd_priv   *pcmdpriv = &padapter->cmdpriv;
 517
 518        ph2c = kzalloc(sizeof(*ph2c), GFP_KERNEL);
 519        psetop = kzalloc(sizeof(*psetop), GFP_KERNEL);
 520        if (!ph2c || !psetop) {
 521                kfree(ph2c);
 522                kfree(psetop);
 523                return false;
 524        }
 525
 526        init_h2fwcmd_w_parm_no_rsp(ph2c, psetop, _SetOpMode_CMD_);
 527        psetop->mode = (u8)networktype;
 528
 529        return rtw_enqueue_cmd(pcmdpriv, ph2c);
 530}
 531
 532u8 rtw_setstakey_cmd(struct adapter *padapter, u8 *psta, u8 unicast_key)
 533{
 534        struct cmd_obj *ph2c;
 535        struct set_stakey_parm *psetstakey_para;
 536        struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
 537        struct set_stakey_rsp *psetstakey_rsp = NULL;
 538
 539        struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
 540        struct security_priv *psecuritypriv = &padapter->securitypriv;
 541        struct sta_info *sta = (struct sta_info *)psta;
 542
 543        ph2c = kzalloc(sizeof(*ph2c), GFP_KERNEL);
 544        psetstakey_para = kzalloc(sizeof(*psetstakey_para), GFP_KERNEL);
 545        psetstakey_rsp = kzalloc(sizeof(*psetstakey_rsp), GFP_KERNEL);
 546
 547        if (!ph2c || !psetstakey_para || !psetstakey_rsp) {
 548                kfree(ph2c);
 549                kfree(psetstakey_para);
 550                kfree(psetstakey_rsp);
 551                return _FAIL;
 552        }
 553
 554        init_h2fwcmd_w_parm_no_rsp(ph2c, psetstakey_para, _SetStaKey_CMD_);
 555        ph2c->rsp = (u8 *)psetstakey_rsp;
 556        ph2c->rspsz = sizeof(struct set_stakey_rsp);
 557
 558        ether_addr_copy(psetstakey_para->addr, sta->hwaddr);
 559
 560        if (check_fwstate(pmlmepriv, WIFI_STATION_STATE))
 561                psetstakey_para->algorithm = (unsigned char)psecuritypriv->dot11PrivacyAlgrthm;
 562        else
 563                GET_ENCRY_ALGO(psecuritypriv, sta, psetstakey_para->algorithm, false);
 564
 565        if (unicast_key)
 566                memcpy(&psetstakey_para->key, &sta->dot118021x_UncstKey, 16);
 567        else
 568                memcpy(&psetstakey_para->key,
 569                       &psecuritypriv->dot118021XGrpKey[psecuritypriv->dot118021XGrpKeyid].skey, 16);
 570
 571        /* jeff: set this because at least sw key is ready */
 572        padapter->securitypriv.busetkipkey = true;
 573
 574        return rtw_enqueue_cmd(pcmdpriv, ph2c);
 575}
 576
 577u8 rtw_clearstakey_cmd(struct adapter *padapter, u8 *psta, u8 entry, u8 enqueue)
 578{
 579        struct cmd_obj *ph2c;
 580        struct set_stakey_parm  *psetstakey_para;
 581        struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
 582        struct set_stakey_rsp *psetstakey_rsp = NULL;
 583        struct sta_info *sta = (struct sta_info *)psta;
 584        u8      res = _SUCCESS;
 585
 586        if (!enqueue) {
 587                clear_cam_entry(padapter, entry);
 588        } else {
 589                ph2c = kzalloc(sizeof(*ph2c), GFP_ATOMIC);
 590                if (!ph2c) {
 591                        res = _FAIL;
 592                        goto exit;
 593                }
 594
 595                psetstakey_para = kzalloc(sizeof(*psetstakey_para), GFP_ATOMIC);
 596                if (!psetstakey_para) {
 597                        kfree(ph2c);
 598                        res = _FAIL;
 599                        goto exit;
 600                }
 601
 602                psetstakey_rsp = kzalloc(sizeof(*psetstakey_rsp), GFP_ATOMIC);
 603                if (!psetstakey_rsp) {
 604                        kfree(ph2c);
 605                        kfree(psetstakey_para);
 606                        res = _FAIL;
 607                        goto exit;
 608                }
 609
 610                init_h2fwcmd_w_parm_no_rsp(ph2c, psetstakey_para, _SetStaKey_CMD_);
 611                ph2c->rsp = (u8 *)psetstakey_rsp;
 612                ph2c->rspsz = sizeof(struct set_stakey_rsp);
 613
 614                ether_addr_copy(psetstakey_para->addr, sta->hwaddr);
 615
 616                psetstakey_para->algorithm = _NO_PRIVACY_;
 617
 618                psetstakey_para->id = entry;
 619
 620                res = rtw_enqueue_cmd(pcmdpriv, ph2c);
 621        }
 622exit:
 623
 624        return res;
 625}
 626
 627u8 rtw_addbareq_cmd(struct adapter *padapter, u8 tid, u8 *addr)
 628{
 629        struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
 630        struct cmd_obj *ph2c;
 631        struct addBaReq_parm *paddbareq_parm;
 632        u8      res = _SUCCESS;
 633
 634        ph2c = kzalloc(sizeof(*ph2c), GFP_ATOMIC);
 635        if (!ph2c) {
 636                res = _FAIL;
 637                goto exit;
 638        }
 639
 640        paddbareq_parm = kzalloc(sizeof(*paddbareq_parm), GFP_ATOMIC);
 641        if (!paddbareq_parm) {
 642                kfree(ph2c);
 643                res = _FAIL;
 644                goto exit;
 645        }
 646
 647        paddbareq_parm->tid = tid;
 648        memcpy(paddbareq_parm->addr, addr, ETH_ALEN);
 649
 650        init_h2fwcmd_w_parm_no_rsp(ph2c, paddbareq_parm, _AddBAReq_CMD_);
 651
 652        res = rtw_enqueue_cmd(pcmdpriv, ph2c);
 653
 654exit:
 655
 656        return res;
 657}
 658
 659u8 rtw_dynamic_chk_wk_cmd(struct adapter *padapter)
 660{
 661        struct cmd_obj *ph2c;
 662        struct drvextra_cmd_parm *pdrvextra_cmd_parm;
 663        struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
 664        u8      res = _SUCCESS;
 665
 666        ph2c = kzalloc(sizeof(*ph2c), GFP_ATOMIC);
 667        if (!ph2c) {
 668                res = _FAIL;
 669                goto exit;
 670        }
 671
 672        pdrvextra_cmd_parm = kzalloc(sizeof(*pdrvextra_cmd_parm), GFP_ATOMIC);
 673        if (!pdrvextra_cmd_parm) {
 674                kfree(ph2c);
 675                res = _FAIL;
 676                goto exit;
 677        }
 678
 679        pdrvextra_cmd_parm->ec_id = DYNAMIC_CHK_WK_CID;
 680        pdrvextra_cmd_parm->type_size = 0;
 681        pdrvextra_cmd_parm->pbuf = (u8 *)padapter;
 682
 683        init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, _Set_Drv_Extra_CMD_);
 684
 685        res = rtw_enqueue_cmd(pcmdpriv, ph2c);
 686exit:
 687        return res;
 688}
 689
 690u8 rtw_set_chplan_cmd(struct adapter *padapter, u8 chplan, u8 enqueue)
 691{
 692        struct  cmd_obj *pcmdobj;
 693        struct  SetChannelPlan_param *setChannelPlan_param;
 694        struct  cmd_priv   *pcmdpriv = &padapter->cmdpriv;
 695
 696        u8      res = _SUCCESS;
 697
 698        /* check input parameter */
 699        if (!rtw_is_channel_plan_valid(chplan)) {
 700                res = _FAIL;
 701                goto exit;
 702        }
 703
 704        /* prepare cmd parameter */
 705        setChannelPlan_param = kzalloc(sizeof(*setChannelPlan_param), GFP_KERNEL);
 706        if (!setChannelPlan_param) {
 707                res = _FAIL;
 708                goto exit;
 709        }
 710        setChannelPlan_param->channel_plan = chplan;
 711
 712        if (enqueue) {
 713                /* need enqueue, prepare cmd_obj and enqueue */
 714                pcmdobj = kzalloc(sizeof(*pcmdobj), GFP_KERNEL);
 715                if (!pcmdobj) {
 716                        kfree(setChannelPlan_param);
 717                        res = _FAIL;
 718                        goto exit;
 719                }
 720
 721                init_h2fwcmd_w_parm_no_rsp(pcmdobj, setChannelPlan_param, _SetChannelPlan_CMD_);
 722                res = rtw_enqueue_cmd(pcmdpriv, pcmdobj);
 723        } else {
 724                /* no need to enqueue, do the cmd hdl directly and free cmd parameter */
 725                if (set_chplan_hdl(padapter, (unsigned char *)setChannelPlan_param) != H2C_SUCCESS)
 726                        res = _FAIL;
 727
 728                kfree(setChannelPlan_param);
 729        }
 730
 731        if (res == _SUCCESS)
 732                padapter->mlmepriv.ChannelPlan = chplan;
 733
 734exit:
 735
 736        return res;
 737}
 738
 739static void traffic_status_watchdog(struct adapter *padapter)
 740{
 741        u8      bEnterPS;
 742        u8      bBusyTraffic = false, bTxBusyTraffic = false, bRxBusyTraffic = false;
 743        u8      bHigherBusyTraffic = false, bHigherBusyRxTraffic = false, bHigherBusyTxTraffic = false;
 744        struct mlme_priv                *pmlmepriv = &padapter->mlmepriv;
 745
 746        /*  */
 747        /*  Determine if our traffic is busy now */
 748        /*  */
 749        if (check_fwstate(pmlmepriv, _FW_LINKED)) {
 750                if (pmlmepriv->LinkDetectInfo.NumRxOkInPeriod > 100 ||
 751                    pmlmepriv->LinkDetectInfo.NumTxOkInPeriod > 100) {
 752                        bBusyTraffic = true;
 753
 754                        if (pmlmepriv->LinkDetectInfo.NumRxOkInPeriod >
 755                            pmlmepriv->LinkDetectInfo.NumTxOkInPeriod)
 756                                bRxBusyTraffic = true;
 757                        else
 758                                bTxBusyTraffic = true;
 759                }
 760
 761                /*  Higher Tx/Rx data. */
 762                if (pmlmepriv->LinkDetectInfo.NumRxOkInPeriod > 4000 ||
 763                    pmlmepriv->LinkDetectInfo.NumTxOkInPeriod > 4000) {
 764                        bHigherBusyTraffic = true;
 765
 766                        if (pmlmepriv->LinkDetectInfo.NumRxOkInPeriod >
 767                            pmlmepriv->LinkDetectInfo.NumTxOkInPeriod)
 768                                bHigherBusyRxTraffic = true;
 769                        else
 770                                bHigherBusyTxTraffic = true;
 771                }
 772
 773                /*  check traffic for  powersaving. */
 774                if (((pmlmepriv->LinkDetectInfo.NumRxUnicastOkInPeriod + pmlmepriv->LinkDetectInfo.NumTxOkInPeriod) > 8) ||
 775                    (pmlmepriv->LinkDetectInfo.NumRxUnicastOkInPeriod > 2))
 776                        bEnterPS = false;
 777                else
 778                        bEnterPS = true;
 779
 780                /*  LeisurePS only work in infra mode. */
 781                if (bEnterPS)
 782                        LPS_Enter(padapter);
 783                else
 784                        LPS_Leave(padapter);
 785        } else {
 786                LPS_Leave(padapter);
 787        }
 788
 789        pmlmepriv->LinkDetectInfo.NumRxOkInPeriod = 0;
 790        pmlmepriv->LinkDetectInfo.NumTxOkInPeriod = 0;
 791        pmlmepriv->LinkDetectInfo.NumRxUnicastOkInPeriod = 0;
 792        pmlmepriv->LinkDetectInfo.bBusyTraffic = bBusyTraffic;
 793        pmlmepriv->LinkDetectInfo.bTxBusyTraffic = bTxBusyTraffic;
 794        pmlmepriv->LinkDetectInfo.bRxBusyTraffic = bRxBusyTraffic;
 795        pmlmepriv->LinkDetectInfo.bHigherBusyTraffic = bHigherBusyTraffic;
 796        pmlmepriv->LinkDetectInfo.bHigherBusyRxTraffic = bHigherBusyRxTraffic;
 797        pmlmepriv->LinkDetectInfo.bHigherBusyTxTraffic = bHigherBusyTxTraffic;
 798}
 799
 800static void dynamic_chk_wk_hdl(struct adapter *padapter, u8 *pbuf, int sz)
 801{
 802        struct mlme_priv *pmlmepriv;
 803
 804        padapter = (struct adapter *)pbuf;
 805        pmlmepriv = &padapter->mlmepriv;
 806
 807#ifdef CONFIG_88EU_AP_MODE
 808        if (check_fwstate(pmlmepriv, WIFI_AP_STATE))
 809                expire_timeout_chk(padapter);
 810#endif
 811
 812        linked_status_chk(padapter);
 813        traffic_status_watchdog(padapter);
 814
 815        rtw_hal_dm_watchdog(padapter);
 816}
 817
 818static void lps_ctrl_wk_hdl(struct adapter *padapter, u8 lps_ctrl_type)
 819{
 820        struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv;
 821        struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
 822        u8      mstatus;
 823
 824        if (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) ||
 825            check_fwstate(pmlmepriv, WIFI_ADHOC_STATE))
 826                return;
 827
 828        switch (lps_ctrl_type) {
 829        case LPS_CTRL_SCAN:
 830                if (check_fwstate(pmlmepriv, _FW_LINKED)) {
 831                        /* connect */
 832                        LPS_Leave(padapter);
 833                }
 834                break;
 835        case LPS_CTRL_JOINBSS:
 836                LPS_Leave(padapter);
 837                break;
 838        case LPS_CTRL_CONNECT:
 839                mstatus = 1;/* connect */
 840                /*  Reset LPS Setting */
 841                padapter->pwrctrlpriv.LpsIdleCount = 0;
 842                rtw_hal_set_hwreg(padapter, HW_VAR_H2C_FW_JOINBSSRPT, (u8 *)(&mstatus));
 843                break;
 844        case LPS_CTRL_DISCONNECT:
 845                mstatus = 0;/* disconnect */
 846                LPS_Leave(padapter);
 847                rtw_hal_set_hwreg(padapter, HW_VAR_H2C_FW_JOINBSSRPT, (u8 *)(&mstatus));
 848                break;
 849        case LPS_CTRL_SPECIAL_PACKET:
 850                pwrpriv->DelayLPSLastTimeStamp = jiffies;
 851                LPS_Leave(padapter);
 852                break;
 853        case LPS_CTRL_LEAVE:
 854                LPS_Leave(padapter);
 855                break;
 856        default:
 857                break;
 858        }
 859}
 860
 861u8 rtw_lps_ctrl_wk_cmd(struct adapter *padapter, u8 lps_ctrl_type, u8 enqueue)
 862{
 863        struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
 864        struct drvextra_cmd_parm *pdrvextra_cmd_parm;
 865        struct cmd_obj  *ph2c;
 866
 867        if (!enqueue) {
 868                lps_ctrl_wk_hdl(padapter, lps_ctrl_type);
 869                return _SUCCESS;
 870        }
 871
 872        ph2c = kzalloc(sizeof(*ph2c), GFP_ATOMIC);
 873        pdrvextra_cmd_parm = kzalloc(sizeof(*pdrvextra_cmd_parm), GFP_ATOMIC);
 874        if (!ph2c || !pdrvextra_cmd_parm) {
 875                kfree(ph2c);
 876                kfree(pdrvextra_cmd_parm);
 877                return _FAIL;
 878        }
 879
 880        pdrvextra_cmd_parm->ec_id = LPS_CTRL_WK_CID;
 881        pdrvextra_cmd_parm->type_size = lps_ctrl_type;
 882
 883        init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, _Set_Drv_Extra_CMD_);
 884        return rtw_enqueue_cmd(pcmdpriv, ph2c);
 885}
 886
 887static void rpt_timer_setting_wk_hdl(struct adapter *padapter, u16 min_time)
 888{
 889        rtw_hal_set_hwreg(padapter, HW_VAR_RPT_TIMER_SETTING, (u8 *)(&min_time));
 890}
 891
 892u8 rtw_rpt_timer_cfg_cmd(struct adapter *padapter, u16 min_time)
 893{
 894        struct cmd_obj          *ph2c;
 895        struct drvextra_cmd_parm        *pdrvextra_cmd_parm;
 896        struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
 897
 898        u8      res = _SUCCESS;
 899
 900        ph2c = kzalloc(sizeof(*ph2c), GFP_ATOMIC);
 901        if (!ph2c) {
 902                res = _FAIL;
 903                goto exit;
 904        }
 905
 906        pdrvextra_cmd_parm = kzalloc(sizeof(*pdrvextra_cmd_parm), GFP_ATOMIC);
 907        if (!pdrvextra_cmd_parm) {
 908                kfree(ph2c);
 909                res = _FAIL;
 910                goto exit;
 911        }
 912
 913        pdrvextra_cmd_parm->ec_id = RTP_TIMER_CFG_WK_CID;
 914        pdrvextra_cmd_parm->type_size = min_time;
 915        pdrvextra_cmd_parm->pbuf = NULL;
 916        init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, _Set_Drv_Extra_CMD_);
 917        res = rtw_enqueue_cmd(pcmdpriv, ph2c);
 918exit:
 919
 920        return res;
 921}
 922
 923static void antenna_select_wk_hdl(struct adapter *padapter, u8 antenna)
 924{
 925        rtw_hal_set_hwreg(padapter, HW_VAR_ANTENNA_DIVERSITY_SELECT, (u8 *)(&antenna));
 926}
 927
 928u8 rtw_antenna_select_cmd(struct adapter *padapter, u8 antenna, u8 enqueue)
 929{
 930        struct cmd_obj          *ph2c;
 931        struct drvextra_cmd_parm        *pdrvextra_cmd_parm;
 932        struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
 933        u8      support_ant_div;
 934        u8      res = _SUCCESS;
 935
 936        rtw_hal_get_def_var(padapter, HAL_DEF_IS_SUPPORT_ANT_DIV, &support_ant_div);
 937        if (!support_ant_div)
 938                return res;
 939
 940        if (enqueue) {
 941                ph2c = kzalloc(sizeof(*ph2c), GFP_KERNEL);
 942                if (!ph2c) {
 943                        res = _FAIL;
 944                        goto exit;
 945                }
 946
 947                pdrvextra_cmd_parm = kzalloc(sizeof(*pdrvextra_cmd_parm), GFP_KERNEL);
 948                if (!pdrvextra_cmd_parm) {
 949                        kfree(ph2c);
 950                        res = _FAIL;
 951                        goto exit;
 952                }
 953
 954                pdrvextra_cmd_parm->ec_id = ANT_SELECT_WK_CID;
 955                pdrvextra_cmd_parm->type_size = antenna;
 956                pdrvextra_cmd_parm->pbuf = NULL;
 957                init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, _Set_Drv_Extra_CMD_);
 958
 959                res = rtw_enqueue_cmd(pcmdpriv, ph2c);
 960        } else {
 961                antenna_select_wk_hdl(padapter, antenna);
 962        }
 963exit:
 964
 965        return res;
 966}
 967
 968u8 rtw_ps_cmd(struct adapter *padapter)
 969{
 970        struct cmd_obj          *ppscmd;
 971        struct drvextra_cmd_parm        *pdrvextra_cmd_parm;
 972        struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
 973
 974        ppscmd = kzalloc(sizeof(*ppscmd), GFP_ATOMIC);
 975        pdrvextra_cmd_parm = kzalloc(sizeof(*pdrvextra_cmd_parm), GFP_ATOMIC);
 976        if (!ppscmd || !pdrvextra_cmd_parm) {
 977                kfree(ppscmd);
 978                kfree(pdrvextra_cmd_parm);
 979                return _FAIL;
 980        }
 981
 982        pdrvextra_cmd_parm->ec_id = POWER_SAVING_CTRL_WK_CID;
 983        pdrvextra_cmd_parm->pbuf = NULL;
 984        init_h2fwcmd_w_parm_no_rsp(ppscmd, pdrvextra_cmd_parm, _Set_Drv_Extra_CMD_);
 985
 986        return rtw_enqueue_cmd(pcmdpriv, ppscmd);
 987}
 988
 989#ifdef CONFIG_88EU_AP_MODE
 990
 991static void rtw_chk_hi_queue_hdl(struct adapter *padapter)
 992{
 993        int cnt = 0;
 994        struct sta_info *psta_bmc;
 995        struct sta_priv *pstapriv = &padapter->stapriv;
 996
 997        psta_bmc = rtw_get_bcmc_stainfo(padapter);
 998        if (!psta_bmc)
 999                return;
1000
1001        if (psta_bmc->sleepq_len == 0) {
1002                u8 val = 0;
1003
1004                rtw_hal_get_hwreg(padapter, HW_VAR_CHK_HI_QUEUE_EMPTY, &val);
1005
1006                while (!val) {
1007                        msleep(100);
1008
1009                        cnt++;
1010
1011                        if (cnt > 10)
1012                                break;
1013
1014                        rtw_hal_get_hwreg(padapter, HW_VAR_CHK_HI_QUEUE_EMPTY, &val);
1015                }
1016
1017                if (cnt <= 10) {
1018                        pstapriv->tim_bitmap &= ~BIT(0);
1019                        pstapriv->sta_dz_bitmap &= ~BIT(0);
1020
1021                        update_beacon(padapter, WLAN_EID_TIM, NULL, false);
1022                } else { /* re check again */
1023                        rtw_chk_hi_queue_cmd(padapter);
1024                }
1025        }
1026}
1027
1028u8 rtw_chk_hi_queue_cmd(struct adapter *padapter)
1029{
1030        struct cmd_obj  *ph2c;
1031        struct drvextra_cmd_parm        *pdrvextra_cmd_parm;
1032        struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
1033        u8      res = _SUCCESS;
1034
1035        ph2c = kzalloc(sizeof(*ph2c), GFP_ATOMIC);
1036        if (!ph2c) {
1037                res = _FAIL;
1038                goto exit;
1039        }
1040
1041        pdrvextra_cmd_parm = kzalloc(sizeof(*pdrvextra_cmd_parm), GFP_ATOMIC);
1042        if (!pdrvextra_cmd_parm) {
1043                kfree(ph2c);
1044                res = _FAIL;
1045                goto exit;
1046        }
1047
1048        pdrvextra_cmd_parm->ec_id = CHECK_HIQ_WK_CID;
1049        pdrvextra_cmd_parm->type_size = 0;
1050        pdrvextra_cmd_parm->pbuf = NULL;
1051
1052        init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, _Set_Drv_Extra_CMD_);
1053
1054        res = rtw_enqueue_cmd(pcmdpriv, ph2c);
1055exit:
1056        return res;
1057}
1058#endif
1059
1060u8 rtw_drvextra_cmd_hdl(struct adapter *padapter, unsigned char *pbuf)
1061{
1062        struct drvextra_cmd_parm *pdrvextra_cmd;
1063
1064        if (!pbuf)
1065                return H2C_PARAMETERS_ERROR;
1066
1067        pdrvextra_cmd = (struct drvextra_cmd_parm *)pbuf;
1068
1069        switch (pdrvextra_cmd->ec_id) {
1070        case DYNAMIC_CHK_WK_CID:
1071                dynamic_chk_wk_hdl(padapter, pdrvextra_cmd->pbuf, pdrvextra_cmd->type_size);
1072                break;
1073        case POWER_SAVING_CTRL_WK_CID:
1074                rtw_ps_processor(padapter);
1075                break;
1076        case LPS_CTRL_WK_CID:
1077                lps_ctrl_wk_hdl(padapter, (u8)pdrvextra_cmd->type_size);
1078                break;
1079        case RTP_TIMER_CFG_WK_CID:
1080                rpt_timer_setting_wk_hdl(padapter, pdrvextra_cmd->type_size);
1081                break;
1082        case ANT_SELECT_WK_CID:
1083                antenna_select_wk_hdl(padapter, pdrvextra_cmd->type_size);
1084                break;
1085#ifdef CONFIG_88EU_AP_MODE
1086        case CHECK_HIQ_WK_CID:
1087                rtw_chk_hi_queue_hdl(padapter);
1088                break;
1089#endif /* CONFIG_88EU_AP_MODE */
1090        default:
1091                break;
1092        }
1093
1094        if (pdrvextra_cmd->pbuf && pdrvextra_cmd->type_size > 0)
1095                kfree(pdrvextra_cmd->pbuf);
1096
1097        return H2C_SUCCESS;
1098}
1099
1100void rtw_survey_cmd_callback(struct adapter *padapter,  struct cmd_obj *pcmd)
1101{
1102        struct  mlme_priv *pmlmepriv = &padapter->mlmepriv;
1103
1104        if (pcmd->res == H2C_DROPPED) {
1105                /* TODO: cancel timer and do timeout handler directly... */
1106                /* need to make timeout handlerOS independent */
1107                mod_timer(&pmlmepriv->scan_to_timer,
1108                          jiffies + msecs_to_jiffies(1));
1109        } else if (pcmd->res != H2C_SUCCESS) {
1110                mod_timer(&pmlmepriv->scan_to_timer,
1111                          jiffies + msecs_to_jiffies(1));
1112        }
1113}
1114
1115void rtw_disassoc_cmd_callback(struct adapter *padapter, struct cmd_obj *pcmd)
1116{
1117        struct  mlme_priv *pmlmepriv = &padapter->mlmepriv;
1118
1119        if (pcmd->res != H2C_SUCCESS) {
1120                spin_lock_bh(&pmlmepriv->lock);
1121                set_fwstate(pmlmepriv, _FW_LINKED);
1122                spin_unlock_bh(&pmlmepriv->lock);
1123        }
1124}
1125
1126void rtw_joinbss_cmd_callback(struct adapter *padapter,  struct cmd_obj *pcmd)
1127{
1128        struct  mlme_priv *pmlmepriv = &padapter->mlmepriv;
1129
1130        if (pcmd->res == H2C_DROPPED) {
1131                /* TODO: cancel timer and do timeout handler directly... */
1132                /* need to make timeout handlerOS independent */
1133                mod_timer(&pmlmepriv->assoc_timer,
1134                          jiffies + msecs_to_jiffies(1));
1135        } else if (pcmd->res != H2C_SUCCESS) {
1136                mod_timer(&pmlmepriv->assoc_timer,
1137                          jiffies + msecs_to_jiffies(1));
1138        }
1139}
1140
1141void rtw_createbss_cmd_callback(struct adapter *padapter, struct cmd_obj *pcmd)
1142{
1143        struct sta_info *psta = NULL;
1144        struct wlan_network *pwlan = NULL;
1145        struct  mlme_priv *pmlmepriv = &padapter->mlmepriv;
1146        struct wlan_bssid_ex *pnetwork = (struct wlan_bssid_ex *)pcmd->parmbuf;
1147        struct wlan_network *tgt_network = &pmlmepriv->cur_network;
1148
1149        if (pcmd->res != H2C_SUCCESS) {
1150                mod_timer(&pmlmepriv->assoc_timer,
1151                          jiffies + msecs_to_jiffies(1));
1152        }
1153
1154        del_timer_sync(&pmlmepriv->assoc_timer);
1155
1156        spin_lock_bh(&pmlmepriv->lock);
1157
1158        if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) {
1159                psta = rtw_get_stainfo(&padapter->stapriv, pnetwork->MacAddress);
1160                if (!psta) {
1161                        psta = rtw_alloc_stainfo(&padapter->stapriv, pnetwork->MacAddress);
1162                        if (!psta) {
1163                                goto createbss_cmd_fail;
1164                        }
1165                }
1166
1167                rtw_indicate_connect(padapter);
1168        } else {
1169                pwlan = rtw_alloc_network(pmlmepriv);
1170                spin_lock_bh(&pmlmepriv->scanned_queue.lock);
1171                if (!pwlan) {
1172                        pwlan = rtw_get_oldest_wlan_network(&pmlmepriv->scanned_queue);
1173                        if (!pwlan) {
1174                                spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
1175                                goto createbss_cmd_fail;
1176                        }
1177                        pwlan->last_scanned = jiffies;
1178                } else {
1179                        list_add_tail(&pwlan->list,
1180                                      &pmlmepriv->scanned_queue.queue);
1181                }
1182
1183                pnetwork->Length = get_wlan_bssid_ex_sz(pnetwork);
1184                memcpy(&pwlan->network, pnetwork, pnetwork->Length);
1185
1186                memcpy(&tgt_network->network, pnetwork, (get_wlan_bssid_ex_sz(pnetwork)));
1187
1188                _clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING);
1189
1190                spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
1191                /*  we will set _FW_LINKED when there is one more sat to
1192                 *  join us (rtw_stassoc_event_callback)
1193                 */
1194        }
1195
1196createbss_cmd_fail:
1197
1198        spin_unlock_bh(&pmlmepriv->lock);
1199}
1200
1201void rtw_setassocsta_cmdrsp_callback(struct adapter *padapter,  struct cmd_obj *pcmd)
1202{
1203        struct sta_priv *pstapriv = &padapter->stapriv;
1204        struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1205        struct set_assocsta_parm *passocsta_parm = (struct set_assocsta_parm *)(pcmd->parmbuf);
1206        struct set_assocsta_rsp *passocsta_rsp = (struct set_assocsta_rsp *)(pcmd->rsp);
1207        struct sta_info *psta = rtw_get_stainfo(pstapriv, passocsta_parm->addr);
1208
1209        if (!psta)
1210                return;
1211
1212        psta->aid = passocsta_rsp->cam_id;
1213        psta->mac_id = passocsta_rsp->cam_id;
1214
1215        spin_lock_bh(&pmlmepriv->lock);
1216
1217        set_fwstate(pmlmepriv, _FW_LINKED);
1218        spin_unlock_bh(&pmlmepriv->lock);
1219}
1220