rtw_cmd.c revision 7552d72a5c34a8d55037ce0c1a8cd8c3a7e86341
1/****************************************************************************** 2 * 3 * Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved. 4 * 5 * This program is free software; you can redistribute it and/or modify it 6 * under the terms of version 2 of the GNU General Public License as 7 * published by the Free Software Foundation. 8 * 9 * This program is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 12 * more details. 13 * 14 * You should have received a copy of the GNU General Public License along with 15 * this program; if not, write to the Free Software Foundation, Inc., 16 * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA 17 * 18 * 19 ******************************************************************************/ 20#define _RTW_CMD_C_ 21 22#include <osdep_service.h> 23#include <drv_types.h> 24#include <recv_osdep.h> 25#include <cmd_osdep.h> 26#include <mlme_osdep.h> 27#include <rtw_br_ext.h> 28#include <rtw_mlme_ext.h> 29 30/* 31Caller and the rtw_cmd_thread can protect cmd_q by spin_lock. 32No irqsave is necessary. 33*/ 34 35int _rtw_init_cmd_priv (struct cmd_priv *pcmdpriv) 36{ 37 int res = _SUCCESS; 38 39_func_enter_; 40 41 _rtw_init_sema(&(pcmdpriv->cmd_queue_sema), 0); 42 /* _rtw_init_sema(&(pcmdpriv->cmd_done_sema), 0); */ 43 _rtw_init_sema(&(pcmdpriv->terminate_cmdthread_sema), 0); 44 45 46 _rtw_init_queue(&(pcmdpriv->cmd_queue)); 47 48 /* allocate DMA-able/Non-Page memory for cmd_buf and rsp_buf */ 49 50 pcmdpriv->cmd_seq = 1; 51 52 pcmdpriv->cmd_allocated_buf = rtw_zmalloc(MAX_CMDSZ + CMDBUFF_ALIGN_SZ); 53 54 if (pcmdpriv->cmd_allocated_buf == NULL) { 55 res = _FAIL; 56 goto exit; 57 } 58 59 pcmdpriv->cmd_buf = pcmdpriv->cmd_allocated_buf + CMDBUFF_ALIGN_SZ - ((size_t)(pcmdpriv->cmd_allocated_buf) & (CMDBUFF_ALIGN_SZ-1)); 60 61 pcmdpriv->rsp_allocated_buf = rtw_zmalloc(MAX_RSPSZ + 4); 62 63 if (pcmdpriv->rsp_allocated_buf == NULL) { 64 res = _FAIL; 65 goto exit; 66 } 67 68 pcmdpriv->rsp_buf = pcmdpriv->rsp_allocated_buf + 4 - ((size_t)(pcmdpriv->rsp_allocated_buf) & 3); 69 70 pcmdpriv->cmd_issued_cnt = 0; 71 pcmdpriv->cmd_done_cnt = 0; 72 pcmdpriv->rsp_cnt = 0; 73exit: 74_func_exit_; 75 return res; 76} 77 78static void c2h_wk_callback(struct work_struct *work); 79 80int _rtw_init_evt_priv(struct evt_priv *pevtpriv) 81{ 82 int res = _SUCCESS; 83 84_func_enter_; 85 86 /* allocate DMA-able/Non-Page memory for cmd_buf and rsp_buf */ 87 ATOMIC_SET(&pevtpriv->event_seq, 0); 88 pevtpriv->evt_done_cnt = 0; 89 90 _init_workitem(&pevtpriv->c2h_wk, c2h_wk_callback, NULL); 91 pevtpriv->c2h_wk_alive = false; 92 pevtpriv->c2h_queue = rtw_cbuf_alloc(C2H_QUEUE_MAX_LEN+1); 93 94_func_exit_; 95 96 return res; 97} 98 99void rtw_free_evt_priv(struct evt_priv *pevtpriv) 100{ 101_func_enter_; 102 103 RT_TRACE(_module_rtl871x_cmd_c_, _drv_info_, ("+rtw_free_evt_priv\n")); 104 105 _cancel_workitem_sync(&pevtpriv->c2h_wk); 106 while (pevtpriv->c2h_wk_alive) 107 rtw_msleep_os(10); 108 109 while (!rtw_cbuf_empty(pevtpriv->c2h_queue)) { 110 void *c2h = rtw_cbuf_pop(pevtpriv->c2h_queue); 111 if (c2h != NULL && c2h != (void *)pevtpriv) 112 kfree(c2h); 113 } 114 RT_TRACE(_module_rtl871x_cmd_c_, _drv_info_, ("-rtw_free_evt_priv\n")); 115 116_func_exit_; 117} 118 119void _rtw_free_cmd_priv (struct cmd_priv *pcmdpriv) 120{ 121_func_enter_; 122 123 if (pcmdpriv) { 124 _rtw_spinlock_free(&(pcmdpriv->cmd_queue.lock)); 125 _rtw_free_sema(&(pcmdpriv->cmd_queue_sema)); 126 _rtw_free_sema(&(pcmdpriv->terminate_cmdthread_sema)); 127 128 if (pcmdpriv->cmd_allocated_buf) 129 kfree(pcmdpriv->cmd_allocated_buf); 130 131 if (pcmdpriv->rsp_allocated_buf) 132 kfree(pcmdpriv->rsp_allocated_buf); 133 } 134_func_exit_; 135} 136 137/* 138Calling Context: 139 140rtw_enqueue_cmd can only be called between kernel thread, 141since only spin_lock is used. 142 143ISR/Call-Back functions can't call this sub-function. 144 145*/ 146 147int _rtw_enqueue_cmd(struct __queue *queue, struct cmd_obj *obj) 148{ 149 unsigned long irqL; 150 151_func_enter_; 152 153 if (obj == NULL) 154 goto exit; 155 156 /* _enter_critical_bh(&queue->lock, &irqL); */ 157 _enter_critical(&queue->lock, &irqL); 158 159 rtw_list_insert_tail(&obj->list, &queue->queue); 160 161 /* _exit_critical_bh(&queue->lock, &irqL); */ 162 _exit_critical(&queue->lock, &irqL); 163 164exit: 165 166_func_exit_; 167 168 return _SUCCESS; 169} 170 171struct cmd_obj *_rtw_dequeue_cmd(struct __queue *queue) 172{ 173 unsigned long irqL; 174 struct cmd_obj *obj; 175 176_func_enter_; 177 178 /* _enter_critical_bh(&(queue->lock), &irqL); */ 179 _enter_critical(&queue->lock, &irqL); 180 if (rtw_is_list_empty(&(queue->queue))) { 181 obj = NULL; 182 } else { 183 obj = LIST_CONTAINOR(get_next(&(queue->queue)), struct cmd_obj, list); 184 rtw_list_delete(&obj->list); 185 } 186 187 /* _exit_critical_bh(&(queue->lock), &irqL); */ 188 _exit_critical(&queue->lock, &irqL); 189 190_func_exit_; 191 192 return obj; 193} 194 195u32 rtw_init_cmd_priv(struct cmd_priv *pcmdpriv) 196{ 197 u32 res; 198_func_enter_; 199 res = _rtw_init_cmd_priv (pcmdpriv); 200_func_exit_; 201 return res; 202} 203 204u32 rtw_init_evt_priv (struct evt_priv *pevtpriv) 205{ 206 int res; 207_func_enter_; 208 res = _rtw_init_evt_priv(pevtpriv); 209_func_exit_; 210 return res; 211} 212 213void rtw_free_cmd_priv(struct cmd_priv *pcmdpriv) 214{ 215_func_enter_; 216 RT_TRACE(_module_rtl871x_cmd_c_, _drv_info_, ("rtw_free_cmd_priv\n")); 217 _rtw_free_cmd_priv(pcmdpriv); 218_func_exit_; 219} 220 221static int rtw_cmd_filter(struct cmd_priv *pcmdpriv, struct cmd_obj *cmd_obj) 222{ 223 u8 bAllow = false; /* set to true to allow enqueuing cmd when hw_init_completed is false */ 224 225 /* To decide allow or not */ 226 if ((pcmdpriv->padapter->pwrctrlpriv.bHWPwrPindetect) && 227 (!pcmdpriv->padapter->registrypriv.usbss_enable)) { 228 if (cmd_obj->cmdcode == GEN_CMD_CODE(_Set_Drv_Extra)) { 229 struct drvextra_cmd_parm *pdrvextra_cmd_parm = (struct drvextra_cmd_parm *)cmd_obj->parmbuf; 230 if (pdrvextra_cmd_parm->ec_id == POWER_SAVING_CTRL_WK_CID) 231 bAllow = true; 232 } 233 } 234 235 if (cmd_obj->cmdcode == GEN_CMD_CODE(_SetChannelPlan)) 236 bAllow = true; 237 238 if ((!pcmdpriv->padapter->hw_init_completed && !bAllow) || 239 !pcmdpriv->cmdthd_running) /* com_thread not running */ 240 return _FAIL; 241 return _SUCCESS; 242} 243 244u32 rtw_enqueue_cmd(struct cmd_priv *pcmdpriv, struct cmd_obj *cmd_obj) 245{ 246 int res = _FAIL; 247 struct adapter *padapter = pcmdpriv->padapter; 248 249_func_enter_; 250 251 if (cmd_obj == NULL) 252 goto exit; 253 254 cmd_obj->padapter = padapter; 255 256 res = rtw_cmd_filter(pcmdpriv, cmd_obj); 257 if (_FAIL == res) { 258 rtw_free_cmd_obj(cmd_obj); 259 goto exit; 260 } 261 262 res = _rtw_enqueue_cmd(&pcmdpriv->cmd_queue, cmd_obj); 263 264 if (res == _SUCCESS) 265 _rtw_up_sema(&pcmdpriv->cmd_queue_sema); 266 267exit: 268 269_func_exit_; 270 271 return res; 272} 273 274struct cmd_obj *rtw_dequeue_cmd(struct cmd_priv *pcmdpriv) 275{ 276 struct cmd_obj *cmd_obj; 277 278_func_enter_; 279 280 cmd_obj = _rtw_dequeue_cmd(&pcmdpriv->cmd_queue); 281 282_func_exit_; 283 return cmd_obj; 284} 285 286void rtw_cmd_clr_isr(struct cmd_priv *pcmdpriv) 287{ 288_func_enter_; 289 pcmdpriv->cmd_done_cnt++; 290 /* _rtw_up_sema(&(pcmdpriv->cmd_done_sema)); */ 291_func_exit_; 292} 293 294void rtw_free_cmd_obj(struct cmd_obj *pcmd) 295{ 296_func_enter_; 297 298 if ((pcmd->cmdcode != _JoinBss_CMD_) && (pcmd->cmdcode != _CreateBss_CMD_)) { 299 /* free parmbuf in cmd_obj */ 300 kfree(pcmd->parmbuf); 301 } 302 303 if (pcmd->rsp != NULL) { 304 if (pcmd->rspsz != 0) { 305 /* free rsp in cmd_obj */ 306 kfree(pcmd->rsp); 307 } 308 } 309 310 /* free cmd_obj */ 311 kfree(pcmd); 312 313_func_exit_; 314} 315 316int rtw_cmd_thread(void *context) 317{ 318 u8 ret; 319 struct cmd_obj *pcmd; 320 u8 *pcmdbuf; 321 u8 (*cmd_hdl)(struct adapter *padapter, u8 *pbuf); 322 void (*pcmd_callback)(struct adapter *dev, struct cmd_obj *pcmd); 323 struct adapter *padapter = (struct adapter *)context; 324 struct cmd_priv *pcmdpriv = &(padapter->cmdpriv); 325 326_func_enter_; 327 328 thread_enter("RTW_CMD_THREAD"); 329 330 pcmdbuf = pcmdpriv->cmd_buf; 331 332 pcmdpriv->cmdthd_running = true; 333 _rtw_up_sema(&pcmdpriv->terminate_cmdthread_sema); 334 335 RT_TRACE(_module_rtl871x_cmd_c_, _drv_info_, ("start r871x rtw_cmd_thread !!!!\n")); 336 337 while (1) { 338 if (_rtw_down_sema(&pcmdpriv->cmd_queue_sema) == _FAIL) 339 break; 340 341 if (padapter->bDriverStopped || 342 padapter->bSurpriseRemoved) { 343 DBG_88E("%s: DriverStopped(%d) SurpriseRemoved(%d) break at line %d\n", 344 __func__, padapter->bDriverStopped, padapter->bSurpriseRemoved, __LINE__); 345 break; 346 } 347_next: 348 if (padapter->bDriverStopped || 349 padapter->bSurpriseRemoved) { 350 DBG_88E("%s: DriverStopped(%d) SurpriseRemoved(%d) break at line %d\n", 351 __func__, padapter->bDriverStopped, padapter->bSurpriseRemoved, __LINE__); 352 break; 353 } 354 355 pcmd = rtw_dequeue_cmd(pcmdpriv); 356 if (!pcmd) 357 continue; 358 359 if (_FAIL == rtw_cmd_filter(pcmdpriv, pcmd)) { 360 pcmd->res = H2C_DROPPED; 361 goto post_process; 362 } 363 364 pcmdpriv->cmd_issued_cnt++; 365 366 pcmd->cmdsz = _RND4((pcmd->cmdsz));/* _RND4 */ 367 368 memcpy(pcmdbuf, pcmd->parmbuf, pcmd->cmdsz); 369 370 if (pcmd->cmdcode < ARRAY_SIZE(wlancmds)) { 371 cmd_hdl = wlancmds[pcmd->cmdcode].h2cfuns; 372 373 if (cmd_hdl) { 374 ret = cmd_hdl(pcmd->padapter, pcmdbuf); 375 pcmd->res = ret; 376 } 377 378 pcmdpriv->cmd_seq++; 379 } else { 380 pcmd->res = H2C_PARAMETERS_ERROR; 381 } 382 383 cmd_hdl = NULL; 384 385post_process: 386 387 /* call callback function for post-processed */ 388 if (pcmd->cmdcode < ARRAY_SIZE(rtw_cmd_callback)) { 389 pcmd_callback = rtw_cmd_callback[pcmd->cmdcode].callback; 390 if (pcmd_callback == NULL) { 391 RT_TRACE(_module_rtl871x_cmd_c_, _drv_info_, ("mlme_cmd_hdl(): pcmd_callback = 0x%p, cmdcode = 0x%x\n", pcmd_callback, pcmd->cmdcode)); 392 rtw_free_cmd_obj(pcmd); 393 } else { 394 /* todo: !!! fill rsp_buf to pcmd->rsp if (pcmd->rsp!= NULL) */ 395 pcmd_callback(pcmd->padapter, pcmd);/* need conider that free cmd_obj in rtw_cmd_callback */ 396 } 397 } else { 398 RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_, ("%s: cmdcode = 0x%x callback not defined!\n", __func__, pcmd->cmdcode)); 399 rtw_free_cmd_obj(pcmd); 400 } 401 402 flush_signals_thread(); 403 404 goto _next; 405 } 406 pcmdpriv->cmdthd_running = false; 407 408 /* free all cmd_obj resources */ 409 do { 410 pcmd = rtw_dequeue_cmd(pcmdpriv); 411 if (pcmd == NULL) 412 break; 413 414 /* DBG_88E("%s: leaving... drop cmdcode:%u\n", __func__, pcmd->cmdcode); */ 415 416 rtw_free_cmd_obj(pcmd); 417 } while (1); 418 419 _rtw_up_sema(&pcmdpriv->terminate_cmdthread_sema); 420 421_func_exit_; 422 423 thread_exit(); 424} 425 426u8 rtw_setstandby_cmd(struct adapter *padapter, uint action) 427{ 428 struct cmd_obj *ph2c; 429 struct usb_suspend_parm *psetusbsuspend; 430 struct cmd_priv *pcmdpriv = &padapter->cmdpriv; 431 432 u8 ret = _SUCCESS; 433 434_func_enter_; 435 436 ph2c = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj)); 437 if (ph2c == NULL) { 438 ret = _FAIL; 439 goto exit; 440 } 441 442 psetusbsuspend = (struct usb_suspend_parm *)rtw_zmalloc(sizeof(struct usb_suspend_parm)); 443 if (psetusbsuspend == NULL) { 444 kfree(ph2c); 445 ret = _FAIL; 446 goto exit; 447 } 448 449 psetusbsuspend->action = action; 450 451 init_h2fwcmd_w_parm_no_rsp(ph2c, psetusbsuspend, GEN_CMD_CODE(_SetUsbSuspend)); 452 453 ret = rtw_enqueue_cmd(pcmdpriv, ph2c); 454 455exit: 456 457_func_exit_; 458 459 return ret; 460} 461 462/* 463rtw_sitesurvey_cmd(~) 464 ### NOTE:#### (!!!!) 465 MUST TAKE CARE THAT BEFORE CALLING THIS FUNC, YOU SHOULD HAVE LOCKED pmlmepriv->lock 466*/ 467u8 rtw_sitesurvey_cmd(struct adapter *padapter, struct ndis_802_11_ssid *ssid, int ssid_num, 468 struct rtw_ieee80211_channel *ch, int ch_num) 469{ 470 u8 res = _FAIL; 471 struct cmd_obj *ph2c; 472 struct sitesurvey_parm *psurveyPara; 473 struct cmd_priv *pcmdpriv = &padapter->cmdpriv; 474 struct mlme_priv *pmlmepriv = &padapter->mlmepriv; 475 476_func_enter_; 477 if (check_fwstate(pmlmepriv, _FW_LINKED) == true) { 478 rtw_lps_ctrl_wk_cmd(padapter, LPS_CTRL_SCAN, 1); 479 } 480 481 if (check_fwstate(pmlmepriv, _FW_LINKED) == true) { 482 p2p_ps_wk_cmd(padapter, P2P_PS_SCAN, 1); 483 } 484 485 ph2c = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj)); 486 if (ph2c == NULL) 487 return _FAIL; 488 489 psurveyPara = (struct sitesurvey_parm *)rtw_zmalloc(sizeof(struct sitesurvey_parm)); 490 if (psurveyPara == NULL) { 491 kfree(ph2c); 492 return _FAIL; 493 } 494 495 rtw_free_network_queue(padapter, false); 496 497 RT_TRACE(_module_rtl871x_cmd_c_, _drv_info_, ("%s: flush network queue\n", __func__)); 498 499 init_h2fwcmd_w_parm_no_rsp(ph2c, psurveyPara, GEN_CMD_CODE(_SiteSurvey)); 500 501 /* psurveyPara->bsslimit = 48; */ 502 psurveyPara->scan_mode = pmlmepriv->scan_mode; 503 504 /* prepare ssid list */ 505 if (ssid) { 506 int i; 507 for (i = 0; i < ssid_num && i < RTW_SSID_SCAN_AMOUNT; i++) { 508 if (ssid[i].SsidLength) { 509 memcpy(&psurveyPara->ssid[i], &ssid[i], sizeof(struct ndis_802_11_ssid)); 510 psurveyPara->ssid_num++; 511 if (0) 512 DBG_88E(FUNC_ADPT_FMT" ssid:(%s, %d)\n", FUNC_ADPT_ARG(padapter), 513 psurveyPara->ssid[i].Ssid, psurveyPara->ssid[i].SsidLength); 514 } 515 } 516 } 517 518 /* prepare channel list */ 519 if (ch) { 520 int i; 521 for (i = 0; i < ch_num && i < RTW_CHANNEL_SCAN_AMOUNT; i++) { 522 if (ch[i].hw_value && !(ch[i].flags & RTW_IEEE80211_CHAN_DISABLED)) { 523 memcpy(&psurveyPara->ch[i], &ch[i], sizeof(struct rtw_ieee80211_channel)); 524 psurveyPara->ch_num++; 525 if (0) 526 DBG_88E(FUNC_ADPT_FMT" ch:%u\n", FUNC_ADPT_ARG(padapter), 527 psurveyPara->ch[i].hw_value); 528 } 529 } 530 } 531 532 set_fwstate(pmlmepriv, _FW_UNDER_SURVEY); 533 534 res = rtw_enqueue_cmd(pcmdpriv, ph2c); 535 536 if (res == _SUCCESS) { 537 pmlmepriv->scan_start_time = rtw_get_current_time(); 538 539 _set_timer(&pmlmepriv->scan_to_timer, SCANNING_TIMEOUT); 540 541 rtw_led_control(padapter, LED_CTL_SITE_SURVEY); 542 543 pmlmepriv->scan_interval = SCAN_INTERVAL;/* 30*2 sec = 60sec */ 544 } else { 545 _clr_fwstate_(pmlmepriv, _FW_UNDER_SURVEY); 546 } 547 548_func_exit_; 549 550 return res; 551} 552 553u8 rtw_setdatarate_cmd(struct adapter *padapter, u8 *rateset) 554{ 555 struct cmd_obj *ph2c; 556 struct setdatarate_parm *pbsetdataratepara; 557 struct cmd_priv *pcmdpriv = &padapter->cmdpriv; 558 u8 res = _SUCCESS; 559 560_func_enter_; 561 562 ph2c = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj)); 563 if (ph2c == NULL) { 564 res = _FAIL; 565 goto exit; 566 } 567 568 pbsetdataratepara = (struct setdatarate_parm *)rtw_zmalloc(sizeof(struct setdatarate_parm)); 569 if (pbsetdataratepara == NULL) { 570 kfree(ph2c); 571 res = _FAIL; 572 goto exit; 573 } 574 575 init_h2fwcmd_w_parm_no_rsp(ph2c, pbsetdataratepara, GEN_CMD_CODE(_SetDataRate)); 576 pbsetdataratepara->mac_id = 5; 577 memcpy(pbsetdataratepara->datarates, rateset, NumRates); 578 res = rtw_enqueue_cmd(pcmdpriv, ph2c); 579exit: 580 581_func_exit_; 582 583 return res; 584} 585 586u8 rtw_setbasicrate_cmd(struct adapter *padapter, u8 *rateset) 587{ 588 struct cmd_obj *ph2c; 589 struct setbasicrate_parm *pssetbasicratepara; 590 struct cmd_priv *pcmdpriv = &padapter->cmdpriv; 591 u8 res = _SUCCESS; 592 593_func_enter_; 594 595 ph2c = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj)); 596 if (ph2c == NULL) { 597 res = _FAIL; 598 goto exit; 599 } 600 pssetbasicratepara = (struct setbasicrate_parm *)rtw_zmalloc(sizeof(struct setbasicrate_parm)); 601 602 if (pssetbasicratepara == NULL) { 603 kfree(ph2c); 604 res = _FAIL; 605 goto exit; 606 } 607 608 init_h2fwcmd_w_parm_no_rsp(ph2c, pssetbasicratepara, _SetBasicRate_CMD_); 609 610 memcpy(pssetbasicratepara->basicrates, rateset, NumRates); 611 612 res = rtw_enqueue_cmd(pcmdpriv, ph2c); 613exit: 614 615_func_exit_; 616 617 return res; 618} 619 620 621/* 622unsigned char rtw_setphy_cmd(unsigned char *adapter) 623 6241. be called only after rtw_update_registrypriv_dev_network(~) or mp testing program 6252. for AdHoc/Ap mode or mp mode? 626 627*/ 628u8 rtw_setphy_cmd(struct adapter *padapter, u8 modem, u8 ch) 629{ 630 struct cmd_obj *ph2c; 631 struct setphy_parm *psetphypara; 632 struct cmd_priv *pcmdpriv = &padapter->cmdpriv; 633 u8 res = _SUCCESS; 634 635_func_enter_; 636 637 ph2c = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj)); 638 if (ph2c == NULL) { 639 res = _FAIL; 640 goto exit; 641 } 642 psetphypara = (struct setphy_parm *)rtw_zmalloc(sizeof(struct setphy_parm)); 643 644 if (psetphypara == NULL) { 645 kfree(ph2c); 646 res = _FAIL; 647 goto exit; 648 } 649 650 init_h2fwcmd_w_parm_no_rsp(ph2c, psetphypara, _SetPhy_CMD_); 651 652 RT_TRACE(_module_rtl871x_cmd_c_, _drv_info_, ("CH =%d, modem =%d", ch, modem)); 653 654 psetphypara->modem = modem; 655 psetphypara->rfchannel = ch; 656 657 res = rtw_enqueue_cmd(pcmdpriv, ph2c); 658exit: 659_func_exit_; 660 return res; 661} 662 663u8 rtw_setbbreg_cmd(struct adapter *padapter, u8 offset, u8 val) 664{ 665 struct cmd_obj *ph2c; 666 struct writeBB_parm *pwritebbparm; 667 struct cmd_priv *pcmdpriv = &padapter->cmdpriv; 668 u8 res = _SUCCESS; 669 670_func_enter_; 671 ph2c = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj)); 672 if (ph2c == NULL) { 673 res = _FAIL; 674 goto exit; 675 } 676 pwritebbparm = (struct writeBB_parm *)rtw_zmalloc(sizeof(struct writeBB_parm)); 677 678 if (pwritebbparm == NULL) { 679 kfree(ph2c); 680 res = _FAIL; 681 goto exit; 682 } 683 684 init_h2fwcmd_w_parm_no_rsp(ph2c, pwritebbparm, GEN_CMD_CODE(_SetBBReg)); 685 686 pwritebbparm->offset = offset; 687 pwritebbparm->value = val; 688 689 res = rtw_enqueue_cmd(pcmdpriv, ph2c); 690exit: 691_func_exit_; 692 return res; 693} 694 695u8 rtw_getbbreg_cmd(struct adapter *padapter, u8 offset, u8 *pval) 696{ 697 struct cmd_obj *ph2c; 698 struct readBB_parm *prdbbparm; 699 struct cmd_priv *pcmdpriv = &padapter->cmdpriv; 700 u8 res = _SUCCESS; 701 702_func_enter_; 703 ph2c = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj)); 704 if (ph2c == NULL) { 705 res = _FAIL; 706 goto exit; 707 } 708 prdbbparm = (struct readBB_parm *)rtw_zmalloc(sizeof(struct readBB_parm)); 709 710 if (prdbbparm == NULL) { 711 kfree(ph2c); 712 return _FAIL; 713 } 714 715 _rtw_init_listhead(&ph2c->list); 716 ph2c->cmdcode = GEN_CMD_CODE(_GetBBReg); 717 ph2c->parmbuf = (unsigned char *)prdbbparm; 718 ph2c->cmdsz = sizeof(struct readBB_parm); 719 ph2c->rsp = pval; 720 ph2c->rspsz = sizeof(struct readBB_rsp); 721 722 prdbbparm->offset = offset; 723 724 res = rtw_enqueue_cmd(pcmdpriv, ph2c); 725exit: 726_func_exit_; 727 return res; 728} 729 730u8 rtw_setrfreg_cmd(struct adapter *padapter, u8 offset, u32 val) 731{ 732 struct cmd_obj *ph2c; 733 struct writeRF_parm *pwriterfparm; 734 struct cmd_priv *pcmdpriv = &padapter->cmdpriv; 735 u8 res = _SUCCESS; 736_func_enter_; 737 ph2c = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj)); 738 if (ph2c == NULL) { 739 res = _FAIL; 740 goto exit; 741 } 742 pwriterfparm = (struct writeRF_parm *)rtw_zmalloc(sizeof(struct writeRF_parm)); 743 744 if (pwriterfparm == NULL) { 745 kfree(ph2c); 746 res = _FAIL; 747 goto exit; 748 } 749 750 init_h2fwcmd_w_parm_no_rsp(ph2c, pwriterfparm, GEN_CMD_CODE(_SetRFReg)); 751 752 pwriterfparm->offset = offset; 753 pwriterfparm->value = val; 754 755 res = rtw_enqueue_cmd(pcmdpriv, ph2c); 756exit: 757_func_exit_; 758 return res; 759} 760 761u8 rtw_getrfreg_cmd(struct adapter *padapter, u8 offset, u8 *pval) 762{ 763 struct cmd_obj *ph2c; 764 struct readRF_parm *prdrfparm; 765 struct cmd_priv *pcmdpriv = &padapter->cmdpriv; 766 u8 res = _SUCCESS; 767 768_func_enter_; 769 770 ph2c = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj)); 771 if (ph2c == NULL) { 772 res = _FAIL; 773 goto exit; 774 } 775 776 prdrfparm = (struct readRF_parm *)rtw_zmalloc(sizeof(struct readRF_parm)); 777 if (prdrfparm == NULL) { 778 kfree(ph2c); 779 res = _FAIL; 780 goto exit; 781 } 782 783 _rtw_init_listhead(&ph2c->list); 784 ph2c->cmdcode = GEN_CMD_CODE(_GetRFReg); 785 ph2c->parmbuf = (unsigned char *)prdrfparm; 786 ph2c->cmdsz = sizeof(struct readRF_parm); 787 ph2c->rsp = pval; 788 ph2c->rspsz = sizeof(struct readRF_rsp); 789 790 prdrfparm->offset = offset; 791 792 res = rtw_enqueue_cmd(pcmdpriv, ph2c); 793 794exit: 795 796_func_exit_; 797 798 return res; 799} 800 801void rtw_getbbrfreg_cmdrsp_callback(struct adapter *padapter, struct cmd_obj *pcmd) 802{ 803 _func_enter_; 804 805 kfree(pcmd->parmbuf); 806 kfree(pcmd); 807 808 if (padapter->registrypriv.mp_mode == 1) 809 padapter->mppriv.workparam.bcompleted = true; 810_func_exit_; 811} 812 813void rtw_readtssi_cmdrsp_callback(struct adapter *padapter, struct cmd_obj *pcmd) 814{ 815 _func_enter_; 816 817 kfree(pcmd->parmbuf); 818 kfree(pcmd); 819 820 if (padapter->registrypriv.mp_mode == 1) 821 padapter->mppriv.workparam.bcompleted = true; 822_func_exit_; 823} 824 825u8 rtw_createbss_cmd(struct adapter *padapter) 826{ 827 struct cmd_obj *pcmd; 828 struct cmd_priv *pcmdpriv = &padapter->cmdpriv; 829 struct mlme_priv *pmlmepriv = &padapter->mlmepriv; 830 struct wlan_bssid_ex *pdev_network = &padapter->registrypriv.dev_network; 831 u8 res = _SUCCESS; 832 833_func_enter_; 834 835 rtw_led_control(padapter, LED_CTL_START_TO_LINK); 836 837 if (pmlmepriv->assoc_ssid.SsidLength == 0) 838 RT_TRACE(_module_rtl871x_cmd_c_, _drv_info_, (" createbss for Any SSid:%s\n", pmlmepriv->assoc_ssid.Ssid)); 839 else 840 RT_TRACE(_module_rtl871x_cmd_c_, _drv_info_, (" createbss for SSid:%s\n", pmlmepriv->assoc_ssid.Ssid)); 841 842 pcmd = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj)); 843 if (pcmd == NULL) { 844 res = _FAIL; 845 goto exit; 846 } 847 848 _rtw_init_listhead(&pcmd->list); 849 pcmd->cmdcode = _CreateBss_CMD_; 850 pcmd->parmbuf = (unsigned char *)pdev_network; 851 pcmd->cmdsz = get_wlan_bssid_ex_sz((struct wlan_bssid_ex *)pdev_network); 852 pcmd->rsp = NULL; 853 pcmd->rspsz = 0; 854 pdev_network->Length = pcmd->cmdsz; 855 res = rtw_enqueue_cmd(pcmdpriv, pcmd); 856exit: 857 858_func_exit_; 859 860 return res; 861} 862 863u8 rtw_createbss_cmd_ex(struct adapter *padapter, unsigned char *pbss, unsigned int sz) 864{ 865 struct cmd_obj *pcmd; 866 struct cmd_priv *pcmdpriv = &padapter->cmdpriv; 867 u8 res = _SUCCESS; 868 869_func_enter_; 870 871 pcmd = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj)); 872 if (pcmd == NULL) { 873 res = _FAIL; 874 goto exit; 875 } 876 877 _rtw_init_listhead(&pcmd->list); 878 pcmd->cmdcode = GEN_CMD_CODE(_CreateBss); 879 pcmd->parmbuf = pbss; 880 pcmd->cmdsz = sz; 881 pcmd->rsp = NULL; 882 pcmd->rspsz = 0; 883 884 res = rtw_enqueue_cmd(pcmdpriv, pcmd); 885 886exit: 887 888_func_exit_; 889 890 return res; 891} 892 893u8 rtw_joinbss_cmd(struct adapter *padapter, struct wlan_network *pnetwork) 894{ 895 u8 res = _SUCCESS; 896 uint t_len = 0; 897 struct wlan_bssid_ex *psecnetwork; 898 struct cmd_obj *pcmd; 899 struct cmd_priv *pcmdpriv = &padapter->cmdpriv; 900 struct mlme_priv *pmlmepriv = &padapter->mlmepriv; 901 struct qos_priv *pqospriv = &pmlmepriv->qospriv; 902 struct security_priv *psecuritypriv = &padapter->securitypriv; 903 struct registry_priv *pregistrypriv = &padapter->registrypriv; 904 struct ht_priv *phtpriv = &pmlmepriv->htpriv; 905 enum ndis_802_11_network_infra ndis_network_mode = pnetwork->network.InfrastructureMode; 906 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; 907 struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); 908 909_func_enter_; 910 911 rtw_led_control(padapter, LED_CTL_START_TO_LINK); 912 913 if (pmlmepriv->assoc_ssid.SsidLength == 0) { 914 RT_TRACE(_module_rtl871x_cmd_c_, _drv_info_, ("+Join cmd: Any SSid\n")); 915 } else { 916 RT_TRACE(_module_rtl871x_cmd_c_, _drv_notice_, ("+Join cmd: SSid =[%s]\n", pmlmepriv->assoc_ssid.Ssid)); 917 } 918 919 pcmd = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj)); 920 if (pcmd == NULL) { 921 res = _FAIL; 922 RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_, ("rtw_joinbss_cmd: memory allocate for cmd_obj fail!!!\n")); 923 goto exit; 924 } 925 /* for IEs is fix buf size */ 926 t_len = sizeof(struct wlan_bssid_ex); 927 928 929 /* for hidden ap to set fw_state here */ 930 if (!check_fwstate(pmlmepriv, WIFI_STATION_STATE|WIFI_ADHOC_STATE)) { 931 switch (ndis_network_mode) { 932 case Ndis802_11IBSS: 933 set_fwstate(pmlmepriv, WIFI_ADHOC_STATE); 934 break; 935 case Ndis802_11Infrastructure: 936 set_fwstate(pmlmepriv, WIFI_STATION_STATE); 937 break; 938 case Ndis802_11APMode: 939 case Ndis802_11AutoUnknown: 940 case Ndis802_11InfrastructureMax: 941 break; 942 } 943 } 944 945 psecnetwork = (struct wlan_bssid_ex *)&psecuritypriv->sec_bss; 946 if (psecnetwork == NULL) { 947 if (pcmd != NULL) 948 kfree(pcmd); 949 950 res = _FAIL; 951 952 RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_, ("rtw_joinbss_cmd :psecnetwork == NULL!!!\n")); 953 954 goto exit; 955 } 956 957 _rtw_memset(psecnetwork, 0, t_len); 958 959 memcpy(psecnetwork, &pnetwork->network, get_wlan_bssid_ex_sz(&pnetwork->network)); 960 961 psecuritypriv->authenticator_ie[0] = (unsigned char)psecnetwork->IELength; 962 963 if ((psecnetwork->IELength-12) < (256-1)) { 964 memcpy(&psecuritypriv->authenticator_ie[1], &psecnetwork->IEs[12], psecnetwork->IELength-12); 965 } else { 966 memcpy(&psecuritypriv->authenticator_ie[1], &psecnetwork->IEs[12], (256-1)); 967 } 968 969 psecnetwork->IELength = 0; 970 /* Added by Albert 2009/02/18 */ 971 /* If the the driver wants to use the bssid to create the connection. */ 972 /* If not, we have to copy the connecting AP's MAC address to it so that */ 973 /* the driver just has the bssid information for PMKIDList searching. */ 974 975 if (!pmlmepriv->assoc_by_bssid) 976 memcpy(&pmlmepriv->assoc_bssid[0], &pnetwork->network.MacAddress[0], ETH_ALEN); 977 978 psecnetwork->IELength = rtw_restruct_sec_ie(padapter, &pnetwork->network.IEs[0], &psecnetwork->IEs[0], pnetwork->network.IELength); 979 980 981 pqospriv->qos_option = 0; 982 983 if (pregistrypriv->wmm_enable) { 984 u32 tmp_len; 985 986 tmp_len = rtw_restruct_wmm_ie(padapter, &pnetwork->network.IEs[0], &psecnetwork->IEs[0], pnetwork->network.IELength, psecnetwork->IELength); 987 988 if (psecnetwork->IELength != tmp_len) { 989 psecnetwork->IELength = tmp_len; 990 pqospriv->qos_option = 1; /* There is WMM IE in this corresp. beacon */ 991 } else { 992 pqospriv->qos_option = 0;/* There is no WMM IE in this corresp. beacon */ 993 } 994 } 995 996 phtpriv->ht_option = false; 997 if (pregistrypriv->ht_enable) { 998 /* Added by Albert 2010/06/23 */ 999 /* For the WEP mode, we will use the bg mode to do the connection to avoid some IOT issue. */ 1000 /* Especially for Realtek 8192u SoftAP. */ 1001 if ((padapter->securitypriv.dot11PrivacyAlgrthm != _WEP40_) && 1002 (padapter->securitypriv.dot11PrivacyAlgrthm != _WEP104_) && 1003 (padapter->securitypriv.dot11PrivacyAlgrthm != _TKIP_)) { 1004 /* rtw_restructure_ht_ie */ 1005 rtw_restructure_ht_ie(padapter, &pnetwork->network.IEs[0], &psecnetwork->IEs[0], 1006 pnetwork->network.IELength, &psecnetwork->IELength); 1007 } 1008 } 1009 1010 pmlmeinfo->assoc_AP_vendor = check_assoc_AP(pnetwork->network.IEs, pnetwork->network.IELength); 1011 1012 if (pmlmeinfo->assoc_AP_vendor == HT_IOT_PEER_TENDA) 1013 padapter->pwrctrlpriv.smart_ps = 0; 1014 else 1015 padapter->pwrctrlpriv.smart_ps = padapter->registrypriv.smart_ps; 1016 1017 DBG_88E("%s: smart_ps =%d\n", __func__, padapter->pwrctrlpriv.smart_ps); 1018 1019 pcmd->cmdsz = get_wlan_bssid_ex_sz(psecnetwork);/* get cmdsz before endian conversion */ 1020 1021 _rtw_init_listhead(&pcmd->list); 1022 pcmd->cmdcode = _JoinBss_CMD_;/* GEN_CMD_CODE(_JoinBss) */ 1023 pcmd->parmbuf = (unsigned char *)psecnetwork; 1024 pcmd->rsp = NULL; 1025 pcmd->rspsz = 0; 1026 1027 res = rtw_enqueue_cmd(pcmdpriv, pcmd); 1028 1029exit: 1030 1031_func_exit_; 1032 1033 return res; 1034} 1035 1036u8 rtw_disassoc_cmd(struct adapter *padapter, u32 deauth_timeout_ms, bool enqueue) /* for sta_mode */ 1037{ 1038 struct cmd_obj *cmdobj = NULL; 1039 struct disconnect_parm *param = NULL; 1040 struct cmd_priv *cmdpriv = &padapter->cmdpriv; 1041 u8 res = _SUCCESS; 1042 1043_func_enter_; 1044 1045 RT_TRACE(_module_rtl871x_cmd_c_, _drv_notice_, ("+rtw_disassoc_cmd\n")); 1046 1047 /* prepare cmd parameter */ 1048 param = (struct disconnect_parm *)rtw_zmalloc(sizeof(*param)); 1049 if (param == NULL) { 1050 res = _FAIL; 1051 goto exit; 1052 } 1053 param->deauth_timeout_ms = deauth_timeout_ms; 1054 1055 if (enqueue) { 1056 /* need enqueue, prepare cmd_obj and enqueue */ 1057 cmdobj = (struct cmd_obj *)rtw_zmalloc(sizeof(*cmdobj)); 1058 if (cmdobj == NULL) { 1059 res = _FAIL; 1060 kfree(param); 1061 goto exit; 1062 } 1063 init_h2fwcmd_w_parm_no_rsp(cmdobj, param, _DisConnect_CMD_); 1064 res = rtw_enqueue_cmd(cmdpriv, cmdobj); 1065 } else { 1066 /* no need to enqueue, do the cmd hdl directly and free cmd parameter */ 1067 if (H2C_SUCCESS != disconnect_hdl(padapter, (u8 *)param)) 1068 res = _FAIL; 1069 kfree(param); 1070 } 1071 1072exit: 1073 1074_func_exit_; 1075 1076 return res; 1077} 1078 1079u8 rtw_setopmode_cmd(struct adapter *padapter, enum ndis_802_11_network_infra networktype) 1080{ 1081 struct cmd_obj *ph2c; 1082 struct setopmode_parm *psetop; 1083 1084 struct cmd_priv *pcmdpriv = &padapter->cmdpriv; 1085 u8 res = _SUCCESS; 1086 1087_func_enter_; 1088 1089 ph2c = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj)); 1090 if (ph2c == NULL) { 1091 res = false; 1092 goto exit; 1093 } 1094 psetop = (struct setopmode_parm *)rtw_zmalloc(sizeof(struct setopmode_parm)); 1095 1096 if (psetop == NULL) { 1097 kfree(ph2c); 1098 res = false; 1099 goto exit; 1100 } 1101 1102 init_h2fwcmd_w_parm_no_rsp(ph2c, psetop, _SetOpMode_CMD_); 1103 psetop->mode = (u8)networktype; 1104 1105 res = rtw_enqueue_cmd(pcmdpriv, ph2c); 1106 1107exit: 1108 1109_func_exit_; 1110 1111 return res; 1112} 1113 1114u8 rtw_setstakey_cmd(struct adapter *padapter, u8 *psta, u8 unicast_key) 1115{ 1116 struct cmd_obj *ph2c; 1117 struct set_stakey_parm *psetstakey_para; 1118 struct cmd_priv *pcmdpriv = &padapter->cmdpriv; 1119 struct set_stakey_rsp *psetstakey_rsp = NULL; 1120 1121 struct mlme_priv *pmlmepriv = &padapter->mlmepriv; 1122 struct security_priv *psecuritypriv = &padapter->securitypriv; 1123 struct sta_info *sta = (struct sta_info *)psta; 1124 u8 res = _SUCCESS; 1125 1126_func_enter_; 1127 1128 ph2c = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj)); 1129 if (ph2c == NULL) { 1130 res = _FAIL; 1131 goto exit; 1132 } 1133 1134 psetstakey_para = (struct set_stakey_parm *)rtw_zmalloc(sizeof(struct set_stakey_parm)); 1135 if (psetstakey_para == NULL) { 1136 kfree(ph2c); 1137 res = _FAIL; 1138 goto exit; 1139 } 1140 1141 psetstakey_rsp = (struct set_stakey_rsp *)rtw_zmalloc(sizeof(struct set_stakey_rsp)); 1142 if (psetstakey_rsp == NULL) { 1143 kfree(ph2c); 1144 kfree(psetstakey_para); 1145 res = _FAIL; 1146 goto exit; 1147 } 1148 1149 init_h2fwcmd_w_parm_no_rsp(ph2c, psetstakey_para, _SetStaKey_CMD_); 1150 ph2c->rsp = (u8 *)psetstakey_rsp; 1151 ph2c->rspsz = sizeof(struct set_stakey_rsp); 1152 1153 memcpy(psetstakey_para->addr, sta->hwaddr, ETH_ALEN); 1154 1155 if (check_fwstate(pmlmepriv, WIFI_STATION_STATE)) 1156 psetstakey_para->algorithm = (unsigned char) psecuritypriv->dot11PrivacyAlgrthm; 1157 else 1158 GET_ENCRY_ALGO(psecuritypriv, sta, psetstakey_para->algorithm, false); 1159 1160 if (unicast_key) 1161 memcpy(&psetstakey_para->key, &sta->dot118021x_UncstKey, 16); 1162 else 1163 memcpy(&psetstakey_para->key, &psecuritypriv->dot118021XGrpKey[psecuritypriv->dot118021XGrpKeyid].skey, 16); 1164 1165 /* jeff: set this because at least sw key is ready */ 1166 padapter->securitypriv.busetkipkey = true; 1167 1168 res = rtw_enqueue_cmd(pcmdpriv, ph2c); 1169 1170exit: 1171 1172_func_exit_; 1173 1174 return res; 1175} 1176 1177u8 rtw_clearstakey_cmd(struct adapter *padapter, u8 *psta, u8 entry, u8 enqueue) 1178{ 1179 struct cmd_obj *ph2c; 1180 struct set_stakey_parm *psetstakey_para; 1181 struct cmd_priv *pcmdpriv = &padapter->cmdpriv; 1182 struct set_stakey_rsp *psetstakey_rsp = NULL; 1183 struct sta_info *sta = (struct sta_info *)psta; 1184 u8 res = _SUCCESS; 1185 1186_func_enter_; 1187 1188 if (!enqueue) { 1189 clear_cam_entry(padapter, entry); 1190 } else { 1191 ph2c = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj)); 1192 if (ph2c == NULL) { 1193 res = _FAIL; 1194 goto exit; 1195 } 1196 1197 psetstakey_para = (struct set_stakey_parm *)rtw_zmalloc(sizeof(struct set_stakey_parm)); 1198 if (psetstakey_para == NULL) { 1199 kfree(ph2c); 1200 res = _FAIL; 1201 goto exit; 1202 } 1203 1204 psetstakey_rsp = (struct set_stakey_rsp *)rtw_zmalloc(sizeof(struct set_stakey_rsp)); 1205 if (psetstakey_rsp == NULL) { 1206 kfree(ph2c); 1207 kfree(psetstakey_para); 1208 res = _FAIL; 1209 goto exit; 1210 } 1211 1212 init_h2fwcmd_w_parm_no_rsp(ph2c, psetstakey_para, _SetStaKey_CMD_); 1213 ph2c->rsp = (u8 *)psetstakey_rsp; 1214 ph2c->rspsz = sizeof(struct set_stakey_rsp); 1215 1216 memcpy(psetstakey_para->addr, sta->hwaddr, ETH_ALEN); 1217 1218 psetstakey_para->algorithm = _NO_PRIVACY_; 1219 1220 psetstakey_para->id = entry; 1221 1222 res = rtw_enqueue_cmd(pcmdpriv, ph2c); 1223 } 1224exit: 1225 1226_func_exit_; 1227 1228 return res; 1229} 1230 1231u8 rtw_setrttbl_cmd(struct adapter *padapter, struct setratable_parm *prate_table) 1232{ 1233 struct cmd_obj *ph2c; 1234 struct setratable_parm *psetrttblparm; 1235 struct cmd_priv *pcmdpriv = &padapter->cmdpriv; 1236 u8 res = _SUCCESS; 1237_func_enter_; 1238 1239 ph2c = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj)); 1240 if (ph2c == NULL) { 1241 res = _FAIL; 1242 goto exit; 1243 } 1244 psetrttblparm = (struct setratable_parm *)rtw_zmalloc(sizeof(struct setratable_parm)); 1245 1246 if (psetrttblparm == NULL) { 1247 kfree(ph2c); 1248 res = _FAIL; 1249 goto exit; 1250 } 1251 1252 init_h2fwcmd_w_parm_no_rsp(ph2c, psetrttblparm, GEN_CMD_CODE(_SetRaTable)); 1253 1254 memcpy(psetrttblparm, prate_table, sizeof(struct setratable_parm)); 1255 1256 res = rtw_enqueue_cmd(pcmdpriv, ph2c); 1257exit: 1258_func_exit_; 1259 return res; 1260} 1261 1262u8 rtw_getrttbl_cmd(struct adapter *padapter, struct getratable_rsp *pval) 1263{ 1264 struct cmd_obj *ph2c; 1265 struct getratable_parm *pgetrttblparm; 1266 struct cmd_priv *pcmdpriv = &padapter->cmdpriv; 1267 u8 res = _SUCCESS; 1268_func_enter_; 1269 1270 ph2c = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj)); 1271 if (ph2c == NULL) { 1272 res = _FAIL; 1273 goto exit; 1274 } 1275 pgetrttblparm = (struct getratable_parm *)rtw_zmalloc(sizeof(struct getratable_parm)); 1276 1277 if (pgetrttblparm == NULL) { 1278 kfree(ph2c); 1279 res = _FAIL; 1280 goto exit; 1281 } 1282 1283/* init_h2fwcmd_w_parm_no_rsp(ph2c, psetrttblparm, GEN_CMD_CODE(_SetRaTable)); */ 1284 1285 _rtw_init_listhead(&ph2c->list); 1286 ph2c->cmdcode = GEN_CMD_CODE(_GetRaTable); 1287 ph2c->parmbuf = (unsigned char *)pgetrttblparm; 1288 ph2c->cmdsz = sizeof(struct getratable_parm); 1289 ph2c->rsp = (u8 *)pval; 1290 ph2c->rspsz = sizeof(struct getratable_rsp); 1291 1292 pgetrttblparm->rsvd = 0x0; 1293 1294 res = rtw_enqueue_cmd(pcmdpriv, ph2c); 1295exit: 1296_func_exit_; 1297 return res; 1298} 1299 1300u8 rtw_setassocsta_cmd(struct adapter *padapter, u8 *mac_addr) 1301{ 1302 struct cmd_priv *pcmdpriv = &padapter->cmdpriv; 1303 struct cmd_obj *ph2c; 1304 struct set_assocsta_parm *psetassocsta_para; 1305 struct set_stakey_rsp *psetassocsta_rsp = NULL; 1306 1307 u8 res = _SUCCESS; 1308 1309_func_enter_; 1310 1311 ph2c = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj)); 1312 if (ph2c == NULL) { 1313 res = _FAIL; 1314 goto exit; 1315 } 1316 1317 psetassocsta_para = (struct set_assocsta_parm *)rtw_zmalloc(sizeof(struct set_assocsta_parm)); 1318 if (psetassocsta_para == NULL) { 1319 kfree(ph2c); 1320 res = _FAIL; 1321 goto exit; 1322 } 1323 1324 psetassocsta_rsp = (struct set_stakey_rsp *)rtw_zmalloc(sizeof(struct set_assocsta_rsp)); 1325 if (psetassocsta_rsp == NULL) { 1326 kfree(ph2c); 1327 kfree(psetassocsta_para); 1328 return _FAIL; 1329 } 1330 1331 init_h2fwcmd_w_parm_no_rsp(ph2c, psetassocsta_para, _SetAssocSta_CMD_); 1332 ph2c->rsp = (u8 *)psetassocsta_rsp; 1333 ph2c->rspsz = sizeof(struct set_assocsta_rsp); 1334 1335 memcpy(psetassocsta_para->addr, mac_addr, ETH_ALEN); 1336 1337 res = rtw_enqueue_cmd(pcmdpriv, ph2c); 1338 1339exit: 1340 1341_func_exit_; 1342 1343 return res; 1344 } 1345 1346u8 rtw_addbareq_cmd(struct adapter *padapter, u8 tid, u8 *addr) 1347{ 1348 struct cmd_priv *pcmdpriv = &padapter->cmdpriv; 1349 struct cmd_obj *ph2c; 1350 struct addBaReq_parm *paddbareq_parm; 1351 u8 res = _SUCCESS; 1352 1353_func_enter_; 1354 1355 ph2c = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj)); 1356 if (ph2c == NULL) { 1357 res = _FAIL; 1358 goto exit; 1359 } 1360 1361 paddbareq_parm = (struct addBaReq_parm *)rtw_zmalloc(sizeof(struct addBaReq_parm)); 1362 if (paddbareq_parm == NULL) { 1363 kfree(ph2c); 1364 res = _FAIL; 1365 goto exit; 1366 } 1367 1368 paddbareq_parm->tid = tid; 1369 memcpy(paddbareq_parm->addr, addr, ETH_ALEN); 1370 1371 init_h2fwcmd_w_parm_no_rsp(ph2c, paddbareq_parm, GEN_CMD_CODE(_AddBAReq)); 1372 1373 /* DBG_88E("rtw_addbareq_cmd, tid =%d\n", tid); */ 1374 1375 /* rtw_enqueue_cmd(pcmdpriv, ph2c); */ 1376 res = rtw_enqueue_cmd(pcmdpriv, ph2c); 1377 1378exit: 1379 1380_func_exit_; 1381 1382 return res; 1383} 1384 1385u8 rtw_dynamic_chk_wk_cmd(struct adapter *padapter) 1386{ 1387 struct cmd_obj *ph2c; 1388 struct drvextra_cmd_parm *pdrvextra_cmd_parm; 1389 struct cmd_priv *pcmdpriv = &padapter->cmdpriv; 1390 u8 res = _SUCCESS; 1391 1392_func_enter_; 1393 1394 ph2c = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj)); 1395 if (ph2c == NULL) { 1396 res = _FAIL; 1397 goto exit; 1398 } 1399 1400 pdrvextra_cmd_parm = (struct drvextra_cmd_parm *)rtw_zmalloc(sizeof(struct drvextra_cmd_parm)); 1401 if (pdrvextra_cmd_parm == NULL) { 1402 kfree(ph2c); 1403 res = _FAIL; 1404 goto exit; 1405 } 1406 1407 pdrvextra_cmd_parm->ec_id = DYNAMIC_CHK_WK_CID; 1408 pdrvextra_cmd_parm->type_size = 0; 1409 pdrvextra_cmd_parm->pbuf = (u8 *)padapter; 1410 1411 init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, GEN_CMD_CODE(_Set_Drv_Extra)); 1412 1413 1414 /* rtw_enqueue_cmd(pcmdpriv, ph2c); */ 1415 res = rtw_enqueue_cmd(pcmdpriv, ph2c); 1416exit: 1417_func_exit_; 1418 return res; 1419} 1420 1421u8 rtw_set_ch_cmd(struct adapter *padapter, u8 ch, u8 bw, u8 ch_offset, u8 enqueue) 1422{ 1423 struct cmd_obj *pcmdobj; 1424 struct set_ch_parm *set_ch_parm; 1425 struct cmd_priv *pcmdpriv = &padapter->cmdpriv; 1426 1427 u8 res = _SUCCESS; 1428 1429_func_enter_; 1430 1431 DBG_88E(FUNC_NDEV_FMT" ch:%u, bw:%u, ch_offset:%u\n", 1432 FUNC_NDEV_ARG(padapter->pnetdev), ch, bw, ch_offset); 1433 1434 /* check input parameter */ 1435 1436 /* prepare cmd parameter */ 1437 set_ch_parm = (struct set_ch_parm *)rtw_zmalloc(sizeof(*set_ch_parm)); 1438 if (set_ch_parm == NULL) { 1439 res = _FAIL; 1440 goto exit; 1441 } 1442 set_ch_parm->ch = ch; 1443 set_ch_parm->bw = bw; 1444 set_ch_parm->ch_offset = ch_offset; 1445 1446 if (enqueue) { 1447 /* need enqueue, prepare cmd_obj and enqueue */ 1448 pcmdobj = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj)); 1449 if (pcmdobj == NULL) { 1450 kfree(set_ch_parm); 1451 res = _FAIL; 1452 goto exit; 1453 } 1454 1455 init_h2fwcmd_w_parm_no_rsp(pcmdobj, set_ch_parm, GEN_CMD_CODE(_SetChannel)); 1456 res = rtw_enqueue_cmd(pcmdpriv, pcmdobj); 1457 } else { 1458 /* no need to enqueue, do the cmd hdl directly and free cmd parameter */ 1459 if (H2C_SUCCESS != set_ch_hdl(padapter, (u8 *)set_ch_parm)) 1460 res = _FAIL; 1461 1462 kfree(set_ch_parm); 1463 } 1464 1465 /* do something based on res... */ 1466 1467exit: 1468 1469 DBG_88E(FUNC_NDEV_FMT" res:%u\n", FUNC_NDEV_ARG(padapter->pnetdev), res); 1470 1471_func_exit_; 1472 1473 return res; 1474} 1475 1476u8 rtw_set_chplan_cmd(struct adapter *padapter, u8 chplan, u8 enqueue) 1477{ 1478 struct cmd_obj *pcmdobj; 1479 struct SetChannelPlan_param *setChannelPlan_param; 1480 struct cmd_priv *pcmdpriv = &padapter->cmdpriv; 1481 1482 u8 res = _SUCCESS; 1483 1484_func_enter_; 1485 1486 RT_TRACE(_module_rtl871x_cmd_c_, _drv_notice_, ("+rtw_set_chplan_cmd\n")); 1487 1488 /* check input parameter */ 1489 if (!rtw_is_channel_plan_valid(chplan)) { 1490 res = _FAIL; 1491 goto exit; 1492 } 1493 1494 /* prepare cmd parameter */ 1495 setChannelPlan_param = (struct SetChannelPlan_param *)rtw_zmalloc(sizeof(struct SetChannelPlan_param)); 1496 if (setChannelPlan_param == NULL) { 1497 res = _FAIL; 1498 goto exit; 1499 } 1500 setChannelPlan_param->channel_plan = chplan; 1501 1502 if (enqueue) { 1503 /* need enqueue, prepare cmd_obj and enqueue */ 1504 pcmdobj = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj)); 1505 if (pcmdobj == NULL) { 1506 kfree(setChannelPlan_param); 1507 res = _FAIL; 1508 goto exit; 1509 } 1510 1511 init_h2fwcmd_w_parm_no_rsp(pcmdobj, setChannelPlan_param, GEN_CMD_CODE(_SetChannelPlan)); 1512 res = rtw_enqueue_cmd(pcmdpriv, pcmdobj); 1513 } else { 1514 /* no need to enqueue, do the cmd hdl directly and free cmd parameter */ 1515 if (H2C_SUCCESS != set_chplan_hdl(padapter, (unsigned char *)setChannelPlan_param)) 1516 res = _FAIL; 1517 1518 kfree(setChannelPlan_param); 1519 } 1520 1521 /* do something based on res... */ 1522 if (res == _SUCCESS) 1523 padapter->mlmepriv.ChannelPlan = chplan; 1524 1525exit: 1526 1527_func_exit_; 1528 1529 return res; 1530} 1531 1532u8 rtw_led_blink_cmd(struct adapter *padapter, struct LED_871x *pLed) 1533{ 1534 struct cmd_obj *pcmdobj; 1535 struct LedBlink_param *ledBlink_param; 1536 struct cmd_priv *pcmdpriv = &padapter->cmdpriv; 1537 1538 u8 res = _SUCCESS; 1539 1540_func_enter_; 1541 1542 RT_TRACE(_module_rtl871x_cmd_c_, _drv_notice_, ("+rtw_led_blink_cmd\n")); 1543 1544 pcmdobj = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj)); 1545 if (pcmdobj == NULL) { 1546 res = _FAIL; 1547 goto exit; 1548 } 1549 1550 ledBlink_param = (struct LedBlink_param *)rtw_zmalloc(sizeof(struct LedBlink_param)); 1551 if (ledBlink_param == NULL) { 1552 kfree(pcmdobj); 1553 res = _FAIL; 1554 goto exit; 1555 } 1556 1557 ledBlink_param->pLed = pLed; 1558 1559 init_h2fwcmd_w_parm_no_rsp(pcmdobj, ledBlink_param, GEN_CMD_CODE(_LedBlink)); 1560 res = rtw_enqueue_cmd(pcmdpriv, pcmdobj); 1561 1562exit: 1563 1564_func_exit_; 1565 1566 return res; 1567} 1568 1569u8 rtw_set_csa_cmd(struct adapter *padapter, u8 new_ch_no) 1570{ 1571 struct cmd_obj *pcmdobj; 1572 struct SetChannelSwitch_param *setChannelSwitch_param; 1573 struct cmd_priv *pcmdpriv = &padapter->cmdpriv; 1574 1575 u8 res = _SUCCESS; 1576 1577_func_enter_; 1578 1579 RT_TRACE(_module_rtl871x_cmd_c_, _drv_notice_, ("+rtw_set_csa_cmd\n")); 1580 1581 pcmdobj = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj)); 1582 if (pcmdobj == NULL) { 1583 res = _FAIL; 1584 goto exit; 1585 } 1586 1587 setChannelSwitch_param = (struct SetChannelSwitch_param *)rtw_zmalloc(sizeof(struct SetChannelSwitch_param)); 1588 if (setChannelSwitch_param == NULL) { 1589 kfree(pcmdobj); 1590 res = _FAIL; 1591 goto exit; 1592 } 1593 1594 setChannelSwitch_param->new_ch_no = new_ch_no; 1595 1596 init_h2fwcmd_w_parm_no_rsp(pcmdobj, setChannelSwitch_param, GEN_CMD_CODE(_SetChannelSwitch)); 1597 res = rtw_enqueue_cmd(pcmdpriv, pcmdobj); 1598 1599exit: 1600 1601_func_exit_; 1602 1603 return res; 1604} 1605 1606u8 rtw_tdls_cmd(struct adapter *padapter, u8 *addr, u8 option) 1607{ 1608 return _SUCCESS; 1609} 1610 1611static void traffic_status_watchdog(struct adapter *padapter) 1612{ 1613 u8 bEnterPS; 1614 u8 bBusyTraffic = false, bTxBusyTraffic = false, bRxBusyTraffic = false; 1615 u8 bHigherBusyTraffic = false, bHigherBusyRxTraffic = false, bHigherBusyTxTraffic = false; 1616 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); 1617 1618 /* */ 1619 /* Determine if our traffic is busy now */ 1620 /* */ 1621 if (check_fwstate(pmlmepriv, _FW_LINKED)) { 1622 if (pmlmepriv->LinkDetectInfo.NumRxOkInPeriod > 100 || 1623 pmlmepriv->LinkDetectInfo.NumTxOkInPeriod > 100) { 1624 bBusyTraffic = true; 1625 1626 if (pmlmepriv->LinkDetectInfo.NumRxOkInPeriod > pmlmepriv->LinkDetectInfo.NumTxOkInPeriod) 1627 bRxBusyTraffic = true; 1628 else 1629 bTxBusyTraffic = true; 1630 } 1631 1632 /* Higher Tx/Rx data. */ 1633 if (pmlmepriv->LinkDetectInfo.NumRxOkInPeriod > 4000 || 1634 pmlmepriv->LinkDetectInfo.NumTxOkInPeriod > 4000) { 1635 bHigherBusyTraffic = true; 1636 1637 if (pmlmepriv->LinkDetectInfo.NumRxOkInPeriod > pmlmepriv->LinkDetectInfo.NumTxOkInPeriod) 1638 bHigherBusyRxTraffic = true; 1639 else 1640 bHigherBusyTxTraffic = true; 1641 } 1642 1643 /* check traffic for powersaving. */ 1644 if (((pmlmepriv->LinkDetectInfo.NumRxUnicastOkInPeriod + pmlmepriv->LinkDetectInfo.NumTxOkInPeriod) > 8) || 1645 (pmlmepriv->LinkDetectInfo.NumRxUnicastOkInPeriod > 2)) 1646 bEnterPS = false; 1647 else 1648 bEnterPS = true; 1649 1650 /* LeisurePS only work in infra mode. */ 1651 if (bEnterPS) 1652 LPS_Enter(padapter); 1653 else 1654 LPS_Leave(padapter); 1655 } else { 1656 LPS_Leave(padapter); 1657 } 1658 1659 pmlmepriv->LinkDetectInfo.NumRxOkInPeriod = 0; 1660 pmlmepriv->LinkDetectInfo.NumTxOkInPeriod = 0; 1661 pmlmepriv->LinkDetectInfo.NumRxUnicastOkInPeriod = 0; 1662 pmlmepriv->LinkDetectInfo.bBusyTraffic = bBusyTraffic; 1663 pmlmepriv->LinkDetectInfo.bTxBusyTraffic = bTxBusyTraffic; 1664 pmlmepriv->LinkDetectInfo.bRxBusyTraffic = bRxBusyTraffic; 1665 pmlmepriv->LinkDetectInfo.bHigherBusyTraffic = bHigherBusyTraffic; 1666 pmlmepriv->LinkDetectInfo.bHigherBusyRxTraffic = bHigherBusyRxTraffic; 1667 pmlmepriv->LinkDetectInfo.bHigherBusyTxTraffic = bHigherBusyTxTraffic; 1668} 1669 1670static void dynamic_chk_wk_hdl(struct adapter *padapter, u8 *pbuf, int sz) 1671{ 1672 struct mlme_priv *pmlmepriv; 1673 1674 padapter = (struct adapter *)pbuf; 1675 pmlmepriv = &(padapter->mlmepriv); 1676 1677#ifdef CONFIG_88EU_AP_MODE 1678 if (check_fwstate(pmlmepriv, WIFI_AP_STATE) == true) 1679 expire_timeout_chk(padapter); 1680#endif 1681 1682 rtw_hal_sreset_xmit_status_check(padapter); 1683 1684 linked_status_chk(padapter); 1685 traffic_status_watchdog(padapter); 1686 1687 rtw_hal_dm_watchdog(padapter); 1688} 1689 1690static void lps_ctrl_wk_hdl(struct adapter *padapter, u8 lps_ctrl_type) 1691{ 1692 struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv; 1693 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); 1694 u8 mstatus; 1695 1696_func_enter_; 1697 1698 if ((check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) == true) || 1699 (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE) == true)) 1700 return; 1701 1702 switch (lps_ctrl_type) { 1703 case LPS_CTRL_SCAN: 1704 if (check_fwstate(pmlmepriv, _FW_LINKED) == true) { 1705 /* connect */ 1706 LPS_Leave(padapter); 1707 } 1708 break; 1709 case LPS_CTRL_JOINBSS: 1710 LPS_Leave(padapter); 1711 break; 1712 case LPS_CTRL_CONNECT: 1713 mstatus = 1;/* connect */ 1714 /* Reset LPS Setting */ 1715 padapter->pwrctrlpriv.LpsIdleCount = 0; 1716 rtw_hal_set_hwreg(padapter, HW_VAR_H2C_FW_JOINBSSRPT, (u8 *)(&mstatus)); 1717 break; 1718 case LPS_CTRL_DISCONNECT: 1719 mstatus = 0;/* disconnect */ 1720 LPS_Leave(padapter); 1721 rtw_hal_set_hwreg(padapter, HW_VAR_H2C_FW_JOINBSSRPT, (u8 *)(&mstatus)); 1722 break; 1723 case LPS_CTRL_SPECIAL_PACKET: 1724 /* DBG_88E("LPS_CTRL_SPECIAL_PACKET\n"); */ 1725 pwrpriv->DelayLPSLastTimeStamp = rtw_get_current_time(); 1726 LPS_Leave(padapter); 1727 break; 1728 case LPS_CTRL_LEAVE: 1729 LPS_Leave(padapter); 1730 break; 1731 default: 1732 break; 1733 } 1734 1735_func_exit_; 1736} 1737 1738u8 rtw_lps_ctrl_wk_cmd(struct adapter *padapter, u8 lps_ctrl_type, u8 enqueue) 1739{ 1740 struct cmd_obj *ph2c; 1741 struct drvextra_cmd_parm *pdrvextra_cmd_parm; 1742 struct cmd_priv *pcmdpriv = &padapter->cmdpriv; 1743 /* struct pwrctrl_priv *pwrctrlpriv = &padapter->pwrctrlpriv; */ 1744 u8 res = _SUCCESS; 1745 1746_func_enter_; 1747 1748 /* if (!pwrctrlpriv->bLeisurePs) */ 1749 /* return res; */ 1750 1751 if (enqueue) { 1752 ph2c = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj)); 1753 if (ph2c == NULL) { 1754 res = _FAIL; 1755 goto exit; 1756 } 1757 1758 pdrvextra_cmd_parm = (struct drvextra_cmd_parm *)rtw_zmalloc(sizeof(struct drvextra_cmd_parm)); 1759 if (pdrvextra_cmd_parm == NULL) { 1760 kfree(ph2c); 1761 res = _FAIL; 1762 goto exit; 1763 } 1764 1765 pdrvextra_cmd_parm->ec_id = LPS_CTRL_WK_CID; 1766 pdrvextra_cmd_parm->type_size = lps_ctrl_type; 1767 pdrvextra_cmd_parm->pbuf = NULL; 1768 1769 init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, GEN_CMD_CODE(_Set_Drv_Extra)); 1770 1771 res = rtw_enqueue_cmd(pcmdpriv, ph2c); 1772 } else { 1773 lps_ctrl_wk_hdl(padapter, lps_ctrl_type); 1774 } 1775 1776exit: 1777 1778_func_exit_; 1779 1780 return res; 1781} 1782 1783static void rpt_timer_setting_wk_hdl(struct adapter *padapter, u16 min_time) 1784{ 1785 rtw_hal_set_hwreg(padapter, HW_VAR_RPT_TIMER_SETTING, (u8 *)(&min_time)); 1786} 1787 1788u8 rtw_rpt_timer_cfg_cmd(struct adapter *padapter, u16 min_time) 1789{ 1790 struct cmd_obj *ph2c; 1791 struct drvextra_cmd_parm *pdrvextra_cmd_parm; 1792 struct cmd_priv *pcmdpriv = &padapter->cmdpriv; 1793 1794 u8 res = _SUCCESS; 1795 1796_func_enter_; 1797 ph2c = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj)); 1798 if (ph2c == NULL) { 1799 res = _FAIL; 1800 goto exit; 1801 } 1802 1803 pdrvextra_cmd_parm = (struct drvextra_cmd_parm *)rtw_zmalloc(sizeof(struct drvextra_cmd_parm)); 1804 if (pdrvextra_cmd_parm == NULL) { 1805 kfree(ph2c); 1806 res = _FAIL; 1807 goto exit; 1808 } 1809 1810 pdrvextra_cmd_parm->ec_id = RTP_TIMER_CFG_WK_CID; 1811 pdrvextra_cmd_parm->type_size = min_time; 1812 pdrvextra_cmd_parm->pbuf = NULL; 1813 init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, GEN_CMD_CODE(_Set_Drv_Extra)); 1814 res = rtw_enqueue_cmd(pcmdpriv, ph2c); 1815exit: 1816 1817_func_exit_; 1818 1819 return res; 1820} 1821 1822static void antenna_select_wk_hdl(struct adapter *padapter, u8 antenna) 1823{ 1824 rtw_hal_set_hwreg(padapter, HW_VAR_ANTENNA_DIVERSITY_SELECT, (u8 *)(&antenna)); 1825} 1826 1827u8 rtw_antenna_select_cmd(struct adapter *padapter, u8 antenna, u8 enqueue) 1828{ 1829 struct cmd_obj *ph2c; 1830 struct drvextra_cmd_parm *pdrvextra_cmd_parm; 1831 struct cmd_priv *pcmdpriv = &padapter->cmdpriv; 1832 u8 support_ant_div; 1833 u8 res = _SUCCESS; 1834 1835_func_enter_; 1836 rtw_hal_get_def_var(padapter, HAL_DEF_IS_SUPPORT_ANT_DIV, &support_ant_div); 1837 if (!support_ant_div) 1838 return res; 1839 1840 if (enqueue) { 1841 ph2c = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj)); 1842 if (ph2c == NULL) { 1843 res = _FAIL; 1844 goto exit; 1845 } 1846 1847 pdrvextra_cmd_parm = (struct drvextra_cmd_parm *)rtw_zmalloc(sizeof(struct drvextra_cmd_parm)); 1848 if (pdrvextra_cmd_parm == NULL) { 1849 kfree(ph2c); 1850 res = _FAIL; 1851 goto exit; 1852 } 1853 1854 pdrvextra_cmd_parm->ec_id = ANT_SELECT_WK_CID; 1855 pdrvextra_cmd_parm->type_size = antenna; 1856 pdrvextra_cmd_parm->pbuf = NULL; 1857 init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, GEN_CMD_CODE(_Set_Drv_Extra)); 1858 1859 res = rtw_enqueue_cmd(pcmdpriv, ph2c); 1860 } else { 1861 antenna_select_wk_hdl(padapter, antenna); 1862 } 1863exit: 1864 1865_func_exit_; 1866 1867 return res; 1868} 1869 1870static void power_saving_wk_hdl(struct adapter *padapter, u8 *pbuf, int sz) 1871{ 1872 rtw_ps_processor(padapter); 1873} 1874 1875#ifdef CONFIG_88EU_P2P 1876u8 p2p_protocol_wk_cmd(struct adapter *padapter, int intCmdType) 1877{ 1878 struct cmd_obj *ph2c; 1879 struct drvextra_cmd_parm *pdrvextra_cmd_parm; 1880 struct wifidirect_info *pwdinfo = &(padapter->wdinfo); 1881 struct cmd_priv *pcmdpriv = &padapter->cmdpriv; 1882 u8 res = _SUCCESS; 1883 1884_func_enter_; 1885 1886 if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE)) 1887 return res; 1888 1889 ph2c = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj)); 1890 if (ph2c == NULL) { 1891 res = _FAIL; 1892 goto exit; 1893 } 1894 1895 pdrvextra_cmd_parm = (struct drvextra_cmd_parm *)rtw_zmalloc(sizeof(struct drvextra_cmd_parm)); 1896 if (pdrvextra_cmd_parm == NULL) { 1897 kfree(ph2c); 1898 res = _FAIL; 1899 goto exit; 1900 } 1901 1902 pdrvextra_cmd_parm->ec_id = P2P_PROTO_WK_CID; 1903 pdrvextra_cmd_parm->type_size = intCmdType; /* As the command tppe. */ 1904 pdrvextra_cmd_parm->pbuf = NULL; /* Must be NULL here */ 1905 1906 init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, GEN_CMD_CODE(_Set_Drv_Extra)); 1907 1908 res = rtw_enqueue_cmd(pcmdpriv, ph2c); 1909 1910exit: 1911 1912_func_exit_; 1913 1914 return res; 1915} 1916#endif /* CONFIG_88EU_P2P */ 1917 1918u8 rtw_ps_cmd(struct adapter *padapter) 1919{ 1920 struct cmd_obj *ppscmd; 1921 struct drvextra_cmd_parm *pdrvextra_cmd_parm; 1922 struct cmd_priv *pcmdpriv = &padapter->cmdpriv; 1923 1924 u8 res = _SUCCESS; 1925_func_enter_; 1926 1927 ppscmd = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj)); 1928 if (ppscmd == NULL) { 1929 res = _FAIL; 1930 goto exit; 1931 } 1932 1933 pdrvextra_cmd_parm = (struct drvextra_cmd_parm *)rtw_zmalloc(sizeof(struct drvextra_cmd_parm)); 1934 if (pdrvextra_cmd_parm == NULL) { 1935 kfree(ppscmd); 1936 res = _FAIL; 1937 goto exit; 1938 } 1939 1940 pdrvextra_cmd_parm->ec_id = POWER_SAVING_CTRL_WK_CID; 1941 pdrvextra_cmd_parm->pbuf = NULL; 1942 init_h2fwcmd_w_parm_no_rsp(ppscmd, pdrvextra_cmd_parm, GEN_CMD_CODE(_Set_Drv_Extra)); 1943 1944 res = rtw_enqueue_cmd(pcmdpriv, ppscmd); 1945 1946exit: 1947 1948_func_exit_; 1949 1950 return res; 1951} 1952 1953#ifdef CONFIG_88EU_AP_MODE 1954 1955static void rtw_chk_hi_queue_hdl(struct adapter *padapter) 1956{ 1957 int cnt = 0; 1958 struct sta_info *psta_bmc; 1959 struct sta_priv *pstapriv = &padapter->stapriv; 1960 1961 psta_bmc = rtw_get_bcmc_stainfo(padapter); 1962 if (!psta_bmc) 1963 return; 1964 1965 if (psta_bmc->sleepq_len == 0) { 1966 u8 val = 0; 1967 1968 /* while ((rtw_read32(padapter, 0x414)&0x00ffff00)!= 0) */ 1969 /* while ((rtw_read32(padapter, 0x414)&0x0000ff00)!= 0) */ 1970 1971 rtw_hal_get_hwreg(padapter, HW_VAR_CHK_HI_QUEUE_EMPTY, &val); 1972 1973 while (!val) { 1974 rtw_msleep_os(100); 1975 1976 cnt++; 1977 1978 if (cnt > 10) 1979 break; 1980 1981 rtw_hal_get_hwreg(padapter, HW_VAR_CHK_HI_QUEUE_EMPTY, &val); 1982 } 1983 1984 if (cnt <= 10) { 1985 pstapriv->tim_bitmap &= ~BIT(0); 1986 pstapriv->sta_dz_bitmap &= ~BIT(0); 1987 1988 update_beacon(padapter, _TIM_IE_, NULL, false); 1989 } else { /* re check again */ 1990 rtw_chk_hi_queue_cmd(padapter); 1991 } 1992 } 1993} 1994 1995u8 rtw_chk_hi_queue_cmd(struct adapter *padapter) 1996{ 1997 struct cmd_obj *ph2c; 1998 struct drvextra_cmd_parm *pdrvextra_cmd_parm; 1999 struct cmd_priv *pcmdpriv = &padapter->cmdpriv; 2000 u8 res = _SUCCESS; 2001 2002 ph2c = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj)); 2003 if (ph2c == NULL) { 2004 res = _FAIL; 2005 goto exit; 2006 } 2007 2008 pdrvextra_cmd_parm = (struct drvextra_cmd_parm *)rtw_zmalloc(sizeof(struct drvextra_cmd_parm)); 2009 if (pdrvextra_cmd_parm == NULL) { 2010 kfree(ph2c); 2011 res = _FAIL; 2012 goto exit; 2013 } 2014 2015 pdrvextra_cmd_parm->ec_id = CHECK_HIQ_WK_CID; 2016 pdrvextra_cmd_parm->type_size = 0; 2017 pdrvextra_cmd_parm->pbuf = NULL; 2018 2019 init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, GEN_CMD_CODE(_Set_Drv_Extra)); 2020 2021 res = rtw_enqueue_cmd(pcmdpriv, ph2c); 2022exit: 2023 return res; 2024} 2025#endif 2026 2027u8 rtw_c2h_wk_cmd(struct adapter *padapter, u8 *c2h_evt) 2028{ 2029 struct cmd_obj *ph2c; 2030 struct drvextra_cmd_parm *pdrvextra_cmd_parm; 2031 struct cmd_priv *pcmdpriv = &padapter->cmdpriv; 2032 u8 res = _SUCCESS; 2033 2034 ph2c = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj)); 2035 if (ph2c == NULL) { 2036 res = _FAIL; 2037 goto exit; 2038 } 2039 2040 pdrvextra_cmd_parm = (struct drvextra_cmd_parm *)rtw_zmalloc(sizeof(struct drvextra_cmd_parm)); 2041 if (pdrvextra_cmd_parm == NULL) { 2042 kfree(ph2c); 2043 res = _FAIL; 2044 goto exit; 2045 } 2046 2047 pdrvextra_cmd_parm->ec_id = C2H_WK_CID; 2048 pdrvextra_cmd_parm->type_size = c2h_evt ? 16 : 0; 2049 pdrvextra_cmd_parm->pbuf = c2h_evt; 2050 2051 init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, GEN_CMD_CODE(_Set_Drv_Extra)); 2052 2053 res = rtw_enqueue_cmd(pcmdpriv, ph2c); 2054 2055exit: 2056 2057 return res; 2058} 2059 2060static s32 c2h_evt_hdl(struct adapter *adapter, struct c2h_evt_hdr *c2h_evt, c2h_id_filter filter) 2061{ 2062 s32 ret = _FAIL; 2063 u8 buf[16]; 2064 2065 if (!c2h_evt) { 2066 /* No c2h event in cmd_obj, read c2h event before handling*/ 2067 if (c2h_evt_read(adapter, buf) == _SUCCESS) { 2068 c2h_evt = (struct c2h_evt_hdr *)buf; 2069 2070 if (filter && filter(c2h_evt->id) == false) 2071 goto exit; 2072 2073 ret = rtw_hal_c2h_handler(adapter, c2h_evt); 2074 } 2075 } else { 2076 if (filter && filter(c2h_evt->id) == false) 2077 goto exit; 2078 2079 ret = rtw_hal_c2h_handler(adapter, c2h_evt); 2080 } 2081exit: 2082 return ret; 2083} 2084 2085static void c2h_wk_callback(struct work_struct *work) 2086{ 2087 struct evt_priv *evtpriv = container_of(work, struct evt_priv, c2h_wk); 2088 struct adapter *adapter = container_of(evtpriv, struct adapter, evtpriv); 2089 struct c2h_evt_hdr *c2h_evt; 2090 c2h_id_filter ccx_id_filter = rtw_hal_c2h_id_filter_ccx(adapter); 2091 2092 evtpriv->c2h_wk_alive = true; 2093 2094 while (!rtw_cbuf_empty(evtpriv->c2h_queue)) { 2095 if ((c2h_evt = (struct c2h_evt_hdr *)rtw_cbuf_pop(evtpriv->c2h_queue)) != NULL) { 2096 /* This C2H event is read, clear it */ 2097 c2h_evt_clear(adapter); 2098 } else if ((c2h_evt = (struct c2h_evt_hdr *)rtw_malloc(16)) != NULL) { 2099 /* This C2H event is not read, read & clear now */ 2100 if (c2h_evt_read(adapter, (u8 *)c2h_evt) != _SUCCESS) 2101 continue; 2102 } 2103 2104 /* Special pointer to trigger c2h_evt_clear only */ 2105 if ((void *)c2h_evt == (void *)evtpriv) 2106 continue; 2107 2108 if (!c2h_evt_exist(c2h_evt)) { 2109 kfree(c2h_evt); 2110 continue; 2111 } 2112 2113 if (ccx_id_filter(c2h_evt->id) == true) { 2114 /* Handle CCX report here */ 2115 rtw_hal_c2h_handler(adapter, c2h_evt); 2116 kfree(c2h_evt); 2117 } else { 2118#ifdef CONFIG_88EU_P2P 2119 /* Enqueue into cmd_thread for others */ 2120 rtw_c2h_wk_cmd(adapter, (u8 *)c2h_evt); 2121#endif 2122 } 2123 } 2124 2125 evtpriv->c2h_wk_alive = false; 2126} 2127 2128u8 rtw_drvextra_cmd_hdl(struct adapter *padapter, unsigned char *pbuf) 2129{ 2130 struct drvextra_cmd_parm *pdrvextra_cmd; 2131 2132 if (!pbuf) 2133 return H2C_PARAMETERS_ERROR; 2134 2135 pdrvextra_cmd = (struct drvextra_cmd_parm *)pbuf; 2136 2137 switch (pdrvextra_cmd->ec_id) { 2138 case DYNAMIC_CHK_WK_CID: 2139 dynamic_chk_wk_hdl(padapter, pdrvextra_cmd->pbuf, pdrvextra_cmd->type_size); 2140 break; 2141 case POWER_SAVING_CTRL_WK_CID: 2142 power_saving_wk_hdl(padapter, pdrvextra_cmd->pbuf, pdrvextra_cmd->type_size); 2143 break; 2144 case LPS_CTRL_WK_CID: 2145 lps_ctrl_wk_hdl(padapter, (u8)pdrvextra_cmd->type_size); 2146 break; 2147 case RTP_TIMER_CFG_WK_CID: 2148 rpt_timer_setting_wk_hdl(padapter, pdrvextra_cmd->type_size); 2149 break; 2150 case ANT_SELECT_WK_CID: 2151 antenna_select_wk_hdl(padapter, pdrvextra_cmd->type_size); 2152 break; 2153#ifdef CONFIG_88EU_P2P 2154 case P2P_PS_WK_CID: 2155 p2p_ps_wk_hdl(padapter, pdrvextra_cmd->type_size); 2156 break; 2157 case P2P_PROTO_WK_CID: 2158 /* Commented by Albert 2011/07/01 */ 2159 /* I used the type_size as the type command */ 2160 p2p_protocol_wk_hdl(padapter, pdrvextra_cmd->type_size); 2161 break; 2162#endif 2163#ifdef CONFIG_88EU_AP_MODE 2164 case CHECK_HIQ_WK_CID: 2165 rtw_chk_hi_queue_hdl(padapter); 2166 break; 2167#endif /* CONFIG_88EU_AP_MODE */ 2168 case C2H_WK_CID: 2169 c2h_evt_hdl(padapter, (struct c2h_evt_hdr *)pdrvextra_cmd->pbuf, NULL); 2170 break; 2171 default: 2172 break; 2173 } 2174 2175 if (pdrvextra_cmd->pbuf && pdrvextra_cmd->type_size > 0) 2176 kfree(pdrvextra_cmd->pbuf); 2177 2178 return H2C_SUCCESS; 2179} 2180 2181void rtw_survey_cmd_callback(struct adapter *padapter, struct cmd_obj *pcmd) 2182{ 2183 struct mlme_priv *pmlmepriv = &padapter->mlmepriv; 2184 2185_func_enter_; 2186 2187 if (pcmd->res == H2C_DROPPED) { 2188 /* TODO: cancel timer and do timeout handler directly... */ 2189 /* need to make timeout handlerOS independent */ 2190 _set_timer(&pmlmepriv->scan_to_timer, 1); 2191 } else if (pcmd->res != H2C_SUCCESS) { 2192 _set_timer(&pmlmepriv->scan_to_timer, 1); 2193 RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_, ("\n ********Error: MgntActrtw_set_802_11_bssid_LIST_SCAN Fail ************\n\n.")); 2194 } 2195 2196 /* free cmd */ 2197 rtw_free_cmd_obj(pcmd); 2198 2199_func_exit_; 2200} 2201void rtw_disassoc_cmd_callback(struct adapter *padapter, struct cmd_obj *pcmd) 2202{ 2203 unsigned long irqL; 2204 struct mlme_priv *pmlmepriv = &padapter->mlmepriv; 2205 2206_func_enter_; 2207 2208 if (pcmd->res != H2C_SUCCESS) { 2209 _enter_critical_bh(&pmlmepriv->lock, &irqL); 2210 set_fwstate(pmlmepriv, _FW_LINKED); 2211 _exit_critical_bh(&pmlmepriv->lock, &irqL); 2212 2213 RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_, ("\n ***Error: disconnect_cmd_callback Fail ***\n.")); 2214 2215 goto exit; 2216 } else /* clear bridge database */ 2217 nat25_db_cleanup(padapter); 2218 2219 /* free cmd */ 2220 rtw_free_cmd_obj(pcmd); 2221 2222exit: 2223 2224_func_exit_; 2225} 2226 2227void rtw_joinbss_cmd_callback(struct adapter *padapter, struct cmd_obj *pcmd) 2228{ 2229 struct mlme_priv *pmlmepriv = &padapter->mlmepriv; 2230 2231_func_enter_; 2232 2233 if (pcmd->res == H2C_DROPPED) { 2234 /* TODO: cancel timer and do timeout handler directly... */ 2235 /* need to make timeout handlerOS independent */ 2236 _set_timer(&pmlmepriv->assoc_timer, 1); 2237 } else if (pcmd->res != H2C_SUCCESS) { 2238 RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_, ("********Error:rtw_select_and_join_from_scanned_queue Wait Sema Fail ************\n")); 2239 _set_timer(&pmlmepriv->assoc_timer, 1); 2240 } 2241 2242 rtw_free_cmd_obj(pcmd); 2243 2244_func_exit_; 2245} 2246 2247void rtw_createbss_cmd_callback(struct adapter *padapter, struct cmd_obj *pcmd) 2248{ 2249 unsigned long irqL; 2250 u8 timer_cancelled; 2251 struct sta_info *psta = NULL; 2252 struct wlan_network *pwlan = NULL; 2253 struct mlme_priv *pmlmepriv = &padapter->mlmepriv; 2254 struct wlan_bssid_ex *pnetwork = (struct wlan_bssid_ex *)pcmd->parmbuf; 2255 struct wlan_network *tgt_network = &(pmlmepriv->cur_network); 2256 2257_func_enter_; 2258 2259 if ((pcmd->res != H2C_SUCCESS)) { 2260 RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_, ("\n ********Error: rtw_createbss_cmd_callback Fail ************\n\n.")); 2261 _set_timer(&pmlmepriv->assoc_timer, 1); 2262 } 2263 2264 _cancel_timer(&pmlmepriv->assoc_timer, &timer_cancelled); 2265 2266 _enter_critical_bh(&pmlmepriv->lock, &irqL); 2267 2268 if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) { 2269 psta = rtw_get_stainfo(&padapter->stapriv, pnetwork->MacAddress); 2270 if (!psta) { 2271 psta = rtw_alloc_stainfo(&padapter->stapriv, pnetwork->MacAddress); 2272 if (psta == NULL) { 2273 RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_, ("\nCan't alloc sta_info when createbss_cmd_callback\n")); 2274 goto createbss_cmd_fail ; 2275 } 2276 } 2277 2278 rtw_indicate_connect(padapter); 2279 } else { 2280 unsigned long irqL; 2281 2282 pwlan = _rtw_alloc_network(pmlmepriv); 2283 _enter_critical_bh(&(pmlmepriv->scanned_queue.lock), &irqL); 2284 if (pwlan == NULL) { 2285 pwlan = rtw_get_oldest_wlan_network(&pmlmepriv->scanned_queue); 2286 if (pwlan == NULL) { 2287 RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_, ("\n Error: can't get pwlan in rtw_joinbss_event_callback\n")); 2288 _exit_critical_bh(&(pmlmepriv->scanned_queue.lock), &irqL); 2289 goto createbss_cmd_fail; 2290 } 2291 pwlan->last_scanned = rtw_get_current_time(); 2292 } else { 2293 rtw_list_insert_tail(&(pwlan->list), &pmlmepriv->scanned_queue.queue); 2294 } 2295 2296 pnetwork->Length = get_wlan_bssid_ex_sz(pnetwork); 2297 memcpy(&(pwlan->network), pnetwork, pnetwork->Length); 2298 2299 memcpy(&tgt_network->network, pnetwork, (get_wlan_bssid_ex_sz(pnetwork))); 2300 2301 _clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING); 2302 2303 _exit_critical_bh(&(pmlmepriv->scanned_queue.lock), &irqL); 2304 /* we will set _FW_LINKED when there is one more sat to join us (rtw_stassoc_event_callback) */ 2305 } 2306 2307createbss_cmd_fail: 2308 2309 _exit_critical_bh(&pmlmepriv->lock, &irqL); 2310 2311 rtw_free_cmd_obj(pcmd); 2312 2313_func_exit_; 2314} 2315 2316void rtw_setstaKey_cmdrsp_callback(struct adapter *padapter, struct cmd_obj *pcmd) 2317{ 2318 struct sta_priv *pstapriv = &padapter->stapriv; 2319 struct set_stakey_rsp *psetstakey_rsp = (struct set_stakey_rsp *)(pcmd->rsp); 2320 struct sta_info *psta = rtw_get_stainfo(pstapriv, psetstakey_rsp->addr); 2321 2322_func_enter_; 2323 2324 if (psta == NULL) { 2325 RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_, ("\nERROR: rtw_setstaKey_cmdrsp_callback => can't get sta_info\n\n")); 2326 goto exit; 2327 } 2328exit: 2329 rtw_free_cmd_obj(pcmd); 2330_func_exit_; 2331} 2332 2333void rtw_setassocsta_cmdrsp_callback(struct adapter *padapter, struct cmd_obj *pcmd) 2334{ 2335 unsigned long irqL; 2336 struct sta_priv *pstapriv = &padapter->stapriv; 2337 struct mlme_priv *pmlmepriv = &padapter->mlmepriv; 2338 struct set_assocsta_parm *passocsta_parm = (struct set_assocsta_parm *)(pcmd->parmbuf); 2339 struct set_assocsta_rsp *passocsta_rsp = (struct set_assocsta_rsp *)(pcmd->rsp); 2340 struct sta_info *psta = rtw_get_stainfo(pstapriv, passocsta_parm->addr); 2341 2342_func_enter_; 2343 2344 if (psta == NULL) { 2345 RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_, ("\nERROR: setassocsta_cmdrsp_callbac => can't get sta_info\n\n")); 2346 goto exit; 2347 } 2348 2349 psta->aid = passocsta_rsp->cam_id; 2350 psta->mac_id = passocsta_rsp->cam_id; 2351 2352 _enter_critical_bh(&pmlmepriv->lock, &irqL); 2353 2354 if ((check_fwstate(pmlmepriv, WIFI_MP_STATE) == true) && (check_fwstate(pmlmepriv, _FW_UNDER_LINKING) == true)) 2355 _clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING); 2356 2357 set_fwstate(pmlmepriv, _FW_LINKED); 2358 _exit_critical_bh(&pmlmepriv->lock, &irqL); 2359 2360exit: 2361 rtw_free_cmd_obj(pcmd); 2362 2363_func_exit_; 2364} 2365