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