cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

rtl871x_cmd.c (24005B)


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