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