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