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