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 static sint _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 _FAIL; 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 _FAIL; 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 _SUCCESS; 74 } 75 76 static sint _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 _FAIL; 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 _SUCCESS; 88 } 89 90 static void _free_evt_priv(struct evt_priv *pevtpriv) 91 { 92 kfree(pevtpriv->evt_allocated_buf); 93 } 94 95 static void _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 * _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 static sint _enqueue_cmd(struct __queue *queue, struct cmd_obj *obj) 114 { 115 unsigned long irqL; 116 117 if (!obj) 118 return _SUCCESS; 119 spin_lock_irqsave(&queue->lock, irqL); 120 list_add_tail(&obj->list, &queue->queue); 121 spin_unlock_irqrestore(&queue->lock, irqL); 122 return _SUCCESS; 123 } 124 125 static struct cmd_obj *_dequeue_cmd(struct __queue *queue) 126 { 127 unsigned long irqL; 128 struct cmd_obj *obj; 129 130 spin_lock_irqsave(&queue->lock, irqL); 131 obj = list_first_entry_or_null(&queue->queue, 132 struct cmd_obj, list); 133 if (obj) 134 list_del_init(&obj->list); 135 spin_unlock_irqrestore(&queue->lock, irqL); 136 return obj; 137 } 138 139 u32 r8712_init_cmd_priv(struct cmd_priv *pcmdpriv) 140 { 141 return _init_cmd_priv(pcmdpriv); 142 } 143 144 u32 r8712_init_evt_priv(struct evt_priv *pevtpriv) 145 { 146 return _init_evt_priv(pevtpriv); 147 } 148 149 void r8712_free_evt_priv(struct evt_priv *pevtpriv) 150 { 151 _free_evt_priv(pevtpriv); 152 } 153 154 void r8712_free_cmd_priv(struct cmd_priv *pcmdpriv) 155 { 156 _free_cmd_priv(pcmdpriv); 157 } 158 159 u32 r8712_enqueue_cmd(struct cmd_priv *pcmdpriv, struct cmd_obj *obj) 160 { 161 int res; 162 163 if (pcmdpriv->padapter->eeprompriv.bautoload_fail_flag) 164 return _FAIL; 165 res = _enqueue_cmd(&pcmdpriv->cmd_queue, obj); 166 complete(&pcmdpriv->cmd_queue_comp); 167 return res; 168 } 169 170 u32 r8712_enqueue_cmd_ex(struct cmd_priv *pcmdpriv, struct cmd_obj *obj) 171 { 172 unsigned long irqL; 173 struct __queue *queue; 174 175 if (!obj) 176 return _SUCCESS; 177 if (pcmdpriv->padapter->eeprompriv.bautoload_fail_flag) 178 return _FAIL; 179 queue = &pcmdpriv->cmd_queue; 180 spin_lock_irqsave(&queue->lock, irqL); 181 list_add_tail(&obj->list, &queue->queue); 182 spin_unlock_irqrestore(&queue->lock, irqL); 183 complete(&pcmdpriv->cmd_queue_comp); 184 return _SUCCESS; 185 } 186 187 struct cmd_obj *r8712_dequeue_cmd(struct __queue *queue) 188 { 189 return _dequeue_cmd(queue); 190 } 191 192 void r8712_free_cmd_obj(struct cmd_obj *pcmd) 193 { 194 if ((pcmd->cmdcode != _JoinBss_CMD_) && 195 (pcmd->cmdcode != _CreateBss_CMD_)) 196 kfree(pcmd->parmbuf); 197 if (pcmd->rsp != NULL) { 198 if (pcmd->rspsz != 0) 199 kfree(pcmd->rsp); 200 } 201 kfree(pcmd); 202 } 203 204 /* 205 * r8712_sitesurvey_cmd(~) 206 * ### NOTE:#### (!!!!) 207 * MUST TAKE CARE THAT BEFORE CALLING THIS FUNC, 208 * YOU SHOULD HAVE LOCKED pmlmepriv->lock 209 */ 210 u8 r8712_sitesurvey_cmd(struct _adapter *padapter, 211 struct ndis_802_11_ssid *pssid) 212 { 213 struct cmd_obj *ph2c; 214 struct sitesurvey_parm *psurveyPara; 215 struct cmd_priv *pcmdpriv = &padapter->cmdpriv; 216 struct mlme_priv *pmlmepriv = &padapter->mlmepriv; 217 218 ph2c = kmalloc(sizeof(*ph2c), GFP_ATOMIC); 219 if (!ph2c) 220 return _FAIL; 221 psurveyPara = kmalloc(sizeof(*psurveyPara), GFP_ATOMIC); 222 if (!psurveyPara) { 223 kfree(ph2c); 224 return _FAIL; 225 } 226 init_h2fwcmd_w_parm_no_rsp(ph2c, psurveyPara, 227 GEN_CMD_CODE(_SiteSurvey)); 228 psurveyPara->bsslimit = cpu_to_le32(48); 229 psurveyPara->passive_mode = cpu_to_le32(pmlmepriv->passive_mode); 230 psurveyPara->ss_ssidlen = 0; 231 memset(psurveyPara->ss_ssid, 0, IW_ESSID_MAX_SIZE + 1); 232 if ((pssid != NULL) && (pssid->SsidLength)) { 233 memcpy(psurveyPara->ss_ssid, pssid->Ssid, pssid->SsidLength); 234 psurveyPara->ss_ssidlen = cpu_to_le32(pssid->SsidLength); 235 } 236 set_fwstate(pmlmepriv, _FW_UNDER_SURVEY); 237 r8712_enqueue_cmd(pcmdpriv, ph2c); 238 mod_timer(&pmlmepriv->scan_to_timer, 239 jiffies + msecs_to_jiffies(SCANNING_TIMEOUT)); 240 padapter->ledpriv.LedControlHandler(padapter, LED_CTL_SITE_SURVEY); 241 padapter->blnEnableRxFF0Filter = 0; 242 return _SUCCESS; 243 } 244 245 u8 r8712_setdatarate_cmd(struct _adapter *padapter, u8 *rateset) 246 { 247 struct cmd_obj *ph2c; 248 struct setdatarate_parm *pbsetdataratepara; 249 struct cmd_priv *pcmdpriv = &padapter->cmdpriv; 250 251 ph2c = kmalloc(sizeof(*ph2c), GFP_ATOMIC); 252 if (!ph2c) 253 return _FAIL; 254 pbsetdataratepara = kmalloc(sizeof(*pbsetdataratepara), GFP_ATOMIC); 255 if (!pbsetdataratepara) { 256 kfree(ph2c); 257 return _FAIL; 258 } 259 init_h2fwcmd_w_parm_no_rsp(ph2c, pbsetdataratepara, 260 GEN_CMD_CODE(_SetDataRate)); 261 pbsetdataratepara->mac_id = 5; 262 memcpy(pbsetdataratepara->datarates, rateset, NumRates); 263 r8712_enqueue_cmd(pcmdpriv, ph2c); 264 return _SUCCESS; 265 } 266 267 u8 r8712_set_chplan_cmd(struct _adapter *padapter, int chplan) 268 { 269 struct cmd_obj *ph2c; 270 struct SetChannelPlan_param *psetchplanpara; 271 struct cmd_priv *pcmdpriv = &padapter->cmdpriv; 272 273 ph2c = kmalloc(sizeof(*ph2c), GFP_ATOMIC); 274 if (!ph2c) 275 return _FAIL; 276 psetchplanpara = kmalloc(sizeof(*psetchplanpara), GFP_ATOMIC); 277 if (!psetchplanpara) { 278 kfree(ph2c); 279 return _FAIL; 280 } 281 init_h2fwcmd_w_parm_no_rsp(ph2c, psetchplanpara, 282 GEN_CMD_CODE(_SetChannelPlan)); 283 psetchplanpara->ChannelPlan = chplan; 284 r8712_enqueue_cmd(pcmdpriv, ph2c); 285 return _SUCCESS; 286 } 287 288 u8 r8712_setbasicrate_cmd(struct _adapter *padapter, u8 *rateset) 289 { 290 struct cmd_obj *ph2c; 291 struct setbasicrate_parm *pssetbasicratepara; 292 struct cmd_priv *pcmdpriv = &padapter->cmdpriv; 293 294 ph2c = kmalloc(sizeof(*ph2c), GFP_ATOMIC); 295 if (!ph2c) 296 return _FAIL; 297 pssetbasicratepara = kmalloc(sizeof(*pssetbasicratepara), GFP_ATOMIC); 298 if (!pssetbasicratepara) { 299 kfree(ph2c); 300 return _FAIL; 301 } 302 init_h2fwcmd_w_parm_no_rsp(ph2c, pssetbasicratepara, 303 _SetBasicRate_CMD_); 304 memcpy(pssetbasicratepara->basicrates, rateset, NumRates); 305 r8712_enqueue_cmd(pcmdpriv, ph2c); 306 return _SUCCESS; 307 } 308 309 u8 r8712_setfwdig_cmd(struct _adapter *padapter, u8 type) 310 { 311 struct cmd_obj *ph2c; 312 struct writePTM_parm *pwriteptmparm; 313 struct cmd_priv *pcmdpriv = &padapter->cmdpriv; 314 315 ph2c = kmalloc(sizeof(*ph2c), GFP_ATOMIC); 316 if (!ph2c) 317 return _FAIL; 318 pwriteptmparm = kmalloc(sizeof(*pwriteptmparm), GFP_ATOMIC); 319 if (!pwriteptmparm) { 320 kfree(ph2c); 321 return _FAIL; 322 } 323 init_h2fwcmd_w_parm_no_rsp(ph2c, pwriteptmparm, GEN_CMD_CODE(_SetDIG)); 324 pwriteptmparm->type = type; 325 r8712_enqueue_cmd(pcmdpriv, ph2c); 326 return _SUCCESS; 327 } 328 329 u8 r8712_setfwra_cmd(struct _adapter *padapter, u8 type) 330 { 331 struct cmd_obj *ph2c; 332 struct writePTM_parm *pwriteptmparm; 333 struct cmd_priv *pcmdpriv = &padapter->cmdpriv; 334 335 ph2c = kmalloc(sizeof(*ph2c), GFP_ATOMIC); 336 if (!ph2c) 337 return _FAIL; 338 pwriteptmparm = kmalloc(sizeof(*pwriteptmparm), GFP_ATOMIC); 339 if (!pwriteptmparm) { 340 kfree(ph2c); 341 return _FAIL; 342 } 343 init_h2fwcmd_w_parm_no_rsp(ph2c, pwriteptmparm, GEN_CMD_CODE(_SetRA)); 344 pwriteptmparm->type = type; 345 r8712_enqueue_cmd(pcmdpriv, ph2c); 346 return _SUCCESS; 347 } 348 349 u8 r8712_setrfreg_cmd(struct _adapter *padapter, u8 offset, u32 val) 350 { 351 struct cmd_obj *ph2c; 352 struct writeRF_parm *pwriterfparm; 353 struct cmd_priv *pcmdpriv = &padapter->cmdpriv; 354 355 ph2c = kmalloc(sizeof(*ph2c), GFP_ATOMIC); 356 if (!ph2c) 357 return _FAIL; 358 pwriterfparm = kmalloc(sizeof(*pwriterfparm), GFP_ATOMIC); 359 if (!pwriterfparm) { 360 kfree(ph2c); 361 return _FAIL; 362 } 363 init_h2fwcmd_w_parm_no_rsp(ph2c, pwriterfparm, GEN_CMD_CODE(_SetRFReg)); 364 pwriterfparm->offset = offset; 365 pwriterfparm->value = val; 366 r8712_enqueue_cmd(pcmdpriv, ph2c); 367 return _SUCCESS; 368 } 369 370 u8 r8712_getrfreg_cmd(struct _adapter *padapter, u8 offset, u8 *pval) 371 { 372 struct cmd_obj *ph2c; 373 struct readRF_parm *prdrfparm; 374 struct cmd_priv *pcmdpriv = &padapter->cmdpriv; 375 376 ph2c = kmalloc(sizeof(*ph2c), GFP_ATOMIC); 377 if (!ph2c) 378 return _FAIL; 379 prdrfparm = kmalloc(sizeof(*prdrfparm), GFP_ATOMIC); 380 if (!prdrfparm) { 381 kfree(ph2c); 382 return _FAIL; 383 } 384 INIT_LIST_HEAD(&ph2c->list); 385 ph2c->cmdcode = GEN_CMD_CODE(_GetRFReg); 386 ph2c->parmbuf = (unsigned char *)prdrfparm; 387 ph2c->cmdsz = sizeof(struct readRF_parm); 388 ph2c->rsp = pval; 389 ph2c->rspsz = sizeof(struct readRF_rsp); 390 prdrfparm->offset = offset; 391 r8712_enqueue_cmd(pcmdpriv, ph2c); 392 return _SUCCESS; 393 } 394 395 void r8712_getbbrfreg_cmdrsp_callback(struct _adapter *padapter, 396 struct cmd_obj *pcmd) 397 { 398 kfree(pcmd->parmbuf); 399 kfree(pcmd); 400 padapter->mppriv.workparam.bcompleted = true; 401 } 402 403 void r8712_readtssi_cmdrsp_callback(struct _adapter *padapter, 404 struct cmd_obj *pcmd) 405 { 406 kfree(pcmd->parmbuf); 407 kfree(pcmd); 408 409 padapter->mppriv.workparam.bcompleted = true; 410 } 411 412 u8 r8712_createbss_cmd(struct _adapter *padapter) 413 { 414 struct cmd_obj *pcmd; 415 struct cmd_priv *pcmdpriv = &padapter->cmdpriv; 416 struct wlan_bssid_ex *pdev_network = 417 &padapter->registrypriv.dev_network; 418 419 padapter->ledpriv.LedControlHandler(padapter, LED_CTL_START_TO_LINK); 420 pcmd = kmalloc(sizeof(*pcmd), GFP_ATOMIC); 421 if (!pcmd) 422 return _FAIL; 423 INIT_LIST_HEAD(&pcmd->list); 424 pcmd->cmdcode = _CreateBss_CMD_; 425 pcmd->parmbuf = (unsigned char *)pdev_network; 426 pcmd->cmdsz = r8712_get_wlan_bssid_ex_sz(pdev_network); 427 pcmd->rsp = NULL; 428 pcmd->rspsz = 0; 429 /* notes: translate IELength & Length after assign to cmdsz; */ 430 pdev_network->Length = pcmd->cmdsz; 431 pdev_network->IELength = pdev_network->IELength; 432 pdev_network->Ssid.SsidLength = pdev_network->Ssid.SsidLength; 433 r8712_enqueue_cmd(pcmdpriv, pcmd); 434 return _SUCCESS; 435 } 436 437 u8 r8712_joinbss_cmd(struct _adapter *padapter, struct wlan_network *pnetwork) 438 { 439 struct wlan_bssid_ex *psecnetwork; 440 struct cmd_obj *pcmd; 441 struct cmd_priv *pcmdpriv = &padapter->cmdpriv; 442 struct mlme_priv *pmlmepriv = &padapter->mlmepriv; 443 struct qos_priv *pqospriv = &pmlmepriv->qospriv; 444 struct security_priv *psecuritypriv = &padapter->securitypriv; 445 struct registry_priv *pregistrypriv = &padapter->registrypriv; 446 enum NDIS_802_11_NETWORK_INFRASTRUCTURE ndis_network_mode = 447 pnetwork->network.InfrastructureMode; 448 449 padapter->ledpriv.LedControlHandler(padapter, LED_CTL_START_TO_LINK); 450 pcmd = kmalloc(sizeof(*pcmd), GFP_ATOMIC); 451 if (!pcmd) 452 return _FAIL; 453 454 /* for hidden ap to set fw_state here */ 455 if (check_fwstate(pmlmepriv, WIFI_STATION_STATE | WIFI_ADHOC_STATE) != 456 true) { 457 switch (ndis_network_mode) { 458 case Ndis802_11IBSS: 459 pmlmepriv->fw_state |= WIFI_ADHOC_STATE; 460 break; 461 case Ndis802_11Infrastructure: 462 pmlmepriv->fw_state |= WIFI_STATION_STATE; 463 break; 464 case Ndis802_11APMode: 465 case Ndis802_11AutoUnknown: 466 case Ndis802_11InfrastructureMax: 467 break; 468 } 469 } 470 psecnetwork = &psecuritypriv->sec_bss; 471 if (!psecnetwork) { 472 kfree(pcmd); 473 return _FAIL; 474 } 475 memcpy(psecnetwork, &pnetwork->network, sizeof(*psecnetwork)); 476 psecuritypriv->authenticator_ie[0] = (unsigned char) 477 psecnetwork->IELength; 478 if ((psecnetwork->IELength - 12) < (256 - 1)) 479 memcpy(&psecuritypriv->authenticator_ie[1], 480 &psecnetwork->IEs[12], psecnetwork->IELength - 12); 481 else 482 memcpy(&psecuritypriv->authenticator_ie[1], 483 &psecnetwork->IEs[12], (256 - 1)); 484 psecnetwork->IELength = 0; 485 /* 486 * If the driver wants to use the bssid to create the connection. 487 * If not, we copy the connecting AP's MAC address to it so that 488 * the driver just has the bssid information for PMKIDList searching. 489 */ 490 if (!pmlmepriv->assoc_by_bssid) 491 ether_addr_copy(&pmlmepriv->assoc_bssid[0], 492 &pnetwork->network.MacAddress[0]); 493 psecnetwork->IELength = r8712_restruct_sec_ie(padapter, 494 &pnetwork->network.IEs[0], 495 &psecnetwork->IEs[0], 496 pnetwork->network.IELength); 497 pqospriv->qos_option = 0; 498 if (pregistrypriv->wmm_enable) { 499 u32 tmp_len; 500 501 tmp_len = r8712_restruct_wmm_ie(padapter, 502 &pnetwork->network.IEs[0], 503 &psecnetwork->IEs[0], 504 pnetwork->network.IELength, 505 psecnetwork->IELength); 506 if (psecnetwork->IELength != tmp_len) { 507 psecnetwork->IELength = tmp_len; 508 pqospriv->qos_option = 1; /* WMM IE in beacon */ 509 } else { 510 pqospriv->qos_option = 0; /* no WMM IE in beacon */ 511 } 512 } 513 if (pregistrypriv->ht_enable) { 514 /* 515 * For WEP mode, we will use the bg mode to do the connection 516 * to avoid some IOT issues, especially for Realtek 8192u 517 * SoftAP. 518 */ 519 if ((padapter->securitypriv.PrivacyAlgrthm != _WEP40_) && 520 (padapter->securitypriv.PrivacyAlgrthm != _WEP104_)) { 521 /* restructure_ht_ie */ 522 r8712_restructure_ht_ie(padapter, 523 &pnetwork->network.IEs[0], 524 &psecnetwork->IEs[0], 525 pnetwork->network.IELength, 526 &psecnetwork->IELength); 527 } 528 } 529 psecuritypriv->supplicant_ie[0] = (u8)psecnetwork->IELength; 530 if (psecnetwork->IELength < 255) 531 memcpy(&psecuritypriv->supplicant_ie[1], &psecnetwork->IEs[0], 532 psecnetwork->IELength); 533 else 534 memcpy(&psecuritypriv->supplicant_ie[1], &psecnetwork->IEs[0], 535 255); 536 /* get cmdsz before endian conversion */ 537 pcmd->cmdsz = r8712_get_wlan_bssid_ex_sz(psecnetwork); 538 #ifdef __BIG_ENDIAN 539 /* wlan_network endian conversion */ 540 psecnetwork->Length = cpu_to_le32(psecnetwork->Length); 541 psecnetwork->Ssid.SsidLength = cpu_to_le32( 542 psecnetwork->Ssid.SsidLength); 543 psecnetwork->Privacy = cpu_to_le32(psecnetwork->Privacy); 544 psecnetwork->Rssi = cpu_to_le32(psecnetwork->Rssi); 545 psecnetwork->NetworkTypeInUse = cpu_to_le32( 546 psecnetwork->NetworkTypeInUse); 547 psecnetwork->Configuration.ATIMWindow = cpu_to_le32( 548 psecnetwork->Configuration.ATIMWindow); 549 psecnetwork->Configuration.BeaconPeriod = cpu_to_le32( 550 psecnetwork->Configuration.BeaconPeriod); 551 psecnetwork->Configuration.DSConfig = cpu_to_le32( 552 psecnetwork->Configuration.DSConfig); 553 psecnetwork->Configuration.FHConfig.DwellTime = cpu_to_le32( 554 psecnetwork->Configuration.FHConfig.DwellTime); 555 psecnetwork->Configuration.FHConfig.HopPattern = cpu_to_le32( 556 psecnetwork->Configuration.FHConfig.HopPattern); 557 psecnetwork->Configuration.FHConfig.HopSet = cpu_to_le32( 558 psecnetwork->Configuration.FHConfig.HopSet); 559 psecnetwork->Configuration.FHConfig.Length = cpu_to_le32( 560 psecnetwork->Configuration.FHConfig.Length); 561 psecnetwork->Configuration.Length = cpu_to_le32( 562 psecnetwork->Configuration.Length); 563 psecnetwork->InfrastructureMode = cpu_to_le32( 564 psecnetwork->InfrastructureMode); 565 psecnetwork->IELength = cpu_to_le32(psecnetwork->IELength); 566 #endif 567 INIT_LIST_HEAD(&pcmd->list); 568 pcmd->cmdcode = _JoinBss_CMD_; 569 pcmd->parmbuf = (unsigned char *)psecnetwork; 570 pcmd->rsp = NULL; 571 pcmd->rspsz = 0; 572 r8712_enqueue_cmd(pcmdpriv, pcmd); 573 return _SUCCESS; 574 } 575 576 u8 r8712_disassoc_cmd(struct _adapter *padapter) /* for sta_mode */ 577 { 578 struct cmd_obj *pdisconnect_cmd; 579 struct disconnect_parm *pdisconnect; 580 struct cmd_priv *pcmdpriv = &padapter->cmdpriv; 581 582 pdisconnect_cmd = kmalloc(sizeof(*pdisconnect_cmd), GFP_ATOMIC); 583 if (!pdisconnect_cmd) 584 return _FAIL; 585 pdisconnect = kmalloc(sizeof(*pdisconnect), GFP_ATOMIC); 586 if (!pdisconnect) { 587 kfree(pdisconnect_cmd); 588 return _FAIL; 589 } 590 init_h2fwcmd_w_parm_no_rsp(pdisconnect_cmd, pdisconnect, 591 _DisConnect_CMD_); 592 r8712_enqueue_cmd(pcmdpriv, pdisconnect_cmd); 593 return _SUCCESS; 594 } 595 596 u8 r8712_setopmode_cmd(struct _adapter *padapter, 597 enum NDIS_802_11_NETWORK_INFRASTRUCTURE networktype) 598 { 599 struct cmd_obj *ph2c; 600 struct setopmode_parm *psetop; 601 602 struct cmd_priv *pcmdpriv = &padapter->cmdpriv; 603 604 ph2c = kmalloc(sizeof(*ph2c), GFP_ATOMIC); 605 if (!ph2c) 606 return _FAIL; 607 psetop = kmalloc(sizeof(*psetop), GFP_ATOMIC); 608 if (!psetop) { 609 kfree(ph2c); 610 return _FAIL; 611 } 612 init_h2fwcmd_w_parm_no_rsp(ph2c, psetop, _SetOpMode_CMD_); 613 psetop->mode = (u8)networktype; 614 r8712_enqueue_cmd(pcmdpriv, ph2c); 615 return _SUCCESS; 616 } 617 618 u8 r8712_setstakey_cmd(struct _adapter *padapter, u8 *psta, u8 unicast_key) 619 { 620 struct cmd_obj *ph2c; 621 struct set_stakey_parm *psetstakey_para; 622 struct cmd_priv *pcmdpriv = &padapter->cmdpriv; 623 struct set_stakey_rsp *psetstakey_rsp = NULL; 624 struct mlme_priv *pmlmepriv = &padapter->mlmepriv; 625 struct security_priv *psecuritypriv = &padapter->securitypriv; 626 struct sta_info *sta = (struct sta_info *)psta; 627 628 ph2c = kmalloc(sizeof(*ph2c), GFP_ATOMIC); 629 if (!ph2c) 630 return _FAIL; 631 psetstakey_para = kmalloc(sizeof(*psetstakey_para), GFP_ATOMIC); 632 if (!psetstakey_para) { 633 kfree(ph2c); 634 return _FAIL; 635 } 636 psetstakey_rsp = kmalloc(sizeof(*psetstakey_rsp), GFP_ATOMIC); 637 if (!psetstakey_rsp) { 638 kfree(ph2c); 639 kfree(psetstakey_para); 640 return _FAIL; 641 } 642 init_h2fwcmd_w_parm_no_rsp(ph2c, psetstakey_para, _SetStaKey_CMD_); 643 ph2c->rsp = (u8 *) psetstakey_rsp; 644 ph2c->rspsz = sizeof(struct set_stakey_rsp); 645 ether_addr_copy(psetstakey_para->addr, sta->hwaddr); 646 if (check_fwstate(pmlmepriv, WIFI_STATION_STATE)) 647 psetstakey_para->algorithm = (unsigned char) 648 psecuritypriv->PrivacyAlgrthm; 649 else 650 GET_ENCRY_ALGO(psecuritypriv, sta, 651 psetstakey_para->algorithm, false); 652 if (unicast_key) 653 memcpy(&psetstakey_para->key, &sta->x_UncstKey, 16); 654 else 655 memcpy(&psetstakey_para->key, 656 &psecuritypriv->XGrpKey[ 657 psecuritypriv->XGrpKeyid - 1]. skey, 16); 658 r8712_enqueue_cmd(pcmdpriv, ph2c); 659 return _SUCCESS; 660 } 661 662 u8 r8712_setrfintfs_cmd(struct _adapter *padapter, u8 mode) 663 { 664 struct cmd_obj *ph2c; 665 struct setrfintfs_parm *psetrfintfsparm; 666 struct cmd_priv *pcmdpriv = &padapter->cmdpriv; 667 668 ph2c = kmalloc(sizeof(*ph2c), GFP_ATOMIC); 669 if (!ph2c) 670 return _FAIL; 671 psetrfintfsparm = kmalloc(sizeof(*psetrfintfsparm), GFP_ATOMIC); 672 if (!psetrfintfsparm) { 673 kfree(ph2c); 674 return _FAIL; 675 } 676 init_h2fwcmd_w_parm_no_rsp(ph2c, psetrfintfsparm, 677 GEN_CMD_CODE(_SetRFIntFs)); 678 psetrfintfsparm->rfintfs = mode; 679 r8712_enqueue_cmd(pcmdpriv, ph2c); 680 return _SUCCESS; 681 } 682 683 u8 r8712_setrttbl_cmd(struct _adapter *padapter, 684 struct setratable_parm *prate_table) 685 { 686 struct cmd_obj *ph2c; 687 struct setratable_parm *psetrttblparm; 688 struct cmd_priv *pcmdpriv = &padapter->cmdpriv; 689 690 ph2c = kmalloc(sizeof(*ph2c), GFP_ATOMIC); 691 if (!ph2c) 692 return _FAIL; 693 psetrttblparm = kmalloc(sizeof(*psetrttblparm), GFP_ATOMIC); 694 if (!psetrttblparm) { 695 kfree(ph2c); 696 return _FAIL; 697 } 698 init_h2fwcmd_w_parm_no_rsp(ph2c, psetrttblparm, 699 GEN_CMD_CODE(_SetRaTable)); 700 memcpy(psetrttblparm, prate_table, sizeof(struct setratable_parm)); 701 r8712_enqueue_cmd(pcmdpriv, ph2c); 702 return _SUCCESS; 703 } 704 705 u8 r8712_setMacAddr_cmd(struct _adapter *padapter, u8 *mac_addr) 706 { 707 struct cmd_priv *pcmdpriv = &padapter->cmdpriv; 708 struct cmd_obj *ph2c; 709 struct SetMacAddr_param *psetMacAddr_para; 710 711 ph2c = kmalloc(sizeof(*ph2c), GFP_ATOMIC); 712 if (!ph2c) 713 return _FAIL; 714 psetMacAddr_para = kmalloc(sizeof(*psetMacAddr_para), GFP_ATOMIC); 715 if (!psetMacAddr_para) { 716 kfree(ph2c); 717 return _FAIL; 718 } 719 init_h2fwcmd_w_parm_no_rsp(ph2c, psetMacAddr_para, 720 _SetMacAddress_CMD_); 721 ether_addr_copy(psetMacAddr_para->MacAddr, mac_addr); 722 r8712_enqueue_cmd(pcmdpriv, ph2c); 723 return _SUCCESS; 724 } 725 726 u8 r8712_setassocsta_cmd(struct _adapter *padapter, u8 *mac_addr) 727 { 728 struct cmd_priv *pcmdpriv = &padapter->cmdpriv; 729 struct cmd_obj *ph2c; 730 struct set_assocsta_parm *psetassocsta_para; 731 struct set_assocsta_rsp *psetassocsta_rsp = NULL; 732 733 ph2c = kmalloc(sizeof(*ph2c), GFP_ATOMIC); 734 if (!ph2c) 735 return _FAIL; 736 psetassocsta_para = kmalloc(sizeof(*psetassocsta_para), GFP_ATOMIC); 737 if (!psetassocsta_para) { 738 kfree(ph2c); 739 return _FAIL; 740 } 741 psetassocsta_rsp = kmalloc(sizeof(*psetassocsta_rsp), GFP_ATOMIC); 742 if (!psetassocsta_rsp) { 743 kfree(ph2c); 744 kfree(psetassocsta_para); 745 return _FAIL; 746 } 747 init_h2fwcmd_w_parm_no_rsp(ph2c, psetassocsta_para, _SetAssocSta_CMD_); 748 ph2c->rsp = (u8 *) psetassocsta_rsp; 749 ph2c->rspsz = sizeof(struct set_assocsta_rsp); 750 ether_addr_copy(psetassocsta_para->addr, mac_addr); 751 r8712_enqueue_cmd(pcmdpriv, ph2c); 752 return _SUCCESS; 753 } 754 755 u8 r8712_addbareq_cmd(struct _adapter *padapter, u8 tid) 756 { 757 struct cmd_priv *pcmdpriv = &padapter->cmdpriv; 758 struct cmd_obj *ph2c; 759 struct addBaReq_parm *paddbareq_parm; 760 761 ph2c = kmalloc(sizeof(*ph2c), GFP_ATOMIC); 762 if (!ph2c) 763 return _FAIL; 764 paddbareq_parm = kmalloc(sizeof(*paddbareq_parm), GFP_ATOMIC); 765 if (!paddbareq_parm) { 766 kfree(ph2c); 767 return _FAIL; 768 } 769 paddbareq_parm->tid = tid; 770 init_h2fwcmd_w_parm_no_rsp(ph2c, paddbareq_parm, 771 GEN_CMD_CODE(_AddBAReq)); 772 r8712_enqueue_cmd_ex(pcmdpriv, ph2c); 773 return _SUCCESS; 774 } 775 776 u8 r8712_wdg_wk_cmd(struct _adapter *padapter) 777 { 778 struct cmd_obj *ph2c; 779 struct drvint_cmd_parm *pdrvintcmd_param; 780 struct cmd_priv *pcmdpriv = &padapter->cmdpriv; 781 782 ph2c = kmalloc(sizeof(*ph2c), GFP_ATOMIC); 783 if (!ph2c) 784 return _FAIL; 785 pdrvintcmd_param = kmalloc(sizeof(*pdrvintcmd_param), GFP_ATOMIC); 786 if (!pdrvintcmd_param) { 787 kfree(ph2c); 788 return _FAIL; 789 } 790 pdrvintcmd_param->i_cid = WDG_WK_CID; 791 pdrvintcmd_param->sz = 0; 792 pdrvintcmd_param->pbuf = NULL; 793 init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvintcmd_param, _DRV_INT_CMD_); 794 r8712_enqueue_cmd_ex(pcmdpriv, ph2c); 795 return _SUCCESS; 796 } 797 798 void r8712_survey_cmd_callback(struct _adapter *padapter, struct cmd_obj *pcmd) 799 { 800 struct mlme_priv *pmlmepriv = &padapter->mlmepriv; 801 802 if (pcmd->res != H2C_SUCCESS) 803 clr_fwstate(pmlmepriv, _FW_UNDER_SURVEY); 804 r8712_free_cmd_obj(pcmd); 805 } 806 807 void r8712_disassoc_cmd_callback(struct _adapter *padapter, 808 struct cmd_obj *pcmd) 809 { 810 unsigned long irqL; 811 struct mlme_priv *pmlmepriv = &padapter->mlmepriv; 812 813 if (pcmd->res != H2C_SUCCESS) { 814 spin_lock_irqsave(&pmlmepriv->lock, irqL); 815 set_fwstate(pmlmepriv, _FW_LINKED); 816 spin_unlock_irqrestore(&pmlmepriv->lock, irqL); 817 return; 818 } 819 r8712_free_cmd_obj(pcmd); 820 } 821 822 void r8712_joinbss_cmd_callback(struct _adapter *padapter, struct cmd_obj *pcmd) 823 { 824 struct mlme_priv *pmlmepriv = &padapter->mlmepriv; 825 826 if (pcmd->res != H2C_SUCCESS) 827 mod_timer(&pmlmepriv->assoc_timer, 828 jiffies + msecs_to_jiffies(1)); 829 r8712_free_cmd_obj(pcmd); 830 } 831 832 void r8712_createbss_cmd_callback(struct _adapter *padapter, 833 struct cmd_obj *pcmd) 834 { 835 unsigned long irqL; 836 struct sta_info *psta = NULL; 837 struct wlan_network *pwlan = NULL; 838 struct mlme_priv *pmlmepriv = &padapter->mlmepriv; 839 struct wlan_bssid_ex *pnetwork = (struct wlan_bssid_ex *)pcmd->parmbuf; 840 struct wlan_network *tgt_network = &(pmlmepriv->cur_network); 841 842 if (pcmd->res != H2C_SUCCESS) 843 mod_timer(&pmlmepriv->assoc_timer, 844 jiffies + msecs_to_jiffies(1)); 845 del_timer(&pmlmepriv->assoc_timer); 846 #ifdef __BIG_ENDIAN 847 /* endian_convert */ 848 pnetwork->Length = le32_to_cpu(pnetwork->Length); 849 pnetwork->Ssid.SsidLength = le32_to_cpu(pnetwork->Ssid.SsidLength); 850 pnetwork->Privacy = le32_to_cpu(pnetwork->Privacy); 851 pnetwork->Rssi = le32_to_cpu(pnetwork->Rssi); 852 pnetwork->NetworkTypeInUse = le32_to_cpu(pnetwork->NetworkTypeInUse); 853 pnetwork->Configuration.ATIMWindow = 854 le32_to_cpu(pnetwork->Configuration.ATIMWindow); 855 pnetwork->Configuration.DSConfig = 856 le32_to_cpu(pnetwork->Configuration.DSConfig); 857 pnetwork->Configuration.FHConfig.DwellTime = 858 le32_to_cpu(pnetwork->Configuration.FHConfig.DwellTime); 859 pnetwork->Configuration.FHConfig.HopPattern = 860 le32_to_cpu(pnetwork->Configuration.FHConfig.HopPattern); 861 pnetwork->Configuration.FHConfig.HopSet = 862 le32_to_cpu(pnetwork->Configuration.FHConfig.HopSet); 863 pnetwork->Configuration.FHConfig.Length = 864 le32_to_cpu(pnetwork->Configuration.FHConfig.Length); 865 pnetwork->Configuration.Length = 866 le32_to_cpu(pnetwork->Configuration.Length); 867 pnetwork->InfrastructureMode = 868 le32_to_cpu(pnetwork->InfrastructureMode); 869 pnetwork->IELength = le32_to_cpu(pnetwork->IELength); 870 #endif 871 spin_lock_irqsave(&pmlmepriv->lock, irqL); 872 if ((pmlmepriv->fw_state) & WIFI_AP_STATE) { 873 psta = r8712_get_stainfo(&padapter->stapriv, 874 pnetwork->MacAddress); 875 if (!psta) { 876 psta = r8712_alloc_stainfo(&padapter->stapriv, 877 pnetwork->MacAddress); 878 if (!psta) 879 goto createbss_cmd_fail; 880 } 881 r8712_indicate_connect(padapter); 882 } else { 883 pwlan = _r8712_alloc_network(pmlmepriv); 884 if (!pwlan) { 885 pwlan = r8712_get_oldest_wlan_network( 886 &pmlmepriv->scanned_queue); 887 if (!pwlan) 888 goto createbss_cmd_fail; 889 pwlan->last_scanned = jiffies; 890 } else { 891 list_add_tail(&(pwlan->list), 892 &pmlmepriv->scanned_queue.queue); 893 } 894 pnetwork->Length = r8712_get_wlan_bssid_ex_sz(pnetwork); 895 memcpy(&(pwlan->network), pnetwork, pnetwork->Length); 896 pwlan->fixed = true; 897 memcpy(&tgt_network->network, pnetwork, 898 (r8712_get_wlan_bssid_ex_sz(pnetwork))); 899 if (pmlmepriv->fw_state & _FW_UNDER_LINKING) 900 pmlmepriv->fw_state ^= _FW_UNDER_LINKING; 901 /* 902 * we will set _FW_LINKED when there is one more sat to 903 * join us (stassoc_event_callback) 904 */ 905 } 906 createbss_cmd_fail: 907 spin_unlock_irqrestore(&pmlmepriv->lock, irqL); 908 r8712_free_cmd_obj(pcmd); 909 } 910 911 void r8712_setstaKey_cmdrsp_callback(struct _adapter *padapter, 912 struct cmd_obj *pcmd) 913 { 914 struct sta_priv *pstapriv = &padapter->stapriv; 915 struct set_stakey_rsp *psetstakey_rsp = (struct set_stakey_rsp *) 916 (pcmd->rsp); 917 struct sta_info *psta = r8712_get_stainfo(pstapriv, 918 psetstakey_rsp->addr); 919 920 if (!psta) 921 goto exit; 922 psta->aid = psta->mac_id = psetstakey_rsp->keyid; /*CAM_ID(CAM_ENTRY)*/ 923 exit: 924 r8712_free_cmd_obj(pcmd); 925 } 926 927 void r8712_setassocsta_cmdrsp_callback(struct _adapter *padapter, 928 struct cmd_obj *pcmd) 929 { 930 unsigned long irqL; 931 struct sta_priv *pstapriv = &padapter->stapriv; 932 struct mlme_priv *pmlmepriv = &padapter->mlmepriv; 933 struct set_assocsta_parm *passocsta_parm = 934 (struct set_assocsta_parm *)(pcmd->parmbuf); 935 struct set_assocsta_rsp *passocsta_rsp = 936 (struct set_assocsta_rsp *) (pcmd->rsp); 937 struct sta_info *psta = r8712_get_stainfo(pstapriv, 938 passocsta_parm->addr); 939 940 if (!psta) 941 return; 942 psta->aid = psta->mac_id = passocsta_rsp->cam_id; 943 spin_lock_irqsave(&pmlmepriv->lock, irqL); 944 if ((check_fwstate(pmlmepriv, WIFI_MP_STATE)) && 945 (check_fwstate(pmlmepriv, _FW_UNDER_LINKING))) 946 pmlmepriv->fw_state ^= _FW_UNDER_LINKING; 947 set_fwstate(pmlmepriv, _FW_LINKED); 948 spin_unlock_irqrestore(&pmlmepriv->lock, irqL); 949 r8712_free_cmd_obj(pcmd); 950 } 951 952 u8 r8712_disconnectCtrlEx_cmd(struct _adapter *adapter, u32 enableDrvCtrl, 953 u32 tryPktCnt, u32 tryPktInterval, u32 firstStageTO) 954 { 955 struct cmd_obj *ph2c; 956 struct DisconnectCtrlEx_param *param; 957 struct cmd_priv *pcmdpriv = &adapter->cmdpriv; 958 959 ph2c = kmalloc(sizeof(*ph2c), GFP_ATOMIC); 960 if (!ph2c) 961 return _FAIL; 962 param = kzalloc(sizeof(*param), GFP_ATOMIC); 963 if (!param) { 964 kfree(ph2c); 965 return _FAIL; 966 } 967 968 param->EnableDrvCtrl = (unsigned char)enableDrvCtrl; 969 param->TryPktCnt = (unsigned char)tryPktCnt; 970 param->TryPktInterval = (unsigned char)tryPktInterval; 971 param->FirstStageTO = (unsigned int)firstStageTO; 972 973 init_h2fwcmd_w_parm_no_rsp(ph2c, param, 974 GEN_CMD_CODE(_DisconnectCtrlEx)); 975 r8712_enqueue_cmd(pcmdpriv, ph2c); 976 return _SUCCESS; 977 } 978