1 // SPDX-License-Identifier: GPL-2.0 2 /****************************************************************************** 3 * 4 * Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved. 5 * 6 ******************************************************************************/ 7 #include <drv_types.h> 8 #include <rtw_debug.h> 9 #include <hal_btcoex.h> 10 #include <linux/jiffies.h> 11 12 static struct _cmd_callback rtw_cmd_callback[] = { 13 {GEN_CMD_CODE(_Read_MACREG), NULL}, /*0*/ 14 {GEN_CMD_CODE(_Write_MACREG), NULL}, 15 {GEN_CMD_CODE(_Read_BBREG), &rtw_getbbrfreg_cmdrsp_callback}, 16 {GEN_CMD_CODE(_Write_BBREG), NULL}, 17 {GEN_CMD_CODE(_Read_RFREG), &rtw_getbbrfreg_cmdrsp_callback}, 18 {GEN_CMD_CODE(_Write_RFREG), NULL}, /*5*/ 19 {GEN_CMD_CODE(_Read_EEPROM), NULL}, 20 {GEN_CMD_CODE(_Write_EEPROM), NULL}, 21 {GEN_CMD_CODE(_Read_EFUSE), NULL}, 22 {GEN_CMD_CODE(_Write_EFUSE), NULL}, 23 24 {GEN_CMD_CODE(_Read_CAM), NULL}, /*10*/ 25 {GEN_CMD_CODE(_Write_CAM), NULL}, 26 {GEN_CMD_CODE(_setBCNITV), NULL}, 27 {GEN_CMD_CODE(_setMBIDCFG), NULL}, 28 {GEN_CMD_CODE(_JoinBss), &rtw_joinbss_cmd_callback}, /*14*/ 29 {GEN_CMD_CODE(_DisConnect), &rtw_disassoc_cmd_callback}, /*15*/ 30 {GEN_CMD_CODE(_CreateBss), &rtw_createbss_cmd_callback}, 31 {GEN_CMD_CODE(_SetOpMode), NULL}, 32 {GEN_CMD_CODE(_SiteSurvey), &rtw_survey_cmd_callback}, /*18*/ 33 {GEN_CMD_CODE(_SetAuth), NULL}, 34 35 {GEN_CMD_CODE(_SetKey), NULL}, /*20*/ 36 {GEN_CMD_CODE(_SetStaKey), &rtw_setstaKey_cmdrsp_callback}, 37 {GEN_CMD_CODE(_SetAssocSta), &rtw_setassocsta_cmdrsp_callback}, 38 {GEN_CMD_CODE(_DelAssocSta), NULL}, 39 {GEN_CMD_CODE(_SetStaPwrState), NULL}, 40 {GEN_CMD_CODE(_SetBasicRate), NULL}, /*25*/ 41 {GEN_CMD_CODE(_GetBasicRate), NULL}, 42 {GEN_CMD_CODE(_SetDataRate), NULL}, 43 {GEN_CMD_CODE(_GetDataRate), NULL}, 44 {GEN_CMD_CODE(_SetPhyInfo), NULL}, 45 46 {GEN_CMD_CODE(_GetPhyInfo), NULL}, /*30*/ 47 {GEN_CMD_CODE(_SetPhy), NULL}, 48 {GEN_CMD_CODE(_GetPhy), NULL}, 49 {GEN_CMD_CODE(_readRssi), NULL}, 50 {GEN_CMD_CODE(_readGain), NULL}, 51 {GEN_CMD_CODE(_SetAtim), NULL}, /*35*/ 52 {GEN_CMD_CODE(_SetPwrMode), NULL}, 53 {GEN_CMD_CODE(_JoinbssRpt), NULL}, 54 {GEN_CMD_CODE(_SetRaTable), NULL}, 55 {GEN_CMD_CODE(_GetRaTable), NULL}, 56 57 {GEN_CMD_CODE(_GetCCXReport), NULL}, /*40*/ 58 {GEN_CMD_CODE(_GetDTMReport), NULL}, 59 {GEN_CMD_CODE(_GetTXRateStatistics), NULL}, 60 {GEN_CMD_CODE(_SetUsbSuspend), NULL}, 61 {GEN_CMD_CODE(_SetH2cLbk), NULL}, 62 {GEN_CMD_CODE(_AddBAReq), NULL}, /*45*/ 63 {GEN_CMD_CODE(_SetChannel), NULL}, /*46*/ 64 {GEN_CMD_CODE(_SetTxPower), NULL}, 65 {GEN_CMD_CODE(_SwitchAntenna), NULL}, 66 {GEN_CMD_CODE(_SetCrystalCap), NULL}, 67 {GEN_CMD_CODE(_SetSingleCarrierTx), NULL}, /*50*/ 68 69 {GEN_CMD_CODE(_SetSingleToneTx), NULL}, /*51*/ 70 {GEN_CMD_CODE(_SetCarrierSuppressionTx), NULL}, 71 {GEN_CMD_CODE(_SetContinuousTx), NULL}, 72 {GEN_CMD_CODE(_SwitchBandwidth), NULL}, /*54*/ 73 {GEN_CMD_CODE(_TX_Beacon), NULL},/*55*/ 74 75 {GEN_CMD_CODE(_Set_MLME_EVT), NULL},/*56*/ 76 {GEN_CMD_CODE(_Set_Drv_Extra), NULL},/*57*/ 77 {GEN_CMD_CODE(_Set_H2C_MSG), NULL},/*58*/ 78 {GEN_CMD_CODE(_SetChannelPlan), NULL},/*59*/ 79 80 {GEN_CMD_CODE(_SetChannelSwitch), NULL},/*60*/ 81 {GEN_CMD_CODE(_TDLS), NULL},/*61*/ 82 {GEN_CMD_CODE(_ChkBMCSleepq), NULL}, /*62*/ 83 84 {GEN_CMD_CODE(_RunInThreadCMD), NULL},/*63*/ 85 }; 86 87 static struct cmd_hdl wlancmds[] = { 88 GEN_DRV_CMD_HANDLER(0, NULL) /*0*/ 89 GEN_DRV_CMD_HANDLER(0, NULL) 90 GEN_DRV_CMD_HANDLER(0, NULL) 91 GEN_DRV_CMD_HANDLER(0, NULL) 92 GEN_DRV_CMD_HANDLER(0, NULL) 93 GEN_DRV_CMD_HANDLER(0, NULL) 94 GEN_MLME_EXT_HANDLER(0, NULL) 95 GEN_MLME_EXT_HANDLER(0, NULL) 96 GEN_MLME_EXT_HANDLER(0, NULL) 97 GEN_MLME_EXT_HANDLER(0, NULL) 98 GEN_MLME_EXT_HANDLER(0, NULL) /*10*/ 99 GEN_MLME_EXT_HANDLER(0, NULL) 100 GEN_MLME_EXT_HANDLER(0, NULL) 101 GEN_MLME_EXT_HANDLER(0, NULL) 102 GEN_MLME_EXT_HANDLER(sizeof(struct joinbss_parm), join_cmd_hdl) /*14*/ 103 GEN_MLME_EXT_HANDLER(sizeof(struct disconnect_parm), disconnect_hdl) 104 GEN_MLME_EXT_HANDLER(sizeof(struct createbss_parm), createbss_hdl) 105 GEN_MLME_EXT_HANDLER(sizeof(struct setopmode_parm), setopmode_hdl) 106 GEN_MLME_EXT_HANDLER(sizeof(struct sitesurvey_parm), sitesurvey_cmd_hdl) /*18*/ 107 GEN_MLME_EXT_HANDLER(sizeof(struct setauth_parm), setauth_hdl) 108 GEN_MLME_EXT_HANDLER(sizeof(struct setkey_parm), setkey_hdl) /*20*/ 109 GEN_MLME_EXT_HANDLER(sizeof(struct set_stakey_parm), set_stakey_hdl) 110 GEN_MLME_EXT_HANDLER(sizeof(struct set_assocsta_parm), NULL) 111 GEN_MLME_EXT_HANDLER(sizeof(struct del_assocsta_parm), NULL) 112 GEN_MLME_EXT_HANDLER(sizeof(struct setstapwrstate_parm), NULL) 113 GEN_MLME_EXT_HANDLER(sizeof(struct setbasicrate_parm), NULL) 114 GEN_MLME_EXT_HANDLER(sizeof(struct getbasicrate_parm), NULL) 115 GEN_MLME_EXT_HANDLER(sizeof(struct setdatarate_parm), NULL) 116 GEN_MLME_EXT_HANDLER(sizeof(struct getdatarate_parm), NULL) 117 GEN_MLME_EXT_HANDLER(sizeof(struct setphyinfo_parm), NULL) 118 GEN_MLME_EXT_HANDLER(sizeof(struct getphyinfo_parm), NULL) /*30*/ 119 GEN_MLME_EXT_HANDLER(sizeof(struct setphy_parm), NULL) 120 GEN_MLME_EXT_HANDLER(sizeof(struct getphy_parm), NULL) 121 GEN_MLME_EXT_HANDLER(0, NULL) 122 GEN_MLME_EXT_HANDLER(0, NULL) 123 GEN_MLME_EXT_HANDLER(0, NULL) 124 GEN_MLME_EXT_HANDLER(0, NULL) 125 GEN_MLME_EXT_HANDLER(0, NULL) 126 GEN_MLME_EXT_HANDLER(0, NULL) 127 GEN_MLME_EXT_HANDLER(0, NULL) 128 GEN_MLME_EXT_HANDLER(0, NULL) /*40*/ 129 GEN_MLME_EXT_HANDLER(0, NULL) 130 GEN_MLME_EXT_HANDLER(0, NULL) 131 GEN_MLME_EXT_HANDLER(0, NULL) 132 GEN_MLME_EXT_HANDLER(0, NULL) 133 GEN_MLME_EXT_HANDLER(sizeof(struct addBaReq_parm), add_ba_hdl) 134 GEN_MLME_EXT_HANDLER(sizeof(struct set_ch_parm), set_ch_hdl) /* 46 */ 135 GEN_MLME_EXT_HANDLER(0, NULL) 136 GEN_MLME_EXT_HANDLER(0, NULL) 137 GEN_MLME_EXT_HANDLER(0, NULL) 138 GEN_MLME_EXT_HANDLER(0, NULL) /*50*/ 139 GEN_MLME_EXT_HANDLER(0, NULL) 140 GEN_MLME_EXT_HANDLER(0, NULL) 141 GEN_MLME_EXT_HANDLER(0, NULL) 142 GEN_MLME_EXT_HANDLER(0, NULL) 143 GEN_MLME_EXT_HANDLER(sizeof(struct Tx_Beacon_param), tx_beacon_hdl) /*55*/ 144 145 GEN_MLME_EXT_HANDLER(0, mlme_evt_hdl) /*56*/ 146 GEN_MLME_EXT_HANDLER(0, rtw_drvextra_cmd_hdl) /*57*/ 147 148 GEN_MLME_EXT_HANDLER(0, h2c_msg_hdl) /*58*/ 149 GEN_MLME_EXT_HANDLER(sizeof(struct SetChannelPlan_param), set_chplan_hdl) /*59*/ 150 151 GEN_MLME_EXT_HANDLER(sizeof(struct SetChannelSwitch_param), set_csa_hdl) /*60*/ 152 GEN_MLME_EXT_HANDLER(sizeof(struct TDLSoption_param), tdls_hdl) /*61*/ 153 GEN_MLME_EXT_HANDLER(0, chk_bmc_sleepq_hdl) /*62*/ 154 GEN_MLME_EXT_HANDLER(sizeof(struct RunInThread_param), run_in_thread_hdl) /*63*/ 155 }; 156 157 /* 158 * Caller and the rtw_cmd_thread can protect cmd_q by spin_lock. 159 * No irqsave is necessary. 160 */ 161 162 int rtw_init_cmd_priv(struct cmd_priv *pcmdpriv) 163 { 164 int res = 0; 165 166 init_completion(&pcmdpriv->cmd_queue_comp); 167 init_completion(&pcmdpriv->terminate_cmdthread_comp); 168 169 INIT_LIST_HEAD(&pcmdpriv->cmd_queue.queue); 170 spin_lock_init(&pcmdpriv->cmd_queue.lock); 171 172 /* allocate DMA-able/Non-Page memory for cmd_buf and rsp_buf */ 173 174 pcmdpriv->cmd_seq = 1; 175 176 pcmdpriv->cmd_allocated_buf = rtw_zmalloc(MAX_CMDSZ + CMDBUFF_ALIGN_SZ); 177 178 if (!pcmdpriv->cmd_allocated_buf) { 179 res = -ENOMEM; 180 goto exit; 181 } 182 183 pcmdpriv->cmd_buf = pcmdpriv->cmd_allocated_buf + CMDBUFF_ALIGN_SZ - ((SIZE_PTR)(pcmdpriv->cmd_allocated_buf) & (CMDBUFF_ALIGN_SZ-1)); 184 185 pcmdpriv->rsp_allocated_buf = rtw_zmalloc(MAX_RSPSZ + 4); 186 187 if (!pcmdpriv->rsp_allocated_buf) { 188 res = -ENOMEM; 189 goto exit; 190 } 191 192 pcmdpriv->rsp_buf = pcmdpriv->rsp_allocated_buf + 4 - ((SIZE_PTR)(pcmdpriv->rsp_allocated_buf) & 3); 193 194 pcmdpriv->cmd_issued_cnt = 0; 195 pcmdpriv->cmd_done_cnt = 0; 196 pcmdpriv->rsp_cnt = 0; 197 198 mutex_init(&pcmdpriv->sctx_mutex); 199 exit: 200 return res; 201 } 202 203 static void c2h_wk_callback(struct work_struct *work); 204 int rtw_init_evt_priv(struct evt_priv *pevtpriv) 205 { 206 /* allocate DMA-able/Non-Page memory for cmd_buf and rsp_buf */ 207 atomic_set(&pevtpriv->event_seq, 0); 208 pevtpriv->evt_done_cnt = 0; 209 210 _init_workitem(&pevtpriv->c2h_wk, c2h_wk_callback, NULL); 211 pevtpriv->c2h_wk_alive = false; 212 pevtpriv->c2h_queue = rtw_cbuf_alloc(C2H_QUEUE_MAX_LEN+1); 213 if (!pevtpriv->c2h_queue) 214 return -ENOMEM; 215 216 return 0; 217 } 218 219 void _rtw_free_evt_priv(struct evt_priv *pevtpriv) 220 { 221 _cancel_workitem_sync(&pevtpriv->c2h_wk); 222 while (pevtpriv->c2h_wk_alive) 223 msleep(10); 224 225 while (!rtw_cbuf_empty(pevtpriv->c2h_queue)) { 226 void *c2h = rtw_cbuf_pop(pevtpriv->c2h_queue); 227 228 if (c2h && c2h != (void *)pevtpriv) 229 kfree(c2h); 230 } 231 kfree(pevtpriv->c2h_queue); 232 } 233 234 void _rtw_free_cmd_priv(struct cmd_priv *pcmdpriv) 235 { 236 if (pcmdpriv) { 237 kfree(pcmdpriv->cmd_allocated_buf); 238 239 kfree(pcmdpriv->rsp_allocated_buf); 240 241 mutex_destroy(&pcmdpriv->sctx_mutex); 242 } 243 } 244 245 /* 246 * Calling Context: 247 * 248 * rtw_enqueue_cmd can only be called between kernel thread, 249 * since only spin_lock is used. 250 * 251 * ISR/Call-Back functions can't call this sub-function. 252 * 253 */ 254 255 int _rtw_enqueue_cmd(struct __queue *queue, struct cmd_obj *obj) 256 { 257 unsigned long irqL; 258 259 if (!obj) 260 goto exit; 261 262 /* spin_lock_bh(&queue->lock); */ 263 spin_lock_irqsave(&queue->lock, irqL); 264 265 list_add_tail(&obj->list, &queue->queue); 266 267 /* spin_unlock_bh(&queue->lock); */ 268 spin_unlock_irqrestore(&queue->lock, irqL); 269 270 exit: 271 return _SUCCESS; 272 } 273 274 struct cmd_obj *_rtw_dequeue_cmd(struct __queue *queue) 275 { 276 unsigned long irqL; 277 struct cmd_obj *obj; 278 279 /* spin_lock_bh(&(queue->lock)); */ 280 spin_lock_irqsave(&queue->lock, irqL); 281 if (list_empty(&(queue->queue))) 282 obj = NULL; 283 else { 284 obj = container_of(get_next(&(queue->queue)), struct cmd_obj, list); 285 list_del_init(&obj->list); 286 } 287 288 /* spin_unlock_bh(&(queue->lock)); */ 289 spin_unlock_irqrestore(&queue->lock, irqL); 290 291 return obj; 292 } 293 294 void rtw_free_evt_priv(struct evt_priv *pevtpriv) 295 { 296 _rtw_free_evt_priv(pevtpriv); 297 } 298 299 void rtw_free_cmd_priv(struct cmd_priv *pcmdpriv) 300 { 301 _rtw_free_cmd_priv(pcmdpriv); 302 } 303 304 int rtw_cmd_filter(struct cmd_priv *pcmdpriv, struct cmd_obj *cmd_obj); 305 int rtw_cmd_filter(struct cmd_priv *pcmdpriv, struct cmd_obj *cmd_obj) 306 { 307 u8 bAllow = false; /* set to true to allow enqueuing cmd when hw_init_completed is false */ 308 309 if (cmd_obj->cmdcode == GEN_CMD_CODE(_SetChannelPlan)) 310 bAllow = true; 311 312 if ((!pcmdpriv->padapter->hw_init_completed && !bAllow) || 313 !atomic_read(&pcmdpriv->cmdthd_running)) /* com_thread not running */ 314 return _FAIL; 315 316 return _SUCCESS; 317 } 318 319 320 321 int rtw_enqueue_cmd(struct cmd_priv *pcmdpriv, struct cmd_obj *cmd_obj) 322 { 323 int res = _FAIL; 324 struct adapter *padapter = pcmdpriv->padapter; 325 326 if (!cmd_obj) 327 goto exit; 328 329 cmd_obj->padapter = padapter; 330 331 res = rtw_cmd_filter(pcmdpriv, cmd_obj); 332 if (res == _FAIL) { 333 rtw_free_cmd_obj(cmd_obj); 334 goto exit; 335 } 336 337 res = _rtw_enqueue_cmd(&pcmdpriv->cmd_queue, cmd_obj); 338 339 if (res == _SUCCESS) 340 complete(&pcmdpriv->cmd_queue_comp); 341 342 exit: 343 return res; 344 } 345 346 struct cmd_obj *rtw_dequeue_cmd(struct cmd_priv *pcmdpriv) 347 { 348 return _rtw_dequeue_cmd(&pcmdpriv->cmd_queue); 349 } 350 351 void rtw_free_cmd_obj(struct cmd_obj *pcmd) 352 { 353 if ((pcmd->cmdcode != _JoinBss_CMD_) && 354 (pcmd->cmdcode != _CreateBss_CMD_)) { 355 /* free parmbuf in cmd_obj */ 356 kfree(pcmd->parmbuf); 357 } 358 359 if (pcmd->rsp) { 360 if (pcmd->rspsz != 0) { 361 /* free rsp in cmd_obj */ 362 kfree(pcmd->rsp); 363 } 364 } 365 366 /* free cmd_obj */ 367 kfree(pcmd); 368 } 369 370 371 void rtw_stop_cmd_thread(struct adapter *adapter) 372 { 373 if (adapter->cmdThread && 374 atomic_read(&(adapter->cmdpriv.cmdthd_running)) && 375 adapter->cmdpriv.stop_req == 0) { 376 adapter->cmdpriv.stop_req = 1; 377 complete(&adapter->cmdpriv.cmd_queue_comp); 378 wait_for_completion(&adapter->cmdpriv.terminate_cmdthread_comp); 379 } 380 } 381 382 int rtw_cmd_thread(void *context) 383 { 384 u8 ret; 385 struct cmd_obj *pcmd; 386 u8 *pcmdbuf; 387 u8 (*cmd_hdl)(struct adapter *padapter, u8 *pbuf); 388 void (*pcmd_callback)(struct adapter *dev, struct cmd_obj *pcmd); 389 struct adapter *padapter = context; 390 struct cmd_priv *pcmdpriv = &(padapter->cmdpriv); 391 struct drvextra_cmd_parm *extra_parm = NULL; 392 393 thread_enter("RTW_CMD_THREAD"); 394 395 pcmdbuf = pcmdpriv->cmd_buf; 396 397 pcmdpriv->stop_req = 0; 398 atomic_set(&(pcmdpriv->cmdthd_running), true); 399 complete(&pcmdpriv->terminate_cmdthread_comp); 400 401 while (1) { 402 if (wait_for_completion_interruptible(&pcmdpriv->cmd_queue_comp)) { 403 netdev_dbg(padapter->pnetdev, 404 FUNC_ADPT_FMT " wait_for_completion_interruptible(&pcmdpriv->cmd_queue_comp) return != 0, break\n", 405 FUNC_ADPT_ARG(padapter)); 406 break; 407 } 408 409 if (padapter->bDriverStopped || padapter->bSurpriseRemoved) { 410 netdev_dbg(padapter->pnetdev, 411 "%s: DriverStopped(%d) SurpriseRemoved(%d) break at line %d\n", 412 __func__, padapter->bDriverStopped, 413 padapter->bSurpriseRemoved, __LINE__); 414 break; 415 } 416 417 if (pcmdpriv->stop_req) { 418 netdev_dbg(padapter->pnetdev, 419 FUNC_ADPT_FMT " stop_req:%u, break\n", 420 FUNC_ADPT_ARG(padapter), 421 pcmdpriv->stop_req); 422 break; 423 } 424 425 if (list_empty(&pcmdpriv->cmd_queue.queue)) 426 continue; 427 428 if (rtw_register_cmd_alive(padapter) != _SUCCESS) 429 continue; 430 431 _next: 432 if (padapter->bDriverStopped || padapter->bSurpriseRemoved) { 433 netdev_dbg(padapter->pnetdev, 434 "%s: DriverStopped(%d) SurpriseRemoved(%d) break at line %d\n", 435 __func__, padapter->bDriverStopped, 436 padapter->bSurpriseRemoved, __LINE__); 437 break; 438 } 439 440 pcmd = rtw_dequeue_cmd(pcmdpriv); 441 if (!pcmd) { 442 rtw_unregister_cmd_alive(padapter); 443 continue; 444 } 445 446 if (rtw_cmd_filter(pcmdpriv, pcmd) == _FAIL) { 447 pcmd->res = H2C_DROPPED; 448 goto post_process; 449 } 450 451 pcmdpriv->cmd_issued_cnt++; 452 453 pcmd->cmdsz = round_up((pcmd->cmdsz), 4); 454 455 memcpy(pcmdbuf, pcmd->parmbuf, pcmd->cmdsz); 456 457 if (pcmd->cmdcode < ARRAY_SIZE(wlancmds)) { 458 cmd_hdl = wlancmds[pcmd->cmdcode].h2cfuns; 459 460 if (cmd_hdl) { 461 ret = cmd_hdl(pcmd->padapter, pcmdbuf); 462 pcmd->res = ret; 463 } 464 465 pcmdpriv->cmd_seq++; 466 } else { 467 pcmd->res = H2C_PARAMETERS_ERROR; 468 } 469 470 cmd_hdl = NULL; 471 472 post_process: 473 474 if (mutex_lock_interruptible(&(pcmd->padapter->cmdpriv.sctx_mutex)) == 0) { 475 if (pcmd->sctx) { 476 netdev_dbg(padapter->pnetdev, 477 FUNC_ADPT_FMT " pcmd->sctx\n", 478 FUNC_ADPT_ARG(pcmd->padapter)); 479 480 if (pcmd->res == H2C_SUCCESS) 481 rtw_sctx_done(&pcmd->sctx); 482 else 483 rtw_sctx_done_err(&pcmd->sctx, RTW_SCTX_DONE_CMD_ERROR); 484 } 485 mutex_unlock(&(pcmd->padapter->cmdpriv.sctx_mutex)); 486 } 487 488 /* call callback function for post-processed */ 489 if (pcmd->cmdcode < ARRAY_SIZE(rtw_cmd_callback)) { 490 pcmd_callback = rtw_cmd_callback[pcmd->cmdcode].callback; 491 if (!pcmd_callback) { 492 rtw_free_cmd_obj(pcmd); 493 } else { 494 /* todo: !!! fill rsp_buf to pcmd->rsp if (pcmd->rsp!= NULL) */ 495 pcmd_callback(pcmd->padapter, pcmd);/* need consider that free cmd_obj in rtw_cmd_callback */ 496 } 497 } else { 498 rtw_free_cmd_obj(pcmd); 499 } 500 501 flush_signals_thread(); 502 503 goto _next; 504 505 } 506 507 /* free all cmd_obj resources */ 508 do { 509 pcmd = rtw_dequeue_cmd(pcmdpriv); 510 if (!pcmd) { 511 rtw_unregister_cmd_alive(padapter); 512 break; 513 } 514 515 if (pcmd->cmdcode == GEN_CMD_CODE(_Set_Drv_Extra)) { 516 extra_parm = (struct drvextra_cmd_parm *)pcmd->parmbuf; 517 if (extra_parm->pbuf && extra_parm->size > 0) 518 kfree(extra_parm->pbuf); 519 } 520 521 rtw_free_cmd_obj(pcmd); 522 } while (1); 523 524 complete(&pcmdpriv->terminate_cmdthread_comp); 525 atomic_set(&(pcmdpriv->cmdthd_running), false); 526 527 thread_exit(); 528 } 529 530 /* 531 * rtw_sitesurvey_cmd(~) 532 * ### NOTE:#### (!!!!) 533 * MUST TAKE CARE THAT BEFORE CALLING THIS FUNC, YOU SHOULD HAVE LOCKED pmlmepriv->lock 534 */ 535 536 u8 rtw_sitesurvey_cmd(struct adapter *padapter, struct ndis_802_11_ssid *ssid, int ssid_num, 537 struct rtw_ieee80211_channel *ch, int ch_num) 538 { 539 u8 res = _FAIL; 540 struct cmd_obj *ph2c; 541 struct sitesurvey_parm *psurveyPara; 542 struct cmd_priv *pcmdpriv = &padapter->cmdpriv; 543 struct mlme_priv *pmlmepriv = &padapter->mlmepriv; 544 545 if (check_fwstate(pmlmepriv, _FW_LINKED)) 546 rtw_lps_ctrl_wk_cmd(padapter, LPS_CTRL_SCAN, 1); 547 548 ph2c = rtw_zmalloc(sizeof(struct cmd_obj)); 549 if (!ph2c) 550 return _FAIL; 551 552 psurveyPara = rtw_zmalloc(sizeof(struct sitesurvey_parm)); 553 if (!psurveyPara) { 554 kfree(ph2c); 555 return _FAIL; 556 } 557 558 rtw_free_network_queue(padapter, false); 559 560 init_h2fwcmd_w_parm_no_rsp(ph2c, psurveyPara, GEN_CMD_CODE(_SiteSurvey)); 561 562 /* psurveyPara->bsslimit = 48; */ 563 psurveyPara->scan_mode = pmlmepriv->scan_mode; 564 565 /* prepare ssid list */ 566 if (ssid) { 567 int i; 568 569 for (i = 0; i < ssid_num && i < RTW_SSID_SCAN_AMOUNT; i++) { 570 if (ssid[i].ssid_length) { 571 memcpy(&psurveyPara->ssid[i], &ssid[i], sizeof(struct ndis_802_11_ssid)); 572 psurveyPara->ssid_num++; 573 } 574 } 575 } 576 577 /* prepare channel list */ 578 if (ch) { 579 int i; 580 581 for (i = 0; i < ch_num && i < RTW_CHANNEL_SCAN_AMOUNT; i++) { 582 if (ch[i].hw_value && !(ch[i].flags & RTW_IEEE80211_CHAN_DISABLED)) { 583 memcpy(&psurveyPara->ch[i], &ch[i], sizeof(struct rtw_ieee80211_channel)); 584 psurveyPara->ch_num++; 585 } 586 } 587 } 588 589 set_fwstate(pmlmepriv, _FW_UNDER_SURVEY); 590 591 res = rtw_enqueue_cmd(pcmdpriv, ph2c); 592 593 if (res == _SUCCESS) { 594 595 pmlmepriv->scan_start_time = jiffies; 596 _set_timer(&pmlmepriv->scan_to_timer, SCANNING_TIMEOUT); 597 } else { 598 _clr_fwstate_(pmlmepriv, _FW_UNDER_SURVEY); 599 } 600 return res; 601 } 602 603 u8 rtw_setdatarate_cmd(struct adapter *padapter, u8 *rateset) 604 { 605 struct cmd_obj *ph2c; 606 struct setdatarate_parm *pbsetdataratepara; 607 struct cmd_priv *pcmdpriv = &padapter->cmdpriv; 608 u8 res = _SUCCESS; 609 610 ph2c = rtw_zmalloc(sizeof(struct cmd_obj)); 611 if (!ph2c) { 612 res = _FAIL; 613 goto exit; 614 } 615 616 pbsetdataratepara = rtw_zmalloc(sizeof(struct setdatarate_parm)); 617 if (!pbsetdataratepara) { 618 kfree(ph2c); 619 res = _FAIL; 620 goto exit; 621 } 622 623 init_h2fwcmd_w_parm_no_rsp(ph2c, pbsetdataratepara, GEN_CMD_CODE(_SetDataRate)); 624 pbsetdataratepara->mac_id = 5; 625 memcpy(pbsetdataratepara->datarates, rateset, NumRates); 626 627 res = rtw_enqueue_cmd(pcmdpriv, ph2c); 628 exit: 629 return res; 630 } 631 632 void rtw_getbbrfreg_cmdrsp_callback(struct adapter *padapter, struct cmd_obj *pcmd) 633 { 634 /* rtw_free_cmd_obj(pcmd); */ 635 kfree(pcmd->parmbuf); 636 kfree(pcmd); 637 } 638 639 u8 rtw_createbss_cmd(struct adapter *padapter) 640 { 641 struct cmd_obj *pcmd; 642 struct cmd_priv *pcmdpriv = &padapter->cmdpriv; 643 struct wlan_bssid_ex *pdev_network = &padapter->registrypriv.dev_network; 644 u8 res = _SUCCESS; 645 646 pcmd = rtw_zmalloc(sizeof(struct cmd_obj)); 647 if (!pcmd) { 648 res = _FAIL; 649 goto exit; 650 } 651 652 INIT_LIST_HEAD(&pcmd->list); 653 pcmd->cmdcode = _CreateBss_CMD_; 654 pcmd->parmbuf = (unsigned char *)pdev_network; 655 pcmd->cmdsz = get_wlan_bssid_ex_sz((struct wlan_bssid_ex *)pdev_network); 656 pcmd->rsp = NULL; 657 pcmd->rspsz = 0; 658 659 pdev_network->length = pcmd->cmdsz; 660 661 res = rtw_enqueue_cmd(pcmdpriv, pcmd); 662 663 exit: 664 return res; 665 } 666 667 int rtw_startbss_cmd(struct adapter *padapter, int flags) 668 { 669 struct cmd_obj *pcmd; 670 struct cmd_priv *pcmdpriv = &padapter->cmdpriv; 671 struct submit_ctx sctx; 672 int res = _SUCCESS; 673 674 if (flags & RTW_CMDF_DIRECTLY) { 675 /* no need to enqueue, do the cmd hdl directly and free cmd parameter */ 676 start_bss_network(padapter); 677 } else { 678 /* need enqueue, prepare cmd_obj and enqueue */ 679 pcmd = rtw_zmalloc(sizeof(struct cmd_obj)); 680 if (!pcmd) { 681 res = _FAIL; 682 goto exit; 683 } 684 685 INIT_LIST_HEAD(&pcmd->list); 686 pcmd->cmdcode = GEN_CMD_CODE(_CreateBss); 687 pcmd->parmbuf = NULL; 688 pcmd->cmdsz = 0; 689 pcmd->rsp = NULL; 690 pcmd->rspsz = 0; 691 692 if (flags & RTW_CMDF_WAIT_ACK) { 693 pcmd->sctx = &sctx; 694 rtw_sctx_init(&sctx, 2000); 695 } 696 697 res = rtw_enqueue_cmd(pcmdpriv, pcmd); 698 699 if (res == _SUCCESS && (flags & RTW_CMDF_WAIT_ACK)) { 700 rtw_sctx_wait(&sctx); 701 if (mutex_lock_interruptible(&pcmdpriv->sctx_mutex) == 0) { 702 if (sctx.status == RTW_SCTX_SUBMITTED) 703 pcmd->sctx = NULL; 704 mutex_unlock(&pcmdpriv->sctx_mutex); 705 } 706 } 707 } 708 709 exit: 710 return res; 711 } 712 713 u8 rtw_joinbss_cmd(struct adapter *padapter, struct wlan_network *pnetwork) 714 { 715 u8 res = _SUCCESS; 716 uint t_len = 0; 717 struct wlan_bssid_ex *psecnetwork; 718 struct cmd_obj *pcmd; 719 struct cmd_priv *pcmdpriv = &padapter->cmdpriv; 720 struct mlme_priv *pmlmepriv = &padapter->mlmepriv; 721 struct qos_priv *pqospriv = &pmlmepriv->qospriv; 722 struct security_priv *psecuritypriv = &padapter->securitypriv; 723 struct registry_priv *pregistrypriv = &padapter->registrypriv; 724 struct ht_priv *phtpriv = &pmlmepriv->htpriv; 725 enum ndis_802_11_network_infrastructure ndis_network_mode = pnetwork->network.infrastructure_mode; 726 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; 727 struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); 728 u32 tmp_len; 729 u8 *ptmp = NULL; 730 731 pcmd = rtw_zmalloc(sizeof(struct cmd_obj)); 732 if (!pcmd) { 733 res = _FAIL; 734 goto exit; 735 } 736 /* for ies is fix buf size */ 737 t_len = sizeof(struct wlan_bssid_ex); 738 739 740 /* for hidden ap to set fw_state here */ 741 if (check_fwstate(pmlmepriv, WIFI_STATION_STATE|WIFI_ADHOC_STATE) != true) { 742 switch (ndis_network_mode) { 743 case Ndis802_11IBSS: 744 set_fwstate(pmlmepriv, WIFI_ADHOC_STATE); 745 break; 746 747 case Ndis802_11Infrastructure: 748 set_fwstate(pmlmepriv, WIFI_STATION_STATE); 749 break; 750 751 case Ndis802_11APMode: 752 case Ndis802_11AutoUnknown: 753 case Ndis802_11InfrastructureMax: 754 break; 755 756 } 757 } 758 759 psecnetwork = (struct wlan_bssid_ex *)&psecuritypriv->sec_bss; 760 761 memset(psecnetwork, 0, t_len); 762 763 memcpy(psecnetwork, &pnetwork->network, get_wlan_bssid_ex_sz(&pnetwork->network)); 764 765 psecuritypriv->authenticator_ie[0] = (unsigned char)psecnetwork->ie_length; 766 767 if ((psecnetwork->ie_length-12) < (256-1)) 768 memcpy(&psecuritypriv->authenticator_ie[1], &psecnetwork->ies[12], psecnetwork->ie_length-12); 769 else 770 memcpy(&psecuritypriv->authenticator_ie[1], &psecnetwork->ies[12], (256-1)); 771 772 psecnetwork->ie_length = 0; 773 /* Added by Albert 2009/02/18 */ 774 /* If the driver wants to use the bssid to create the connection. */ 775 /* If not, we have to copy the connecting AP's MAC address to it so that */ 776 /* the driver just has the bssid information for PMKIDList searching. */ 777 778 if (!pmlmepriv->assoc_by_bssid) 779 memcpy(&pmlmepriv->assoc_bssid[0], &pnetwork->network.mac_address[0], ETH_ALEN); 780 781 psecnetwork->ie_length = rtw_restruct_sec_ie(padapter, &pnetwork->network.ies[0], &psecnetwork->ies[0], pnetwork->network.ie_length); 782 783 784 pqospriv->qos_option = 0; 785 786 if (pregistrypriv->wmm_enable) { 787 tmp_len = rtw_restruct_wmm_ie(padapter, &pnetwork->network.ies[0], &psecnetwork->ies[0], pnetwork->network.ie_length, psecnetwork->ie_length); 788 789 if (psecnetwork->ie_length != tmp_len) { 790 psecnetwork->ie_length = tmp_len; 791 pqospriv->qos_option = 1; /* There is WMM IE in this corresp. beacon */ 792 } else { 793 pqospriv->qos_option = 0;/* There is no WMM IE in this corresp. beacon */ 794 } 795 } 796 797 phtpriv->ht_option = false; 798 ptmp = rtw_get_ie(&pnetwork->network.ies[12], WLAN_EID_HT_CAPABILITY, &tmp_len, pnetwork->network.ie_length-12); 799 if (pregistrypriv->ht_enable && ptmp && tmp_len > 0) { 800 /* Added by Albert 2010/06/23 */ 801 /* For the WEP mode, we will use the bg mode to do the connection to avoid some IOT issue. */ 802 /* Especially for Realtek 8192u SoftAP. */ 803 if ((padapter->securitypriv.dot11PrivacyAlgrthm != _WEP40_) && 804 (padapter->securitypriv.dot11PrivacyAlgrthm != _WEP104_) && 805 (padapter->securitypriv.dot11PrivacyAlgrthm != _TKIP_)) { 806 rtw_ht_use_default_setting(padapter); 807 808 rtw_build_wmm_ie_ht(padapter, &psecnetwork->ies[12], &psecnetwork->ie_length); 809 810 /* rtw_restructure_ht_ie */ 811 rtw_restructure_ht_ie(padapter, &pnetwork->network.ies[12], &psecnetwork->ies[0], 812 pnetwork->network.ie_length-12, &psecnetwork->ie_length, 813 pnetwork->network.configuration.ds_config); 814 } 815 } 816 817 rtw_append_exented_cap(padapter, &psecnetwork->ies[0], &psecnetwork->ie_length); 818 819 pmlmeinfo->assoc_AP_vendor = check_assoc_AP(pnetwork->network.ies, pnetwork->network.ie_length); 820 821 pcmd->cmdsz = get_wlan_bssid_ex_sz(psecnetwork);/* get cmdsz before endian conversion */ 822 823 INIT_LIST_HEAD(&pcmd->list); 824 pcmd->cmdcode = _JoinBss_CMD_;/* GEN_CMD_CODE(_JoinBss) */ 825 pcmd->parmbuf = (unsigned char *)psecnetwork; 826 pcmd->rsp = NULL; 827 pcmd->rspsz = 0; 828 829 res = rtw_enqueue_cmd(pcmdpriv, pcmd); 830 831 exit: 832 return res; 833 } 834 835 u8 rtw_disassoc_cmd(struct adapter *padapter, u32 deauth_timeout_ms, bool enqueue) /* for sta_mode */ 836 { 837 struct cmd_obj *cmdobj = NULL; 838 struct disconnect_parm *param = NULL; 839 struct cmd_priv *cmdpriv = &padapter->cmdpriv; 840 u8 res = _SUCCESS; 841 842 /* prepare cmd parameter */ 843 param = rtw_zmalloc(sizeof(*param)); 844 if (!param) { 845 res = _FAIL; 846 goto exit; 847 } 848 param->deauth_timeout_ms = deauth_timeout_ms; 849 850 if (enqueue) { 851 /* need enqueue, prepare cmd_obj and enqueue */ 852 cmdobj = rtw_zmalloc(sizeof(*cmdobj)); 853 if (!cmdobj) { 854 res = _FAIL; 855 kfree(param); 856 goto exit; 857 } 858 init_h2fwcmd_w_parm_no_rsp(cmdobj, param, _DisConnect_CMD_); 859 res = rtw_enqueue_cmd(cmdpriv, cmdobj); 860 } else { 861 /* no need to enqueue, do the cmd hdl directly and free cmd parameter */ 862 if (disconnect_hdl(padapter, (u8 *)param) != H2C_SUCCESS) 863 res = _FAIL; 864 kfree(param); 865 } 866 867 exit: 868 return res; 869 } 870 871 u8 rtw_setopmode_cmd(struct adapter *padapter, enum ndis_802_11_network_infrastructure networktype, bool enqueue) 872 { 873 struct cmd_obj *ph2c; 874 struct setopmode_parm *psetop; 875 876 struct cmd_priv *pcmdpriv = &padapter->cmdpriv; 877 u8 res = _SUCCESS; 878 879 psetop = rtw_zmalloc(sizeof(struct setopmode_parm)); 880 881 if (!psetop) { 882 res = _FAIL; 883 goto exit; 884 } 885 psetop->mode = (u8)networktype; 886 887 if (enqueue) { 888 ph2c = rtw_zmalloc(sizeof(struct cmd_obj)); 889 if (!ph2c) { 890 kfree(psetop); 891 res = _FAIL; 892 goto exit; 893 } 894 895 init_h2fwcmd_w_parm_no_rsp(ph2c, psetop, _SetOpMode_CMD_); 896 res = rtw_enqueue_cmd(pcmdpriv, ph2c); 897 } else { 898 setopmode_hdl(padapter, (u8 *)psetop); 899 kfree(psetop); 900 } 901 exit: 902 return res; 903 } 904 905 u8 rtw_setstakey_cmd(struct adapter *padapter, struct sta_info *sta, u8 unicast_key, bool enqueue) 906 { 907 struct cmd_obj *ph2c; 908 struct set_stakey_parm *psetstakey_para; 909 struct cmd_priv *pcmdpriv = &padapter->cmdpriv; 910 struct set_stakey_rsp *psetstakey_rsp = NULL; 911 912 struct mlme_priv *pmlmepriv = &padapter->mlmepriv; 913 struct security_priv *psecuritypriv = &padapter->securitypriv; 914 u8 res = _SUCCESS; 915 916 psetstakey_para = rtw_zmalloc(sizeof(struct set_stakey_parm)); 917 if (!psetstakey_para) { 918 res = _FAIL; 919 goto exit; 920 } 921 922 memcpy(psetstakey_para->addr, sta->hwaddr, ETH_ALEN); 923 924 if (check_fwstate(pmlmepriv, WIFI_STATION_STATE)) 925 psetstakey_para->algorithm = (unsigned char) psecuritypriv->dot11PrivacyAlgrthm; 926 else 927 GET_ENCRY_ALGO(psecuritypriv, sta, psetstakey_para->algorithm, false); 928 929 if (unicast_key) 930 memcpy(&psetstakey_para->key, &sta->dot118021x_UncstKey, 16); 931 else 932 memcpy(&psetstakey_para->key, &psecuritypriv->dot118021XGrpKey[psecuritypriv->dot118021XGrpKeyid].skey, 16); 933 934 /* jeff: set this because at least sw key is ready */ 935 padapter->securitypriv.busetkipkey = true; 936 937 if (enqueue) { 938 ph2c = rtw_zmalloc(sizeof(struct cmd_obj)); 939 if (!ph2c) { 940 kfree(psetstakey_para); 941 res = _FAIL; 942 goto exit; 943 } 944 945 psetstakey_rsp = rtw_zmalloc(sizeof(struct set_stakey_rsp)); 946 if (!psetstakey_rsp) { 947 kfree(ph2c); 948 kfree(psetstakey_para); 949 res = _FAIL; 950 goto exit; 951 } 952 953 init_h2fwcmd_w_parm_no_rsp(ph2c, psetstakey_para, _SetStaKey_CMD_); 954 ph2c->rsp = (u8 *) psetstakey_rsp; 955 ph2c->rspsz = sizeof(struct set_stakey_rsp); 956 res = rtw_enqueue_cmd(pcmdpriv, ph2c); 957 } else { 958 set_stakey_hdl(padapter, (u8 *)psetstakey_para); 959 kfree(psetstakey_para); 960 } 961 exit: 962 return res; 963 } 964 965 u8 rtw_clearstakey_cmd(struct adapter *padapter, struct sta_info *sta, u8 enqueue) 966 { 967 struct cmd_obj *ph2c; 968 struct set_stakey_parm *psetstakey_para; 969 struct cmd_priv *pcmdpriv = &padapter->cmdpriv; 970 struct set_stakey_rsp *psetstakey_rsp = NULL; 971 s16 cam_id = 0; 972 u8 res = _SUCCESS; 973 974 if (!enqueue) { 975 while ((cam_id = rtw_camid_search(padapter, sta->hwaddr, -1)) >= 0) { 976 netdev_dbg(padapter->pnetdev, 977 "clear key for addr:%pM, camid:%d\n", 978 MAC_ARG(sta->hwaddr), cam_id); 979 clear_cam_entry(padapter, cam_id); 980 rtw_camid_free(padapter, cam_id); 981 } 982 } else { 983 ph2c = rtw_zmalloc(sizeof(struct cmd_obj)); 984 if (!ph2c) { 985 res = _FAIL; 986 goto exit; 987 } 988 989 psetstakey_para = rtw_zmalloc(sizeof(struct set_stakey_parm)); 990 if (!psetstakey_para) { 991 kfree(ph2c); 992 res = _FAIL; 993 goto exit; 994 } 995 996 psetstakey_rsp = rtw_zmalloc(sizeof(struct set_stakey_rsp)); 997 if (!psetstakey_rsp) { 998 kfree(ph2c); 999 kfree(psetstakey_para); 1000 res = _FAIL; 1001 goto exit; 1002 } 1003 1004 init_h2fwcmd_w_parm_no_rsp(ph2c, psetstakey_para, _SetStaKey_CMD_); 1005 ph2c->rsp = (u8 *) psetstakey_rsp; 1006 ph2c->rspsz = sizeof(struct set_stakey_rsp); 1007 1008 memcpy(psetstakey_para->addr, sta->hwaddr, ETH_ALEN); 1009 1010 psetstakey_para->algorithm = _NO_PRIVACY_; 1011 1012 res = rtw_enqueue_cmd(pcmdpriv, ph2c); 1013 1014 } 1015 1016 exit: 1017 return res; 1018 } 1019 1020 u8 rtw_addbareq_cmd(struct adapter *padapter, u8 tid, u8 *addr) 1021 { 1022 struct cmd_priv *pcmdpriv = &padapter->cmdpriv; 1023 struct cmd_obj *ph2c; 1024 struct addBaReq_parm *paddbareq_parm; 1025 1026 u8 res = _SUCCESS; 1027 1028 ph2c = rtw_zmalloc(sizeof(struct cmd_obj)); 1029 if (!ph2c) { 1030 res = _FAIL; 1031 goto exit; 1032 } 1033 1034 paddbareq_parm = rtw_zmalloc(sizeof(struct addBaReq_parm)); 1035 if (!paddbareq_parm) { 1036 kfree(ph2c); 1037 res = _FAIL; 1038 goto exit; 1039 } 1040 1041 paddbareq_parm->tid = tid; 1042 memcpy(paddbareq_parm->addr, addr, ETH_ALEN); 1043 1044 init_h2fwcmd_w_parm_no_rsp(ph2c, paddbareq_parm, GEN_CMD_CODE(_AddBAReq)); 1045 1046 /* rtw_enqueue_cmd(pcmdpriv, ph2c); */ 1047 res = rtw_enqueue_cmd(pcmdpriv, ph2c); 1048 1049 exit: 1050 return res; 1051 } 1052 /* add for CONFIG_IEEE80211W, none 11w can use it */ 1053 u8 rtw_reset_securitypriv_cmd(struct adapter *padapter) 1054 { 1055 struct cmd_obj *ph2c; 1056 struct drvextra_cmd_parm *pdrvextra_cmd_parm; 1057 struct cmd_priv *pcmdpriv = &padapter->cmdpriv; 1058 u8 res = _SUCCESS; 1059 1060 ph2c = rtw_zmalloc(sizeof(struct cmd_obj)); 1061 if (!ph2c) { 1062 res = _FAIL; 1063 goto exit; 1064 } 1065 1066 pdrvextra_cmd_parm = rtw_zmalloc(sizeof(struct drvextra_cmd_parm)); 1067 if (!pdrvextra_cmd_parm) { 1068 kfree(ph2c); 1069 res = _FAIL; 1070 goto exit; 1071 } 1072 1073 pdrvextra_cmd_parm->ec_id = RESET_SECURITYPRIV; 1074 pdrvextra_cmd_parm->type = 0; 1075 pdrvextra_cmd_parm->size = 0; 1076 pdrvextra_cmd_parm->pbuf = NULL; 1077 1078 init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, GEN_CMD_CODE(_Set_Drv_Extra)); 1079 1080 1081 /* rtw_enqueue_cmd(pcmdpriv, ph2c); */ 1082 res = rtw_enqueue_cmd(pcmdpriv, ph2c); 1083 1084 exit: 1085 return res; 1086 } 1087 1088 u8 rtw_free_assoc_resources_cmd(struct adapter *padapter) 1089 { 1090 struct cmd_obj *ph2c; 1091 struct drvextra_cmd_parm *pdrvextra_cmd_parm; 1092 struct cmd_priv *pcmdpriv = &padapter->cmdpriv; 1093 u8 res = _SUCCESS; 1094 1095 ph2c = rtw_zmalloc(sizeof(struct cmd_obj)); 1096 if (!ph2c) { 1097 res = _FAIL; 1098 goto exit; 1099 } 1100 1101 pdrvextra_cmd_parm = rtw_zmalloc(sizeof(struct drvextra_cmd_parm)); 1102 if (!pdrvextra_cmd_parm) { 1103 kfree(ph2c); 1104 res = _FAIL; 1105 goto exit; 1106 } 1107 1108 pdrvextra_cmd_parm->ec_id = FREE_ASSOC_RESOURCES; 1109 pdrvextra_cmd_parm->type = 0; 1110 pdrvextra_cmd_parm->size = 0; 1111 pdrvextra_cmd_parm->pbuf = NULL; 1112 1113 init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, GEN_CMD_CODE(_Set_Drv_Extra)); 1114 1115 1116 /* rtw_enqueue_cmd(pcmdpriv, ph2c); */ 1117 res = rtw_enqueue_cmd(pcmdpriv, ph2c); 1118 1119 exit: 1120 return res; 1121 } 1122 1123 u8 rtw_dynamic_chk_wk_cmd(struct adapter *padapter) 1124 { 1125 struct cmd_obj *ph2c; 1126 struct drvextra_cmd_parm *pdrvextra_cmd_parm; 1127 struct cmd_priv *pcmdpriv = &padapter->cmdpriv; 1128 u8 res = _SUCCESS; 1129 1130 /* only primary padapter does this cmd */ 1131 ph2c = rtw_zmalloc(sizeof(struct cmd_obj)); 1132 if (!ph2c) { 1133 res = _FAIL; 1134 goto exit; 1135 } 1136 1137 pdrvextra_cmd_parm = rtw_zmalloc(sizeof(struct drvextra_cmd_parm)); 1138 if (!pdrvextra_cmd_parm) { 1139 kfree(ph2c); 1140 res = _FAIL; 1141 goto exit; 1142 } 1143 1144 pdrvextra_cmd_parm->ec_id = DYNAMIC_CHK_WK_CID; 1145 pdrvextra_cmd_parm->type = 0; 1146 pdrvextra_cmd_parm->size = 0; 1147 pdrvextra_cmd_parm->pbuf = NULL; 1148 init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, GEN_CMD_CODE(_Set_Drv_Extra)); 1149 1150 1151 /* rtw_enqueue_cmd(pcmdpriv, ph2c); */ 1152 res = rtw_enqueue_cmd(pcmdpriv, ph2c); 1153 1154 exit: 1155 return res; 1156 } 1157 1158 u8 rtw_set_chplan_cmd(struct adapter *padapter, u8 chplan, u8 enqueue, u8 swconfig) 1159 { 1160 struct cmd_obj *pcmdobj; 1161 struct SetChannelPlan_param *setChannelPlan_param; 1162 struct cmd_priv *pcmdpriv = &padapter->cmdpriv; 1163 1164 u8 res = _SUCCESS; 1165 1166 /* check if allow software config */ 1167 if (swconfig && rtw_hal_is_disable_sw_channel_plan(padapter)) { 1168 res = _FAIL; 1169 goto exit; 1170 } 1171 1172 /* check input parameter */ 1173 if (!rtw_is_channel_plan_valid(chplan)) { 1174 res = _FAIL; 1175 goto exit; 1176 } 1177 1178 /* prepare cmd parameter */ 1179 setChannelPlan_param = rtw_zmalloc(sizeof(struct SetChannelPlan_param)); 1180 if (!setChannelPlan_param) { 1181 res = _FAIL; 1182 goto exit; 1183 } 1184 setChannelPlan_param->channel_plan = chplan; 1185 1186 if (enqueue) { 1187 /* need enqueue, prepare cmd_obj and enqueue */ 1188 pcmdobj = rtw_zmalloc(sizeof(struct cmd_obj)); 1189 if (!pcmdobj) { 1190 kfree(setChannelPlan_param); 1191 res = _FAIL; 1192 goto exit; 1193 } 1194 1195 init_h2fwcmd_w_parm_no_rsp(pcmdobj, setChannelPlan_param, GEN_CMD_CODE(_SetChannelPlan)); 1196 res = rtw_enqueue_cmd(pcmdpriv, pcmdobj); 1197 } else { 1198 /* no need to enqueue, do the cmd hdl directly and free cmd parameter */ 1199 if (set_chplan_hdl(padapter, (unsigned char *)setChannelPlan_param) != H2C_SUCCESS) 1200 res = _FAIL; 1201 1202 kfree(setChannelPlan_param); 1203 } 1204 1205 /* do something based on res... */ 1206 if (res == _SUCCESS) 1207 padapter->mlmepriv.ChannelPlan = chplan; 1208 1209 exit: 1210 return res; 1211 } 1212 1213 static void collect_traffic_statistics(struct adapter *padapter) 1214 { 1215 struct dvobj_priv *pdvobjpriv = adapter_to_dvobj(padapter); 1216 1217 /* Tx */ 1218 pdvobjpriv->traffic_stat.tx_bytes = padapter->xmitpriv.tx_bytes; 1219 pdvobjpriv->traffic_stat.tx_pkts = padapter->xmitpriv.tx_pkts; 1220 pdvobjpriv->traffic_stat.tx_drop = padapter->xmitpriv.tx_drop; 1221 1222 /* Rx */ 1223 pdvobjpriv->traffic_stat.rx_bytes = padapter->recvpriv.rx_bytes; 1224 pdvobjpriv->traffic_stat.rx_pkts = padapter->recvpriv.rx_pkts; 1225 pdvobjpriv->traffic_stat.rx_drop = padapter->recvpriv.rx_drop; 1226 1227 /* Calculate throughput in last interval */ 1228 pdvobjpriv->traffic_stat.cur_tx_bytes = pdvobjpriv->traffic_stat.tx_bytes - pdvobjpriv->traffic_stat.last_tx_bytes; 1229 pdvobjpriv->traffic_stat.cur_rx_bytes = pdvobjpriv->traffic_stat.rx_bytes - pdvobjpriv->traffic_stat.last_rx_bytes; 1230 pdvobjpriv->traffic_stat.last_tx_bytes = pdvobjpriv->traffic_stat.tx_bytes; 1231 pdvobjpriv->traffic_stat.last_rx_bytes = pdvobjpriv->traffic_stat.rx_bytes; 1232 1233 pdvobjpriv->traffic_stat.cur_tx_tp = (u32)(pdvobjpriv->traffic_stat.cur_tx_bytes * 8/2/1024/1024); 1234 pdvobjpriv->traffic_stat.cur_rx_tp = (u32)(pdvobjpriv->traffic_stat.cur_rx_bytes * 8/2/1024/1024); 1235 } 1236 1237 u8 traffic_status_watchdog(struct adapter *padapter, u8 from_timer) 1238 { 1239 u8 bEnterPS = false; 1240 u16 BusyThresholdHigh = 25; 1241 u16 BusyThresholdLow = 10; 1242 u16 BusyThreshold = BusyThresholdHigh; 1243 u8 bBusyTraffic = false, bTxBusyTraffic = false, bRxBusyTraffic = false; 1244 u8 bHigherBusyTraffic = false, bHigherBusyRxTraffic = false, bHigherBusyTxTraffic = false; 1245 1246 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); 1247 1248 collect_traffic_statistics(padapter); 1249 1250 /* */ 1251 /* Determine if our traffic is busy now */ 1252 /* */ 1253 if ((check_fwstate(pmlmepriv, _FW_LINKED)) 1254 /*&& !MgntInitAdapterInProgress(pMgntInfo)*/) { 1255 /* if we raise bBusyTraffic in last watchdog, using lower threshold. */ 1256 if (pmlmepriv->LinkDetectInfo.bBusyTraffic) 1257 BusyThreshold = BusyThresholdLow; 1258 1259 if (pmlmepriv->LinkDetectInfo.NumRxOkInPeriod > BusyThreshold || 1260 pmlmepriv->LinkDetectInfo.NumTxOkInPeriod > BusyThreshold) { 1261 bBusyTraffic = true; 1262 1263 if (pmlmepriv->LinkDetectInfo.NumRxOkInPeriod > pmlmepriv->LinkDetectInfo.NumTxOkInPeriod) 1264 bRxBusyTraffic = true; 1265 else 1266 bTxBusyTraffic = true; 1267 } 1268 1269 /* Higher Tx/Rx data. */ 1270 if (pmlmepriv->LinkDetectInfo.NumRxOkInPeriod > 4000 || 1271 pmlmepriv->LinkDetectInfo.NumTxOkInPeriod > 4000) { 1272 bHigherBusyTraffic = true; 1273 1274 if (pmlmepriv->LinkDetectInfo.NumRxOkInPeriod > pmlmepriv->LinkDetectInfo.NumTxOkInPeriod) 1275 bHigherBusyRxTraffic = true; 1276 else 1277 bHigherBusyTxTraffic = true; 1278 } 1279 1280 /* check traffic for powersaving. */ 1281 if (((pmlmepriv->LinkDetectInfo.NumRxUnicastOkInPeriod + pmlmepriv->LinkDetectInfo.NumTxOkInPeriod) > 8) || 1282 (pmlmepriv->LinkDetectInfo.NumRxUnicastOkInPeriod > 2)) { 1283 bEnterPS = false; 1284 1285 if (bBusyTraffic) { 1286 if (pmlmepriv->LinkDetectInfo.TrafficTransitionCount <= 4) 1287 pmlmepriv->LinkDetectInfo.TrafficTransitionCount = 4; 1288 1289 pmlmepriv->LinkDetectInfo.TrafficTransitionCount++; 1290 1291 if (pmlmepriv->LinkDetectInfo.TrafficTransitionCount > 30/*TrafficTransitionLevel*/) 1292 pmlmepriv->LinkDetectInfo.TrafficTransitionCount = 30; 1293 } 1294 } else { 1295 if (pmlmepriv->LinkDetectInfo.TrafficTransitionCount >= 2) 1296 pmlmepriv->LinkDetectInfo.TrafficTransitionCount -= 2; 1297 else 1298 pmlmepriv->LinkDetectInfo.TrafficTransitionCount = 0; 1299 1300 if (pmlmepriv->LinkDetectInfo.TrafficTransitionCount == 0) 1301 bEnterPS = true; 1302 } 1303 1304 /* LeisurePS only work in infra mode. */ 1305 if (bEnterPS) { 1306 if (!from_timer) 1307 LPS_Enter(padapter, "TRAFFIC_IDLE"); 1308 } else { 1309 if (!from_timer) 1310 LPS_Leave(padapter, "TRAFFIC_BUSY"); 1311 else 1312 rtw_lps_ctrl_wk_cmd(padapter, LPS_CTRL_TRAFFIC_BUSY, 1); 1313 } 1314 } else { 1315 struct dvobj_priv *dvobj = adapter_to_dvobj(padapter); 1316 int n_assoc_iface = 0; 1317 1318 if (check_fwstate(&(dvobj->padapters->mlmepriv), WIFI_ASOC_STATE)) 1319 n_assoc_iface++; 1320 1321 if (!from_timer && n_assoc_iface == 0) 1322 LPS_Leave(padapter, "NON_LINKED"); 1323 } 1324 1325 pmlmepriv->LinkDetectInfo.NumRxOkInPeriod = 0; 1326 pmlmepriv->LinkDetectInfo.NumTxOkInPeriod = 0; 1327 pmlmepriv->LinkDetectInfo.NumRxUnicastOkInPeriod = 0; 1328 pmlmepriv->LinkDetectInfo.bBusyTraffic = bBusyTraffic; 1329 pmlmepriv->LinkDetectInfo.bTxBusyTraffic = bTxBusyTraffic; 1330 pmlmepriv->LinkDetectInfo.bRxBusyTraffic = bRxBusyTraffic; 1331 pmlmepriv->LinkDetectInfo.bHigherBusyTraffic = bHigherBusyTraffic; 1332 pmlmepriv->LinkDetectInfo.bHigherBusyRxTraffic = bHigherBusyRxTraffic; 1333 pmlmepriv->LinkDetectInfo.bHigherBusyTxTraffic = bHigherBusyTxTraffic; 1334 1335 return bEnterPS; 1336 1337 } 1338 1339 static void dynamic_chk_wk_hdl(struct adapter *padapter) 1340 { 1341 struct mlme_priv *pmlmepriv; 1342 1343 pmlmepriv = &(padapter->mlmepriv); 1344 1345 if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) 1346 expire_timeout_chk(padapter); 1347 1348 /* for debug purpose */ 1349 _linked_info_dump(padapter); 1350 1351 1352 /* if (check_fwstate(pmlmepriv, _FW_UNDER_LINKING|_FW_UNDER_SURVEY) ==false) */ 1353 { 1354 linked_status_chk(padapter); 1355 traffic_status_watchdog(padapter, 0); 1356 } 1357 1358 rtw_hal_dm_watchdog(padapter); 1359 1360 /* check_hw_pbc(padapter, pdrvextra_cmd->pbuf, pdrvextra_cmd->type); */ 1361 1362 /* */ 1363 /* BT-Coexist */ 1364 /* */ 1365 hal_btcoex_Handler(padapter); 1366 1367 1368 /* always call rtw_ps_processor() at last one. */ 1369 if (is_primary_adapter(padapter)) 1370 rtw_ps_processor(padapter); 1371 } 1372 1373 void lps_ctrl_wk_hdl(struct adapter *padapter, u8 lps_ctrl_type); 1374 void lps_ctrl_wk_hdl(struct adapter *padapter, u8 lps_ctrl_type) 1375 { 1376 struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(padapter); 1377 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); 1378 u8 mstatus; 1379 1380 if ((check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE)) || 1381 (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE))) { 1382 return; 1383 } 1384 1385 switch (lps_ctrl_type) { 1386 case LPS_CTRL_SCAN: 1387 hal_btcoex_ScanNotify(padapter, true); 1388 1389 if (check_fwstate(pmlmepriv, _FW_LINKED)) { 1390 /* connect */ 1391 LPS_Leave(padapter, "LPS_CTRL_SCAN"); 1392 } 1393 break; 1394 case LPS_CTRL_JOINBSS: 1395 LPS_Leave(padapter, "LPS_CTRL_JOINBSS"); 1396 break; 1397 case LPS_CTRL_CONNECT: 1398 mstatus = 1;/* connect */ 1399 /* Reset LPS Setting */ 1400 pwrpriv->LpsIdleCount = 0; 1401 rtw_hal_set_hwreg(padapter, HW_VAR_H2C_FW_JOINBSSRPT, (u8 *)(&mstatus)); 1402 rtw_btcoex_MediaStatusNotify(padapter, mstatus); 1403 break; 1404 case LPS_CTRL_DISCONNECT: 1405 mstatus = 0;/* disconnect */ 1406 rtw_btcoex_MediaStatusNotify(padapter, mstatus); 1407 LPS_Leave(padapter, "LPS_CTRL_DISCONNECT"); 1408 rtw_hal_set_hwreg(padapter, HW_VAR_H2C_FW_JOINBSSRPT, (u8 *)(&mstatus)); 1409 break; 1410 case LPS_CTRL_SPECIAL_PACKET: 1411 pwrpriv->DelayLPSLastTimeStamp = jiffies; 1412 hal_btcoex_SpecialPacketNotify(padapter, PACKET_DHCP); 1413 LPS_Leave(padapter, "LPS_CTRL_SPECIAL_PACKET"); 1414 break; 1415 case LPS_CTRL_LEAVE: 1416 LPS_Leave(padapter, "LPS_CTRL_LEAVE"); 1417 break; 1418 case LPS_CTRL_TRAFFIC_BUSY: 1419 LPS_Leave(padapter, "LPS_CTRL_TRAFFIC_BUSY"); 1420 break; 1421 default: 1422 break; 1423 } 1424 } 1425 1426 u8 rtw_lps_ctrl_wk_cmd(struct adapter *padapter, u8 lps_ctrl_type, u8 enqueue) 1427 { 1428 struct cmd_obj *ph2c; 1429 struct drvextra_cmd_parm *pdrvextra_cmd_parm; 1430 struct cmd_priv *pcmdpriv = &padapter->cmdpriv; 1431 /* struct pwrctrl_priv *pwrctrlpriv = adapter_to_pwrctl(padapter); */ 1432 u8 res = _SUCCESS; 1433 1434 /* if (!pwrctrlpriv->bLeisurePs) */ 1435 /* return res; */ 1436 1437 if (enqueue) { 1438 ph2c = rtw_zmalloc(sizeof(struct cmd_obj)); 1439 if (!ph2c) { 1440 res = _FAIL; 1441 goto exit; 1442 } 1443 1444 pdrvextra_cmd_parm = rtw_zmalloc(sizeof(struct drvextra_cmd_parm)); 1445 if (!pdrvextra_cmd_parm) { 1446 kfree(ph2c); 1447 res = _FAIL; 1448 goto exit; 1449 } 1450 1451 pdrvextra_cmd_parm->ec_id = LPS_CTRL_WK_CID; 1452 pdrvextra_cmd_parm->type = lps_ctrl_type; 1453 pdrvextra_cmd_parm->size = 0; 1454 pdrvextra_cmd_parm->pbuf = NULL; 1455 1456 init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, GEN_CMD_CODE(_Set_Drv_Extra)); 1457 1458 res = rtw_enqueue_cmd(pcmdpriv, ph2c); 1459 } else { 1460 lps_ctrl_wk_hdl(padapter, lps_ctrl_type); 1461 } 1462 1463 exit: 1464 return res; 1465 } 1466 1467 static void rtw_dm_in_lps_hdl(struct adapter *padapter) 1468 { 1469 rtw_hal_set_hwreg(padapter, HW_VAR_DM_IN_LPS, NULL); 1470 } 1471 1472 u8 rtw_dm_in_lps_wk_cmd(struct adapter *padapter) 1473 { 1474 struct cmd_obj *ph2c; 1475 struct drvextra_cmd_parm *pdrvextra_cmd_parm; 1476 struct cmd_priv *pcmdpriv = &padapter->cmdpriv; 1477 u8 res = _SUCCESS; 1478 1479 1480 ph2c = rtw_zmalloc(sizeof(struct cmd_obj)); 1481 if (!ph2c) { 1482 res = _FAIL; 1483 goto exit; 1484 } 1485 1486 pdrvextra_cmd_parm = rtw_zmalloc(sizeof(struct drvextra_cmd_parm)); 1487 if (!pdrvextra_cmd_parm) { 1488 kfree(ph2c); 1489 res = _FAIL; 1490 goto exit; 1491 } 1492 1493 pdrvextra_cmd_parm->ec_id = DM_IN_LPS_WK_CID; 1494 pdrvextra_cmd_parm->type = 0; 1495 pdrvextra_cmd_parm->size = 0; 1496 pdrvextra_cmd_parm->pbuf = NULL; 1497 1498 init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, GEN_CMD_CODE(_Set_Drv_Extra)); 1499 1500 res = rtw_enqueue_cmd(pcmdpriv, ph2c); 1501 1502 exit: 1503 1504 return res; 1505 1506 } 1507 1508 static void rtw_lps_change_dtim_hdl(struct adapter *padapter, u8 dtim) 1509 { 1510 struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(padapter); 1511 1512 if (dtim <= 0 || dtim > 16) 1513 return; 1514 1515 if (hal_btcoex_IsBtControlLps(padapter)) 1516 return; 1517 1518 mutex_lock(&pwrpriv->lock); 1519 1520 if (pwrpriv->dtim != dtim) 1521 pwrpriv->dtim = dtim; 1522 1523 if (pwrpriv->fw_current_in_ps_mode && (pwrpriv->pwr_mode > PS_MODE_ACTIVE)) { 1524 u8 ps_mode = pwrpriv->pwr_mode; 1525 1526 rtw_hal_set_hwreg(padapter, HW_VAR_H2C_FW_PWRMODE, (u8 *)(&ps_mode)); 1527 } 1528 1529 mutex_unlock(&pwrpriv->lock); 1530 } 1531 1532 static void rtw_dm_ra_mask_hdl(struct adapter *padapter, struct sta_info *psta) 1533 { 1534 if (psta) 1535 set_sta_rate(padapter, psta); 1536 } 1537 1538 u8 rtw_dm_ra_mask_wk_cmd(struct adapter *padapter, u8 *psta) 1539 { 1540 struct cmd_obj *ph2c; 1541 struct drvextra_cmd_parm *pdrvextra_cmd_parm; 1542 struct cmd_priv *pcmdpriv = &padapter->cmdpriv; 1543 u8 res = _SUCCESS; 1544 1545 1546 ph2c = rtw_zmalloc(sizeof(struct cmd_obj)); 1547 if (!ph2c) { 1548 res = _FAIL; 1549 goto exit; 1550 } 1551 1552 pdrvextra_cmd_parm = rtw_zmalloc(sizeof(struct drvextra_cmd_parm)); 1553 if (!pdrvextra_cmd_parm) { 1554 kfree(ph2c); 1555 res = _FAIL; 1556 goto exit; 1557 } 1558 1559 pdrvextra_cmd_parm->ec_id = DM_RA_MSK_WK_CID; 1560 pdrvextra_cmd_parm->type = 0; 1561 pdrvextra_cmd_parm->size = 0; 1562 pdrvextra_cmd_parm->pbuf = psta; 1563 1564 init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, GEN_CMD_CODE(_Set_Drv_Extra)); 1565 1566 res = rtw_enqueue_cmd(pcmdpriv, ph2c); 1567 1568 exit: 1569 1570 return res; 1571 1572 } 1573 1574 u8 rtw_ps_cmd(struct adapter *padapter) 1575 { 1576 struct cmd_obj *ppscmd; 1577 struct drvextra_cmd_parm *pdrvextra_cmd_parm; 1578 struct cmd_priv *pcmdpriv = &padapter->cmdpriv; 1579 u8 res = _SUCCESS; 1580 1581 ppscmd = rtw_zmalloc(sizeof(struct cmd_obj)); 1582 if (!ppscmd) { 1583 res = _FAIL; 1584 goto exit; 1585 } 1586 1587 pdrvextra_cmd_parm = rtw_zmalloc(sizeof(struct drvextra_cmd_parm)); 1588 if (!pdrvextra_cmd_parm) { 1589 kfree(ppscmd); 1590 res = _FAIL; 1591 goto exit; 1592 } 1593 1594 pdrvextra_cmd_parm->ec_id = POWER_SAVING_CTRL_WK_CID; 1595 pdrvextra_cmd_parm->type = 0; 1596 pdrvextra_cmd_parm->size = 0; 1597 pdrvextra_cmd_parm->pbuf = NULL; 1598 init_h2fwcmd_w_parm_no_rsp(ppscmd, pdrvextra_cmd_parm, GEN_CMD_CODE(_Set_Drv_Extra)); 1599 1600 res = rtw_enqueue_cmd(pcmdpriv, ppscmd); 1601 1602 exit: 1603 return res; 1604 } 1605 1606 u32 g_wait_hiq_empty; 1607 1608 static void rtw_chk_hi_queue_hdl(struct adapter *padapter) 1609 { 1610 struct sta_info *psta_bmc; 1611 struct sta_priv *pstapriv = &padapter->stapriv; 1612 unsigned long start = jiffies; 1613 u8 empty = false; 1614 1615 psta_bmc = rtw_get_bcmc_stainfo(padapter); 1616 if (!psta_bmc) 1617 return; 1618 1619 rtw_hal_get_hwreg(padapter, HW_VAR_CHK_HI_QUEUE_EMPTY, &empty); 1620 1621 while (!empty && jiffies_to_msecs(jiffies - start) < g_wait_hiq_empty) { 1622 msleep(100); 1623 rtw_hal_get_hwreg(padapter, HW_VAR_CHK_HI_QUEUE_EMPTY, &empty); 1624 } 1625 1626 if (psta_bmc->sleepq_len == 0) { 1627 if (empty == _SUCCESS) { 1628 bool update_tim = false; 1629 1630 if (pstapriv->tim_bitmap & BIT(0)) 1631 update_tim = true; 1632 1633 pstapriv->tim_bitmap &= ~BIT(0); 1634 pstapriv->sta_dz_bitmap &= ~BIT(0); 1635 1636 if (update_tim) 1637 update_beacon(padapter, WLAN_EID_TIM, NULL, true); 1638 } else {/* re check again */ 1639 rtw_chk_hi_queue_cmd(padapter); 1640 } 1641 1642 } 1643 1644 } 1645 1646 u8 rtw_chk_hi_queue_cmd(struct adapter *padapter) 1647 { 1648 struct cmd_obj *ph2c; 1649 struct drvextra_cmd_parm *pdrvextra_cmd_parm; 1650 struct cmd_priv *pcmdpriv = &padapter->cmdpriv; 1651 u8 res = _SUCCESS; 1652 1653 ph2c = rtw_zmalloc(sizeof(struct cmd_obj)); 1654 if (!ph2c) { 1655 res = _FAIL; 1656 goto exit; 1657 } 1658 1659 pdrvextra_cmd_parm = rtw_zmalloc(sizeof(struct drvextra_cmd_parm)); 1660 if (!pdrvextra_cmd_parm) { 1661 kfree(ph2c); 1662 res = _FAIL; 1663 goto exit; 1664 } 1665 1666 pdrvextra_cmd_parm->ec_id = CHECK_HIQ_WK_CID; 1667 pdrvextra_cmd_parm->type = 0; 1668 pdrvextra_cmd_parm->size = 0; 1669 pdrvextra_cmd_parm->pbuf = NULL; 1670 1671 init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, GEN_CMD_CODE(_Set_Drv_Extra)); 1672 1673 res = rtw_enqueue_cmd(pcmdpriv, ph2c); 1674 1675 exit: 1676 1677 return res; 1678 1679 } 1680 1681 struct btinfo { 1682 u8 cid; 1683 u8 len; 1684 1685 u8 bConnection:1; 1686 u8 bSCOeSCO:1; 1687 u8 bInQPage:1; 1688 u8 bACLBusy:1; 1689 u8 bSCOBusy:1; 1690 u8 bHID:1; 1691 u8 bA2DP:1; 1692 u8 bFTP:1; 1693 1694 u8 retry_cnt:4; 1695 u8 rsvd_34:1; 1696 u8 rsvd_35:1; 1697 u8 rsvd_36:1; 1698 u8 rsvd_37:1; 1699 1700 u8 rssi; 1701 1702 u8 rsvd_50:1; 1703 u8 rsvd_51:1; 1704 u8 rsvd_52:1; 1705 u8 rsvd_53:1; 1706 u8 rsvd_54:1; 1707 u8 rsvd_55:1; 1708 u8 eSCO_SCO:1; 1709 u8 Master_Slave:1; 1710 1711 u8 rsvd_6; 1712 u8 rsvd_7; 1713 }; 1714 1715 static void rtw_btinfo_hdl(struct adapter *adapter, u8 *buf, u16 buf_len) 1716 { 1717 #define BTINFO_WIFI_FETCH 0x23 1718 #define BTINFO_BT_AUTO_RPT 0x27 1719 struct btinfo *info = (struct btinfo *)buf; 1720 u8 cmd_idx; 1721 u8 len; 1722 1723 cmd_idx = info->cid; 1724 1725 if (info->len > buf_len-2) { 1726 rtw_warn_on(1); 1727 len = buf_len-2; 1728 } else { 1729 len = info->len; 1730 } 1731 1732 /* transform BT-FW btinfo to WiFI-FW C2H format and notify */ 1733 if (cmd_idx == BTINFO_WIFI_FETCH) 1734 buf[1] = 0; 1735 else if (cmd_idx == BTINFO_BT_AUTO_RPT) 1736 buf[1] = 2; 1737 hal_btcoex_BtInfoNotify(adapter, len+1, &buf[1]); 1738 } 1739 1740 u8 rtw_c2h_packet_wk_cmd(struct adapter *padapter, u8 *pbuf, u16 length) 1741 { 1742 struct cmd_obj *ph2c; 1743 struct drvextra_cmd_parm *pdrvextra_cmd_parm; 1744 struct cmd_priv *pcmdpriv = &padapter->cmdpriv; 1745 u8 res = _SUCCESS; 1746 1747 ph2c = rtw_zmalloc(sizeof(struct cmd_obj)); 1748 if (!ph2c) { 1749 res = _FAIL; 1750 goto exit; 1751 } 1752 1753 pdrvextra_cmd_parm = rtw_zmalloc(sizeof(struct drvextra_cmd_parm)); 1754 if (!pdrvextra_cmd_parm) { 1755 kfree(ph2c); 1756 res = _FAIL; 1757 goto exit; 1758 } 1759 1760 pdrvextra_cmd_parm->ec_id = C2H_WK_CID; 1761 pdrvextra_cmd_parm->type = 0; 1762 pdrvextra_cmd_parm->size = length; 1763 pdrvextra_cmd_parm->pbuf = pbuf; 1764 1765 init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, GEN_CMD_CODE(_Set_Drv_Extra)); 1766 1767 res = rtw_enqueue_cmd(pcmdpriv, ph2c); 1768 1769 exit: 1770 return res; 1771 } 1772 1773 /* dont call R/W in this function, beucase SDIO interrupt have claim host */ 1774 /* or deadlock will happen and cause special-systemserver-died in android */ 1775 u8 rtw_c2h_wk_cmd(struct adapter *padapter, u8 *c2h_evt) 1776 { 1777 struct cmd_obj *ph2c; 1778 struct drvextra_cmd_parm *pdrvextra_cmd_parm; 1779 struct cmd_priv *pcmdpriv = &padapter->cmdpriv; 1780 u8 res = _SUCCESS; 1781 1782 ph2c = rtw_zmalloc(sizeof(struct cmd_obj)); 1783 if (!ph2c) { 1784 res = _FAIL; 1785 goto exit; 1786 } 1787 1788 pdrvextra_cmd_parm = rtw_zmalloc(sizeof(struct drvextra_cmd_parm)); 1789 if (!pdrvextra_cmd_parm) { 1790 kfree(ph2c); 1791 res = _FAIL; 1792 goto exit; 1793 } 1794 1795 pdrvextra_cmd_parm->ec_id = C2H_WK_CID; 1796 pdrvextra_cmd_parm->type = 0; 1797 pdrvextra_cmd_parm->size = c2h_evt?16:0; 1798 pdrvextra_cmd_parm->pbuf = c2h_evt; 1799 1800 init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, GEN_CMD_CODE(_Set_Drv_Extra)); 1801 1802 res = rtw_enqueue_cmd(pcmdpriv, ph2c); 1803 1804 exit: 1805 1806 return res; 1807 } 1808 1809 static void c2h_wk_callback(struct work_struct *work) 1810 { 1811 struct evt_priv *evtpriv = container_of(work, struct evt_priv, c2h_wk); 1812 struct adapter *adapter = container_of(evtpriv, struct adapter, evtpriv); 1813 u8 *c2h_evt; 1814 c2h_id_filter ccx_id_filter = rtw_hal_c2h_id_filter_ccx(adapter); 1815 1816 evtpriv->c2h_wk_alive = true; 1817 1818 while (!rtw_cbuf_empty(evtpriv->c2h_queue)) { 1819 c2h_evt = (u8 *)rtw_cbuf_pop(evtpriv->c2h_queue); 1820 if (c2h_evt) { 1821 /* This C2H event is read, clear it */ 1822 c2h_evt_clear(adapter); 1823 } else { 1824 c2h_evt = rtw_malloc(16); 1825 if (c2h_evt) { 1826 /* This C2H event is not read, read & clear now */ 1827 if (c2h_evt_read_88xx(adapter, c2h_evt) != _SUCCESS) { 1828 kfree(c2h_evt); 1829 continue; 1830 } 1831 } 1832 } 1833 1834 /* Special pointer to trigger c2h_evt_clear only */ 1835 if ((void *)c2h_evt == (void *)evtpriv) 1836 continue; 1837 1838 if (!rtw_hal_c2h_valid(adapter, c2h_evt)) { 1839 kfree(c2h_evt); 1840 continue; 1841 } 1842 1843 if (ccx_id_filter(c2h_evt)) { 1844 /* Handle CCX report here */ 1845 rtw_hal_c2h_handler(adapter, c2h_evt); 1846 kfree(c2h_evt); 1847 } else { 1848 /* Enqueue into cmd_thread for others */ 1849 rtw_c2h_wk_cmd(adapter, c2h_evt); 1850 } 1851 } 1852 1853 evtpriv->c2h_wk_alive = false; 1854 } 1855 1856 u8 rtw_drvextra_cmd_hdl(struct adapter *padapter, unsigned char *pbuf) 1857 { 1858 struct drvextra_cmd_parm *pdrvextra_cmd; 1859 1860 if (!pbuf) 1861 return H2C_PARAMETERS_ERROR; 1862 1863 pdrvextra_cmd = (struct drvextra_cmd_parm *)pbuf; 1864 1865 switch (pdrvextra_cmd->ec_id) { 1866 case DYNAMIC_CHK_WK_CID:/* only primary padapter go to this cmd, but execute dynamic_chk_wk_hdl() for two interfaces */ 1867 dynamic_chk_wk_hdl(padapter); 1868 break; 1869 case POWER_SAVING_CTRL_WK_CID: 1870 rtw_ps_processor(padapter); 1871 break; 1872 case LPS_CTRL_WK_CID: 1873 lps_ctrl_wk_hdl(padapter, (u8)pdrvextra_cmd->type); 1874 break; 1875 case DM_IN_LPS_WK_CID: 1876 rtw_dm_in_lps_hdl(padapter); 1877 break; 1878 case LPS_CHANGE_DTIM_CID: 1879 rtw_lps_change_dtim_hdl(padapter, (u8)pdrvextra_cmd->type); 1880 break; 1881 case CHECK_HIQ_WK_CID: 1882 rtw_chk_hi_queue_hdl(padapter); 1883 break; 1884 /* add for CONFIG_IEEE80211W, none 11w can use it */ 1885 case RESET_SECURITYPRIV: 1886 rtw_reset_securitypriv(padapter); 1887 break; 1888 case FREE_ASSOC_RESOURCES: 1889 rtw_free_assoc_resources(padapter, 1); 1890 break; 1891 case C2H_WK_CID: 1892 rtw_hal_set_hwreg_with_buf(padapter, HW_VAR_C2H_HANDLE, pdrvextra_cmd->pbuf, pdrvextra_cmd->size); 1893 break; 1894 case DM_RA_MSK_WK_CID: 1895 rtw_dm_ra_mask_hdl(padapter, (struct sta_info *)pdrvextra_cmd->pbuf); 1896 break; 1897 case BTINFO_WK_CID: 1898 rtw_btinfo_hdl(padapter, pdrvextra_cmd->pbuf, pdrvextra_cmd->size); 1899 break; 1900 default: 1901 break; 1902 } 1903 1904 if (pdrvextra_cmd->pbuf && pdrvextra_cmd->size > 0) 1905 kfree(pdrvextra_cmd->pbuf); 1906 1907 return H2C_SUCCESS; 1908 } 1909 1910 void rtw_survey_cmd_callback(struct adapter *padapter, struct cmd_obj *pcmd) 1911 { 1912 struct mlme_priv *pmlmepriv = &padapter->mlmepriv; 1913 1914 if (pcmd->res == H2C_DROPPED) { 1915 /* TODO: cancel timer and do timeout handler directly... */ 1916 /* need to make timeout handlerOS independent */ 1917 _set_timer(&pmlmepriv->scan_to_timer, 1); 1918 } else if (pcmd->res != H2C_SUCCESS) { 1919 _set_timer(&pmlmepriv->scan_to_timer, 1); 1920 } 1921 1922 /* free cmd */ 1923 rtw_free_cmd_obj(pcmd); 1924 } 1925 1926 void rtw_disassoc_cmd_callback(struct adapter *padapter, struct cmd_obj *pcmd) 1927 { 1928 struct mlme_priv *pmlmepriv = &padapter->mlmepriv; 1929 1930 if (pcmd->res != H2C_SUCCESS) { 1931 spin_lock_bh(&pmlmepriv->lock); 1932 set_fwstate(pmlmepriv, _FW_LINKED); 1933 spin_unlock_bh(&pmlmepriv->lock); 1934 1935 return; 1936 } 1937 /* free cmd */ 1938 rtw_free_cmd_obj(pcmd); 1939 } 1940 1941 void rtw_joinbss_cmd_callback(struct adapter *padapter, struct cmd_obj *pcmd) 1942 { 1943 struct mlme_priv *pmlmepriv = &padapter->mlmepriv; 1944 1945 if (pcmd->res == H2C_DROPPED) { 1946 /* TODO: cancel timer and do timeout handler directly... */ 1947 /* need to make timeout handlerOS independent */ 1948 _set_timer(&pmlmepriv->assoc_timer, 1); 1949 } else if (pcmd->res != H2C_SUCCESS) { 1950 _set_timer(&pmlmepriv->assoc_timer, 1); 1951 } 1952 1953 rtw_free_cmd_obj(pcmd); 1954 } 1955 1956 void rtw_createbss_cmd_callback(struct adapter *padapter, struct cmd_obj *pcmd) 1957 { 1958 struct sta_info *psta = NULL; 1959 struct wlan_network *pwlan = NULL; 1960 struct mlme_priv *pmlmepriv = &padapter->mlmepriv; 1961 struct wlan_bssid_ex *pnetwork = (struct wlan_bssid_ex *)pcmd->parmbuf; 1962 struct wlan_network *tgt_network = &(pmlmepriv->cur_network); 1963 1964 if (!pcmd->parmbuf) 1965 goto exit; 1966 1967 if (pcmd->res != H2C_SUCCESS) 1968 _set_timer(&pmlmepriv->assoc_timer, 1); 1969 1970 del_timer_sync(&pmlmepriv->assoc_timer); 1971 1972 spin_lock_bh(&pmlmepriv->lock); 1973 1974 1975 if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) { 1976 psta = rtw_get_stainfo(&padapter->stapriv, pnetwork->mac_address); 1977 if (!psta) { 1978 psta = rtw_alloc_stainfo(&padapter->stapriv, pnetwork->mac_address); 1979 if (!psta) 1980 goto createbss_cmd_fail; 1981 } 1982 1983 rtw_indicate_connect(padapter); 1984 } else { 1985 pwlan = rtw_alloc_network(pmlmepriv); 1986 spin_lock_bh(&(pmlmepriv->scanned_queue.lock)); 1987 if (!pwlan) { 1988 pwlan = rtw_get_oldest_wlan_network(&pmlmepriv->scanned_queue); 1989 if (!pwlan) { 1990 spin_unlock_bh(&(pmlmepriv->scanned_queue.lock)); 1991 goto createbss_cmd_fail; 1992 } 1993 pwlan->last_scanned = jiffies; 1994 } else { 1995 list_add_tail(&(pwlan->list), &pmlmepriv->scanned_queue.queue); 1996 } 1997 1998 pnetwork->length = get_wlan_bssid_ex_sz(pnetwork); 1999 memcpy(&(pwlan->network), pnetwork, pnetwork->length); 2000 /* pwlan->fixed = true; */ 2001 2002 /* list_add_tail(&(pwlan->list), &pmlmepriv->scanned_queue.queue); */ 2003 2004 /* copy pdev_network information to pmlmepriv->cur_network */ 2005 memcpy(&tgt_network->network, pnetwork, (get_wlan_bssid_ex_sz(pnetwork))); 2006 2007 /* reset ds_config */ 2008 /* tgt_network->network.configuration.ds_config = (u32)rtw_ch2freq(pnetwork->configuration.ds_config); */ 2009 2010 _clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING); 2011 2012 spin_unlock_bh(&(pmlmepriv->scanned_queue.lock)); 2013 /* we will set _FW_LINKED when there is one more sat to join us (rtw_stassoc_event_callback) */ 2014 2015 } 2016 2017 createbss_cmd_fail: 2018 2019 spin_unlock_bh(&pmlmepriv->lock); 2020 exit: 2021 rtw_free_cmd_obj(pcmd); 2022 } 2023 2024 2025 2026 void rtw_setstaKey_cmdrsp_callback(struct adapter *padapter, struct cmd_obj *pcmd) 2027 { 2028 2029 struct sta_priv *pstapriv = &padapter->stapriv; 2030 struct set_stakey_rsp *psetstakey_rsp = (struct set_stakey_rsp *) (pcmd->rsp); 2031 struct sta_info *psta = rtw_get_stainfo(pstapriv, psetstakey_rsp->addr); 2032 2033 if (!psta) 2034 goto exit; 2035 2036 exit: 2037 rtw_free_cmd_obj(pcmd); 2038 } 2039 2040 void rtw_setassocsta_cmdrsp_callback(struct adapter *padapter, struct cmd_obj *pcmd) 2041 { 2042 struct sta_priv *pstapriv = &padapter->stapriv; 2043 struct mlme_priv *pmlmepriv = &padapter->mlmepriv; 2044 struct set_assocsta_parm *passocsta_parm = (struct set_assocsta_parm *)(pcmd->parmbuf); 2045 struct set_assocsta_rsp *passocsta_rsp = (struct set_assocsta_rsp *) (pcmd->rsp); 2046 struct sta_info *psta = rtw_get_stainfo(pstapriv, passocsta_parm->addr); 2047 2048 if (!psta) 2049 goto exit; 2050 2051 psta->aid = passocsta_rsp->cam_id; 2052 psta->mac_id = passocsta_rsp->cam_id; 2053 2054 spin_lock_bh(&pmlmepriv->lock); 2055 2056 if (check_fwstate(pmlmepriv, WIFI_MP_STATE) && check_fwstate(pmlmepriv, _FW_UNDER_LINKING)) 2057 _clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING); 2058 2059 set_fwstate(pmlmepriv, _FW_LINKED); 2060 spin_unlock_bh(&pmlmepriv->lock); 2061 2062 exit: 2063 rtw_free_cmd_obj(pcmd); 2064 } 2065