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