root/drivers/staging/rtl8712/rtl871x_cmd.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. r8712_init_cmd_priv
  2. r8712_init_evt_priv
  3. r8712_free_evt_priv
  4. r8712_free_cmd_priv
  5. r8712_enqueue_cmd
  6. r8712_dequeue_cmd
  7. r8712_enqueue_cmd_ex
  8. r8712_free_cmd_obj
  9. r8712_sitesurvey_cmd
  10. r8712_setdatarate_cmd
  11. r8712_set_chplan_cmd
  12. r8712_setrfreg_cmd
  13. r8712_getrfreg_cmd
  14. r8712_getbbrfreg_cmdrsp_callback
  15. r8712_readtssi_cmdrsp_callback
  16. r8712_createbss_cmd
  17. r8712_joinbss_cmd
  18. r8712_disassoc_cmd
  19. r8712_setopmode_cmd
  20. r8712_setstakey_cmd
  21. r8712_setMacAddr_cmd
  22. r8712_addbareq_cmd
  23. r8712_wdg_wk_cmd
  24. r8712_survey_cmd_callback
  25. r8712_disassoc_cmd_callback
  26. r8712_joinbss_cmd_callback
  27. r8712_createbss_cmd_callback
  28. r8712_setstaKey_cmdrsp_callback
  29. r8712_setassocsta_cmdrsp_callback
  30. r8712_disconnectCtrlEx_cmd

   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 
  46 int 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 
  76 int 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 
  90 void r8712_free_evt_priv(struct evt_priv *pevtpriv)
  91 {
  92         kfree(pevtpriv->evt_allocated_buf);
  93 }
  94 
  95 void 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 
 113 void 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 
 129 struct 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 
 143 void 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 
 159 void 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  */
 177 u8 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 
 212 int 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 
 234 void 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 
 254 int 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 
 275 int 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 
 300 void 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 
 308 void 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 
 317 int 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 
 342 int 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 
 477 void 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 
 496 void 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 
 517 void 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 
 560 void 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 
 580 void 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 
 600 void 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 
 621 void 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 
 630 void 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 
 645 void 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 
 655 void 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         }
 729 createbss_cmd_fail:
 730         spin_unlock_irqrestore(&pmlmepriv->lock, irqL);
 731         r8712_free_cmd_obj(pcmd);
 732 }
 733 
 734 void 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)*/
 746 exit:
 747         r8712_free_cmd_obj(pcmd);
 748 }
 749 
 750 void 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 
 775 void 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 }

/* [<][>][^][v][top][bottom][index][help] */