linux/drivers/staging/rtl8712/rtl871x_cmd.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/******************************************************************************
   3 * rtl871x_cmd.c
   4 *
   5 * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
   6 * Linux device driver for RTL8192SU
   7 *
   8 * Modifications for inclusion into the Linux staging tree are
   9 * Copyright(c) 2010 Larry Finger. All rights reserved.
  10 *
  11 * Contact information:
  12 * WLAN FAE <wlanfae@realtek.com>
  13 * Larry Finger <Larry.Finger@lwfinger.net>
  14 *
  15 ******************************************************************************/
  16
  17#define _RTL871X_CMD_C_
  18
  19#include <linux/compiler.h>
  20#include <linux/kernel.h>
  21#include <linux/errno.h>
  22#include <linux/slab.h>
  23#include <linux/module.h>
  24#include <linux/kref.h>
  25#include <linux/netdevice.h>
  26#include <linux/skbuff.h>
  27#include <linux/usb.h>
  28#include <linux/usb/ch9.h>
  29#include <linux/circ_buf.h>
  30#include <linux/uaccess.h>
  31#include <asm/byteorder.h>
  32#include <linux/atomic.h>
  33#include <linux/semaphore.h>
  34#include <linux/rtnetlink.h>
  35
  36#include "osdep_service.h"
  37#include "drv_types.h"
  38#include "recv_osdep.h"
  39#include "mlme_osdep.h"
  40
  41/*
  42 * Caller and the r8712_cmd_thread can protect cmd_q by spin_lock.
  43 * No irqsave is necessary.
  44 */
  45
  46int r8712_init_cmd_priv(struct cmd_priv *pcmdpriv)
  47{
  48        init_completion(&pcmdpriv->cmd_queue_comp);
  49        init_completion(&pcmdpriv->terminate_cmdthread_comp);
  50
  51        _init_queue(&(pcmdpriv->cmd_queue));
  52
  53        /* allocate DMA-able/Non-Page memory for cmd_buf and rsp_buf */
  54        pcmdpriv->cmd_seq = 1;
  55        pcmdpriv->cmd_allocated_buf = kmalloc(MAX_CMDSZ + CMDBUFF_ALIGN_SZ,
  56                                              GFP_ATOMIC);
  57        if (!pcmdpriv->cmd_allocated_buf)
  58                return -ENOMEM;
  59        pcmdpriv->cmd_buf = pcmdpriv->cmd_allocated_buf  +  CMDBUFF_ALIGN_SZ -
  60                            ((addr_t)(pcmdpriv->cmd_allocated_buf) &
  61                            (CMDBUFF_ALIGN_SZ - 1));
  62        pcmdpriv->rsp_allocated_buf = kmalloc(MAX_RSPSZ + 4, GFP_ATOMIC);
  63        if (!pcmdpriv->rsp_allocated_buf) {
  64                kfree(pcmdpriv->cmd_allocated_buf);
  65                pcmdpriv->cmd_allocated_buf = NULL;
  66                return -ENOMEM;
  67        }
  68        pcmdpriv->rsp_buf = pcmdpriv->rsp_allocated_buf  +  4 -
  69                            ((addr_t)(pcmdpriv->rsp_allocated_buf) & 3);
  70        pcmdpriv->cmd_issued_cnt = 0;
  71        pcmdpriv->cmd_done_cnt = 0;
  72        pcmdpriv->rsp_cnt = 0;
  73        return 0;
  74}
  75
  76int r8712_init_evt_priv(struct evt_priv *pevtpriv)
  77{
  78        /* allocate DMA-able/Non-Page memory for cmd_buf and rsp_buf */
  79        pevtpriv->event_seq = 0;
  80        pevtpriv->evt_allocated_buf = kmalloc(MAX_EVTSZ + 4, GFP_ATOMIC);
  81
  82        if (!pevtpriv->evt_allocated_buf)
  83                return -ENOMEM;
  84        pevtpriv->evt_buf = pevtpriv->evt_allocated_buf  +  4 -
  85                            ((addr_t)(pevtpriv->evt_allocated_buf) & 3);
  86        pevtpriv->evt_done_cnt = 0;
  87        return 0;
  88}
  89
  90void r8712_free_evt_priv(struct evt_priv *pevtpriv)
  91{
  92        kfree(pevtpriv->evt_allocated_buf);
  93}
  94
  95void r8712_free_cmd_priv(struct cmd_priv *pcmdpriv)
  96{
  97        if (pcmdpriv) {
  98                kfree(pcmdpriv->cmd_allocated_buf);
  99                kfree(pcmdpriv->rsp_allocated_buf);
 100        }
 101}
 102
 103/*
 104 * Calling Context:
 105 *
 106 * r8712_enqueue_cmd can only be called between kernel thread,
 107 * since only spin_lock is used.
 108 *
 109 * ISR/Call-Back functions can't call this sub-function.
 110 *
 111 */
 112
 113void r8712_enqueue_cmd(struct cmd_priv *pcmdpriv, struct cmd_obj *obj)
 114{
 115        struct __queue *queue;
 116        unsigned long irqL;
 117
 118        if (pcmdpriv->padapter->eeprompriv.bautoload_fail_flag)
 119                return;
 120        if (!obj)
 121                return;
 122        queue = &pcmdpriv->cmd_queue;
 123        spin_lock_irqsave(&queue->lock, irqL);
 124        list_add_tail(&obj->list, &queue->queue);
 125        spin_unlock_irqrestore(&queue->lock, irqL);
 126        complete(&pcmdpriv->cmd_queue_comp);
 127}
 128
 129struct cmd_obj *r8712_dequeue_cmd(struct  __queue *queue)
 130{
 131        unsigned long irqL;
 132        struct cmd_obj *obj;
 133
 134        spin_lock_irqsave(&queue->lock, irqL);
 135        obj = list_first_entry_or_null(&queue->queue,
 136                                       struct cmd_obj, list);
 137        if (obj)
 138                list_del_init(&obj->list);
 139        spin_unlock_irqrestore(&queue->lock, irqL);
 140        return obj;
 141}
 142
 143void r8712_enqueue_cmd_ex(struct cmd_priv *pcmdpriv, struct cmd_obj *obj)
 144{
 145        unsigned long irqL;
 146        struct  __queue *queue;
 147
 148        if (!obj)
 149                return;
 150        if (pcmdpriv->padapter->eeprompriv.bautoload_fail_flag)
 151                return;
 152        queue = &pcmdpriv->cmd_queue;
 153        spin_lock_irqsave(&queue->lock, irqL);
 154        list_add_tail(&obj->list, &queue->queue);
 155        spin_unlock_irqrestore(&queue->lock, irqL);
 156        complete(&pcmdpriv->cmd_queue_comp);
 157}
 158
 159void r8712_free_cmd_obj(struct cmd_obj *pcmd)
 160{
 161        if ((pcmd->cmdcode != _JoinBss_CMD_) &&
 162            (pcmd->cmdcode != _CreateBss_CMD_))
 163                kfree(pcmd->parmbuf);
 164        if (pcmd->rsp) {
 165                if (pcmd->rspsz != 0)
 166                        kfree(pcmd->rsp);
 167        }
 168        kfree(pcmd);
 169}
 170
 171u8 r8712_sitesurvey_cmd(struct _adapter *padapter,
 172                        struct ndis_802_11_ssid *pssid)
 173        __must_hold(&padapter->mlmepriv.lock)
 174{
 175        struct cmd_obj  *ph2c;
 176        struct sitesurvey_parm  *psurveyPara;
 177        struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
 178        struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
 179
 180        ph2c = kmalloc(sizeof(*ph2c), GFP_ATOMIC);
 181        if (!ph2c)
 182                return _FAIL;
 183        psurveyPara = kmalloc(sizeof(*psurveyPara), GFP_ATOMIC);
 184        if (!psurveyPara) {
 185                kfree(ph2c);
 186                return _FAIL;
 187        }
 188        init_h2fwcmd_w_parm_no_rsp(ph2c, psurveyPara,
 189                                   GEN_CMD_CODE(_SiteSurvey));
 190        psurveyPara->bsslimit = cpu_to_le32(48);
 191        psurveyPara->passive_mode = cpu_to_le32(pmlmepriv->passive_mode);
 192        psurveyPara->ss_ssidlen = 0;
 193        memset(psurveyPara->ss_ssid, 0, IW_ESSID_MAX_SIZE + 1);
 194        if (pssid && pssid->SsidLength) {
 195                int len = min_t(int, pssid->SsidLength, IW_ESSID_MAX_SIZE);
 196
 197                memcpy(psurveyPara->ss_ssid, pssid->Ssid, len);
 198                psurveyPara->ss_ssidlen = cpu_to_le32(len);
 199        }
 200        set_fwstate(pmlmepriv, _FW_UNDER_SURVEY);
 201        r8712_enqueue_cmd(pcmdpriv, ph2c);
 202        mod_timer(&pmlmepriv->scan_to_timer,
 203                  jiffies + msecs_to_jiffies(SCANNING_TIMEOUT));
 204        padapter->ledpriv.LedControlHandler(padapter, LED_CTL_SITE_SURVEY);
 205        padapter->blnEnableRxFF0Filter = 0;
 206        return _SUCCESS;
 207}
 208
 209int r8712_setdatarate_cmd(struct _adapter *padapter, u8 *rateset)
 210{
 211        struct cmd_obj          *ph2c;
 212        struct setdatarate_parm *pbsetdataratepara;
 213        struct cmd_priv         *pcmdpriv = &padapter->cmdpriv;
 214
 215        ph2c = kmalloc(sizeof(*ph2c), GFP_ATOMIC);
 216        if (!ph2c)
 217                return -ENOMEM;
 218        pbsetdataratepara = kmalloc(sizeof(*pbsetdataratepara), GFP_ATOMIC);
 219        if (!pbsetdataratepara) {
 220                kfree(ph2c);
 221                return -ENOMEM;
 222        }
 223        init_h2fwcmd_w_parm_no_rsp(ph2c, pbsetdataratepara,
 224                                   GEN_CMD_CODE(_SetDataRate));
 225        pbsetdataratepara->mac_id = 5;
 226        memcpy(pbsetdataratepara->datarates, rateset, NumRates);
 227        r8712_enqueue_cmd(pcmdpriv, ph2c);
 228        return 0;
 229}
 230
 231void r8712_set_chplan_cmd(struct _adapter *padapter, int chplan)
 232{
 233        struct cmd_obj *ph2c;
 234        struct SetChannelPlan_param *psetchplanpara;
 235        struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
 236
 237        ph2c = kmalloc(sizeof(*ph2c), GFP_ATOMIC);
 238        if (!ph2c)
 239                return;
 240        psetchplanpara = kmalloc(sizeof(*psetchplanpara), GFP_ATOMIC);
 241        if (!psetchplanpara) {
 242                kfree(ph2c);
 243                return;
 244        }
 245        init_h2fwcmd_w_parm_no_rsp(ph2c, psetchplanpara,
 246                                GEN_CMD_CODE(_SetChannelPlan));
 247        psetchplanpara->ChannelPlan = chplan;
 248        r8712_enqueue_cmd(pcmdpriv, ph2c);
 249}
 250
 251int r8712_setrfreg_cmd(struct _adapter  *padapter, u8 offset, u32 val)
 252{
 253        struct cmd_obj *ph2c;
 254        struct writeRF_parm *pwriterfparm;
 255        struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
 256
 257        ph2c = kmalloc(sizeof(*ph2c), GFP_ATOMIC);
 258        if (!ph2c)
 259                return -ENOMEM;
 260        pwriterfparm = kmalloc(sizeof(*pwriterfparm), GFP_ATOMIC);
 261        if (!pwriterfparm) {
 262                kfree(ph2c);
 263                return -ENOMEM;
 264        }
 265        init_h2fwcmd_w_parm_no_rsp(ph2c, pwriterfparm, GEN_CMD_CODE(_SetRFReg));
 266        pwriterfparm->offset = offset;
 267        pwriterfparm->value = val;
 268        r8712_enqueue_cmd(pcmdpriv, ph2c);
 269        return 0;
 270}
 271
 272int r8712_getrfreg_cmd(struct _adapter *padapter, u8 offset, u8 *pval)
 273{
 274        struct cmd_obj *ph2c;
 275        struct readRF_parm *prdrfparm;
 276        struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
 277
 278        ph2c = kmalloc(sizeof(*ph2c), GFP_ATOMIC);
 279        if (!ph2c)
 280                return -ENOMEM;
 281        prdrfparm = kmalloc(sizeof(*prdrfparm), GFP_ATOMIC);
 282        if (!prdrfparm) {
 283                kfree(ph2c);
 284                return -ENOMEM;
 285        }
 286        INIT_LIST_HEAD(&ph2c->list);
 287        ph2c->cmdcode = GEN_CMD_CODE(_GetRFReg);
 288        ph2c->parmbuf = (unsigned char *)prdrfparm;
 289        ph2c->cmdsz =  sizeof(struct readRF_parm);
 290        ph2c->rsp = pval;
 291        ph2c->rspsz = sizeof(struct readRF_rsp);
 292        prdrfparm->offset = offset;
 293        r8712_enqueue_cmd(pcmdpriv, ph2c);
 294        return 0;
 295}
 296
 297void r8712_getbbrfreg_cmdrsp_callback(struct _adapter *padapter,
 298                                      struct cmd_obj *pcmd)
 299{
 300        kfree(pcmd->parmbuf);
 301        kfree(pcmd);
 302        padapter->mppriv.workparam.bcompleted = true;
 303}
 304
 305void r8712_readtssi_cmdrsp_callback(struct _adapter *padapter,
 306                                struct cmd_obj *pcmd)
 307{
 308        kfree(pcmd->parmbuf);
 309        kfree(pcmd);
 310
 311        padapter->mppriv.workparam.bcompleted = true;
 312}
 313
 314int r8712_createbss_cmd(struct _adapter *padapter)
 315{
 316        struct cmd_obj *pcmd;
 317        struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
 318        struct wlan_bssid_ex *pdev_network =
 319                                 &padapter->registrypriv.dev_network;
 320
 321        padapter->ledpriv.LedControlHandler(padapter, LED_CTL_START_TO_LINK);
 322        pcmd = kmalloc(sizeof(*pcmd), GFP_ATOMIC);
 323        if (!pcmd)
 324                return -ENOMEM;
 325        INIT_LIST_HEAD(&pcmd->list);
 326        pcmd->cmdcode = _CreateBss_CMD_;
 327        pcmd->parmbuf = (unsigned char *)pdev_network;
 328        pcmd->cmdsz = r8712_get_wlan_bssid_ex_sz(pdev_network);
 329        pcmd->rsp = NULL;
 330        pcmd->rspsz = 0;
 331        /* notes: translate IELength & Length after assign to cmdsz; */
 332        pdev_network->Length = pcmd->cmdsz;
 333        pdev_network->IELength = pdev_network->IELength;
 334        pdev_network->Ssid.SsidLength = pdev_network->Ssid.SsidLength;
 335        r8712_enqueue_cmd(pcmdpriv, pcmd);
 336        return 0;
 337}
 338
 339int r8712_joinbss_cmd(struct _adapter  *padapter, struct wlan_network *pnetwork)
 340{
 341        struct wlan_bssid_ex *psecnetwork;
 342        struct cmd_obj          *pcmd;
 343        struct cmd_priv         *pcmdpriv = &padapter->cmdpriv;
 344        struct mlme_priv        *pmlmepriv = &padapter->mlmepriv;
 345        struct qos_priv         *pqospriv = &pmlmepriv->qospriv;
 346        struct security_priv    *psecuritypriv = &padapter->securitypriv;
 347        struct registry_priv    *pregistrypriv = &padapter->registrypriv;
 348        enum NDIS_802_11_NETWORK_INFRASTRUCTURE ndis_network_mode =
 349                pnetwork->network.InfrastructureMode;
 350
 351        padapter->ledpriv.LedControlHandler(padapter, LED_CTL_START_TO_LINK);
 352        pcmd = kmalloc(sizeof(*pcmd), GFP_ATOMIC);
 353        if (!pcmd)
 354                return -ENOMEM;
 355
 356        /* for hidden ap to set fw_state here */
 357        if (check_fwstate(pmlmepriv, WIFI_STATION_STATE | WIFI_ADHOC_STATE) !=
 358            true) {
 359                switch (ndis_network_mode) {
 360                case Ndis802_11IBSS:
 361                        pmlmepriv->fw_state |= WIFI_ADHOC_STATE;
 362                        break;
 363                case Ndis802_11Infrastructure:
 364                        pmlmepriv->fw_state |= WIFI_STATION_STATE;
 365                        break;
 366                case Ndis802_11APMode:
 367                case Ndis802_11AutoUnknown:
 368                case Ndis802_11InfrastructureMax:
 369                        break;
 370                }
 371        }
 372        psecnetwork = &psecuritypriv->sec_bss;
 373        memcpy(psecnetwork, &pnetwork->network, sizeof(*psecnetwork));
 374        psecuritypriv->authenticator_ie[0] = (unsigned char)
 375                                             psecnetwork->IELength;
 376        if ((psecnetwork->IELength - 12) < (256 - 1))
 377                memcpy(&psecuritypriv->authenticator_ie[1],
 378                        &psecnetwork->IEs[12], psecnetwork->IELength - 12);
 379        else
 380                memcpy(&psecuritypriv->authenticator_ie[1],
 381                        &psecnetwork->IEs[12], (256 - 1));
 382        psecnetwork->IELength = 0;
 383        /*
 384         * If the driver wants to use the bssid to create the connection.
 385         * If not, we copy the connecting AP's MAC address to it so that
 386         * the driver just has the bssid information for PMKIDList searching.
 387         */
 388        if (!pmlmepriv->assoc_by_bssid)
 389                ether_addr_copy(&pmlmepriv->assoc_bssid[0],
 390                                &pnetwork->network.MacAddress[0]);
 391        psecnetwork->IELength = r8712_restruct_sec_ie(padapter,
 392                                                &pnetwork->network.IEs[0],
 393                                                &psecnetwork->IEs[0],
 394                                                pnetwork->network.IELength);
 395        pqospriv->qos_option = 0;
 396        if (pregistrypriv->wmm_enable) {
 397                u32 tmp_len;
 398
 399                tmp_len = r8712_restruct_wmm_ie(padapter,
 400                                          &pnetwork->network.IEs[0],
 401                                          &psecnetwork->IEs[0],
 402                                          pnetwork->network.IELength,
 403                                          psecnetwork->IELength);
 404                if (psecnetwork->IELength != tmp_len) {
 405                        psecnetwork->IELength = tmp_len;
 406                        pqospriv->qos_option = 1; /* WMM IE in beacon */
 407                } else {
 408                        pqospriv->qos_option = 0; /* no WMM IE in beacon */
 409                }
 410        }
 411        if (pregistrypriv->ht_enable) {
 412                /*
 413                 * For WEP mode, we will use the bg mode to do the connection
 414                 * to avoid some IOT issues, especially for Realtek 8192u
 415                 * SoftAP.
 416                 */
 417                if ((padapter->securitypriv.PrivacyAlgrthm != _WEP40_) &&
 418                    (padapter->securitypriv.PrivacyAlgrthm != _WEP104_)) {
 419                        /* restructure_ht_ie */
 420                        r8712_restructure_ht_ie(padapter,
 421                                                &pnetwork->network.IEs[0],
 422                                                &psecnetwork->IEs[0],
 423                                                pnetwork->network.IELength,
 424                                                &psecnetwork->IELength);
 425                }
 426        }
 427        psecuritypriv->supplicant_ie[0] = (u8)psecnetwork->IELength;
 428        if (psecnetwork->IELength < 255)
 429                memcpy(&psecuritypriv->supplicant_ie[1], &psecnetwork->IEs[0],
 430                        psecnetwork->IELength);
 431        else
 432                memcpy(&psecuritypriv->supplicant_ie[1], &psecnetwork->IEs[0],
 433                        255);
 434        /* get cmdsz before endian conversion */
 435        pcmd->cmdsz = r8712_get_wlan_bssid_ex_sz(psecnetwork);
 436#ifdef __BIG_ENDIAN
 437        /* wlan_network endian conversion */
 438        psecnetwork->Length = cpu_to_le32(psecnetwork->Length);
 439        psecnetwork->Ssid.SsidLength = cpu_to_le32(
 440                                       psecnetwork->Ssid.SsidLength);
 441        psecnetwork->Privacy = cpu_to_le32(psecnetwork->Privacy);
 442        psecnetwork->Rssi = cpu_to_le32(psecnetwork->Rssi);
 443        psecnetwork->NetworkTypeInUse = cpu_to_le32(
 444                                        psecnetwork->NetworkTypeInUse);
 445        psecnetwork->Configuration.ATIMWindow = cpu_to_le32(
 446                                psecnetwork->Configuration.ATIMWindow);
 447        psecnetwork->Configuration.BeaconPeriod = cpu_to_le32(
 448                                 psecnetwork->Configuration.BeaconPeriod);
 449        psecnetwork->Configuration.DSConfig = cpu_to_le32(
 450                                psecnetwork->Configuration.DSConfig);
 451        psecnetwork->Configuration.FHConfig.DwellTime = cpu_to_le32(
 452                                psecnetwork->Configuration.FHConfig.DwellTime);
 453        psecnetwork->Configuration.FHConfig.HopPattern = cpu_to_le32(
 454                                psecnetwork->Configuration.FHConfig.HopPattern);
 455        psecnetwork->Configuration.FHConfig.HopSet = cpu_to_le32(
 456                                psecnetwork->Configuration.FHConfig.HopSet);
 457        psecnetwork->Configuration.FHConfig.Length = cpu_to_le32(
 458                                psecnetwork->Configuration.FHConfig.Length);
 459        psecnetwork->Configuration.Length = cpu_to_le32(
 460                                psecnetwork->Configuration.Length);
 461        psecnetwork->InfrastructureMode = cpu_to_le32(
 462                                psecnetwork->InfrastructureMode);
 463        psecnetwork->IELength = cpu_to_le32(psecnetwork->IELength);
 464#endif
 465        INIT_LIST_HEAD(&pcmd->list);
 466        pcmd->cmdcode = _JoinBss_CMD_;
 467        pcmd->parmbuf = (unsigned char *)psecnetwork;
 468        pcmd->rsp = NULL;
 469        pcmd->rspsz = 0;
 470        r8712_enqueue_cmd(pcmdpriv, pcmd);
 471        return 0;
 472}
 473
 474void r8712_disassoc_cmd(struct _adapter *padapter) /* for sta_mode */
 475{
 476        struct cmd_obj *pdisconnect_cmd;
 477        struct disconnect_parm *pdisconnect;
 478        struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
 479
 480        pdisconnect_cmd = kmalloc(sizeof(*pdisconnect_cmd), GFP_ATOMIC);
 481        if (!pdisconnect_cmd)
 482                return;
 483        pdisconnect = kmalloc(sizeof(*pdisconnect), GFP_ATOMIC);
 484        if (!pdisconnect) {
 485                kfree(pdisconnect_cmd);
 486                return;
 487        }
 488        init_h2fwcmd_w_parm_no_rsp(pdisconnect_cmd, pdisconnect,
 489                                   _DisConnect_CMD_);
 490        r8712_enqueue_cmd(pcmdpriv, pdisconnect_cmd);
 491}
 492
 493void r8712_setopmode_cmd(struct _adapter *padapter,
 494                 enum NDIS_802_11_NETWORK_INFRASTRUCTURE networktype)
 495{
 496        struct cmd_obj *ph2c;
 497        struct setopmode_parm *psetop;
 498
 499        struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
 500
 501        ph2c = kmalloc(sizeof(*ph2c), GFP_ATOMIC);
 502        if (!ph2c)
 503                return;
 504        psetop = kmalloc(sizeof(*psetop), GFP_ATOMIC);
 505        if (!psetop) {
 506                kfree(ph2c);
 507                return;
 508        }
 509        init_h2fwcmd_w_parm_no_rsp(ph2c, psetop, _SetOpMode_CMD_);
 510        psetop->mode = (u8)networktype;
 511        r8712_enqueue_cmd(pcmdpriv, ph2c);
 512}
 513
 514void r8712_setstakey_cmd(struct _adapter *padapter, u8 *psta, u8 unicast_key)
 515{
 516        struct cmd_obj *ph2c;
 517        struct set_stakey_parm *psetstakey_para;
 518        struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
 519        struct set_stakey_rsp *psetstakey_rsp = NULL;
 520        struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
 521        struct security_priv *psecuritypriv = &padapter->securitypriv;
 522        struct sta_info *sta = (struct sta_info *)psta;
 523
 524        ph2c = kmalloc(sizeof(*ph2c), GFP_ATOMIC);
 525        if (!ph2c)
 526                return;
 527        psetstakey_para = kmalloc(sizeof(*psetstakey_para), GFP_ATOMIC);
 528        if (!psetstakey_para) {
 529                kfree(ph2c);
 530                return;
 531        }
 532        psetstakey_rsp = kmalloc(sizeof(*psetstakey_rsp), GFP_ATOMIC);
 533        if (!psetstakey_rsp) {
 534                kfree(ph2c);
 535                kfree(psetstakey_para);
 536                return;
 537        }
 538        init_h2fwcmd_w_parm_no_rsp(ph2c, psetstakey_para, _SetStaKey_CMD_);
 539        ph2c->rsp = (u8 *) psetstakey_rsp;
 540        ph2c->rspsz = sizeof(struct set_stakey_rsp);
 541        ether_addr_copy(psetstakey_para->addr, sta->hwaddr);
 542        if (check_fwstate(pmlmepriv, WIFI_STATION_STATE))
 543                psetstakey_para->algorithm = (unsigned char)
 544                                            psecuritypriv->PrivacyAlgrthm;
 545        else
 546                GET_ENCRY_ALGO(psecuritypriv, sta,
 547                               psetstakey_para->algorithm, false);
 548        if (unicast_key)
 549                memcpy(&psetstakey_para->key, &sta->x_UncstKey, 16);
 550        else
 551                memcpy(&psetstakey_para->key,
 552                        &psecuritypriv->XGrpKey[
 553                        psecuritypriv->XGrpKeyid - 1]. skey, 16);
 554        r8712_enqueue_cmd(pcmdpriv, ph2c);
 555}
 556
 557void r8712_setMacAddr_cmd(struct _adapter *padapter, u8 *mac_addr)
 558{
 559        struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
 560        struct cmd_obj *ph2c;
 561        struct SetMacAddr_param *psetMacAddr_para;
 562
 563        ph2c = kmalloc(sizeof(*ph2c), GFP_ATOMIC);
 564        if (!ph2c)
 565                return;
 566        psetMacAddr_para = kmalloc(sizeof(*psetMacAddr_para), GFP_ATOMIC);
 567        if (!psetMacAddr_para) {
 568                kfree(ph2c);
 569                return;
 570        }
 571        init_h2fwcmd_w_parm_no_rsp(ph2c, psetMacAddr_para,
 572                                   _SetMacAddress_CMD_);
 573        ether_addr_copy(psetMacAddr_para->MacAddr, mac_addr);
 574        r8712_enqueue_cmd(pcmdpriv, ph2c);
 575}
 576
 577void r8712_addbareq_cmd(struct _adapter *padapter, u8 tid)
 578{
 579        struct cmd_priv         *pcmdpriv = &padapter->cmdpriv;
 580        struct cmd_obj          *ph2c;
 581        struct addBaReq_parm    *paddbareq_parm;
 582
 583        ph2c = kmalloc(sizeof(*ph2c), GFP_ATOMIC);
 584        if (!ph2c)
 585                return;
 586        paddbareq_parm = kmalloc(sizeof(*paddbareq_parm), GFP_ATOMIC);
 587        if (!paddbareq_parm) {
 588                kfree(ph2c);
 589                return;
 590        }
 591        paddbareq_parm->tid = tid;
 592        init_h2fwcmd_w_parm_no_rsp(ph2c, paddbareq_parm,
 593                                   GEN_CMD_CODE(_AddBAReq));
 594        r8712_enqueue_cmd_ex(pcmdpriv, ph2c);
 595}
 596
 597void r8712_wdg_wk_cmd(struct _adapter *padapter)
 598{
 599        struct cmd_obj *ph2c;
 600        struct drvint_cmd_parm  *pdrvintcmd_param;
 601        struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
 602
 603        ph2c = kmalloc(sizeof(*ph2c), GFP_ATOMIC);
 604        if (!ph2c)
 605                return;
 606        pdrvintcmd_param = kmalloc(sizeof(*pdrvintcmd_param), GFP_ATOMIC);
 607        if (!pdrvintcmd_param) {
 608                kfree(ph2c);
 609                return;
 610        }
 611        pdrvintcmd_param->i_cid = WDG_WK_CID;
 612        pdrvintcmd_param->sz = 0;
 613        pdrvintcmd_param->pbuf = NULL;
 614        init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvintcmd_param, _DRV_INT_CMD_);
 615        r8712_enqueue_cmd_ex(pcmdpriv, ph2c);
 616}
 617
 618void r8712_survey_cmd_callback(struct _adapter *padapter, struct cmd_obj *pcmd)
 619{
 620        struct  mlme_priv *pmlmepriv = &padapter->mlmepriv;
 621
 622        if (pcmd->res != H2C_SUCCESS)
 623                clr_fwstate(pmlmepriv, _FW_UNDER_SURVEY);
 624        r8712_free_cmd_obj(pcmd);
 625}
 626
 627void r8712_disassoc_cmd_callback(struct _adapter *padapter,
 628                                 struct cmd_obj *pcmd)
 629{
 630        unsigned long irqL;
 631        struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
 632
 633        if (pcmd->res != H2C_SUCCESS) {
 634                spin_lock_irqsave(&pmlmepriv->lock, irqL);
 635                set_fwstate(pmlmepriv, _FW_LINKED);
 636                spin_unlock_irqrestore(&pmlmepriv->lock, irqL);
 637                return;
 638        }
 639        r8712_free_cmd_obj(pcmd);
 640}
 641
 642void r8712_joinbss_cmd_callback(struct _adapter *padapter, struct cmd_obj *pcmd)
 643{
 644        struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
 645
 646        if (pcmd->res != H2C_SUCCESS)
 647                mod_timer(&pmlmepriv->assoc_timer,
 648                          jiffies + msecs_to_jiffies(1));
 649        r8712_free_cmd_obj(pcmd);
 650}
 651
 652void r8712_createbss_cmd_callback(struct _adapter *padapter,
 653                                  struct cmd_obj *pcmd)
 654{
 655        unsigned long irqL;
 656        struct sta_info *psta = NULL;
 657        struct wlan_network *pwlan = NULL;
 658        struct  mlme_priv *pmlmepriv = &padapter->mlmepriv;
 659        struct wlan_bssid_ex *pnetwork = (struct wlan_bssid_ex *)pcmd->parmbuf;
 660        struct wlan_network *tgt_network = &(pmlmepriv->cur_network);
 661
 662        if (pcmd->res != H2C_SUCCESS)
 663                mod_timer(&pmlmepriv->assoc_timer,
 664                          jiffies + msecs_to_jiffies(1));
 665        del_timer(&pmlmepriv->assoc_timer);
 666#ifdef __BIG_ENDIAN
 667        /* endian_convert */
 668        pnetwork->Length = le32_to_cpu(pnetwork->Length);
 669        pnetwork->Ssid.SsidLength = le32_to_cpu(pnetwork->Ssid.SsidLength);
 670        pnetwork->Privacy = le32_to_cpu(pnetwork->Privacy);
 671        pnetwork->Rssi = le32_to_cpu(pnetwork->Rssi);
 672        pnetwork->NetworkTypeInUse = le32_to_cpu(pnetwork->NetworkTypeInUse);
 673        pnetwork->Configuration.ATIMWindow =
 674                le32_to_cpu(pnetwork->Configuration.ATIMWindow);
 675        pnetwork->Configuration.DSConfig =
 676                le32_to_cpu(pnetwork->Configuration.DSConfig);
 677        pnetwork->Configuration.FHConfig.DwellTime =
 678                le32_to_cpu(pnetwork->Configuration.FHConfig.DwellTime);
 679        pnetwork->Configuration.FHConfig.HopPattern =
 680                le32_to_cpu(pnetwork->Configuration.FHConfig.HopPattern);
 681        pnetwork->Configuration.FHConfig.HopSet =
 682                le32_to_cpu(pnetwork->Configuration.FHConfig.HopSet);
 683        pnetwork->Configuration.FHConfig.Length =
 684                le32_to_cpu(pnetwork->Configuration.FHConfig.Length);
 685        pnetwork->Configuration.Length =
 686                le32_to_cpu(pnetwork->Configuration.Length);
 687        pnetwork->InfrastructureMode =
 688                le32_to_cpu(pnetwork->InfrastructureMode);
 689        pnetwork->IELength = le32_to_cpu(pnetwork->IELength);
 690#endif
 691        spin_lock_irqsave(&pmlmepriv->lock, irqL);
 692        if ((pmlmepriv->fw_state) & WIFI_AP_STATE) {
 693                psta = r8712_get_stainfo(&padapter->stapriv,
 694                                         pnetwork->MacAddress);
 695                if (!psta) {
 696                        psta = r8712_alloc_stainfo(&padapter->stapriv,
 697                                                   pnetwork->MacAddress);
 698                        if (!psta)
 699                                goto createbss_cmd_fail;
 700                }
 701                r8712_indicate_connect(padapter);
 702        } else {
 703                pwlan = _r8712_alloc_network(pmlmepriv);
 704                if (!pwlan) {
 705                        pwlan = r8712_get_oldest_wlan_network(
 706                                &pmlmepriv->scanned_queue);
 707                        if (!pwlan)
 708                                goto createbss_cmd_fail;
 709                        pwlan->last_scanned = jiffies;
 710                } else {
 711                        list_add_tail(&(pwlan->list),
 712                                         &pmlmepriv->scanned_queue.queue);
 713                }
 714                pnetwork->Length = r8712_get_wlan_bssid_ex_sz(pnetwork);
 715                memcpy(&(pwlan->network), pnetwork, pnetwork->Length);
 716                pwlan->fixed = true;
 717                memcpy(&tgt_network->network, pnetwork,
 718                        (r8712_get_wlan_bssid_ex_sz(pnetwork)));
 719                if (pmlmepriv->fw_state & _FW_UNDER_LINKING)
 720                        pmlmepriv->fw_state ^= _FW_UNDER_LINKING;
 721                /*
 722                 * we will set _FW_LINKED when there is one more sat to
 723                 * join us (stassoc_event_callback)
 724                 */
 725        }
 726createbss_cmd_fail:
 727        spin_unlock_irqrestore(&pmlmepriv->lock, irqL);
 728        r8712_free_cmd_obj(pcmd);
 729}
 730
 731void r8712_setstaKey_cmdrsp_callback(struct _adapter *padapter,
 732                                     struct cmd_obj *pcmd)
 733{
 734        struct sta_priv *pstapriv = &padapter->stapriv;
 735        struct set_stakey_rsp *psetstakey_rsp = (struct set_stakey_rsp *)
 736                                                (pcmd->rsp);
 737        struct sta_info *psta = r8712_get_stainfo(pstapriv,
 738                                                  psetstakey_rsp->addr);
 739
 740        if (!psta)
 741                goto exit;
 742        psta->aid = psta->mac_id = psetstakey_rsp->keyid; /*CAM_ID(CAM_ENTRY)*/
 743exit:
 744        r8712_free_cmd_obj(pcmd);
 745}
 746
 747void r8712_setassocsta_cmdrsp_callback(struct _adapter *padapter,
 748                                       struct cmd_obj *pcmd)
 749{
 750        unsigned long   irqL;
 751        struct sta_priv *pstapriv = &padapter->stapriv;
 752        struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
 753        struct set_assocsta_parm *passocsta_parm =
 754                                (struct set_assocsta_parm *)(pcmd->parmbuf);
 755        struct set_assocsta_rsp *passocsta_rsp =
 756                                (struct set_assocsta_rsp *) (pcmd->rsp);
 757        struct sta_info *psta = r8712_get_stainfo(pstapriv,
 758                                                  passocsta_parm->addr);
 759
 760        if (!psta)
 761                return;
 762        psta->aid = psta->mac_id = passocsta_rsp->cam_id;
 763        spin_lock_irqsave(&pmlmepriv->lock, irqL);
 764        if ((check_fwstate(pmlmepriv, WIFI_MP_STATE)) &&
 765            (check_fwstate(pmlmepriv, _FW_UNDER_LINKING)))
 766                pmlmepriv->fw_state ^= _FW_UNDER_LINKING;
 767        set_fwstate(pmlmepriv, _FW_LINKED);
 768        spin_unlock_irqrestore(&pmlmepriv->lock, irqL);
 769        r8712_free_cmd_obj(pcmd);
 770}
 771
 772void r8712_disconnectCtrlEx_cmd(struct _adapter *adapter, u32 enableDrvCtrl,
 773                        u32 tryPktCnt, u32 tryPktInterval, u32 firstStageTO)
 774{
 775        struct cmd_obj *ph2c;
 776        struct DisconnectCtrlEx_param *param;
 777        struct cmd_priv *pcmdpriv = &adapter->cmdpriv;
 778
 779        ph2c = kmalloc(sizeof(*ph2c), GFP_ATOMIC);
 780        if (!ph2c)
 781                return;
 782        param = kzalloc(sizeof(*param), GFP_ATOMIC);
 783        if (!param) {
 784                kfree(ph2c);
 785                return;
 786        }
 787
 788        param->EnableDrvCtrl = (unsigned char)enableDrvCtrl;
 789        param->TryPktCnt = (unsigned char)tryPktCnt;
 790        param->TryPktInterval = (unsigned char)tryPktInterval;
 791        param->FirstStageTO = (unsigned int)firstStageTO;
 792
 793        init_h2fwcmd_w_parm_no_rsp(ph2c, param,
 794                                GEN_CMD_CODE(_DisconnectCtrlEx));
 795        r8712_enqueue_cmd(pcmdpriv, ph2c);
 796}
 797