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                memcpy(psurveyPara->ss_ssid, pssid->Ssid, pssid->SsidLength);
 196                psurveyPara->ss_ssidlen = cpu_to_le32(pssid->SsidLength);
 197        }
 198        set_fwstate(pmlmepriv, _FW_UNDER_SURVEY);
 199        r8712_enqueue_cmd(pcmdpriv, ph2c);
 200        mod_timer(&pmlmepriv->scan_to_timer,
 201                  jiffies + msecs_to_jiffies(SCANNING_TIMEOUT));
 202        padapter->ledpriv.LedControlHandler(padapter, LED_CTL_SITE_SURVEY);
 203        padapter->blnEnableRxFF0Filter = 0;
 204        return _SUCCESS;
 205}
 206
 207int r8712_setdatarate_cmd(struct _adapter *padapter, u8 *rateset)
 208{
 209        struct cmd_obj          *ph2c;
 210        struct setdatarate_parm *pbsetdataratepara;
 211        struct cmd_priv         *pcmdpriv = &padapter->cmdpriv;
 212
 213        ph2c = kmalloc(sizeof(*ph2c), GFP_ATOMIC);
 214        if (!ph2c)
 215                return -ENOMEM;
 216        pbsetdataratepara = kmalloc(sizeof(*pbsetdataratepara), GFP_ATOMIC);
 217        if (!pbsetdataratepara) {
 218                kfree(ph2c);
 219                return -ENOMEM;
 220        }
 221        init_h2fwcmd_w_parm_no_rsp(ph2c, pbsetdataratepara,
 222                                   GEN_CMD_CODE(_SetDataRate));
 223        pbsetdataratepara->mac_id = 5;
 224        memcpy(pbsetdataratepara->datarates, rateset, NumRates);
 225        r8712_enqueue_cmd(pcmdpriv, ph2c);
 226        return 0;
 227}
 228
 229void r8712_set_chplan_cmd(struct _adapter *padapter, int chplan)
 230{
 231        struct cmd_obj *ph2c;
 232        struct SetChannelPlan_param *psetchplanpara;
 233        struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
 234
 235        ph2c = kmalloc(sizeof(*ph2c), GFP_ATOMIC);
 236        if (!ph2c)
 237                return;
 238        psetchplanpara = kmalloc(sizeof(*psetchplanpara), GFP_ATOMIC);
 239        if (!psetchplanpara) {
 240                kfree(ph2c);
 241                return;
 242        }
 243        init_h2fwcmd_w_parm_no_rsp(ph2c, psetchplanpara,
 244                                GEN_CMD_CODE(_SetChannelPlan));
 245        psetchplanpara->ChannelPlan = chplan;
 246        r8712_enqueue_cmd(pcmdpriv, ph2c);
 247}
 248
 249int r8712_setrfreg_cmd(struct _adapter  *padapter, u8 offset, u32 val)
 250{
 251        struct cmd_obj *ph2c;
 252        struct writeRF_parm *pwriterfparm;
 253        struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
 254
 255        ph2c = kmalloc(sizeof(*ph2c), GFP_ATOMIC);
 256        if (!ph2c)
 257                return -ENOMEM;
 258        pwriterfparm = kmalloc(sizeof(*pwriterfparm), GFP_ATOMIC);
 259        if (!pwriterfparm) {
 260                kfree(ph2c);
 261                return -ENOMEM;
 262        }
 263        init_h2fwcmd_w_parm_no_rsp(ph2c, pwriterfparm, GEN_CMD_CODE(_SetRFReg));
 264        pwriterfparm->offset = offset;
 265        pwriterfparm->value = val;
 266        r8712_enqueue_cmd(pcmdpriv, ph2c);
 267        return 0;
 268}
 269
 270int r8712_getrfreg_cmd(struct _adapter *padapter, u8 offset, u8 *pval)
 271{
 272        struct cmd_obj *ph2c;
 273        struct readRF_parm *prdrfparm;
 274        struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
 275
 276        ph2c = kmalloc(sizeof(*ph2c), GFP_ATOMIC);
 277        if (!ph2c)
 278                return -ENOMEM;
 279        prdrfparm = kmalloc(sizeof(*prdrfparm), GFP_ATOMIC);
 280        if (!prdrfparm) {
 281                kfree(ph2c);
 282                return -ENOMEM;
 283        }
 284        INIT_LIST_HEAD(&ph2c->list);
 285        ph2c->cmdcode = GEN_CMD_CODE(_GetRFReg);
 286        ph2c->parmbuf = (unsigned char *)prdrfparm;
 287        ph2c->cmdsz =  sizeof(struct readRF_parm);
 288        ph2c->rsp = pval;
 289        ph2c->rspsz = sizeof(struct readRF_rsp);
 290        prdrfparm->offset = offset;
 291        r8712_enqueue_cmd(pcmdpriv, ph2c);
 292        return 0;
 293}
 294
 295void r8712_getbbrfreg_cmdrsp_callback(struct _adapter *padapter,
 296                                      struct cmd_obj *pcmd)
 297{
 298        kfree(pcmd->parmbuf);
 299        kfree(pcmd);
 300        padapter->mppriv.workparam.bcompleted = true;
 301}
 302
 303void r8712_readtssi_cmdrsp_callback(struct _adapter *padapter,
 304                                struct cmd_obj *pcmd)
 305{
 306        kfree(pcmd->parmbuf);
 307        kfree(pcmd);
 308
 309        padapter->mppriv.workparam.bcompleted = true;
 310}
 311
 312int r8712_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 =
 317                                 &padapter->registrypriv.dev_network;
 318
 319        padapter->ledpriv.LedControlHandler(padapter, LED_CTL_START_TO_LINK);
 320        pcmd = kmalloc(sizeof(*pcmd), GFP_ATOMIC);
 321        if (!pcmd)
 322                return -ENOMEM;
 323        INIT_LIST_HEAD(&pcmd->list);
 324        pcmd->cmdcode = _CreateBss_CMD_;
 325        pcmd->parmbuf = (unsigned char *)pdev_network;
 326        pcmd->cmdsz = r8712_get_wlan_bssid_ex_sz(pdev_network);
 327        pcmd->rsp = NULL;
 328        pcmd->rspsz = 0;
 329        /* notes: translate IELength & Length after assign to cmdsz; */
 330        pdev_network->Length = pcmd->cmdsz;
 331        pdev_network->IELength = pdev_network->IELength;
 332        pdev_network->Ssid.SsidLength = pdev_network->Ssid.SsidLength;
 333        r8712_enqueue_cmd(pcmdpriv, pcmd);
 334        return 0;
 335}
 336
 337int r8712_joinbss_cmd(struct _adapter  *padapter, struct wlan_network *pnetwork)
 338{
 339        struct wlan_bssid_ex *psecnetwork;
 340        struct cmd_obj          *pcmd;
 341        struct cmd_priv         *pcmdpriv = &padapter->cmdpriv;
 342        struct mlme_priv        *pmlmepriv = &padapter->mlmepriv;
 343        struct qos_priv         *pqospriv = &pmlmepriv->qospriv;
 344        struct security_priv    *psecuritypriv = &padapter->securitypriv;
 345        struct registry_priv    *pregistrypriv = &padapter->registrypriv;
 346        enum NDIS_802_11_NETWORK_INFRASTRUCTURE ndis_network_mode =
 347                pnetwork->network.InfrastructureMode;
 348
 349        padapter->ledpriv.LedControlHandler(padapter, LED_CTL_START_TO_LINK);
 350        pcmd = kmalloc(sizeof(*pcmd), GFP_ATOMIC);
 351        if (!pcmd)
 352                return -ENOMEM;
 353
 354        /* for hidden ap to set fw_state here */
 355        if (check_fwstate(pmlmepriv, WIFI_STATION_STATE | WIFI_ADHOC_STATE) !=
 356            true) {
 357                switch (ndis_network_mode) {
 358                case Ndis802_11IBSS:
 359                        pmlmepriv->fw_state |= WIFI_ADHOC_STATE;
 360                        break;
 361                case Ndis802_11Infrastructure:
 362                        pmlmepriv->fw_state |= WIFI_STATION_STATE;
 363                        break;
 364                case Ndis802_11APMode:
 365                case Ndis802_11AutoUnknown:
 366                case Ndis802_11InfrastructureMax:
 367                        break;
 368                }
 369        }
 370        psecnetwork = &psecuritypriv->sec_bss;
 371        memcpy(psecnetwork, &pnetwork->network, sizeof(*psecnetwork));
 372        psecuritypriv->authenticator_ie[0] = (unsigned char)
 373                                             psecnetwork->IELength;
 374        if ((psecnetwork->IELength - 12) < (256 - 1))
 375                memcpy(&psecuritypriv->authenticator_ie[1],
 376                        &psecnetwork->IEs[12], psecnetwork->IELength - 12);
 377        else
 378                memcpy(&psecuritypriv->authenticator_ie[1],
 379                        &psecnetwork->IEs[12], (256 - 1));
 380        psecnetwork->IELength = 0;
 381        /*
 382         * If the driver wants to use the bssid to create the connection.
 383         * If not, we copy the connecting AP's MAC address to it so that
 384         * the driver just has the bssid information for PMKIDList searching.
 385         */
 386        if (!pmlmepriv->assoc_by_bssid)
 387                ether_addr_copy(&pmlmepriv->assoc_bssid[0],
 388                                &pnetwork->network.MacAddress[0]);
 389        psecnetwork->IELength = r8712_restruct_sec_ie(padapter,
 390                                                &pnetwork->network.IEs[0],
 391                                                &psecnetwork->IEs[0],
 392                                                pnetwork->network.IELength);
 393        pqospriv->qos_option = 0;
 394        if (pregistrypriv->wmm_enable) {
 395                u32 tmp_len;
 396
 397                tmp_len = r8712_restruct_wmm_ie(padapter,
 398                                          &pnetwork->network.IEs[0],
 399                                          &psecnetwork->IEs[0],
 400                                          pnetwork->network.IELength,
 401                                          psecnetwork->IELength);
 402                if (psecnetwork->IELength != tmp_len) {
 403                        psecnetwork->IELength = tmp_len;
 404                        pqospriv->qos_option = 1; /* WMM IE in beacon */
 405                } else {
 406                        pqospriv->qos_option = 0; /* no WMM IE in beacon */
 407                }
 408        }
 409        if (pregistrypriv->ht_enable) {
 410                /*
 411                 * For WEP mode, we will use the bg mode to do the connection
 412                 * to avoid some IOT issues, especially for Realtek 8192u
 413                 * SoftAP.
 414                 */
 415                if ((padapter->securitypriv.PrivacyAlgrthm != _WEP40_) &&
 416                    (padapter->securitypriv.PrivacyAlgrthm != _WEP104_)) {
 417                        /* restructure_ht_ie */
 418                        r8712_restructure_ht_ie(padapter,
 419                                                &pnetwork->network.IEs[0],
 420                                                &psecnetwork->IEs[0],
 421                                                pnetwork->network.IELength,
 422                                                &psecnetwork->IELength);
 423                }
 424        }
 425        psecuritypriv->supplicant_ie[0] = (u8)psecnetwork->IELength;
 426        if (psecnetwork->IELength < 255)
 427                memcpy(&psecuritypriv->supplicant_ie[1], &psecnetwork->IEs[0],
 428                        psecnetwork->IELength);
 429        else
 430                memcpy(&psecuritypriv->supplicant_ie[1], &psecnetwork->IEs[0],
 431                        255);
 432        /* get cmdsz before endian conversion */
 433        pcmd->cmdsz = r8712_get_wlan_bssid_ex_sz(psecnetwork);
 434#ifdef __BIG_ENDIAN
 435        /* wlan_network endian conversion */
 436        psecnetwork->Length = cpu_to_le32(psecnetwork->Length);
 437        psecnetwork->Ssid.SsidLength = cpu_to_le32(
 438                                       psecnetwork->Ssid.SsidLength);
 439        psecnetwork->Privacy = cpu_to_le32(psecnetwork->Privacy);
 440        psecnetwork->Rssi = cpu_to_le32(psecnetwork->Rssi);
 441        psecnetwork->NetworkTypeInUse = cpu_to_le32(
 442                                        psecnetwork->NetworkTypeInUse);
 443        psecnetwork->Configuration.ATIMWindow = cpu_to_le32(
 444                                psecnetwork->Configuration.ATIMWindow);
 445        psecnetwork->Configuration.BeaconPeriod = cpu_to_le32(
 446                                 psecnetwork->Configuration.BeaconPeriod);
 447        psecnetwork->Configuration.DSConfig = cpu_to_le32(
 448                                psecnetwork->Configuration.DSConfig);
 449        psecnetwork->Configuration.FHConfig.DwellTime = cpu_to_le32(
 450                                psecnetwork->Configuration.FHConfig.DwellTime);
 451        psecnetwork->Configuration.FHConfig.HopPattern = cpu_to_le32(
 452                                psecnetwork->Configuration.FHConfig.HopPattern);
 453        psecnetwork->Configuration.FHConfig.HopSet = cpu_to_le32(
 454                                psecnetwork->Configuration.FHConfig.HopSet);
 455        psecnetwork->Configuration.FHConfig.Length = cpu_to_le32(
 456                                psecnetwork->Configuration.FHConfig.Length);
 457        psecnetwork->Configuration.Length = cpu_to_le32(
 458                                psecnetwork->Configuration.Length);
 459        psecnetwork->InfrastructureMode = cpu_to_le32(
 460                                psecnetwork->InfrastructureMode);
 461        psecnetwork->IELength = cpu_to_le32(psecnetwork->IELength);
 462#endif
 463        INIT_LIST_HEAD(&pcmd->list);
 464        pcmd->cmdcode = _JoinBss_CMD_;
 465        pcmd->parmbuf = (unsigned char *)psecnetwork;
 466        pcmd->rsp = NULL;
 467        pcmd->rspsz = 0;
 468        r8712_enqueue_cmd(pcmdpriv, pcmd);
 469        return 0;
 470}
 471
 472void r8712_disassoc_cmd(struct _adapter *padapter) /* for sta_mode */
 473{
 474        struct cmd_obj *pdisconnect_cmd;
 475        struct disconnect_parm *pdisconnect;
 476        struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
 477
 478        pdisconnect_cmd = kmalloc(sizeof(*pdisconnect_cmd), GFP_ATOMIC);
 479        if (!pdisconnect_cmd)
 480                return;
 481        pdisconnect = kmalloc(sizeof(*pdisconnect), GFP_ATOMIC);
 482        if (!pdisconnect) {
 483                kfree(pdisconnect_cmd);
 484                return;
 485        }
 486        init_h2fwcmd_w_parm_no_rsp(pdisconnect_cmd, pdisconnect,
 487                                   _DisConnect_CMD_);
 488        r8712_enqueue_cmd(pcmdpriv, pdisconnect_cmd);
 489}
 490
 491void r8712_setopmode_cmd(struct _adapter *padapter,
 492                 enum NDIS_802_11_NETWORK_INFRASTRUCTURE networktype)
 493{
 494        struct cmd_obj *ph2c;
 495        struct setopmode_parm *psetop;
 496
 497        struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
 498
 499        ph2c = kmalloc(sizeof(*ph2c), GFP_ATOMIC);
 500        if (!ph2c)
 501                return;
 502        psetop = kmalloc(sizeof(*psetop), GFP_ATOMIC);
 503        if (!psetop) {
 504                kfree(ph2c);
 505                return;
 506        }
 507        init_h2fwcmd_w_parm_no_rsp(ph2c, psetop, _SetOpMode_CMD_);
 508        psetop->mode = (u8)networktype;
 509        r8712_enqueue_cmd(pcmdpriv, ph2c);
 510}
 511
 512void r8712_setstakey_cmd(struct _adapter *padapter, u8 *psta, u8 unicast_key)
 513{
 514        struct cmd_obj *ph2c;
 515        struct set_stakey_parm *psetstakey_para;
 516        struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
 517        struct set_stakey_rsp *psetstakey_rsp = NULL;
 518        struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
 519        struct security_priv *psecuritypriv = &padapter->securitypriv;
 520        struct sta_info *sta = (struct sta_info *)psta;
 521
 522        ph2c = kmalloc(sizeof(*ph2c), GFP_ATOMIC);
 523        if (!ph2c)
 524                return;
 525        psetstakey_para = kmalloc(sizeof(*psetstakey_para), GFP_ATOMIC);
 526        if (!psetstakey_para) {
 527                kfree(ph2c);
 528                return;
 529        }
 530        psetstakey_rsp = kmalloc(sizeof(*psetstakey_rsp), GFP_ATOMIC);
 531        if (!psetstakey_rsp) {
 532                kfree(ph2c);
 533                kfree(psetstakey_para);
 534                return;
 535        }
 536        init_h2fwcmd_w_parm_no_rsp(ph2c, psetstakey_para, _SetStaKey_CMD_);
 537        ph2c->rsp = (u8 *) psetstakey_rsp;
 538        ph2c->rspsz = sizeof(struct set_stakey_rsp);
 539        ether_addr_copy(psetstakey_para->addr, sta->hwaddr);
 540        if (check_fwstate(pmlmepriv, WIFI_STATION_STATE))
 541                psetstakey_para->algorithm = (unsigned char)
 542                                            psecuritypriv->PrivacyAlgrthm;
 543        else
 544                GET_ENCRY_ALGO(psecuritypriv, sta,
 545                               psetstakey_para->algorithm, false);
 546        if (unicast_key)
 547                memcpy(&psetstakey_para->key, &sta->x_UncstKey, 16);
 548        else
 549                memcpy(&psetstakey_para->key,
 550                        &psecuritypriv->XGrpKey[
 551                        psecuritypriv->XGrpKeyid - 1]. skey, 16);
 552        r8712_enqueue_cmd(pcmdpriv, ph2c);
 553}
 554
 555void r8712_setMacAddr_cmd(struct _adapter *padapter, u8 *mac_addr)
 556{
 557        struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
 558        struct cmd_obj *ph2c;
 559        struct SetMacAddr_param *psetMacAddr_para;
 560
 561        ph2c = kmalloc(sizeof(*ph2c), GFP_ATOMIC);
 562        if (!ph2c)
 563                return;
 564        psetMacAddr_para = kmalloc(sizeof(*psetMacAddr_para), GFP_ATOMIC);
 565        if (!psetMacAddr_para) {
 566                kfree(ph2c);
 567                return;
 568        }
 569        init_h2fwcmd_w_parm_no_rsp(ph2c, psetMacAddr_para,
 570                                   _SetMacAddress_CMD_);
 571        ether_addr_copy(psetMacAddr_para->MacAddr, mac_addr);
 572        r8712_enqueue_cmd(pcmdpriv, ph2c);
 573}
 574
 575void r8712_addbareq_cmd(struct _adapter *padapter, u8 tid)
 576{
 577        struct cmd_priv         *pcmdpriv = &padapter->cmdpriv;
 578        struct cmd_obj          *ph2c;
 579        struct addBaReq_parm    *paddbareq_parm;
 580
 581        ph2c = kmalloc(sizeof(*ph2c), GFP_ATOMIC);
 582        if (!ph2c)
 583                return;
 584        paddbareq_parm = kmalloc(sizeof(*paddbareq_parm), GFP_ATOMIC);
 585        if (!paddbareq_parm) {
 586                kfree(ph2c);
 587                return;
 588        }
 589        paddbareq_parm->tid = tid;
 590        init_h2fwcmd_w_parm_no_rsp(ph2c, paddbareq_parm,
 591                                   GEN_CMD_CODE(_AddBAReq));
 592        r8712_enqueue_cmd_ex(pcmdpriv, ph2c);
 593}
 594
 595void r8712_wdg_wk_cmd(struct _adapter *padapter)
 596{
 597        struct cmd_obj *ph2c;
 598        struct drvint_cmd_parm  *pdrvintcmd_param;
 599        struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
 600
 601        ph2c = kmalloc(sizeof(*ph2c), GFP_ATOMIC);
 602        if (!ph2c)
 603                return;
 604        pdrvintcmd_param = kmalloc(sizeof(*pdrvintcmd_param), GFP_ATOMIC);
 605        if (!pdrvintcmd_param) {
 606                kfree(ph2c);
 607                return;
 608        }
 609        pdrvintcmd_param->i_cid = WDG_WK_CID;
 610        pdrvintcmd_param->sz = 0;
 611        pdrvintcmd_param->pbuf = NULL;
 612        init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvintcmd_param, _DRV_INT_CMD_);
 613        r8712_enqueue_cmd_ex(pcmdpriv, ph2c);
 614}
 615
 616void r8712_survey_cmd_callback(struct _adapter *padapter, struct cmd_obj *pcmd)
 617{
 618        struct  mlme_priv *pmlmepriv = &padapter->mlmepriv;
 619
 620        if (pcmd->res != H2C_SUCCESS)
 621                clr_fwstate(pmlmepriv, _FW_UNDER_SURVEY);
 622        r8712_free_cmd_obj(pcmd);
 623}
 624
 625void r8712_disassoc_cmd_callback(struct _adapter *padapter,
 626                                 struct cmd_obj *pcmd)
 627{
 628        unsigned long irqL;
 629        struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
 630
 631        if (pcmd->res != H2C_SUCCESS) {
 632                spin_lock_irqsave(&pmlmepriv->lock, irqL);
 633                set_fwstate(pmlmepriv, _FW_LINKED);
 634                spin_unlock_irqrestore(&pmlmepriv->lock, irqL);
 635                return;
 636        }
 637        r8712_free_cmd_obj(pcmd);
 638}
 639
 640void r8712_joinbss_cmd_callback(struct _adapter *padapter, struct cmd_obj *pcmd)
 641{
 642        struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
 643
 644        if (pcmd->res != H2C_SUCCESS)
 645                mod_timer(&pmlmepriv->assoc_timer,
 646                          jiffies + msecs_to_jiffies(1));
 647        r8712_free_cmd_obj(pcmd);
 648}
 649
 650void r8712_createbss_cmd_callback(struct _adapter *padapter,
 651                                  struct cmd_obj *pcmd)
 652{
 653        unsigned long irqL;
 654        struct sta_info *psta = NULL;
 655        struct wlan_network *pwlan = NULL;
 656        struct  mlme_priv *pmlmepriv = &padapter->mlmepriv;
 657        struct wlan_bssid_ex *pnetwork = (struct wlan_bssid_ex *)pcmd->parmbuf;
 658        struct wlan_network *tgt_network = &(pmlmepriv->cur_network);
 659
 660        if (pcmd->res != H2C_SUCCESS)
 661                mod_timer(&pmlmepriv->assoc_timer,
 662                          jiffies + msecs_to_jiffies(1));
 663        del_timer(&pmlmepriv->assoc_timer);
 664#ifdef __BIG_ENDIAN
 665        /* endian_convert */
 666        pnetwork->Length = le32_to_cpu(pnetwork->Length);
 667        pnetwork->Ssid.SsidLength = le32_to_cpu(pnetwork->Ssid.SsidLength);
 668        pnetwork->Privacy = le32_to_cpu(pnetwork->Privacy);
 669        pnetwork->Rssi = le32_to_cpu(pnetwork->Rssi);
 670        pnetwork->NetworkTypeInUse = le32_to_cpu(pnetwork->NetworkTypeInUse);
 671        pnetwork->Configuration.ATIMWindow =
 672                le32_to_cpu(pnetwork->Configuration.ATIMWindow);
 673        pnetwork->Configuration.DSConfig =
 674                le32_to_cpu(pnetwork->Configuration.DSConfig);
 675        pnetwork->Configuration.FHConfig.DwellTime =
 676                le32_to_cpu(pnetwork->Configuration.FHConfig.DwellTime);
 677        pnetwork->Configuration.FHConfig.HopPattern =
 678                le32_to_cpu(pnetwork->Configuration.FHConfig.HopPattern);
 679        pnetwork->Configuration.FHConfig.HopSet =
 680                le32_to_cpu(pnetwork->Configuration.FHConfig.HopSet);
 681        pnetwork->Configuration.FHConfig.Length =
 682                le32_to_cpu(pnetwork->Configuration.FHConfig.Length);
 683        pnetwork->Configuration.Length =
 684                le32_to_cpu(pnetwork->Configuration.Length);
 685        pnetwork->InfrastructureMode =
 686                le32_to_cpu(pnetwork->InfrastructureMode);
 687        pnetwork->IELength = le32_to_cpu(pnetwork->IELength);
 688#endif
 689        spin_lock_irqsave(&pmlmepriv->lock, irqL);
 690        if ((pmlmepriv->fw_state) & WIFI_AP_STATE) {
 691                psta = r8712_get_stainfo(&padapter->stapriv,
 692                                         pnetwork->MacAddress);
 693                if (!psta) {
 694                        psta = r8712_alloc_stainfo(&padapter->stapriv,
 695                                                   pnetwork->MacAddress);
 696                        if (!psta)
 697                                goto createbss_cmd_fail;
 698                }
 699                r8712_indicate_connect(padapter);
 700        } else {
 701                pwlan = _r8712_alloc_network(pmlmepriv);
 702                if (!pwlan) {
 703                        pwlan = r8712_get_oldest_wlan_network(
 704                                &pmlmepriv->scanned_queue);
 705                        if (!pwlan)
 706                                goto createbss_cmd_fail;
 707                        pwlan->last_scanned = jiffies;
 708                } else {
 709                        list_add_tail(&(pwlan->list),
 710                                         &pmlmepriv->scanned_queue.queue);
 711                }
 712                pnetwork->Length = r8712_get_wlan_bssid_ex_sz(pnetwork);
 713                memcpy(&(pwlan->network), pnetwork, pnetwork->Length);
 714                pwlan->fixed = true;
 715                memcpy(&tgt_network->network, pnetwork,
 716                        (r8712_get_wlan_bssid_ex_sz(pnetwork)));
 717                if (pmlmepriv->fw_state & _FW_UNDER_LINKING)
 718                        pmlmepriv->fw_state ^= _FW_UNDER_LINKING;
 719                /*
 720                 * we will set _FW_LINKED when there is one more sat to
 721                 * join us (stassoc_event_callback)
 722                 */
 723        }
 724createbss_cmd_fail:
 725        spin_unlock_irqrestore(&pmlmepriv->lock, irqL);
 726        r8712_free_cmd_obj(pcmd);
 727}
 728
 729void r8712_setstaKey_cmdrsp_callback(struct _adapter *padapter,
 730                                     struct cmd_obj *pcmd)
 731{
 732        struct sta_priv *pstapriv = &padapter->stapriv;
 733        struct set_stakey_rsp *psetstakey_rsp = (struct set_stakey_rsp *)
 734                                                (pcmd->rsp);
 735        struct sta_info *psta = r8712_get_stainfo(pstapriv,
 736                                                  psetstakey_rsp->addr);
 737
 738        if (!psta)
 739                goto exit;
 740        psta->aid = psta->mac_id = psetstakey_rsp->keyid; /*CAM_ID(CAM_ENTRY)*/
 741exit:
 742        r8712_free_cmd_obj(pcmd);
 743}
 744
 745void r8712_setassocsta_cmdrsp_callback(struct _adapter *padapter,
 746                                       struct cmd_obj *pcmd)
 747{
 748        unsigned long   irqL;
 749        struct sta_priv *pstapriv = &padapter->stapriv;
 750        struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
 751        struct set_assocsta_parm *passocsta_parm =
 752                                (struct set_assocsta_parm *)(pcmd->parmbuf);
 753        struct set_assocsta_rsp *passocsta_rsp =
 754                                (struct set_assocsta_rsp *) (pcmd->rsp);
 755        struct sta_info *psta = r8712_get_stainfo(pstapriv,
 756                                                  passocsta_parm->addr);
 757
 758        if (!psta)
 759                return;
 760        psta->aid = psta->mac_id = passocsta_rsp->cam_id;
 761        spin_lock_irqsave(&pmlmepriv->lock, irqL);
 762        if ((check_fwstate(pmlmepriv, WIFI_MP_STATE)) &&
 763            (check_fwstate(pmlmepriv, _FW_UNDER_LINKING)))
 764                pmlmepriv->fw_state ^= _FW_UNDER_LINKING;
 765        set_fwstate(pmlmepriv, _FW_LINKED);
 766        spin_unlock_irqrestore(&pmlmepriv->lock, irqL);
 767        r8712_free_cmd_obj(pcmd);
 768}
 769
 770void r8712_disconnectCtrlEx_cmd(struct _adapter *adapter, u32 enableDrvCtrl,
 771                        u32 tryPktCnt, u32 tryPktInterval, u32 firstStageTO)
 772{
 773        struct cmd_obj *ph2c;
 774        struct DisconnectCtrlEx_param *param;
 775        struct cmd_priv *pcmdpriv = &adapter->cmdpriv;
 776
 777        ph2c = kmalloc(sizeof(*ph2c), GFP_ATOMIC);
 778        if (!ph2c)
 779                return;
 780        param = kzalloc(sizeof(*param), GFP_ATOMIC);
 781        if (!param) {
 782                kfree(ph2c);
 783                return;
 784        }
 785
 786        param->EnableDrvCtrl = (unsigned char)enableDrvCtrl;
 787        param->TryPktCnt = (unsigned char)tryPktCnt;
 788        param->TryPktInterval = (unsigned char)tryPktInterval;
 789        param->FirstStageTO = (unsigned int)firstStageTO;
 790
 791        init_h2fwcmd_w_parm_no_rsp(ph2c, param,
 792                                GEN_CMD_CODE(_DisconnectCtrlEx));
 793        r8712_enqueue_cmd(pcmdpriv, ph2c);
 794}
 795