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}