1 /******************************************************************************
2 *
3 * Copyright(c) 2007 - 2017 Realtek Corporation.
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of version 2 of the GNU General Public License as
7 * published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 *****************************************************************************/
15 #define _RTW_CMD_C_
16
17 #include <drv_types.h>
18 #include <hal_data.h>
19
20 #ifndef DBG_CMD_EXECUTE
21 #define DBG_CMD_EXECUTE 0
22 #endif
23
24 /*
25 Caller and the rtw_cmd_thread can protect cmd_q by spin_lock.
26 No irqsave is necessary.
27 */
28
_rtw_init_cmd_priv(struct cmd_priv * pcmdpriv)29 sint _rtw_init_cmd_priv(struct cmd_priv *pcmdpriv)
30 {
31 sint res = _SUCCESS;
32
33
34 _rtw_init_sema(&(pcmdpriv->cmd_queue_sema), 0);
35 /* _rtw_init_sema(&(pcmdpriv->cmd_done_sema), 0); */
36 _rtw_init_sema(&(pcmdpriv->start_cmdthread_sema), 0);
37
38 _rtw_init_queue(&(pcmdpriv->cmd_queue));
39
40 /* allocate DMA-able/Non-Page memory for cmd_buf and rsp_buf */
41
42 pcmdpriv->cmd_seq = 1;
43
44 pcmdpriv->cmd_allocated_buf = rtw_zmalloc(MAX_CMDSZ + CMDBUFF_ALIGN_SZ);
45
46 if (pcmdpriv->cmd_allocated_buf == NULL) {
47 res = _FAIL;
48 goto exit;
49 }
50
51 pcmdpriv->cmd_buf = pcmdpriv->cmd_allocated_buf + CMDBUFF_ALIGN_SZ - ((SIZE_PTR)(pcmdpriv->cmd_allocated_buf) & (CMDBUFF_ALIGN_SZ - 1));
52
53 pcmdpriv->rsp_allocated_buf = rtw_zmalloc(MAX_RSPSZ + 4);
54
55 if (pcmdpriv->rsp_allocated_buf == NULL) {
56 res = _FAIL;
57 goto exit;
58 }
59
60 pcmdpriv->rsp_buf = pcmdpriv->rsp_allocated_buf + 4 - ((SIZE_PTR)(pcmdpriv->rsp_allocated_buf) & 3);
61
62 pcmdpriv->cmd_issued_cnt = pcmdpriv->cmd_done_cnt = pcmdpriv->rsp_cnt = 0;
63
64 _rtw_mutex_init(&pcmdpriv->sctx_mutex);
65 exit:
66
67
68 return res;
69
70 }
71
72 #ifdef CONFIG_C2H_WK
c2h_wk_callback(_workitem * work)73 static void c2h_wk_callback(_workitem *work)
74 {
75 struct evt_priv *evtpriv = container_of(work, struct evt_priv, c2h_wk);
76 _adapter *adapter = container_of(evtpriv, _adapter, evtpriv);
77 u8 *c2h_evt;
78 c2h_id_filter direct_hdl_filter = rtw_hal_c2h_id_handle_directly;
79 u8 id, seq, plen;
80 u8 *payload;
81
82 evtpriv->c2h_wk_alive = _TRUE;
83
84 while (!rtw_cbuf_empty(evtpriv->c2h_queue)) {
85 c2h_evt = (u8 *)rtw_cbuf_pop(evtpriv->c2h_queue);
86 if (c2h_evt != NULL) {
87 /* This C2H event is read, clear it */
88 c2h_evt_clear(adapter);
89 } else {
90 c2h_evt = (u8 *)rtw_malloc(C2H_REG_LEN);
91 if (c2h_evt == NULL) {
92 rtw_warn_on(1);
93 continue;
94 }
95
96 /* This C2H event is not read, read & clear now */
97 if (rtw_hal_c2h_evt_read(adapter, c2h_evt) != _SUCCESS) {
98 rtw_mfree(c2h_evt, C2H_REG_LEN);
99 continue;
100 }
101 }
102
103 /* Special pointer to trigger c2h_evt_clear only */
104 if ((void *)c2h_evt == (void *)evtpriv)
105 continue;
106
107 if (!rtw_hal_c2h_valid(adapter, c2h_evt)
108 || rtw_hal_c2h_reg_hdr_parse(adapter, c2h_evt, &id, &seq, &plen, &payload) != _SUCCESS
109 ) {
110 rtw_mfree(c2h_evt, C2H_REG_LEN);
111 continue;
112 }
113
114 if (direct_hdl_filter(adapter, id, seq, plen, payload) == _TRUE) {
115 /* Handle directly */
116 rtw_hal_c2h_handler(adapter, id, seq, plen, payload);
117 rtw_mfree(c2h_evt, C2H_REG_LEN);
118 } else {
119 /* Enqueue into cmd_thread for others */
120 rtw_c2h_reg_wk_cmd(adapter, c2h_evt);
121 rtw_mfree(c2h_evt, C2H_REG_LEN);
122 }
123 }
124
125 evtpriv->c2h_wk_alive = _FALSE;
126 }
127 #endif /* CONFIG_C2H_WK */
128
_rtw_init_evt_priv(struct evt_priv * pevtpriv)129 sint _rtw_init_evt_priv(struct evt_priv *pevtpriv)
130 {
131 sint res = _SUCCESS;
132
133
134 #ifdef CONFIG_H2CLBK
135 _rtw_init_sema(&(pevtpriv->lbkevt_done), 0);
136 pevtpriv->lbkevt_limit = 0;
137 pevtpriv->lbkevt_num = 0;
138 pevtpriv->cmdevt_parm = NULL;
139 #endif
140
141 /* allocate DMA-able/Non-Page memory for cmd_buf and rsp_buf */
142 ATOMIC_SET(&pevtpriv->event_seq, 0);
143 pevtpriv->evt_done_cnt = 0;
144
145 #ifdef CONFIG_EVENT_THREAD_MODE
146
147 _rtw_init_sema(&(pevtpriv->evt_notify), 0);
148
149 pevtpriv->evt_allocated_buf = rtw_zmalloc(MAX_EVTSZ + 4);
150 if (pevtpriv->evt_allocated_buf == NULL) {
151 res = _FAIL;
152 goto exit;
153 }
154 pevtpriv->evt_buf = pevtpriv->evt_allocated_buf + 4 - ((unsigned int)(pevtpriv->evt_allocated_buf) & 3);
155
156
157 #if defined(CONFIG_SDIO_HCI) || defined(CONFIG_GSPI_HCI)
158 pevtpriv->allocated_c2h_mem = rtw_zmalloc(C2H_MEM_SZ + 4);
159
160 if (pevtpriv->allocated_c2h_mem == NULL) {
161 res = _FAIL;
162 goto exit;
163 }
164
165 pevtpriv->c2h_mem = pevtpriv->allocated_c2h_mem + 4\
166 - ((u32)(pevtpriv->allocated_c2h_mem) & 3);
167 #endif /* end of CONFIG_SDIO_HCI */
168
169 _rtw_init_queue(&(pevtpriv->evt_queue));
170
171 exit:
172
173 #endif /* end of CONFIG_EVENT_THREAD_MODE */
174
175 #ifdef CONFIG_C2H_WK
176 _init_workitem(&pevtpriv->c2h_wk, c2h_wk_callback, NULL);
177 pevtpriv->c2h_wk_alive = _FALSE;
178 pevtpriv->c2h_queue = rtw_cbuf_alloc(C2H_QUEUE_MAX_LEN + 1);
179 #endif
180
181
182 return res;
183 }
184
_rtw_free_evt_priv(struct evt_priv * pevtpriv)185 void _rtw_free_evt_priv(struct evt_priv *pevtpriv)
186 {
187
188
189 #ifdef CONFIG_EVENT_THREAD_MODE
190 _rtw_free_sema(&(pevtpriv->evt_notify));
191
192 if (pevtpriv->evt_allocated_buf)
193 rtw_mfree(pevtpriv->evt_allocated_buf, MAX_EVTSZ + 4);
194 #endif
195
196 #ifdef CONFIG_C2H_WK
197 _cancel_workitem_sync(&pevtpriv->c2h_wk);
198 while (pevtpriv->c2h_wk_alive)
199 rtw_msleep_os(10);
200
201 while (!rtw_cbuf_empty(pevtpriv->c2h_queue)) {
202 void *c2h;
203 c2h = rtw_cbuf_pop(pevtpriv->c2h_queue);
204 if (c2h != NULL && c2h != (void *)pevtpriv)
205 rtw_mfree(c2h, 16);
206 }
207 rtw_cbuf_free(pevtpriv->c2h_queue);
208 #endif
209
210
211
212 }
213
_rtw_free_cmd_priv(struct cmd_priv * pcmdpriv)214 void _rtw_free_cmd_priv(struct cmd_priv *pcmdpriv)
215 {
216
217 if (pcmdpriv) {
218 _rtw_spinlock_free(&(pcmdpriv->cmd_queue.lock));
219 _rtw_free_sema(&(pcmdpriv->cmd_queue_sema));
220 /* _rtw_free_sema(&(pcmdpriv->cmd_done_sema)); */
221 _rtw_free_sema(&(pcmdpriv->start_cmdthread_sema));
222
223 if (pcmdpriv->cmd_allocated_buf)
224 rtw_mfree(pcmdpriv->cmd_allocated_buf, MAX_CMDSZ + CMDBUFF_ALIGN_SZ);
225
226 if (pcmdpriv->rsp_allocated_buf)
227 rtw_mfree(pcmdpriv->rsp_allocated_buf, MAX_RSPSZ + 4);
228
229 _rtw_mutex_free(&pcmdpriv->sctx_mutex);
230 }
231 }
232
233 /*
234 Calling Context:
235
236 rtw_enqueue_cmd can only be called between kernel thread,
237 since only spin_lock is used.
238
239 ISR/Call-Back functions can't call this sub-function.
240
241 */
242 #ifdef DBG_CMD_QUEUE
243 extern u8 dump_cmd_id;
244 #endif
245
_rtw_enqueue_cmd(_queue * queue,struct cmd_obj * obj,bool to_head)246 sint _rtw_enqueue_cmd(_queue *queue, struct cmd_obj *obj, bool to_head)
247 {
248 _irqL irqL;
249
250
251 if (obj == NULL)
252 goto exit;
253
254 /* _enter_critical_bh(&queue->lock, &irqL); */
255 _enter_critical(&queue->lock, &irqL);
256
257 if (to_head)
258 rtw_list_insert_head(&obj->list, &queue->queue);
259 else
260 rtw_list_insert_tail(&obj->list, &queue->queue);
261
262 #ifdef DBG_CMD_QUEUE
263 if (dump_cmd_id) {
264 RTW_INFO("%s===> cmdcode:0x%02x\n", __FUNCTION__, obj->cmdcode);
265 if (obj->cmdcode == CMD_SET_MLME_EVT) {
266 if (obj->parmbuf) {
267 struct rtw_evt_header *evt_hdr = (struct rtw_evt_header *)(obj->parmbuf);
268 RTW_INFO("evt_hdr->id:%d\n", evt_hdr->id);
269 }
270 }
271 if (obj->cmdcode == CMD_SET_DRV_EXTRA) {
272 if (obj->parmbuf) {
273 struct drvextra_cmd_parm *pdrvextra_cmd_parm = (struct drvextra_cmd_parm *)(obj->parmbuf);
274 RTW_INFO("pdrvextra_cmd_parm->ec_id:0x%02x\n", pdrvextra_cmd_parm->ec_id);
275 }
276 }
277 }
278
279 if (queue->queue.prev->next != &queue->queue) {
280 RTW_INFO("[%d] head %p, tail %p, tail->prev->next %p[tail], tail->next %p[head]\n", __LINE__,
281 &queue->queue, queue->queue.prev, queue->queue.prev->prev->next, queue->queue.prev->next);
282
283 RTW_INFO("==========%s============\n", __FUNCTION__);
284 RTW_INFO("head:%p,obj_addr:%p\n", &queue->queue, obj);
285 RTW_INFO("padapter: %p\n", obj->padapter);
286 RTW_INFO("cmdcode: 0x%02x\n", obj->cmdcode);
287 RTW_INFO("res: %d\n", obj->res);
288 RTW_INFO("parmbuf: %p\n", obj->parmbuf);
289 RTW_INFO("cmdsz: %d\n", obj->cmdsz);
290 RTW_INFO("rsp: %p\n", obj->rsp);
291 RTW_INFO("rspsz: %d\n", obj->rspsz);
292 RTW_INFO("sctx: %p\n", obj->sctx);
293 RTW_INFO("list->next: %p\n", obj->list.next);
294 RTW_INFO("list->prev: %p\n", obj->list.prev);
295 }
296 #endif /* DBG_CMD_QUEUE */
297
298 /* _exit_critical_bh(&queue->lock, &irqL); */
299 _exit_critical(&queue->lock, &irqL);
300
301 exit:
302
303
304 return _SUCCESS;
305 }
306
_rtw_dequeue_cmd(_queue * queue)307 struct cmd_obj *_rtw_dequeue_cmd(_queue *queue)
308 {
309 _irqL irqL;
310 struct cmd_obj *obj;
311
312
313 /* _enter_critical_bh(&(queue->lock), &irqL); */
314 _enter_critical(&queue->lock, &irqL);
315
316 #ifdef DBG_CMD_QUEUE
317 if (queue->queue.prev->next != &queue->queue) {
318 RTW_INFO("[%d] head %p, tail %p, tail->prev->next %p[tail], tail->next %p[head]\n", __LINE__,
319 &queue->queue, queue->queue.prev, queue->queue.prev->prev->next, queue->queue.prev->next);
320 }
321 #endif /* DBG_CMD_QUEUE */
322
323
324 if (rtw_is_list_empty(&(queue->queue)))
325 obj = NULL;
326 else {
327 obj = LIST_CONTAINOR(get_next(&(queue->queue)), struct cmd_obj, list);
328
329 #ifdef DBG_CMD_QUEUE
330 if (queue->queue.prev->next != &queue->queue) {
331 RTW_INFO("==========%s============\n", __FUNCTION__);
332 RTW_INFO("head:%p,obj_addr:%p\n", &queue->queue, obj);
333 RTW_INFO("padapter: %p\n", obj->padapter);
334 RTW_INFO("cmdcode: 0x%02x\n", obj->cmdcode);
335 RTW_INFO("res: %d\n", obj->res);
336 RTW_INFO("parmbuf: %p\n", obj->parmbuf);
337 RTW_INFO("cmdsz: %d\n", obj->cmdsz);
338 RTW_INFO("rsp: %p\n", obj->rsp);
339 RTW_INFO("rspsz: %d\n", obj->rspsz);
340 RTW_INFO("sctx: %p\n", obj->sctx);
341 RTW_INFO("list->next: %p\n", obj->list.next);
342 RTW_INFO("list->prev: %p\n", obj->list.prev);
343 }
344
345 if (dump_cmd_id) {
346 RTW_INFO("%s===> cmdcode:0x%02x\n", __FUNCTION__, obj->cmdcode);
347 if (obj->cmdcode == CMD_SET_DRV_EXTRA) {
348 if (obj->parmbuf) {
349 struct drvextra_cmd_parm *pdrvextra_cmd_parm = (struct drvextra_cmd_parm *)(obj->parmbuf);
350 printk("pdrvextra_cmd_parm->ec_id:0x%02x\n", pdrvextra_cmd_parm->ec_id);
351 }
352 }
353
354 }
355 #endif /* DBG_CMD_QUEUE */
356
357 rtw_list_delete(&obj->list);
358 }
359
360 /* _exit_critical_bh(&(queue->lock), &irqL); */
361 _exit_critical(&queue->lock, &irqL);
362
363
364 return obj;
365 }
366
rtw_init_cmd_priv(struct cmd_priv * pcmdpriv)367 u32 rtw_init_cmd_priv(struct cmd_priv *pcmdpriv)
368 {
369 u32 res;
370 res = _rtw_init_cmd_priv(pcmdpriv);
371 return res;
372 }
373
rtw_init_evt_priv(struct evt_priv * pevtpriv)374 u32 rtw_init_evt_priv(struct evt_priv *pevtpriv)
375 {
376 int res;
377 res = _rtw_init_evt_priv(pevtpriv);
378 return res;
379 }
380
rtw_free_evt_priv(struct evt_priv * pevtpriv)381 void rtw_free_evt_priv(struct evt_priv *pevtpriv)
382 {
383 _rtw_free_evt_priv(pevtpriv);
384 }
385
rtw_free_cmd_priv(struct cmd_priv * pcmdpriv)386 void rtw_free_cmd_priv(struct cmd_priv *pcmdpriv)
387 {
388 _rtw_free_cmd_priv(pcmdpriv);
389 }
390
391 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)392 int rtw_cmd_filter(struct cmd_priv *pcmdpriv, struct cmd_obj *cmd_obj)
393 {
394 #ifndef CONFIG_MAC_LOOPBACK_DRIVER
395 u8 bAllow = _FALSE; /* set to _TRUE to allow enqueuing cmd when hw_init_completed is _FALSE */
396 #else
397 u8 bAllow = _TRUE; /* hw_init_completed is _FALSE in the case of MAC loopback*/
398 #endif
399
400 #ifdef SUPPORT_HW_RFOFF_DETECTED
401 /* To decide allow or not */
402 if ((adapter_to_pwrctl(pcmdpriv->padapter)->bHWPwrPindetect)
403 && (!pcmdpriv->padapter->registrypriv.usbss_enable)
404 ) {
405 if (cmd_obj->cmdcode == CMD_SET_DRV_EXTRA) {
406 struct drvextra_cmd_parm *pdrvextra_cmd_parm = (struct drvextra_cmd_parm *)cmd_obj->parmbuf;
407 if (pdrvextra_cmd_parm->ec_id == POWER_SAVING_CTRL_WK_CID) {
408 /* RTW_INFO("==>enqueue POWER_SAVING_CTRL_WK_CID\n"); */
409 bAllow = _TRUE;
410 }
411 }
412 }
413 #endif
414
415 if (cmd_obj->cmdcode == CMD_SET_CHANPLAN)
416 bAllow = _TRUE;
417
418 if (cmd_obj->no_io)
419 bAllow = _TRUE;
420
421 if ((!rtw_is_hw_init_completed(pcmdpriv->padapter) && (bAllow == _FALSE))
422 || ATOMIC_READ(&(pcmdpriv->cmdthd_running)) == _FALSE /* com_thread not running */
423 ) {
424 if (DBG_CMD_EXECUTE)
425 RTW_INFO(ADPT_FMT" drop "CMD_FMT" hw_init_completed:%u, cmdthd_running:%u\n", ADPT_ARG(cmd_obj->padapter)
426 , CMD_ARG(cmd_obj), rtw_get_hw_init_completed(cmd_obj->padapter), ATOMIC_READ(&pcmdpriv->cmdthd_running));
427 if (0)
428 rtw_warn_on(1);
429
430 return _FAIL;
431 }
432 return _SUCCESS;
433 }
434
435
436
rtw_enqueue_cmd(struct cmd_priv * pcmdpriv,struct cmd_obj * cmd_obj)437 u32 rtw_enqueue_cmd(struct cmd_priv *pcmdpriv, struct cmd_obj *cmd_obj)
438 {
439 int res = _FAIL;
440 PADAPTER padapter = pcmdpriv->padapter;
441
442
443 if (cmd_obj == NULL)
444 goto exit;
445
446 cmd_obj->padapter = padapter;
447
448 #ifdef CONFIG_CONCURRENT_MODE
449 /* change pcmdpriv to primary's pcmdpriv */
450 if (!is_primary_adapter(padapter))
451 pcmdpriv = &(GET_PRIMARY_ADAPTER(padapter)->cmdpriv);
452 #endif
453
454 res = rtw_cmd_filter(pcmdpriv, cmd_obj);
455 if ((_FAIL == res) || (cmd_obj->cmdsz > MAX_CMDSZ)) {
456 if (cmd_obj->cmdsz > MAX_CMDSZ) {
457 RTW_INFO("%s failed due to obj->cmdsz(%d) > MAX_CMDSZ(%d)\n", __func__, cmd_obj->cmdsz, MAX_CMDSZ);
458 rtw_warn_on(1);
459 }
460
461 if (cmd_obj->cmdcode == CMD_SET_DRV_EXTRA) {
462 struct drvextra_cmd_parm *extra_parm = (struct drvextra_cmd_parm *)cmd_obj->parmbuf;
463
464 if (extra_parm->pbuf && extra_parm->size > 0)
465 rtw_mfree(extra_parm->pbuf, extra_parm->size);
466 }
467 rtw_free_cmd_obj(cmd_obj);
468 goto exit;
469 }
470
471 res = _rtw_enqueue_cmd(&pcmdpriv->cmd_queue, cmd_obj, 0);
472
473 if (res == _SUCCESS)
474 _rtw_up_sema(&pcmdpriv->cmd_queue_sema);
475
476 exit:
477
478
479 return res;
480 }
481
rtw_dequeue_cmd(struct cmd_priv * pcmdpriv)482 struct cmd_obj *rtw_dequeue_cmd(struct cmd_priv *pcmdpriv)
483 {
484 struct cmd_obj *cmd_obj;
485
486
487 cmd_obj = _rtw_dequeue_cmd(&pcmdpriv->cmd_queue);
488
489 return cmd_obj;
490 }
491
rtw_cmd_clr_isr(struct cmd_priv * pcmdpriv)492 void rtw_cmd_clr_isr(struct cmd_priv *pcmdpriv)
493 {
494 pcmdpriv->cmd_done_cnt++;
495 /* _rtw_up_sema(&(pcmdpriv->cmd_done_sema)); */
496 }
497
rtw_free_cmd_obj(struct cmd_obj * pcmd)498 void rtw_free_cmd_obj(struct cmd_obj *pcmd)
499 {
500 if (pcmd->parmbuf != NULL) {
501 /* free parmbuf in cmd_obj */
502 rtw_mfree((unsigned char *)pcmd->parmbuf, pcmd->cmdsz);
503 }
504 if (pcmd->rsp != NULL) {
505 if (pcmd->rspsz != 0) {
506 /* free rsp in cmd_obj */
507 rtw_mfree((unsigned char *)pcmd->rsp, pcmd->rspsz);
508 }
509 }
510
511 /* free cmd_obj */
512 rtw_mfree((unsigned char *)pcmd, sizeof(struct cmd_obj));
513 }
514
515
rtw_stop_cmd_thread(_adapter * adapter)516 void rtw_stop_cmd_thread(_adapter *adapter)
517 {
518 if (adapter->cmdThread) {
519 _rtw_up_sema(&adapter->cmdpriv.cmd_queue_sema);
520 rtw_thread_stop(adapter->cmdThread);
521 adapter->cmdThread = NULL;
522 }
523 }
524
rtw_cmd_thread(thread_context context)525 thread_return rtw_cmd_thread(thread_context context)
526 {
527 u8 ret;
528 struct cmd_obj *pcmd;
529 u8 *pcmdbuf, *prspbuf;
530 systime cmd_start_time;
531 u32 cmd_process_time;
532 u8(*cmd_hdl)(_adapter *padapter, u8 *pbuf);
533 void (*pcmd_callback)(_adapter *dev, struct cmd_obj *pcmd);
534 PADAPTER padapter = (PADAPTER)context;
535 struct cmd_priv *pcmdpriv = &(padapter->cmdpriv);
536 struct drvextra_cmd_parm *extra_parm = NULL;
537 _irqL irqL;
538
539 thread_enter("RTW_CMD_THREAD");
540
541 pcmdbuf = pcmdpriv->cmd_buf;
542 prspbuf = pcmdpriv->rsp_buf;
543 ATOMIC_SET(&(pcmdpriv->cmdthd_running), _TRUE);
544 _rtw_up_sema(&pcmdpriv->start_cmdthread_sema);
545
546
547 while (1) {
548 if (_rtw_down_sema(&pcmdpriv->cmd_queue_sema) == _FAIL) {
549 RTW_PRINT(FUNC_ADPT_FMT" _rtw_down_sema(&pcmdpriv->cmd_queue_sema) return _FAIL, break\n", FUNC_ADPT_ARG(padapter));
550 break;
551 }
552
553 if (RTW_CANNOT_RUN(padapter)) {
554 RTW_DBG(FUNC_ADPT_FMT "- bDriverStopped(%s) bSurpriseRemoved(%s)\n",
555 FUNC_ADPT_ARG(padapter),
556 rtw_is_drv_stopped(padapter) ? "True" : "False",
557 rtw_is_surprise_removed(padapter) ? "True" : "False");
558 break;
559 }
560
561 _enter_critical(&pcmdpriv->cmd_queue.lock, &irqL);
562 if (rtw_is_list_empty(&(pcmdpriv->cmd_queue.queue))) {
563 /* RTW_INFO("%s: cmd queue is empty!\n", __func__); */
564 _exit_critical(&pcmdpriv->cmd_queue.lock, &irqL);
565 continue;
566 }
567 _exit_critical(&pcmdpriv->cmd_queue.lock, &irqL);
568
569 _next:
570 if (RTW_CANNOT_RUN(padapter)) {
571 RTW_PRINT("%s: DriverStopped(%s) SurpriseRemoved(%s) break at line %d\n",
572 __func__
573 , rtw_is_drv_stopped(padapter) ? "True" : "False"
574 , rtw_is_surprise_removed(padapter) ? "True" : "False"
575 , __LINE__);
576 break;
577 }
578
579 pcmd = rtw_dequeue_cmd(pcmdpriv);
580 if (!pcmd) {
581 #ifdef CONFIG_LPS_LCLK
582 rtw_unregister_cmd_alive(padapter);
583 #endif
584 continue;
585 }
586
587 cmd_start_time = rtw_get_current_time();
588 pcmdpriv->cmd_issued_cnt++;
589
590 if (pcmd->cmdsz > MAX_CMDSZ) {
591 RTW_ERR("%s cmdsz:%d > MAX_CMDSZ:%d\n", __func__, pcmd->cmdsz, MAX_CMDSZ);
592 pcmd->res = H2C_PARAMETERS_ERROR;
593 goto post_process;
594 }
595
596 if (pcmd->cmdcode >= (sizeof(wlancmds) / sizeof(struct rtw_cmd))) {
597 RTW_ERR("%s undefined cmdcode:%d\n", __func__, pcmd->cmdcode);
598 pcmd->res = H2C_PARAMETERS_ERROR;
599 goto post_process;
600 }
601
602 cmd_hdl = wlancmds[pcmd->cmdcode].cmd_hdl;
603 if (!cmd_hdl) {
604 RTW_ERR("%s no cmd_hdl for cmdcode:%d\n", __func__, pcmd->cmdcode);
605 pcmd->res = H2C_PARAMETERS_ERROR;
606 goto post_process;
607 }
608
609 if (_FAIL == rtw_cmd_filter(pcmdpriv, pcmd)) {
610 pcmd->res = H2C_DROPPED;
611 if (pcmd->cmdcode == CMD_SET_DRV_EXTRA) {
612 extra_parm = (struct drvextra_cmd_parm *)pcmd->parmbuf;
613 if (extra_parm && extra_parm->pbuf && extra_parm->size > 0)
614 rtw_mfree(extra_parm->pbuf, extra_parm->size);
615 }
616 #if CONFIG_DFS
617 else if (pcmd->cmdcode == CMD_SET_CHANSWITCH)
618 adapter_to_rfctl(padapter)->csa_ch = 0;
619 #endif
620 goto post_process;
621 }
622
623 #ifdef CONFIG_LPS_LCLK
624 if (pcmd->no_io)
625 rtw_unregister_cmd_alive(padapter);
626 else {
627 if (rtw_register_cmd_alive(padapter) != _SUCCESS) {
628 if (DBG_CMD_EXECUTE)
629 RTW_PRINT("%s: wait to leave LPS_LCLK\n", __func__);
630
631 pcmd->res = H2C_ENQ_HEAD;
632 ret = _rtw_enqueue_cmd(&pcmdpriv->cmd_queue, pcmd, 1);
633 if (ret == _SUCCESS) {
634 if (DBG_CMD_EXECUTE)
635 RTW_INFO(ADPT_FMT" "CMD_FMT" ENQ_HEAD\n", ADPT_ARG(pcmd->padapter), CMD_ARG(pcmd));
636 continue;
637 }
638
639 RTW_INFO(ADPT_FMT" "CMD_FMT" ENQ_HEAD_FAIL\n", ADPT_ARG(pcmd->padapter), CMD_ARG(pcmd));
640 pcmd->res = H2C_ENQ_HEAD_FAIL;
641 rtw_warn_on(1);
642 }
643 }
644 #endif /* CONFIG_LPS_LCLK */
645
646 if (DBG_CMD_EXECUTE)
647 RTW_INFO(ADPT_FMT" "CMD_FMT" %sexecute\n", ADPT_ARG(pcmd->padapter), CMD_ARG(pcmd)
648 , pcmd->res == H2C_ENQ_HEAD ? "ENQ_HEAD " : (pcmd->res == H2C_ENQ_HEAD_FAIL ? "ENQ_HEAD_FAIL " : ""));
649
650 _rtw_memcpy(pcmdbuf, pcmd->parmbuf, pcmd->cmdsz);
651 ret = cmd_hdl(pcmd->padapter, pcmdbuf);
652 pcmd->res = ret;
653
654 pcmdpriv->cmd_seq++;
655
656 post_process:
657
658 _enter_critical_mutex(&(pcmd->padapter->cmdpriv.sctx_mutex), NULL);
659 if (pcmd->sctx) {
660 if (0)
661 RTW_PRINT(FUNC_ADPT_FMT" pcmd->sctx\n", FUNC_ADPT_ARG(pcmd->padapter));
662 if (pcmd->res == H2C_SUCCESS)
663 rtw_sctx_done(&pcmd->sctx);
664 else
665 rtw_sctx_done_err(&pcmd->sctx, RTW_SCTX_DONE_CMD_ERROR);
666 }
667 _exit_critical_mutex(&(pcmd->padapter->cmdpriv.sctx_mutex), NULL);
668
669 cmd_process_time = rtw_get_passing_time_ms(cmd_start_time);
670 if (cmd_process_time > 1000) {
671 RTW_INFO(ADPT_FMT" "CMD_FMT" process_time=%d\n", ADPT_ARG(pcmd->padapter), CMD_ARG(pcmd), cmd_process_time);
672 if (0)
673 rtw_warn_on(1);
674 }
675
676 /* call callback function for post-processed */
677 if (pcmd->cmdcode < (sizeof(wlancmds) / sizeof(struct rtw_cmd)))
678 pcmd_callback = wlancmds[pcmd->cmdcode].callback;
679 else
680 pcmd_callback = NULL;
681
682 if (pcmd_callback == NULL) {
683 rtw_free_cmd_obj(pcmd);
684 } else {
685 /* todo: !!! fill rsp_buf to pcmd->rsp if (pcmd->rsp!=NULL) */
686 pcmd_callback(pcmd->padapter, pcmd);/* need conider that free cmd_obj in rtw_cmd_callback */
687 }
688
689 flush_signals_thread();
690
691 goto _next;
692
693 }
694
695 #ifdef CONFIG_LPS_LCLK
696 rtw_unregister_cmd_alive(padapter);
697 #endif
698
699 /* to avoid enqueue cmd after free all cmd_obj */
700 ATOMIC_SET(&(pcmdpriv->cmdthd_running), _FALSE);
701
702 /* free all cmd_obj resources */
703 do {
704 pcmd = rtw_dequeue_cmd(pcmdpriv);
705 if (pcmd == NULL)
706 break;
707
708 if (0)
709 RTW_INFO("%s: leaving... drop "CMD_FMT"\n", __func__, CMD_ARG(pcmd));
710
711 if (pcmd->cmdcode == CMD_SET_DRV_EXTRA) {
712 extra_parm = (struct drvextra_cmd_parm *)pcmd->parmbuf;
713 if (extra_parm->pbuf && extra_parm->size > 0)
714 rtw_mfree(extra_parm->pbuf, extra_parm->size);
715 }
716 #if CONFIG_DFS
717 else if (pcmd->cmdcode == CMD_SET_CHANSWITCH)
718 adapter_to_rfctl(padapter)->csa_ch = 0;
719 #endif
720
721 _enter_critical_mutex(&(pcmd->padapter->cmdpriv.sctx_mutex), NULL);
722 if (pcmd->sctx) {
723 if (0)
724 RTW_PRINT(FUNC_ADPT_FMT" pcmd->sctx\n", FUNC_ADPT_ARG(pcmd->padapter));
725 rtw_sctx_done_err(&pcmd->sctx, RTW_SCTX_DONE_CMD_DROP);
726 }
727 _exit_critical_mutex(&(pcmd->padapter->cmdpriv.sctx_mutex), NULL);
728
729 rtw_free_cmd_obj(pcmd);
730 } while (1);
731
732 RTW_INFO(FUNC_ADPT_FMT " Exit\n", FUNC_ADPT_ARG(padapter));
733
734 rtw_thread_wait_stop();
735
736 return 0;
737 }
738
739
740 #ifdef CONFIG_EVENT_THREAD_MODE
rtw_enqueue_evt(struct evt_priv * pevtpriv,struct evt_obj * obj)741 u32 rtw_enqueue_evt(struct evt_priv *pevtpriv, struct evt_obj *obj)
742 {
743 _irqL irqL;
744 int res;
745 _queue *queue = &pevtpriv->evt_queue;
746
747
748 res = _SUCCESS;
749
750 if (obj == NULL) {
751 res = _FAIL;
752 goto exit;
753 }
754
755 _enter_critical_bh(&queue->lock, &irqL);
756
757 rtw_list_insert_tail(&obj->list, &queue->queue);
758
759 _exit_critical_bh(&queue->lock, &irqL);
760
761 /* rtw_evt_notify_isr(pevtpriv); */
762
763 exit:
764
765
766 return res;
767 }
768
rtw_dequeue_evt(_queue * queue)769 struct evt_obj *rtw_dequeue_evt(_queue *queue)
770 {
771 _irqL irqL;
772 struct evt_obj *pevtobj;
773
774
775 _enter_critical_bh(&queue->lock, &irqL);
776
777 if (rtw_is_list_empty(&(queue->queue)))
778 pevtobj = NULL;
779 else {
780 pevtobj = LIST_CONTAINOR(get_next(&(queue->queue)), struct evt_obj, list);
781 rtw_list_delete(&pevtobj->list);
782 }
783
784 _exit_critical_bh(&queue->lock, &irqL);
785
786
787 return pevtobj;
788 }
789
rtw_free_evt_obj(struct evt_obj * pevtobj)790 void rtw_free_evt_obj(struct evt_obj *pevtobj)
791 {
792
793 if (pevtobj->parmbuf)
794 rtw_mfree((unsigned char *)pevtobj->parmbuf, pevtobj->evtsz);
795
796 rtw_mfree((unsigned char *)pevtobj, sizeof(struct evt_obj));
797
798 }
799
rtw_evt_notify_isr(struct evt_priv * pevtpriv)800 void rtw_evt_notify_isr(struct evt_priv *pevtpriv)
801 {
802 pevtpriv->evt_done_cnt++;
803 _rtw_up_sema(&(pevtpriv->evt_notify));
804 }
805 #endif
806
rtw_init_sitesurvey_parm(_adapter * padapter,struct sitesurvey_parm * pparm)807 void rtw_init_sitesurvey_parm(_adapter *padapter, struct sitesurvey_parm *pparm)
808 {
809 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
810
811
812 _rtw_memset(pparm, 0, sizeof(struct sitesurvey_parm));
813 pparm->scan_mode = pmlmepriv->scan_mode;
814 }
815
816 /*
817 rtw_sitesurvey_cmd(~)
818 ### NOTE:#### (!!!!)
819 MUST TAKE CARE THAT BEFORE CALLING THIS FUNC, YOU SHOULD HAVE LOCKED pmlmepriv->lock
820 */
rtw_sitesurvey_cmd(_adapter * padapter,struct sitesurvey_parm * pparm)821 u8 rtw_sitesurvey_cmd(_adapter *padapter, struct sitesurvey_parm *pparm)
822 {
823 u8 res = _FAIL;
824 struct cmd_obj *ph2c;
825 struct sitesurvey_parm *psurveyPara;
826 struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
827 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
828
829 #ifdef CONFIG_LPS
830 if (check_fwstate(pmlmepriv, WIFI_ASOC_STATE) == _TRUE)
831 rtw_lps_ctrl_wk_cmd(padapter, LPS_CTRL_SCAN, 0);
832 #endif
833
834 #ifdef CONFIG_P2P_PS
835 if (check_fwstate(pmlmepriv, WIFI_ASOC_STATE) == _TRUE)
836 p2p_ps_wk_cmd(padapter, P2P_PS_SCAN, 1);
837 #endif /* CONFIG_P2P_PS */
838
839 ph2c = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
840 if (ph2c == NULL)
841 return _FAIL;
842
843 psurveyPara = (struct sitesurvey_parm *)rtw_zmalloc(sizeof(struct sitesurvey_parm));
844 if (psurveyPara == NULL) {
845 rtw_mfree((unsigned char *) ph2c, sizeof(struct cmd_obj));
846 return _FAIL;
847 }
848
849 if (pparm)
850 _rtw_memcpy(psurveyPara, pparm, sizeof(struct sitesurvey_parm));
851 else
852 psurveyPara->scan_mode = pmlmepriv->scan_mode;
853
854 rtw_free_network_queue(padapter, _FALSE);
855
856 init_h2fwcmd_w_parm_no_rsp(ph2c, psurveyPara, CMD_SITE_SURVEY);
857
858 set_fwstate(pmlmepriv, WIFI_UNDER_SURVEY);
859
860 res = rtw_enqueue_cmd(pcmdpriv, ph2c);
861
862 if (res == _SUCCESS) {
863 u32 scan_timeout_ms;
864
865 pmlmepriv->scan_start_time = rtw_get_current_time();
866 scan_timeout_ms = rtw_scan_timeout_decision(padapter);
867 mlme_set_scan_to_timer(pmlmepriv,scan_timeout_ms);
868
869 rtw_led_control(padapter, LED_CTL_SITE_SURVEY);
870 } else
871 _clr_fwstate_(pmlmepriv, WIFI_UNDER_SURVEY);
872
873
874 return res;
875 }
876
rtw_readtssi_cmdrsp_callback(_adapter * padapter,struct cmd_obj * pcmd)877 void rtw_readtssi_cmdrsp_callback(_adapter *padapter, struct cmd_obj *pcmd)
878 {
879
880 rtw_mfree((unsigned char *) pcmd->parmbuf, pcmd->cmdsz);
881 rtw_mfree((unsigned char *) pcmd, sizeof(struct cmd_obj));
882
883 #ifdef CONFIG_MP_INCLUDED
884 if (padapter->registrypriv.mp_mode == 1)
885 padapter->mppriv.workparam.bcompleted = _TRUE;
886 #endif
887
888 }
889
890 #ifdef CONFIG_AP_MODE
rtw_createbss_cmd(_adapter * adapter,int flags,bool adhoc,u8 ifbmp,u8 excl_ifbmp,s16 req_ch,s8 req_bw,s8 req_offset)891 static u8 rtw_createbss_cmd(_adapter *adapter, int flags, bool adhoc
892 , u8 ifbmp, u8 excl_ifbmp, s16 req_ch, s8 req_bw, s8 req_offset)
893 {
894 struct cmd_obj *cmdobj;
895 struct createbss_parm *parm;
896 struct cmd_priv *pcmdpriv = &adapter->cmdpriv;
897 struct submit_ctx sctx;
898 u8 res = _SUCCESS;
899
900 if (req_ch > 0 && req_bw >= 0 && req_offset >= 0) {
901 if (!rtw_chset_is_chbw_valid(adapter_to_chset(adapter), req_ch, req_bw, req_offset, 0, 0)) {
902 res = _FAIL;
903 goto exit;
904 }
905 }
906
907 /* prepare cmd parameter */
908 parm = (struct createbss_parm *)rtw_zmalloc(sizeof(*parm));
909 if (parm == NULL) {
910 res = _FAIL;
911 goto exit;
912 }
913
914 if (adhoc) {
915 /* for now, adhoc doesn't support ch,bw,offset request */
916 parm->adhoc = 1;
917 } else {
918 parm->adhoc = 0;
919 parm->ifbmp = ifbmp;
920 parm->excl_ifbmp = excl_ifbmp;
921 parm->req_ch = req_ch;
922 parm->req_bw = req_bw;
923 parm->req_offset = req_offset;
924 }
925
926 if (flags & RTW_CMDF_DIRECTLY) {
927 /* no need to enqueue, do the cmd hdl directly and free cmd parameter */
928 if (H2C_SUCCESS != createbss_hdl(adapter, (u8 *)parm))
929 res = _FAIL;
930 rtw_mfree((u8 *)parm, sizeof(*parm));
931 } else {
932 /* need enqueue, prepare cmd_obj and enqueue */
933 cmdobj = (struct cmd_obj *)rtw_zmalloc(sizeof(*cmdobj));
934 if (cmdobj == NULL) {
935 res = _FAIL;
936 rtw_mfree((u8 *)parm, sizeof(*parm));
937 goto exit;
938 }
939
940 init_h2fwcmd_w_parm_no_rsp(cmdobj, parm, CMD_CREATE_BSS);
941
942 if (flags & RTW_CMDF_WAIT_ACK) {
943 cmdobj->sctx = &sctx;
944 rtw_sctx_init(&sctx, 2000);
945 }
946
947 res = rtw_enqueue_cmd(pcmdpriv, cmdobj);
948
949 if (res == _SUCCESS && (flags & RTW_CMDF_WAIT_ACK)) {
950 rtw_sctx_wait(&sctx, __func__);
951 _enter_critical_mutex(&pcmdpriv->sctx_mutex, NULL);
952 if (sctx.status == RTW_SCTX_SUBMITTED)
953 cmdobj->sctx = NULL;
954 _exit_critical_mutex(&pcmdpriv->sctx_mutex, NULL);
955 }
956 }
957
958 exit:
959 return res;
960 }
961
rtw_create_ibss_cmd(_adapter * adapter,int flags)962 inline u8 rtw_create_ibss_cmd(_adapter *adapter, int flags)
963 {
964 return rtw_createbss_cmd(adapter, flags
965 , 1
966 , 0, 0
967 , 0, REQ_BW_NONE, REQ_OFFSET_NONE /* for now, adhoc doesn't support ch,bw,offset request */
968 );
969 }
970
rtw_startbss_cmd(_adapter * adapter,int flags)971 inline u8 rtw_startbss_cmd(_adapter *adapter, int flags)
972 {
973 return rtw_createbss_cmd(adapter, flags
974 , 0
975 , BIT(adapter->iface_id), 0
976 , 0, REQ_BW_NONE, REQ_OFFSET_NONE /* excute entire AP setup cmd */
977 );
978 }
979
rtw_change_bss_chbw_cmd(_adapter * adapter,int flags,u8 ifbmp,u8 excl_ifbmp,s16 req_ch,s8 req_bw,s8 req_offset)980 inline u8 rtw_change_bss_chbw_cmd(_adapter *adapter, int flags
981 , u8 ifbmp, u8 excl_ifbmp, s16 req_ch, s8 req_bw, s8 req_offset)
982 {
983 return rtw_createbss_cmd(adapter, flags
984 , 0
985 , ifbmp, excl_ifbmp
986 , req_ch, req_bw, req_offset
987 );
988 }
989 #endif /* CONFIG_AP_MODE */
990
991 #ifdef CONFIG_80211D
992 /* Return corresponding country_chplan setting */
rtw_joinbss_check_country_ie(_adapter * adapter,const WLAN_BSSID_EX * network,struct country_chplan * ent,WLAN_BSSID_EX * out_network)993 static bool rtw_joinbss_check_country_ie(_adapter *adapter, const WLAN_BSSID_EX *network, struct country_chplan *ent, WLAN_BSSID_EX *out_network)
994 {
995 struct rf_ctl_t *rfctl = adapter_to_rfctl(adapter);
996 bool ret = 0;
997
998 if (rfctl->regd_src == REGD_SRC_RTK_PRIV
999 && !rtw_rfctl_is_disable_sw_channel_plan(rfctl_to_dvobj(rfctl))
1000 ) {
1001 struct mlme_priv *mlme = &adapter->mlmepriv;
1002 const u8 *country_ie = NULL;
1003 sint country_ie_len = 0;
1004
1005 if (rtw_iface_accept_country_ie(adapter)) {
1006 country_ie = rtw_get_ie(BSS_EX_TLV_IES(network)
1007 , WLAN_EID_COUNTRY, &country_ie_len, BSS_EX_TLV_IES_LEN(network));
1008 if (country_ie) {
1009 if (country_ie_len < 6) {
1010 country_ie = NULL;
1011 country_ie_len = 0;
1012 } else
1013 country_ie_len += 2;
1014 }
1015 }
1016
1017 if (country_ie) {
1018 enum country_ie_slave_status status;
1019
1020 rtw_buf_update(&mlme->recv_country_ie, &mlme->recv_country_ie_len, country_ie, country_ie_len);
1021
1022 status = rtw_get_chplan_from_recv_country_ie(adapter
1023 , network->Configuration.DSConfig > 14 ? BAND_ON_5G : BAND_ON_2_4G
1024 , network->Configuration.DSConfig, country_ie, ent, NULL, __func__);
1025 if (status != COUNTRY_IE_SLAVE_NOCOUNTRY)
1026 ret = 1;
1027
1028 if (out_network) {
1029 _rtw_memcpy(BSS_EX_IES(out_network) + BSS_EX_IES_LEN(out_network)
1030 , country_ie, country_ie_len);
1031 BSS_EX_IES_LEN(out_network) += country_ie_len;
1032 }
1033 } else
1034 rtw_buf_free(&mlme->recv_country_ie, &mlme->recv_country_ie_len);
1035 }
1036
1037 return ret;
1038 }
1039 #endif /* CONFIG_80211D */
1040
rtw_joinbss_cmd(_adapter * padapter,struct wlan_network * pnetwork)1041 u8 rtw_joinbss_cmd(_adapter *padapter, struct wlan_network *pnetwork)
1042 {
1043 u8 *auth, res = _SUCCESS;
1044 uint t_len = 0;
1045 WLAN_BSSID_EX *psecnetwork;
1046 struct cmd_obj *pcmd;
1047 struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
1048 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1049 struct qos_priv *pqospriv = &pmlmepriv->qospriv;
1050 struct security_priv *psecuritypriv = &padapter->securitypriv;
1051 struct registry_priv *pregistrypriv = &padapter->registrypriv;
1052 #ifdef CONFIG_80211D
1053 struct country_chplan country_ent;
1054 #endif
1055 struct country_chplan *req_chplan = NULL;
1056 #ifdef CONFIG_80211N_HT
1057 struct ht_priv *phtpriv = &pmlmepriv->htpriv;
1058 #endif /* CONFIG_80211N_HT */
1059 #ifdef CONFIG_80211AC_VHT
1060 struct vht_priv *pvhtpriv = &pmlmepriv->vhtpriv;
1061 #endif /* CONFIG_80211AC_VHT */
1062 NDIS_802_11_NETWORK_INFRASTRUCTURE ndis_network_mode = pnetwork->network.InfrastructureMode;
1063 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
1064 struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
1065 struct rf_ctl_t *rfctl = adapter_to_rfctl(padapter);
1066 u32 tmp_len;
1067 u8 *ptmp = NULL;
1068
1069 rtw_led_control(padapter, LED_CTL_START_TO_LINK);
1070
1071 pcmd = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
1072 if (pcmd == NULL) {
1073 res = _FAIL;
1074 goto exit;
1075 }
1076 #if 0
1077 /* for IEs is pointer */
1078 t_len = sizeof(u32) + sizeof(NDIS_802_11_MAC_ADDRESS) + 2 +
1079 sizeof(NDIS_802_11_SSID) + sizeof(u32) +
1080 sizeof(NDIS_802_11_RSSI) + sizeof(NDIS_802_11_NETWORK_TYPE) +
1081 sizeof(NDIS_802_11_CONFIGURATION) +
1082 sizeof(NDIS_802_11_NETWORK_INFRASTRUCTURE) +
1083 sizeof(NDIS_802_11_RATES_EX) + sizeof(WLAN_PHY_INFO) + sizeof(u32) + MAX_IE_SZ;
1084 #endif
1085 /* for IEs is fix buf size */
1086 t_len = sizeof(WLAN_BSSID_EX);
1087
1088
1089 /* for hidden ap to set fw_state here */
1090 if (check_fwstate(pmlmepriv, WIFI_STATION_STATE | WIFI_ADHOC_STATE) != _TRUE) {
1091 switch (ndis_network_mode) {
1092 case Ndis802_11IBSS:
1093 set_fwstate(pmlmepriv, WIFI_ADHOC_STATE);
1094 break;
1095
1096 case Ndis802_11Infrastructure:
1097 set_fwstate(pmlmepriv, WIFI_STATION_STATE);
1098 break;
1099
1100 default:
1101 rtw_warn_on(1);
1102 break;
1103 }
1104 }
1105
1106 pmlmeinfo->assoc_AP_vendor = check_assoc_AP(pnetwork->network.IEs, pnetwork->network.IELength);
1107
1108 rtw_phydm_update_ap_vendor_ie(padapter);
1109
1110 #ifdef CONFIG_80211AC_VHT
1111 /* save AP beamform_cap info for BCM IOT issue */
1112 if (pmlmeinfo->assoc_AP_vendor == HT_IOT_PEER_BROADCOM)
1113 get_vht_bf_cap(pnetwork->network.IEs,
1114 pnetwork->network.IELength,
1115 &pvhtpriv->ap_bf_cap);
1116 #endif
1117 /*
1118 Modified by Arvin 2015/05/13
1119 Solution for allocating a new WLAN_BSSID_EX to avoid race condition issue between disconnect and joinbss
1120 */
1121 psecnetwork = (WLAN_BSSID_EX *)rtw_zmalloc(sizeof(WLAN_BSSID_EX));
1122 if (psecnetwork == NULL) {
1123 if (pcmd != NULL)
1124 rtw_mfree((unsigned char *)pcmd, sizeof(struct cmd_obj));
1125
1126 res = _FAIL;
1127
1128
1129 goto exit;
1130 }
1131
1132 _rtw_memset(psecnetwork, 0, t_len);
1133
1134 _rtw_memcpy(psecnetwork, &pnetwork->network, get_WLAN_BSSID_EX_sz(&pnetwork->network));
1135
1136 auth = &psecuritypriv->authenticator_ie[0];
1137 psecuritypriv->authenticator_ie[0] = (unsigned char)psecnetwork->IELength;
1138
1139 if ((psecnetwork->IELength - 12) < (256 - 1))
1140 _rtw_memcpy(&psecuritypriv->authenticator_ie[1], &psecnetwork->IEs[12], psecnetwork->IELength - 12);
1141 else
1142 _rtw_memcpy(&psecuritypriv->authenticator_ie[1], &psecnetwork->IEs[12], (256 - 1));
1143
1144 psecnetwork->IELength = 0;
1145 /* Added by Albert 2009/02/18 */
1146 /* If the the driver wants to use the bssid to create the connection. */
1147 /* If not, we have to copy the connecting AP's MAC address to it so that */
1148 /* the driver just has the bssid information for PMKIDList searching. */
1149
1150 if (pmlmepriv->assoc_by_bssid == _FALSE)
1151 _rtw_memcpy(&pmlmepriv->assoc_bssid[0], &pnetwork->network.MacAddress[0], ETH_ALEN);
1152
1153 /* copy fixed ie */
1154 _rtw_memcpy(psecnetwork->IEs, pnetwork->network.IEs, 12);
1155 psecnetwork->IELength = 12;
1156
1157 psecnetwork->IELength += rtw_restruct_sec_ie(padapter, psecnetwork->IEs + psecnetwork->IELength);
1158
1159
1160 pqospriv->qos_option = 0;
1161
1162 if (pregistrypriv->wmm_enable) {
1163 #ifdef CONFIG_WMMPS_STA
1164 rtw_uapsd_use_default_setting(padapter);
1165 #endif /* CONFIG_WMMPS_STA */
1166 tmp_len = rtw_restruct_wmm_ie(padapter, &pnetwork->network.IEs[0], &psecnetwork->IEs[0], pnetwork->network.IELength, psecnetwork->IELength);
1167
1168 if (psecnetwork->IELength != tmp_len) {
1169 psecnetwork->IELength = tmp_len;
1170 pqospriv->qos_option = 1; /* There is WMM IE in this corresp. beacon */
1171 } else {
1172 pqospriv->qos_option = 0;/* There is no WMM IE in this corresp. beacon */
1173 }
1174 }
1175
1176 #ifdef CONFIG_80211D
1177 if (rtw_joinbss_check_country_ie(padapter, &pnetwork->network, &country_ent, psecnetwork))
1178 req_chplan = &country_ent;
1179 #endif
1180
1181 #ifdef CONFIG_80211N_HT
1182 phtpriv->ht_option = _FALSE;
1183 if (pregistrypriv->ht_enable && is_supported_ht(pregistrypriv->wireless_mode)) {
1184 ptmp = rtw_get_ie(&pnetwork->network.IEs[12], _HT_CAPABILITY_IE_, &tmp_len, pnetwork->network.IELength - 12);
1185 if (ptmp && tmp_len > 0) {
1186 /* Added by Albert 2010/06/23 */
1187 /* For the WEP mode, we will use the bg mode to do the connection to avoid some IOT issue. */
1188 /* Especially for Realtek 8192u SoftAP. */
1189 if ((padapter->securitypriv.dot11PrivacyAlgrthm != _WEP40_) &&
1190 (padapter->securitypriv.dot11PrivacyAlgrthm != _WEP104_) &&
1191 (padapter->securitypriv.dot11PrivacyAlgrthm != _TKIP_)) {
1192 rtw_ht_use_default_setting(padapter);
1193
1194 /* rtw_restructure_ht_ie */
1195 rtw_restructure_ht_ie(padapter, &pnetwork->network.IEs[12], &psecnetwork->IEs[0],
1196 pnetwork->network.IELength - 12, &psecnetwork->IELength,
1197 pnetwork->network.Configuration.DSConfig, req_chplan);
1198 }
1199 }
1200 }
1201
1202 #ifdef CONFIG_80211AC_VHT
1203 pvhtpriv->vht_option = _FALSE;
1204 if (phtpriv->ht_option
1205 && REGSTY_IS_11AC_ENABLE(pregistrypriv)
1206 && is_supported_vht(pregistrypriv->wireless_mode)
1207 && ((req_chplan && COUNTRY_CHPLAN_EN_11AC(req_chplan))
1208 || (!req_chplan && RFCTL_REG_EN_11AC(rfctl)))
1209 ) {
1210 u8 vht_enable = 0;
1211
1212 if (pnetwork->network.Configuration.DSConfig > 14)
1213 vht_enable = 1;
1214 else if ((REGSTY_IS_11AC_24G_ENABLE(pregistrypriv)) && (padapter->registrypriv.wifi_spec == 0))
1215 vht_enable = 1;
1216
1217 if (vht_enable == 1)
1218 rtw_restructure_vht_ie(padapter, &pnetwork->network.IEs[0], &psecnetwork->IEs[0],
1219 pnetwork->network.IELength, &psecnetwork->IELength, req_chplan);
1220 }
1221 #endif
1222 #endif /* CONFIG_80211N_HT */
1223
1224 rtw_append_extended_cap(padapter, &psecnetwork->IEs[0], &psecnetwork->IELength);
1225
1226 #ifdef CONFIG_RTW_80211R
1227 rtw_ft_validate_akm_type(padapter, pnetwork);
1228 #endif
1229
1230 #if 0
1231 psecuritypriv->supplicant_ie[0] = (u8)psecnetwork->IELength;
1232
1233 if (psecnetwork->IELength < (256 - 1))
1234 _rtw_memcpy(&psecuritypriv->supplicant_ie[1], &psecnetwork->IEs[0], psecnetwork->IELength);
1235 else
1236 _rtw_memcpy(&psecuritypriv->supplicant_ie[1], &psecnetwork->IEs[0], (256 - 1));
1237 #endif
1238
1239 pcmd->cmdsz = sizeof(WLAN_BSSID_EX);
1240
1241 _rtw_init_listhead(&pcmd->list);
1242 pcmd->cmdcode = CMD_JOINBSS;/* _JoinBss_CMD_ */
1243 pcmd->parmbuf = (unsigned char *)psecnetwork;
1244 pcmd->rsp = NULL;
1245 pcmd->rspsz = 0;
1246
1247 res = rtw_enqueue_cmd(pcmdpriv, pcmd);
1248
1249 exit:
1250
1251
1252 return res;
1253 }
1254
rtw_disassoc_cmd(_adapter * padapter,u32 deauth_timeout_ms,int flags)1255 u8 rtw_disassoc_cmd(_adapter *padapter, u32 deauth_timeout_ms, int flags) /* for sta_mode */
1256 {
1257 struct cmd_obj *cmdobj = NULL;
1258 struct disconnect_parm *param = NULL;
1259 struct cmd_priv *cmdpriv = &padapter->cmdpriv;
1260 struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
1261 struct submit_ctx sctx;
1262 u8 res = _SUCCESS;
1263
1264 /* prepare cmd parameter */
1265 param = (struct disconnect_parm *)rtw_zmalloc(sizeof(*param));
1266 if (param == NULL) {
1267 res = _FAIL;
1268 goto exit;
1269 }
1270 param->deauth_timeout_ms = deauth_timeout_ms;
1271
1272 if (flags & RTW_CMDF_DIRECTLY) {
1273 /* no need to enqueue, do the cmd hdl directly and free cmd parameter */
1274 if (disconnect_hdl(padapter, (u8 *)param) != H2C_SUCCESS)
1275 res = _FAIL;
1276 rtw_mfree((u8 *)param, sizeof(*param));
1277
1278 } else {
1279 cmdobj = (struct cmd_obj *)rtw_zmalloc(sizeof(*cmdobj));
1280 if (cmdobj == NULL) {
1281 res = _FAIL;
1282 rtw_mfree((u8 *)param, sizeof(*param));
1283 goto exit;
1284 }
1285 init_h2fwcmd_w_parm_no_rsp(cmdobj, param, CMD_DISCONNECT);
1286 if (flags & RTW_CMDF_WAIT_ACK) {
1287 cmdobj->sctx = &sctx;
1288 rtw_sctx_init(&sctx, 2000);
1289 }
1290 res = rtw_enqueue_cmd(cmdpriv, cmdobj);
1291 if (res == _SUCCESS && (flags & RTW_CMDF_WAIT_ACK)) {
1292 rtw_sctx_wait(&sctx, __func__);
1293 _enter_critical_mutex(&pcmdpriv->sctx_mutex, NULL);
1294 if (sctx.status == RTW_SCTX_SUBMITTED)
1295 cmdobj->sctx = NULL;
1296 _exit_critical_mutex(&pcmdpriv->sctx_mutex, NULL);
1297 }
1298 }
1299
1300 exit:
1301
1302
1303 return res;
1304 }
1305
1306 #ifdef CONFIG_AP_MODE
rtw_stop_ap_cmd(_adapter * adapter,u8 flags)1307 u8 rtw_stop_ap_cmd(_adapter *adapter, u8 flags)
1308 {
1309 struct cmd_obj *cmdobj;
1310 struct drvextra_cmd_parm *parm;
1311 struct cmd_priv *pcmdpriv = &adapter->cmdpriv;
1312 struct submit_ctx sctx;
1313 u8 res = _SUCCESS;
1314
1315 if (flags & RTW_CMDF_DIRECTLY) {
1316 /* no need to enqueue, do the cmd hdl directly and free cmd parameter */
1317 if (H2C_SUCCESS != stop_ap_hdl(adapter))
1318 res = _FAIL;
1319 } else {
1320 parm = (struct drvextra_cmd_parm *)rtw_zmalloc(sizeof(struct drvextra_cmd_parm));
1321 if (parm == NULL) {
1322 res = _FAIL;
1323 goto exit;
1324 }
1325
1326 parm->ec_id = STOP_AP_WK_CID;
1327 parm->type = 0;
1328 parm->size = 0;
1329 parm->pbuf = NULL;
1330
1331 /* need enqueue, prepare cmd_obj and enqueue */
1332 cmdobj = (struct cmd_obj *)rtw_zmalloc(sizeof(*cmdobj));
1333 if (cmdobj == NULL) {
1334 res = _FAIL;
1335 goto exit;
1336 }
1337
1338 init_h2fwcmd_w_parm_no_rsp(cmdobj, parm, CMD_SET_DRV_EXTRA);
1339
1340 if (flags & RTW_CMDF_WAIT_ACK) {
1341 cmdobj->sctx = &sctx;
1342 rtw_sctx_init(&sctx, 2000);
1343 }
1344
1345 res = rtw_enqueue_cmd(pcmdpriv, cmdobj);
1346
1347 if (res == _SUCCESS && (flags & RTW_CMDF_WAIT_ACK)) {
1348 rtw_sctx_wait(&sctx, __func__);
1349 _enter_critical_mutex(&pcmdpriv->sctx_mutex, NULL);
1350 if (sctx.status == RTW_SCTX_SUBMITTED)
1351 cmdobj->sctx = NULL;
1352 _exit_critical_mutex(&pcmdpriv->sctx_mutex, NULL);
1353 }
1354 }
1355 exit:
1356 return res;
1357 }
1358 #endif /* CONFIG_AP_MODE */
1359
1360 #ifdef CONFIG_RTW_TOKEN_BASED_XMIT
rtw_tx_control_cmd(_adapter * adapter)1361 u8 rtw_tx_control_cmd(_adapter *adapter)
1362 {
1363 struct cmd_obj *ph2c;
1364 struct drvextra_cmd_parm *pdrvextra_cmd_parm;
1365 struct cmd_priv *pcmdpriv = &adapter->cmdpriv;
1366
1367 u8 res = _SUCCESS;
1368
1369 ph2c = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
1370 if (ph2c == NULL){
1371 res = _FAIL;
1372 goto exit;
1373 }
1374
1375 pdrvextra_cmd_parm = (struct drvextra_cmd_parm *)rtw_zmalloc(sizeof(struct drvextra_cmd_parm));
1376 if (pdrvextra_cmd_parm == NULL) {
1377 rtw_mfree((unsigned char *)ph2c, sizeof(struct cmd_obj));
1378 res = _FAIL;
1379 goto exit;
1380 }
1381
1382 pdrvextra_cmd_parm->ec_id = TBTX_CONTROL_TX_WK_CID;
1383 pdrvextra_cmd_parm->type = 0;
1384 pdrvextra_cmd_parm->size = 0;
1385 pdrvextra_cmd_parm->pbuf = NULL;
1386 init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, CMD_SET_DRV_EXTRA);
1387
1388 res = rtw_enqueue_cmd(pcmdpriv, ph2c);
1389
1390 exit:
1391 return res;
1392 }
1393 #endif
1394
rtw_setopmode_cmd(_adapter * adapter,NDIS_802_11_NETWORK_INFRASTRUCTURE networktype,u8 flags)1395 u8 rtw_setopmode_cmd(_adapter *adapter, NDIS_802_11_NETWORK_INFRASTRUCTURE networktype, u8 flags)
1396 {
1397 struct cmd_obj *cmdobj;
1398 struct setopmode_parm *parm;
1399 struct cmd_priv *pcmdpriv = &adapter->cmdpriv;
1400 struct submit_ctx sctx;
1401 u8 res = _SUCCESS;
1402
1403 /* prepare cmd parameter */
1404 parm = (struct setopmode_parm *)rtw_zmalloc(sizeof(*parm));
1405 if (parm == NULL) {
1406 res = _FAIL;
1407 goto exit;
1408 }
1409 parm->mode = (u8)networktype;
1410
1411 if (flags & RTW_CMDF_DIRECTLY) {
1412 /* no need to enqueue, do the cmd hdl directly and free cmd parameter */
1413 if (H2C_SUCCESS != setopmode_hdl(adapter, (u8 *)parm))
1414 res = _FAIL;
1415 rtw_mfree((u8 *)parm, sizeof(*parm));
1416 } else {
1417 /* need enqueue, prepare cmd_obj and enqueue */
1418 cmdobj = (struct cmd_obj *)rtw_zmalloc(sizeof(*cmdobj));
1419 if (cmdobj == NULL) {
1420 res = _FAIL;
1421 rtw_mfree((u8 *)parm, sizeof(*parm));
1422 goto exit;
1423 }
1424
1425 init_h2fwcmd_w_parm_no_rsp(cmdobj, parm, CMD_SET_OPMODE);
1426
1427 if (flags & RTW_CMDF_WAIT_ACK) {
1428 cmdobj->sctx = &sctx;
1429 rtw_sctx_init(&sctx, 2000);
1430 }
1431
1432 res = rtw_enqueue_cmd(pcmdpriv, cmdobj);
1433
1434 if (res == _SUCCESS && (flags & RTW_CMDF_WAIT_ACK)) {
1435 rtw_sctx_wait(&sctx, __func__);
1436 _enter_critical_mutex(&pcmdpriv->sctx_mutex, NULL);
1437 if (sctx.status == RTW_SCTX_SUBMITTED)
1438 cmdobj->sctx = NULL;
1439 _exit_critical_mutex(&pcmdpriv->sctx_mutex, NULL);
1440 }
1441 }
1442
1443 exit:
1444 return res;
1445 }
1446
rtw_setstakey_cmd(_adapter * padapter,struct sta_info * sta,u8 key_type,bool enqueue)1447 u8 rtw_setstakey_cmd(_adapter *padapter, struct sta_info *sta, u8 key_type, bool enqueue)
1448 {
1449 struct cmd_obj *ph2c;
1450 struct set_stakey_parm *psetstakey_para;
1451 struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
1452 struct set_stakey_rsp *psetstakey_rsp = NULL;
1453
1454 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1455 struct security_priv *psecuritypriv = &padapter->securitypriv;
1456 u8 key_len =16;
1457 u8 res = _SUCCESS;
1458
1459
1460 psetstakey_para = (struct set_stakey_parm *)rtw_zmalloc(sizeof(struct set_stakey_parm));
1461 if (psetstakey_para == NULL) {
1462 res = _FAIL;
1463 goto exit;
1464 }
1465
1466 _rtw_memcpy(psetstakey_para->addr, sta->cmn.mac_addr, ETH_ALEN);
1467
1468 if (check_fwstate(pmlmepriv, WIFI_STATION_STATE))
1469 psetstakey_para->algorithm = (unsigned char) psecuritypriv->dot11PrivacyAlgrthm;
1470 else
1471 GET_ENCRY_ALGO(psecuritypriv, sta, psetstakey_para->algorithm, _FALSE);
1472
1473 if ((psetstakey_para->algorithm == _GCMP_256_) || (psetstakey_para->algorithm == _CCMP_256_))
1474 key_len = 32;
1475
1476 if (key_type == GROUP_KEY) {
1477 _rtw_memcpy(&psetstakey_para->key, &psecuritypriv->dot118021XGrpKey[psecuritypriv->dot118021XGrpKeyid].skey, key_len);
1478 psetstakey_para->gk = 1;
1479 } else if (key_type == UNICAST_KEY)
1480 _rtw_memcpy(&psetstakey_para->key, &sta->dot118021x_UncstKey, key_len);
1481 #ifdef CONFIG_TDLS
1482 else if (key_type == TDLS_KEY) {
1483 _rtw_memcpy(&psetstakey_para->key, sta->tpk.tk, key_len);
1484 psetstakey_para->algorithm = (u8)sta->dot118021XPrivacy;
1485 }
1486 #endif /* CONFIG_TDLS */
1487
1488 /* jeff: set this becasue at least sw key is ready */
1489 padapter->securitypriv.busetkipkey = _TRUE;
1490
1491 if (enqueue) {
1492 ph2c = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
1493 if (ph2c == NULL) {
1494 rtw_mfree((u8 *) psetstakey_para, sizeof(struct set_stakey_parm));
1495 res = _FAIL;
1496 goto exit;
1497 }
1498
1499 psetstakey_rsp = (struct set_stakey_rsp *)rtw_zmalloc(sizeof(struct set_stakey_rsp));
1500 if (psetstakey_rsp == NULL) {
1501 rtw_mfree((u8 *) ph2c, sizeof(struct cmd_obj));
1502 rtw_mfree((u8 *) psetstakey_para, sizeof(struct set_stakey_parm));
1503 res = _FAIL;
1504 goto exit;
1505 }
1506
1507 init_h2fwcmd_w_parm_no_rsp(ph2c, psetstakey_para, CMD_SET_STAKEY);
1508 ph2c->rsp = (u8 *) psetstakey_rsp;
1509 ph2c->rspsz = sizeof(struct set_stakey_rsp);
1510 res = rtw_enqueue_cmd(pcmdpriv, ph2c);
1511 } else {
1512 set_stakey_hdl(padapter, (u8 *)psetstakey_para);
1513 rtw_mfree((u8 *) psetstakey_para, sizeof(struct set_stakey_parm));
1514 }
1515 exit:
1516
1517
1518 return res;
1519 }
1520
rtw_clearstakey_cmd(_adapter * padapter,struct sta_info * sta,u8 enqueue)1521 u8 rtw_clearstakey_cmd(_adapter *padapter, struct sta_info *sta, u8 enqueue)
1522 {
1523 struct cmd_obj *ph2c;
1524 struct set_stakey_parm *psetstakey_para;
1525 struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
1526 struct set_stakey_rsp *psetstakey_rsp = NULL;
1527 s16 cam_id = 0;
1528 u8 res = _SUCCESS;
1529
1530 if (!sta) {
1531 RTW_ERR("%s sta == NULL\n", __func__);
1532 goto exit;
1533 }
1534
1535 if (!enqueue) {
1536 while ((cam_id = rtw_camid_search(padapter, sta->cmn.mac_addr, -1, -1)) >= 0) {
1537 RTW_PRINT("clear key for addr:"MAC_FMT", camid:%d\n", MAC_ARG(sta->cmn.mac_addr), cam_id);
1538 clear_cam_entry(padapter, cam_id);
1539 rtw_camid_free(padapter, cam_id);
1540 }
1541 } else {
1542 ph2c = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
1543 if (ph2c == NULL) {
1544 res = _FAIL;
1545 goto exit;
1546 }
1547
1548 psetstakey_para = (struct set_stakey_parm *)rtw_zmalloc(sizeof(struct set_stakey_parm));
1549 if (psetstakey_para == NULL) {
1550 rtw_mfree((u8 *) ph2c, sizeof(struct cmd_obj));
1551 res = _FAIL;
1552 goto exit;
1553 }
1554
1555 psetstakey_rsp = (struct set_stakey_rsp *)rtw_zmalloc(sizeof(struct set_stakey_rsp));
1556 if (psetstakey_rsp == NULL) {
1557 rtw_mfree((u8 *) ph2c, sizeof(struct cmd_obj));
1558 rtw_mfree((u8 *) psetstakey_para, sizeof(struct set_stakey_parm));
1559 res = _FAIL;
1560 goto exit;
1561 }
1562
1563 init_h2fwcmd_w_parm_no_rsp(ph2c, psetstakey_para, CMD_SET_STAKEY);
1564 ph2c->rsp = (u8 *) psetstakey_rsp;
1565 ph2c->rspsz = sizeof(struct set_stakey_rsp);
1566
1567 _rtw_memcpy(psetstakey_para->addr, sta->cmn.mac_addr, ETH_ALEN);
1568
1569 psetstakey_para->algorithm = _NO_PRIVACY_;
1570
1571 res = rtw_enqueue_cmd(pcmdpriv, ph2c);
1572
1573 }
1574
1575 exit:
1576
1577
1578 return res;
1579 }
1580
rtw_addbareq_cmd(_adapter * padapter,u8 tid,u8 * addr)1581 u8 rtw_addbareq_cmd(_adapter *padapter, u8 tid, u8 *addr)
1582 {
1583 struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
1584 struct cmd_obj *ph2c;
1585 struct addBaReq_parm *paddbareq_parm;
1586
1587 u8 res = _SUCCESS;
1588
1589
1590 ph2c = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
1591 if (ph2c == NULL) {
1592 res = _FAIL;
1593 goto exit;
1594 }
1595
1596 paddbareq_parm = (struct addBaReq_parm *)rtw_zmalloc(sizeof(struct addBaReq_parm));
1597 if (paddbareq_parm == NULL) {
1598 rtw_mfree((unsigned char *)ph2c, sizeof(struct cmd_obj));
1599 res = _FAIL;
1600 goto exit;
1601 }
1602
1603 paddbareq_parm->tid = tid;
1604 _rtw_memcpy(paddbareq_parm->addr, addr, ETH_ALEN);
1605
1606 init_h2fwcmd_w_parm_no_rsp(ph2c, paddbareq_parm, CMD_ADD_BAREQ);
1607
1608 /* RTW_INFO("rtw_addbareq_cmd, tid=%d\n", tid); */
1609
1610 /* rtw_enqueue_cmd(pcmdpriv, ph2c); */
1611 res = rtw_enqueue_cmd(pcmdpriv, ph2c);
1612
1613 exit:
1614
1615
1616 return res;
1617 }
1618
rtw_addbarsp_cmd(_adapter * padapter,u8 * addr,u16 tid,u8 status,u8 size,u16 start_seq)1619 u8 rtw_addbarsp_cmd(_adapter *padapter, u8 *addr, u16 tid, u8 status, u8 size, u16 start_seq)
1620 {
1621 struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
1622 struct cmd_obj *ph2c;
1623 struct addBaRsp_parm *paddBaRsp_parm;
1624 u8 res = _SUCCESS;
1625
1626
1627 ph2c = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
1628 if (ph2c == NULL) {
1629 res = _FAIL;
1630 goto exit;
1631 }
1632
1633 paddBaRsp_parm = (struct addBaRsp_parm *)rtw_zmalloc(sizeof(struct addBaRsp_parm));
1634
1635 if (paddBaRsp_parm == NULL) {
1636 rtw_mfree((unsigned char *)ph2c, sizeof(struct cmd_obj));
1637 res = _FAIL;
1638 goto exit;
1639 }
1640
1641 _rtw_memcpy(paddBaRsp_parm->addr, addr, ETH_ALEN);
1642 paddBaRsp_parm->tid = tid;
1643 paddBaRsp_parm->status = status;
1644 paddBaRsp_parm->size = size;
1645 paddBaRsp_parm->start_seq = start_seq;
1646
1647 init_h2fwcmd_w_parm_no_rsp(ph2c, paddBaRsp_parm, CMD_ADD_BARSP);
1648
1649 res = rtw_enqueue_cmd(pcmdpriv, ph2c);
1650
1651 exit:
1652
1653
1654 return res;
1655 }
1656 /* add for CONFIG_IEEE80211W, none 11w can use it */
rtw_reset_securitypriv_cmd(_adapter * padapter)1657 u8 rtw_reset_securitypriv_cmd(_adapter *padapter)
1658 {
1659 struct cmd_obj *ph2c;
1660 struct drvextra_cmd_parm *pdrvextra_cmd_parm;
1661 struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
1662 u8 res = _SUCCESS;
1663
1664
1665 ph2c = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
1666 if (ph2c == NULL) {
1667 res = _FAIL;
1668 goto exit;
1669 }
1670
1671 pdrvextra_cmd_parm = (struct drvextra_cmd_parm *)rtw_zmalloc(sizeof(struct drvextra_cmd_parm));
1672 if (pdrvextra_cmd_parm == NULL) {
1673 rtw_mfree((unsigned char *)ph2c, sizeof(struct cmd_obj));
1674 res = _FAIL;
1675 goto exit;
1676 }
1677
1678 pdrvextra_cmd_parm->ec_id = RESET_SECURITYPRIV;
1679 pdrvextra_cmd_parm->type = 0;
1680 pdrvextra_cmd_parm->size = 0;
1681 pdrvextra_cmd_parm->pbuf = NULL;
1682
1683 init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, CMD_SET_DRV_EXTRA);
1684
1685
1686 /* rtw_enqueue_cmd(pcmdpriv, ph2c); */
1687 res = rtw_enqueue_cmd(pcmdpriv, ph2c);
1688
1689 exit:
1690
1691
1692 return res;
1693
1694 }
1695
free_assoc_resources_hdl(_adapter * padapter,u8 lock_scanned_queue)1696 void free_assoc_resources_hdl(_adapter *padapter, u8 lock_scanned_queue)
1697 {
1698 rtw_free_assoc_resources(padapter, lock_scanned_queue);
1699 }
1700
rtw_free_assoc_resources_cmd(_adapter * padapter,u8 lock_scanned_queue,int flags)1701 u8 rtw_free_assoc_resources_cmd(_adapter *padapter, u8 lock_scanned_queue, int flags)
1702 {
1703 struct cmd_obj *cmd;
1704 struct drvextra_cmd_parm *pdrvextra_cmd_parm;
1705 struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
1706 struct submit_ctx sctx;
1707 u8 res = _SUCCESS;
1708
1709 if (flags & RTW_CMDF_DIRECTLY) {
1710 free_assoc_resources_hdl(padapter, lock_scanned_queue);
1711 }
1712 else {
1713 cmd = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
1714 if (cmd == NULL) {
1715 res = _FAIL;
1716 goto exit;
1717 }
1718
1719 pdrvextra_cmd_parm = (struct drvextra_cmd_parm *)rtw_zmalloc(sizeof(struct drvextra_cmd_parm));
1720 if (pdrvextra_cmd_parm == NULL) {
1721 rtw_mfree((unsigned char *)cmd, sizeof(struct cmd_obj));
1722 res = _FAIL;
1723 goto exit;
1724 }
1725
1726 pdrvextra_cmd_parm->ec_id = FREE_ASSOC_RESOURCES;
1727 pdrvextra_cmd_parm->type = lock_scanned_queue;
1728 pdrvextra_cmd_parm->size = 0;
1729 pdrvextra_cmd_parm->pbuf = NULL;
1730
1731 init_h2fwcmd_w_parm_no_rsp(cmd, pdrvextra_cmd_parm, CMD_SET_DRV_EXTRA);
1732 if (flags & RTW_CMDF_WAIT_ACK) {
1733 cmd->sctx = &sctx;
1734 rtw_sctx_init(&sctx, 2000);
1735 }
1736
1737 res = rtw_enqueue_cmd(pcmdpriv, cmd);
1738
1739 if (res == _SUCCESS && (flags & RTW_CMDF_WAIT_ACK)) {
1740 rtw_sctx_wait(&sctx, __func__);
1741 _enter_critical_mutex(&pcmdpriv->sctx_mutex, NULL);
1742 if (sctx.status == RTW_SCTX_SUBMITTED)
1743 cmd->sctx = NULL;
1744 _exit_critical_mutex(&pcmdpriv->sctx_mutex, NULL);
1745 }
1746 }
1747 exit:
1748 return res;
1749
1750 }
1751
rtw_dynamic_chk_wk_cmd(_adapter * padapter)1752 u8 rtw_dynamic_chk_wk_cmd(_adapter *padapter)
1753 {
1754 struct cmd_obj *ph2c;
1755 struct drvextra_cmd_parm *pdrvextra_cmd_parm;
1756 struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
1757 u8 res = _SUCCESS;
1758
1759
1760 /* only primary padapter does this cmd */
1761
1762 ph2c = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
1763 if (ph2c == NULL) {
1764 res = _FAIL;
1765 goto exit;
1766 }
1767
1768 pdrvextra_cmd_parm = (struct drvextra_cmd_parm *)rtw_zmalloc(sizeof(struct drvextra_cmd_parm));
1769 if (pdrvextra_cmd_parm == NULL) {
1770 rtw_mfree((unsigned char *)ph2c, sizeof(struct cmd_obj));
1771 res = _FAIL;
1772 goto exit;
1773 }
1774
1775 pdrvextra_cmd_parm->ec_id = DYNAMIC_CHK_WK_CID;
1776 pdrvextra_cmd_parm->type = 0;
1777 pdrvextra_cmd_parm->size = 0;
1778 pdrvextra_cmd_parm->pbuf = NULL;
1779 init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, CMD_SET_DRV_EXTRA);
1780
1781
1782 /* rtw_enqueue_cmd(pcmdpriv, ph2c); */
1783 res = rtw_enqueue_cmd(pcmdpriv, ph2c);
1784
1785 exit:
1786
1787
1788 return res;
1789
1790 }
1791
rtw_iqk_cmd(_adapter * padapter,u8 flags)1792 u8 rtw_iqk_cmd(_adapter *padapter, u8 flags)
1793 {
1794 struct cmd_obj *pcmdobj;
1795 struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
1796 struct submit_ctx sctx;
1797 u8 res = _SUCCESS;
1798
1799 if (flags & RTW_CMDF_DIRECTLY) {
1800 /* no need to enqueue, do the cmd hdl */
1801 rtw_iqk_hdl(padapter, NULL);
1802 } else {
1803 /* need enqueue, prepare cmd_obj and enqueue */
1804 pcmdobj = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
1805 if (pcmdobj == NULL) {
1806 res = _FAIL;
1807 goto exit;
1808 }
1809
1810 init_h2fwcmd_w_parm_no_parm_rsp(pcmdobj, CMD_DO_IQK);
1811
1812 if (flags & RTW_CMDF_WAIT_ACK) {
1813 pcmdobj->sctx = &sctx;
1814 rtw_sctx_init(&sctx, 10 * 1000);
1815 }
1816
1817 res = rtw_enqueue_cmd(pcmdpriv, pcmdobj);
1818
1819 if (res == _SUCCESS && (flags & RTW_CMDF_WAIT_ACK)) {
1820 rtw_sctx_wait(&sctx, __func__);
1821 _enter_critical_mutex(&pcmdpriv->sctx_mutex, NULL);
1822 if (sctx.status == RTW_SCTX_SUBMITTED)
1823 pcmdobj->sctx = NULL;
1824 _exit_critical_mutex(&pcmdpriv->sctx_mutex, NULL);
1825 }
1826 }
1827
1828 exit:
1829
1830 return res;
1831 }
1832
rtw_set_chbw_cmd(_adapter * padapter,u8 ch,u8 bw,u8 ch_offset,u8 flags)1833 u8 rtw_set_chbw_cmd(_adapter *padapter, u8 ch, u8 bw, u8 ch_offset, u8 flags)
1834 {
1835 struct cmd_obj *pcmdobj;
1836 struct set_ch_parm *set_ch_parm;
1837 struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
1838 struct submit_ctx sctx;
1839 u8 res = _SUCCESS;
1840
1841
1842 RTW_INFO(FUNC_NDEV_FMT" ch:%u, bw:%u, ch_offset:%u\n",
1843 FUNC_NDEV_ARG(padapter->pnetdev), ch, bw, ch_offset);
1844
1845 /* check input parameter */
1846
1847 /* prepare cmd parameter */
1848 set_ch_parm = (struct set_ch_parm *)rtw_zmalloc(sizeof(*set_ch_parm));
1849 if (set_ch_parm == NULL) {
1850 res = _FAIL;
1851 goto exit;
1852 }
1853 set_ch_parm->ch = ch;
1854 set_ch_parm->bw = bw;
1855 set_ch_parm->ch_offset = ch_offset;
1856
1857 if (flags & RTW_CMDF_DIRECTLY) {
1858 /* no need to enqueue, do the cmd hdl directly and free cmd parameter */
1859 if (H2C_SUCCESS != rtw_set_chbw_hdl(padapter, (u8 *)set_ch_parm))
1860 res = _FAIL;
1861
1862 rtw_mfree((u8 *)set_ch_parm, sizeof(*set_ch_parm));
1863 } else {
1864 /* need enqueue, prepare cmd_obj and enqueue */
1865 pcmdobj = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
1866 if (pcmdobj == NULL) {
1867 rtw_mfree((u8 *)set_ch_parm, sizeof(*set_ch_parm));
1868 res = _FAIL;
1869 goto exit;
1870 }
1871
1872 init_h2fwcmd_w_parm_no_rsp(pcmdobj, set_ch_parm, CMD_SET_CHANNEL);
1873
1874 if (flags & RTW_CMDF_WAIT_ACK) {
1875 pcmdobj->sctx = &sctx;
1876 rtw_sctx_init(&sctx, 10 * 1000);
1877 }
1878
1879 res = rtw_enqueue_cmd(pcmdpriv, pcmdobj);
1880
1881 if (res == _SUCCESS && (flags & RTW_CMDF_WAIT_ACK)) {
1882 rtw_sctx_wait(&sctx, __func__);
1883 _enter_critical_mutex(&pcmdpriv->sctx_mutex, NULL);
1884 if (sctx.status == RTW_SCTX_SUBMITTED)
1885 pcmdobj->sctx = NULL;
1886 _exit_critical_mutex(&pcmdpriv->sctx_mutex, NULL);
1887 }
1888 }
1889
1890 /* do something based on res... */
1891
1892 exit:
1893
1894 RTW_INFO(FUNC_NDEV_FMT" res:%u\n", FUNC_NDEV_ARG(padapter->pnetdev), res);
1895
1896
1897 return res;
1898 }
1899
_rtw_set_chplan_cmd(_adapter * adapter,int flags,u8 chplan,u8 chplan_6g,const struct country_chplan * country_ent,enum regd_src_t regd_src,enum rtw_regd_inr inr,const struct country_ie_slave_record * cisr)1900 static u8 _rtw_set_chplan_cmd(_adapter *adapter, int flags
1901 , u8 chplan, u8 chplan_6g, const struct country_chplan *country_ent
1902 , enum regd_src_t regd_src, enum rtw_regd_inr inr
1903 , const struct country_ie_slave_record *cisr)
1904 {
1905 struct cmd_obj *cmdobj;
1906 struct SetChannelPlan_param *parm;
1907 struct cmd_priv *pcmdpriv = &adapter->cmdpriv;
1908 struct submit_ctx sctx;
1909 #ifdef PLATFORM_LINUX
1910 bool rtnl_lock_needed = rtw_rtnl_lock_needed(adapter_to_dvobj(adapter));
1911 #endif
1912 u8 res = _SUCCESS;
1913
1914 /* check if allow software config */
1915 if (rtw_rfctl_is_disable_sw_channel_plan(adapter_to_dvobj(adapter)) == _TRUE) {
1916 res = _FAIL;
1917 goto exit;
1918 }
1919
1920 if (country_ent) {
1921 /* if country_entry is provided, replace chplan */
1922 chplan = country_ent->chplan;
1923 #if CONFIG_IEEE80211_BAND_6GHZ
1924 chplan_6g = country_ent->chplan_6g;
1925 #endif
1926 }
1927
1928 /* prepare cmd parameter */
1929 parm = (struct SetChannelPlan_param *)rtw_zmalloc(sizeof(*parm));
1930 if (parm == NULL) {
1931 res = _FAIL;
1932 goto exit;
1933 }
1934 parm->regd_src = regd_src;
1935 parm->inr = inr;
1936 if (country_ent) {
1937 _rtw_memcpy(&parm->country_ent, country_ent, sizeof(parm->country_ent));
1938 parm->has_country = 1;
1939 }
1940 parm->channel_plan = chplan;
1941 #if CONFIG_IEEE80211_BAND_6GHZ
1942 parm->channel_plan_6g = chplan_6g;
1943 #endif
1944 #ifdef CONFIG_80211D
1945 if (cisr) {
1946 _rtw_memcpy(&parm->cisr, cisr, sizeof(*cisr));
1947 parm->has_cisr = 1;
1948 }
1949 #endif
1950 #ifdef PLATFORM_LINUX
1951 if (flags & (RTW_CMDF_DIRECTLY | RTW_CMDF_WAIT_ACK))
1952 parm->rtnl_lock_needed = rtnl_lock_needed; /* synchronous call, follow caller's */
1953 else
1954 parm->rtnl_lock_needed = 1; /* asynchronous call, always needed */
1955 #endif
1956
1957 if (flags & RTW_CMDF_DIRECTLY) {
1958 /* no need to enqueue, do the cmd hdl directly and free cmd parameter */
1959 if (H2C_SUCCESS != rtw_set_chplan_hdl(adapter, (u8 *)parm))
1960 res = _FAIL;
1961 rtw_mfree((u8 *)parm, sizeof(*parm));
1962 } else {
1963 /* need enqueue, prepare cmd_obj and enqueue */
1964 cmdobj = (struct cmd_obj *)rtw_zmalloc(sizeof(*cmdobj));
1965 if (cmdobj == NULL) {
1966 res = _FAIL;
1967 rtw_mfree((u8 *)parm, sizeof(*parm));
1968 goto exit;
1969 }
1970
1971 init_h2fwcmd_w_parm_no_rsp(cmdobj, parm, CMD_SET_CHANPLAN);
1972
1973 if (flags & RTW_CMDF_WAIT_ACK) {
1974 cmdobj->sctx = &sctx;
1975 rtw_sctx_init(&sctx, 2000);
1976 }
1977
1978 res = rtw_enqueue_cmd(pcmdpriv, cmdobj);
1979
1980 if (res == _SUCCESS && (flags & RTW_CMDF_WAIT_ACK)) {
1981 rtw_sctx_wait(&sctx, __func__);
1982 _enter_critical_mutex(&pcmdpriv->sctx_mutex, NULL);
1983 if (sctx.status == RTW_SCTX_SUBMITTED)
1984 cmdobj->sctx = NULL;
1985 _exit_critical_mutex(&pcmdpriv->sctx_mutex, NULL);
1986 if (sctx.status != RTW_SCTX_DONE_SUCCESS)
1987 res = _FAIL;
1988 }
1989
1990 /* allow set channel plan when cmd_thread is not running */
1991 if (res != _SUCCESS && (flags & RTW_CMDF_WAIT_ACK)) {
1992 parm = (struct SetChannelPlan_param *)rtw_zmalloc(sizeof(*parm));
1993 if (parm == NULL) {
1994 res = _FAIL;
1995 goto exit;
1996 }
1997 parm->regd_src = regd_src;
1998 parm->inr = inr;
1999 if (country_ent) {
2000 _rtw_memcpy(&parm->country_ent, country_ent, sizeof(parm->country_ent));
2001 parm->has_country = 1;
2002 }
2003 parm->channel_plan = chplan;
2004 #if CONFIG_IEEE80211_BAND_6GHZ
2005 parm->channel_plan_6g = chplan_6g;
2006 #endif
2007 #ifdef CONFIG_80211D
2008 if (cisr) {
2009 _rtw_memcpy(&parm->cisr, cisr, sizeof(*cisr));
2010 parm->has_cisr = 1;
2011 }
2012 #endif
2013 #ifdef PLATFORM_LINUX
2014 parm->rtnl_lock_needed = rtnl_lock_needed; /* synchronous call, follow caller's */
2015 #endif
2016
2017 if (H2C_SUCCESS != rtw_set_chplan_hdl(adapter, (u8 *)parm))
2018 res = _FAIL;
2019 else
2020 res = _SUCCESS;
2021 rtw_mfree((u8 *)parm, sizeof(*parm));
2022 }
2023 }
2024
2025 exit:
2026 return res;
2027 }
2028
rtw_set_chplan_cmd(_adapter * adapter,int flags,u8 chplan,u8 chplan_6g,enum rtw_regd_inr inr)2029 inline u8 rtw_set_chplan_cmd(_adapter *adapter, int flags, u8 chplan, u8 chplan_6g, enum rtw_regd_inr inr)
2030 {
2031 return _rtw_set_chplan_cmd(adapter, flags, chplan, chplan_6g, NULL, REGD_SRC_RTK_PRIV, inr, NULL);
2032 }
2033
rtw_set_country_cmd(_adapter * adapter,int flags,const char * country_code,enum rtw_regd_inr inr)2034 inline u8 rtw_set_country_cmd(_adapter *adapter, int flags, const char *country_code, enum rtw_regd_inr inr)
2035 {
2036 struct country_chplan ent;
2037
2038 if (IS_ALPHA2_WORLDWIDE(country_code)) {
2039 rtw_get_chplan_worldwide(&ent);
2040 goto cmd;
2041 }
2042
2043 if (is_alpha(country_code[0]) == _FALSE
2044 || is_alpha(country_code[1]) == _FALSE
2045 ) {
2046 RTW_PRINT("%s input country_code is not alpha2\n", __func__);
2047 return _FAIL;
2048 }
2049
2050 if (!rtw_get_chplan_from_country(country_code, &ent)) {
2051 RTW_PRINT("%s unsupported country_code:\"%c%c\"\n", __func__, country_code[0], country_code[1]);
2052 return _FAIL;
2053 }
2054
2055 cmd:
2056 RTW_PRINT("%s country_code:\"%c%c\"\n", __func__, country_code[0], country_code[1]);
2057
2058 return _rtw_set_chplan_cmd(adapter, flags, RTW_CHPLAN_UNSPECIFIED, RTW_CHPLAN_6G_UNSPECIFIED, &ent, REGD_SRC_RTK_PRIV, inr, NULL);
2059 }
2060
2061 #ifdef CONFIG_REGD_SRC_FROM_OS
rtw_sync_os_regd_cmd(_adapter * adapter,int flags,const char * country_code,u8 dfs_region,enum rtw_regd_inr inr)2062 inline u8 rtw_sync_os_regd_cmd(_adapter *adapter, int flags, const char *country_code, u8 dfs_region, enum rtw_regd_inr inr)
2063 {
2064 struct country_chplan ent;
2065 struct country_chplan rtk_ent;
2066 bool rtk_ent_exist;
2067
2068 rtk_ent_exist = rtw_get_chplan_from_country(country_code, &rtk_ent);
2069
2070 _rtw_memcpy(ent.alpha2, country_code, 2);
2071
2072 /*
2073 * Regulation follows OS, the internal txpwr limit selection is searched by alpha2
2074 * "00" => WW, others use string mapping
2075 * When no matching txpwr limit selection is found, use
2076 * 1. txpwr lmit selection associated with alpha2 inside driver regulation database
2077 * 2. WW when driver has no support of this alpha2
2078 */
2079
2080 ent.chplan = rtk_ent_exist ? rtk_ent.chplan : RTW_CHPLAN_UNSPECIFIED;
2081 #if CONFIG_IEEE80211_BAND_6GHZ
2082 ent.chplan_6g = rtk_ent_exist ? rtk_ent.chplan_6g : RTW_CHPLAN_6G_UNSPECIFIED;
2083 #endif
2084 ent.edcca_mode_2g_override = rtk_ent_exist ? rtk_ent.edcca_mode_2g_override : RTW_EDCCA_DEF;
2085 #if CONFIG_IEEE80211_BAND_5GHZ
2086 ent.edcca_mode_5g_override = rtk_ent_exist ? rtk_ent.edcca_mode_5g_override : RTW_EDCCA_DEF;
2087 #endif
2088 #if CONFIG_IEEE80211_BAND_6GHZ
2089 ent.edcca_mode_6g_override = rtk_ent_exist ? rtk_ent.edcca_mode_6g_override : RTW_EDCCA_DEF;
2090 #endif
2091 ent.txpwr_lmt_override = rtk_ent_exist ? rtk_ent.txpwr_lmt_override : TXPWR_LMT_DEF;
2092 #if defined(CONFIG_80211AC_VHT) || defined(CONFIG_80211AX_HE)
2093 ent.proto_en = CHPLAN_PROTO_EN_ALL;
2094 #endif
2095
2096 /* TODO: dfs_region */
2097
2098 return _rtw_set_chplan_cmd(adapter, flags, RTW_CHPLAN_UNSPECIFIED, RTW_CHPLAN_6G_UNSPECIFIED, &ent, REGD_SRC_OS, inr, NULL);
2099 }
2100 #endif /* CONFIG_REGD_SRC_FROM_OS */
2101
rtw_get_chplan_cmd(_adapter * adapter,int flags,struct get_chplan_resp ** chplan)2102 u8 rtw_get_chplan_cmd(_adapter *adapter, int flags, struct get_chplan_resp **chplan)
2103 {
2104 struct cmd_obj *cmdobj;
2105 struct get_channel_plan_param *parm;
2106 struct cmd_priv *pcmdpriv = &adapter->cmdpriv;
2107 struct submit_ctx sctx;
2108 u8 res = _FAIL;
2109
2110 if (!(flags & (RTW_CMDF_DIRECTLY | RTW_CMDF_WAIT_ACK)))
2111 goto exit;
2112
2113 /* prepare cmd parameter */
2114 parm = rtw_zmalloc(sizeof(*parm));
2115 if (parm == NULL)
2116 goto exit;
2117 parm->chplan = chplan;
2118
2119 if (flags & RTW_CMDF_DIRECTLY) {
2120 /* no need to enqueue, do the cmd hdl directly and free cmd parameter */
2121 if (H2C_SUCCESS == rtw_get_chplan_hdl(adapter, (u8 *)parm))
2122 res = _SUCCESS;
2123 rtw_mfree((u8 *)parm, sizeof(*parm));
2124 } else {
2125 /* need enqueue, prepare cmd_obj and enqueue */
2126 cmdobj = (struct cmd_obj *)rtw_zmalloc(sizeof(*cmdobj));
2127 if (cmdobj == NULL) {
2128 rtw_mfree((u8 *)parm, sizeof(*parm));
2129 goto exit;
2130 }
2131
2132 init_h2fwcmd_w_parm_no_rsp(cmdobj, parm, CMD_GET_CHANPLAN);
2133
2134 if (flags & RTW_CMDF_WAIT_ACK) {
2135 cmdobj->sctx = &sctx;
2136 rtw_sctx_init(&sctx, 2000);
2137 }
2138
2139 res = rtw_enqueue_cmd(pcmdpriv, cmdobj);
2140
2141 if (res == _SUCCESS && (flags & RTW_CMDF_WAIT_ACK)) {
2142 rtw_sctx_wait(&sctx, __func__);
2143 _enter_critical_mutex(&pcmdpriv->sctx_mutex, NULL);
2144 if (sctx.status == RTW_SCTX_SUBMITTED)
2145 cmdobj->sctx = NULL;
2146 _exit_critical_mutex(&pcmdpriv->sctx_mutex, NULL);
2147 if (sctx.status != RTW_SCTX_DONE_SUCCESS)
2148 res = _FAIL;
2149 }
2150
2151 /* allow get channel plan when cmd_thread is not running */
2152 if (res != _SUCCESS && (flags & RTW_CMDF_WAIT_ACK)) {
2153 parm = rtw_zmalloc(sizeof(*parm));
2154 if (parm == NULL)
2155 goto exit;
2156 parm->chplan = chplan;
2157
2158 if (H2C_SUCCESS == rtw_get_chplan_hdl(adapter, (u8 *)parm))
2159 res = _SUCCESS;
2160
2161 rtw_mfree((u8 *)parm, sizeof(*parm));
2162 }
2163 }
2164
2165 exit:
2166 return res;
2167 }
2168
2169 #ifdef CONFIG_80211D
rtw_apply_recv_country_ie_cmd(_adapter * adapter,int flags,BAND_TYPE band,u8 opch,const u8 * country_ie)2170 inline u8 rtw_apply_recv_country_ie_cmd(_adapter *adapter, int flags, BAND_TYPE band,u8 opch, const u8 *country_ie)
2171 {
2172 struct country_chplan ent;
2173 struct country_ie_slave_record cisr;
2174
2175 rtw_get_chplan_from_recv_country_ie(adapter, band, opch, country_ie, &ent, &cisr, NULL);
2176
2177 return _rtw_set_chplan_cmd(adapter, flags, RTW_CHPLAN_UNSPECIFIED, RTW_CHPLAN_6G_UNSPECIFIED
2178 , NULL, REGD_SRC_RTK_PRIV, RTW_REGD_SET_BY_COUNTRY_IE, &cisr);
2179 }
2180 #endif /* CONFIG_80211D */
2181
rtw_led_blink_cmd(_adapter * padapter,void * pLed)2182 u8 rtw_led_blink_cmd(_adapter *padapter, void *pLed)
2183 {
2184 struct cmd_obj *pcmdobj;
2185 struct LedBlink_param *ledBlink_param;
2186 struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
2187
2188 u8 res = _SUCCESS;
2189
2190
2191
2192 pcmdobj = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
2193 if (pcmdobj == NULL) {
2194 res = _FAIL;
2195 goto exit;
2196 }
2197
2198 ledBlink_param = (struct LedBlink_param *)rtw_zmalloc(sizeof(struct LedBlink_param));
2199 if (ledBlink_param == NULL) {
2200 rtw_mfree((u8 *)pcmdobj, sizeof(struct cmd_obj));
2201 res = _FAIL;
2202 goto exit;
2203 }
2204
2205 ledBlink_param->pLed = pLed;
2206
2207 init_h2fwcmd_w_parm_no_rsp(pcmdobj, ledBlink_param, CMD_LEDBLINK);
2208 res = rtw_enqueue_cmd(pcmdpriv, pcmdobj);
2209
2210 exit:
2211
2212
2213 return res;
2214 }
2215
rtw_set_csa_cmd(_adapter * adapter)2216 u8 rtw_set_csa_cmd(_adapter *adapter)
2217 {
2218 struct cmd_obj *cmdobj;
2219 struct cmd_priv *cmdpriv = &adapter->cmdpriv;
2220 u8 res = _SUCCESS;
2221
2222 cmdobj = rtw_zmalloc(sizeof(struct cmd_obj));
2223 if (cmdobj == NULL) {
2224 res = _FAIL;
2225 goto exit;
2226 }
2227
2228 init_h2fwcmd_w_parm_no_parm_rsp(cmdobj, CMD_SET_CHANSWITCH);
2229 res = rtw_enqueue_cmd(cmdpriv, cmdobj);
2230
2231 exit:
2232 return res;
2233 }
2234
rtw_set_ap_csa_cmd(_adapter * adapter)2235 u8 rtw_set_ap_csa_cmd(_adapter *adapter)
2236 {
2237 u8 res = _SUCCESS;
2238 #ifdef CONFIG_AP_MODE
2239 struct cmd_obj *cmdobj;
2240 struct cmd_priv *cmdpriv = &adapter->cmdpriv;
2241
2242 RTW_INFO("%s\n", __FUNCTION__);
2243
2244 cmdobj = rtw_zmalloc(sizeof(struct cmd_obj));
2245 if (cmdobj == NULL) {
2246 res = _FAIL;
2247 goto exit;
2248 }
2249
2250 init_h2fwcmd_w_parm_no_parm_rsp(cmdobj, CMD_AP_CHANSWITCH);
2251 res = rtw_enqueue_cmd(cmdpriv, cmdobj);
2252
2253 exit:
2254 #endif /* CONFIG_AP_MODE */
2255 return res;
2256 }
2257
rtw_tdls_cmd(_adapter * padapter,u8 * addr,u8 option)2258 u8 rtw_tdls_cmd(_adapter *padapter, u8 *addr, u8 option)
2259 {
2260 u8 res = _SUCCESS;
2261 #ifdef CONFIG_TDLS
2262 struct cmd_obj *pcmdobj;
2263 struct TDLSoption_param *TDLSoption;
2264 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
2265 struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
2266
2267 pcmdobj = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
2268 if (pcmdobj == NULL) {
2269 res = _FAIL;
2270 goto exit;
2271 }
2272
2273 TDLSoption = (struct TDLSoption_param *)rtw_zmalloc(sizeof(struct TDLSoption_param));
2274 if (TDLSoption == NULL) {
2275 rtw_mfree((u8 *)pcmdobj, sizeof(struct cmd_obj));
2276 res = _FAIL;
2277 goto exit;
2278 }
2279
2280 _rtw_spinlock(&(padapter->tdlsinfo.cmd_lock));
2281 if (addr != NULL)
2282 _rtw_memcpy(TDLSoption->addr, addr, 6);
2283 TDLSoption->option = option;
2284 _rtw_spinunlock(&(padapter->tdlsinfo.cmd_lock));
2285 init_h2fwcmd_w_parm_no_rsp(pcmdobj, TDLSoption, CMD_TDLS);
2286 res = rtw_enqueue_cmd(pcmdpriv, pcmdobj);
2287
2288 exit:
2289 #endif /* CONFIG_TDLS */
2290
2291 return res;
2292 }
2293
rtw_enable_hw_update_tsf_cmd(_adapter * padapter)2294 u8 rtw_enable_hw_update_tsf_cmd(_adapter *padapter)
2295 {
2296 struct cmd_obj *ph2c;
2297 struct drvextra_cmd_parm *pdrvextra_cmd_parm;
2298 struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
2299 u8 res = _SUCCESS;
2300
2301
2302 ph2c = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
2303 if (ph2c == NULL) {
2304 res = _FAIL;
2305 goto exit;
2306 }
2307
2308 pdrvextra_cmd_parm = (struct drvextra_cmd_parm *)rtw_zmalloc(sizeof(struct drvextra_cmd_parm));
2309 if (pdrvextra_cmd_parm == NULL) {
2310 rtw_mfree((unsigned char *)ph2c, sizeof(struct cmd_obj));
2311 res = _FAIL;
2312 goto exit;
2313 }
2314
2315 pdrvextra_cmd_parm->ec_id = EN_HW_UPDATE_TSF_WK_CID;
2316 pdrvextra_cmd_parm->type = 0;
2317 pdrvextra_cmd_parm->size = 0;
2318 pdrvextra_cmd_parm->pbuf = NULL;
2319
2320 init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, CMD_SET_DRV_EXTRA);
2321
2322 res = rtw_enqueue_cmd(pcmdpriv, ph2c);
2323
2324 exit:
2325 return res;
2326 }
2327
rtw_periodic_tsf_update_end_cmd(_adapter * adapter)2328 u8 rtw_periodic_tsf_update_end_cmd(_adapter *adapter)
2329 {
2330 struct cmd_obj *cmdobj;
2331 struct drvextra_cmd_parm *parm;
2332 struct cmd_priv *cmdpriv = &adapter->cmdpriv;
2333 u8 res = _SUCCESS;
2334
2335 cmdobj = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
2336 if (cmdobj == NULL) {
2337 res = _FAIL;
2338 goto exit;
2339 }
2340
2341 parm = (struct drvextra_cmd_parm *)rtw_zmalloc(sizeof(struct drvextra_cmd_parm));
2342 if (parm == NULL) {
2343 rtw_mfree((unsigned char *)cmdobj, sizeof(struct cmd_obj));
2344 res = _FAIL;
2345 goto exit;
2346 }
2347
2348 parm->ec_id = PERIOD_TSF_UPDATE_END_WK_CID;
2349 parm->type = 0;
2350 parm->size = 0;
2351 parm->pbuf = NULL;
2352
2353 init_h2fwcmd_w_parm_no_rsp(cmdobj, parm, CMD_SET_DRV_EXTRA);
2354
2355 res = rtw_enqueue_cmd(cmdpriv, cmdobj);
2356
2357 exit:
2358 return res;
2359 }
rtw_ssmps_wk_hdl(_adapter * adapter,struct ssmps_cmd_parm * ssmp_param)2360 u8 rtw_ssmps_wk_hdl(_adapter *adapter, struct ssmps_cmd_parm *ssmp_param)
2361 {
2362 u8 res = _SUCCESS;
2363 struct sta_info *sta = ssmp_param->sta;
2364 u8 smps = ssmp_param->smps;
2365
2366 if (sta == NULL)
2367 return _FALSE;
2368
2369 if (smps)
2370 rtw_ssmps_enter(adapter, sta);
2371 else
2372 rtw_ssmps_leave(adapter, sta);
2373 return res;
2374 }
2375
rtw_ssmps_wk_cmd(_adapter * adapter,struct sta_info * sta,u8 smps,u8 enqueue)2376 u8 rtw_ssmps_wk_cmd(_adapter *adapter, struct sta_info *sta, u8 smps, u8 enqueue)
2377 {
2378 struct cmd_obj *cmdobj;
2379 struct drvextra_cmd_parm *cmd_parm;
2380 struct ssmps_cmd_parm *ssmp_param;
2381 struct cmd_priv *pcmdpriv = &adapter->cmdpriv;
2382 u8 res = _SUCCESS;
2383
2384 if (enqueue) {
2385 cmdobj = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
2386 if (cmdobj == NULL) {
2387 res = _FAIL;
2388 goto exit;
2389 }
2390
2391 cmd_parm = (struct drvextra_cmd_parm *)rtw_zmalloc(sizeof(struct drvextra_cmd_parm));
2392 if (cmd_parm == NULL) {
2393 rtw_mfree((unsigned char *)cmdobj, sizeof(struct cmd_obj));
2394 res = _FAIL;
2395 goto exit;
2396 }
2397
2398 ssmp_param = (struct ssmps_cmd_parm *)rtw_zmalloc(sizeof(struct ssmps_cmd_parm));
2399 if (ssmp_param == NULL) {
2400 rtw_mfree((u8 *)cmdobj, sizeof(struct cmd_obj));
2401 rtw_mfree((u8 *)cmd_parm, sizeof(struct drvextra_cmd_parm));
2402 res = _FAIL;
2403 goto exit;
2404 }
2405
2406 ssmp_param->smps = smps;
2407 ssmp_param->sta = sta;
2408
2409 cmd_parm->ec_id = SSMPS_WK_CID;
2410 cmd_parm->type = 0;
2411 cmd_parm->size = sizeof(struct ssmps_cmd_parm);
2412 cmd_parm->pbuf = (u8 *)ssmp_param;
2413
2414 init_h2fwcmd_w_parm_no_rsp(cmdobj, cmd_parm, CMD_SET_DRV_EXTRA);
2415
2416 res = rtw_enqueue_cmd(pcmdpriv, cmdobj);
2417 } else {
2418 struct ssmps_cmd_parm tmp_ssmp_param;
2419
2420 tmp_ssmp_param.smps = smps;
2421 tmp_ssmp_param.sta = sta;
2422 rtw_ssmps_wk_hdl(adapter, &tmp_ssmp_param);
2423 }
2424
2425 exit:
2426 return res;
2427 }
2428
2429 #ifdef CONFIG_SUPPORT_STATIC_SMPS
_ssmps_chk_by_tp(_adapter * adapter,u8 from_timer)2430 u8 _ssmps_chk_by_tp(_adapter *adapter, u8 from_timer)
2431 {
2432 u8 enter_smps = _FALSE;
2433 struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
2434 struct mlme_ext_priv *pmlmeext = &(adapter->mlmeextpriv);
2435 struct sta_priv *pstapriv = &adapter->stapriv;
2436 struct sta_info *psta;
2437 u32 tx_tp_mbits, rx_tp_mbits;
2438
2439 if (!MLME_IS_STA(adapter) ||
2440 !hal_is_mimo_support(adapter) ||
2441 !pmlmeext->ssmps_en ||
2442 (pmlmeext->cur_channel > 14)
2443 )
2444 return enter_smps;
2445
2446 psta = rtw_get_stainfo(pstapriv, get_bssid(pmlmepriv));
2447 if (psta == NULL) {
2448 RTW_ERR(ADPT_FMT" sta == NULL\n", ADPT_ARG(adapter));
2449 rtw_warn_on(1);
2450 return enter_smps;
2451 }
2452
2453 if (psta->cmn.mimo_type == RF_1T1R)
2454 return enter_smps;
2455
2456 tx_tp_mbits = psta->sta_stats.tx_tp_kbits >> 10;
2457 rx_tp_mbits = psta->sta_stats.rx_tp_kbits >> 10;
2458
2459 #ifdef DBG_STATIC_SMPS
2460 if (pmlmeext->ssmps_test) {
2461 enter_smps = (pmlmeext->ssmps_test_en == 1) ? _TRUE : _FALSE;
2462 }
2463 else
2464 #endif
2465 {
2466 if ((tx_tp_mbits <= pmlmeext->ssmps_tx_tp_th) &&
2467 (rx_tp_mbits <= pmlmeext->ssmps_rx_tp_th))
2468 enter_smps = _TRUE;
2469 else
2470 enter_smps = _FALSE;
2471 }
2472
2473 if (1) {
2474 RTW_INFO(FUNC_ADPT_FMT" tx_tp:%d [%d], rx_tp:%d [%d] , SSMPS enter :%s\n",
2475 FUNC_ADPT_ARG(adapter),
2476 tx_tp_mbits, pmlmeext->ssmps_tx_tp_th,
2477 rx_tp_mbits, pmlmeext->ssmps_rx_tp_th,
2478 (enter_smps == _TRUE) ? "True" : "False");
2479 #ifdef DBG_STATIC_SMPS
2480 RTW_INFO(FUNC_ADPT_FMT" test:%d test_en:%d\n",
2481 FUNC_ADPT_ARG(adapter),
2482 pmlmeext->ssmps_test,
2483 pmlmeext->ssmps_test_en);
2484 #endif
2485 }
2486
2487 if (enter_smps) {
2488 if (!from_timer && psta->cmn.sm_ps != SM_PS_STATIC)
2489 rtw_ssmps_enter(adapter, psta);
2490 } else {
2491 if (!from_timer && psta->cmn.sm_ps != SM_PS_DISABLE)
2492 rtw_ssmps_leave(adapter, psta);
2493 else {
2494 u8 ps_change = _FALSE;
2495
2496 if (enter_smps && psta->cmn.sm_ps != SM_PS_STATIC)
2497 ps_change = _TRUE;
2498 else if (!enter_smps && psta->cmn.sm_ps != SM_PS_DISABLE)
2499 ps_change = _TRUE;
2500
2501 if (ps_change)
2502 rtw_ssmps_wk_cmd(adapter, psta, enter_smps, 1);
2503 }
2504 }
2505
2506 return enter_smps;
2507 }
2508 #endif /*CONFIG_SUPPORT_STATIC_SMPS*/
2509
2510 #ifdef CONFIG_CTRL_TXSS_BY_TP
rtw_ctrl_txss_update_mimo_type(_adapter * adapter,struct sta_info * sta)2511 void rtw_ctrl_txss_update_mimo_type(_adapter *adapter, struct sta_info *sta)
2512 {
2513 struct mlme_ext_priv *pmlmeext = &(adapter->mlmeextpriv);
2514
2515 pmlmeext->txss_momi_type_bk = sta->cmn.mimo_type;
2516 }
2517
rtw_ctrl_txss(_adapter * adapter,struct sta_info * sta,bool tx_1ss)2518 u8 rtw_ctrl_txss(_adapter *adapter, struct sta_info *sta, bool tx_1ss)
2519 {
2520 struct mlme_ext_priv *pmlmeext = &(adapter->mlmeextpriv);
2521 struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(adapter);
2522 u8 lps_changed = _FALSE;
2523 u8 rst = _SUCCESS;
2524
2525 if (pmlmeext->txss_1ss == tx_1ss)
2526 return _FALSE;
2527
2528 if (pwrpriv->bLeisurePs && pwrpriv->pwr_mode != PS_MODE_ACTIVE) {
2529 lps_changed = _TRUE;
2530 LPS_Leave(adapter, "LPS_CTRL_TXSS");
2531 }
2532
2533 RTW_INFO(ADPT_FMT" STA [" MAC_FMT "] set tx to %d ss\n",
2534 ADPT_ARG(adapter), MAC_ARG(sta->cmn.mac_addr),
2535 (tx_1ss) ? 1 : rtw_get_sta_tx_nss(adapter, sta));
2536
2537 /*ra re-registed*/
2538 sta->cmn.mimo_type = (tx_1ss) ? RF_1T1R : pmlmeext->txss_momi_type_bk;
2539 rtw_phydm_ra_registed(adapter, sta);
2540
2541 /*configure trx mode*/
2542 rtw_phydm_trx_cfg(adapter, tx_1ss);
2543 pmlmeext->txss_1ss = tx_1ss;
2544
2545 if (lps_changed)
2546 LPS_Enter(adapter, "LPS_CTRL_TXSS");
2547
2548 return rst;
2549 }
2550
rtw_ctrl_txss_wk_hdl(_adapter * adapter,struct txss_cmd_parm * txss_param)2551 u8 rtw_ctrl_txss_wk_hdl(_adapter *adapter, struct txss_cmd_parm *txss_param)
2552 {
2553 if (!txss_param->sta)
2554 return _FALSE;
2555
2556 return rtw_ctrl_txss(adapter, txss_param->sta, txss_param->tx_1ss);
2557 }
2558
rtw_ctrl_txss_wk_cmd(_adapter * adapter,struct sta_info * sta,bool tx_1ss,u8 flag)2559 u8 rtw_ctrl_txss_wk_cmd(_adapter *adapter, struct sta_info *sta, bool tx_1ss, u8 flag)
2560 {
2561 struct cmd_obj *cmdobj;
2562 struct drvextra_cmd_parm *cmd_parm;
2563 struct txss_cmd_parm *txss_param;
2564 struct cmd_priv *pcmdpriv = &adapter->cmdpriv;
2565 struct submit_ctx sctx;
2566 u8 res = _SUCCESS;
2567
2568 txss_param = (struct txss_cmd_parm *)rtw_zmalloc(sizeof(struct txss_cmd_parm));
2569 if (txss_param == NULL) {
2570 res = _FAIL;
2571 goto exit;
2572 }
2573
2574 txss_param->tx_1ss = tx_1ss;
2575 txss_param->sta = sta;
2576
2577 if (flag & RTW_CMDF_DIRECTLY) {
2578 res = rtw_ctrl_txss_wk_hdl(adapter, txss_param);
2579 rtw_mfree((u8 *)txss_param, sizeof(*txss_param));
2580 } else {
2581 cmdobj = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
2582 if (cmdobj == NULL) {
2583 res = _FAIL;
2584 goto exit;
2585 }
2586
2587 cmd_parm = (struct drvextra_cmd_parm *)rtw_zmalloc(sizeof(struct drvextra_cmd_parm));
2588 if (cmd_parm == NULL) {
2589 rtw_mfree((u8 *)cmdobj, sizeof(struct cmd_obj));
2590 res = _FAIL;
2591 goto exit;
2592 }
2593
2594 cmd_parm->ec_id = TXSS_WK_CID;
2595 cmd_parm->type = 0;
2596 cmd_parm->size = sizeof(struct txss_cmd_parm);
2597 cmd_parm->pbuf = (u8 *)txss_param;
2598
2599 init_h2fwcmd_w_parm_no_rsp(cmdobj, cmd_parm, CMD_SET_DRV_EXTRA);
2600
2601 if (flag & RTW_CMDF_WAIT_ACK) {
2602 cmdobj->sctx = &sctx;
2603 rtw_sctx_init(&sctx, 10 * 1000);
2604 }
2605
2606 res = rtw_enqueue_cmd(pcmdpriv, cmdobj);
2607 if (res == _SUCCESS && (flag & RTW_CMDF_WAIT_ACK)) {
2608 rtw_sctx_wait(&sctx, __func__);
2609 _enter_critical_mutex(&pcmdpriv->sctx_mutex, NULL);
2610 if (sctx.status == RTW_SCTX_SUBMITTED)
2611 cmdobj->sctx = NULL;
2612 _exit_critical_mutex(&pcmdpriv->sctx_mutex, NULL);
2613 if (sctx.status != RTW_SCTX_DONE_SUCCESS)
2614 res = _FAIL;
2615 }
2616 }
2617
2618 exit:
2619 return res;
2620 }
2621
rtw_ctrl_tx_ss_by_tp(_adapter * adapter,u8 from_timer)2622 void rtw_ctrl_tx_ss_by_tp(_adapter *adapter, u8 from_timer)
2623 {
2624 bool tx_1ss = _FALSE; /*change tx from 2ss to 1ss*/
2625 struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
2626 struct mlme_ext_priv *pmlmeext = &(adapter->mlmeextpriv);
2627 struct sta_priv *pstapriv = &adapter->stapriv;
2628 struct sta_info *psta;
2629 u32 tx_tp_mbits;
2630
2631 if (!MLME_IS_STA(adapter) ||
2632 !hal_is_mimo_support(adapter) ||
2633 !pmlmeext->txss_ctrl_en
2634 )
2635 return;
2636
2637 psta = rtw_get_stainfo(pstapriv, get_bssid(pmlmepriv));
2638 if (psta == NULL) {
2639 RTW_ERR(ADPT_FMT" sta == NULL\n", ADPT_ARG(adapter));
2640 rtw_warn_on(1);
2641 return;
2642 }
2643
2644 tx_tp_mbits = psta->sta_stats.tx_tp_kbits >> 10;
2645 if (tx_tp_mbits >= pmlmeext->txss_tp_th) {
2646 tx_1ss = _FALSE;
2647 } else {
2648 if (pmlmeext->txss_tp_chk_cnt && --pmlmeext->txss_tp_chk_cnt)
2649 tx_1ss = _FALSE;
2650 else
2651 tx_1ss = _TRUE;
2652 }
2653
2654 if (1) {
2655 RTW_INFO(FUNC_ADPT_FMT" tx_tp:%d [%d] tx_1ss(%d):%s\n",
2656 FUNC_ADPT_ARG(adapter),
2657 tx_tp_mbits, pmlmeext->txss_tp_th,
2658 pmlmeext->txss_tp_chk_cnt,
2659 (tx_1ss == _TRUE) ? "True" : "False");
2660 }
2661
2662 if (pmlmeext->txss_1ss != tx_1ss) {
2663 if (from_timer)
2664 rtw_ctrl_txss_wk_cmd(adapter, psta, tx_1ss, 0);
2665 else
2666 rtw_ctrl_txss(adapter, psta, tx_1ss);
2667 }
2668 }
2669 #ifdef DBG_CTRL_TXSS
dbg_ctrl_txss(_adapter * adapter,bool tx_1ss)2670 void dbg_ctrl_txss(_adapter *adapter, bool tx_1ss)
2671 {
2672 struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
2673 struct mlme_ext_priv *pmlmeext = &(adapter->mlmeextpriv);
2674 struct sta_priv *pstapriv = &adapter->stapriv;
2675 struct sta_info *psta;
2676
2677 if (!MLME_IS_STA(adapter) ||
2678 !hal_is_mimo_support(adapter)
2679 )
2680 return;
2681
2682 psta = rtw_get_stainfo(pstapriv, get_bssid(pmlmepriv));
2683 if (psta == NULL) {
2684 RTW_ERR(ADPT_FMT" sta == NULL\n", ADPT_ARG(adapter));
2685 rtw_warn_on(1);
2686 return;
2687 }
2688
2689 rtw_ctrl_txss(adapter, psta, tx_1ss);
2690 }
2691 #endif
2692 #endif /*CONFIG_CTRL_TXSS_BY_TP*/
2693
2694 #ifdef CONFIG_LPS
2695 #ifdef CONFIG_LPS_CHK_BY_TP
2696 #ifdef LPS_BCN_CNT_MONITOR
_bcn_cnt_expected(struct sta_info * psta)2697 static u8 _bcn_cnt_expected(struct sta_info *psta)
2698 {
2699 _adapter *adapter = psta->padapter;
2700 struct mlme_ext_priv *pmlmeext = &adapter->mlmeextpriv;
2701 struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
2702 u8 dtim = rtw_get_bcn_dtim_period(adapter);
2703 u8 bcn_cnt = 0;
2704
2705 if ((pmlmeinfo->bcn_interval !=0) && (dtim != 0))
2706 bcn_cnt = 2000 / pmlmeinfo->bcn_interval / dtim * 4 / 5; /*2s*/
2707 if (0)
2708 RTW_INFO("%s bcn_cnt:%d\n", __func__, bcn_cnt);
2709
2710 if (bcn_cnt == 0) {
2711 RTW_ERR(FUNC_ADPT_FMT" bcn_cnt == 0\n", FUNC_ADPT_ARG(adapter));
2712 rtw_warn_on(1);
2713 }
2714
2715 return bcn_cnt;
2716 }
2717 #endif
_lps_chk_by_tp(_adapter * adapter,u8 from_timer)2718 u8 _lps_chk_by_tp(_adapter *adapter, u8 from_timer)
2719 {
2720 u8 enter_ps = _FALSE;
2721 struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
2722 struct sta_priv *pstapriv = &adapter->stapriv;
2723 struct sta_info *psta;
2724 struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(adapter);
2725 u32 tx_tp_mbits, rx_tp_mbits, bi_tp_mbits;
2726 u8 rx_bcn_cnt;
2727
2728 psta = rtw_get_stainfo(pstapriv, get_bssid(pmlmepriv));
2729 if (psta == NULL) {
2730 RTW_ERR(ADPT_FMT" sta == NULL\n", ADPT_ARG(adapter));
2731 rtw_warn_on(1);
2732 return enter_ps;
2733 }
2734
2735 rx_bcn_cnt = rtw_get_bcn_cnt(psta->padapter);
2736 psta->sta_stats.acc_tx_bytes = psta->sta_stats.tx_bytes;
2737 psta->sta_stats.acc_rx_bytes = psta->sta_stats.rx_bytes;
2738
2739 #if 1
2740 tx_tp_mbits = psta->sta_stats.tx_tp_kbits >> 10;
2741 rx_tp_mbits = psta->sta_stats.rx_tp_kbits >> 10;
2742 bi_tp_mbits = tx_tp_mbits + rx_tp_mbits;
2743 #else
2744 tx_tp_mbits = psta->sta_stats.smooth_tx_tp_kbits >> 10;
2745 rx_tp_mbits = psta->sta_stats.smooth_rx_tp_kbits >> 10;
2746 bi_tp_mbits = tx_tp_mbits + rx_tp_mbits;
2747 #endif
2748
2749 if ((bi_tp_mbits >= pwrpriv->lps_bi_tp_th) ||
2750 (tx_tp_mbits >= pwrpriv->lps_tx_tp_th) ||
2751 (rx_tp_mbits >= pwrpriv->lps_rx_tp_th)) {
2752 enter_ps = _FALSE;
2753 pwrpriv->lps_chk_cnt = pwrpriv->lps_chk_cnt_th;
2754 }
2755 else {
2756 #ifdef LPS_BCN_CNT_MONITOR
2757 u8 bcn_cnt = _bcn_cnt_expected(psta);
2758
2759 if (bcn_cnt && (rx_bcn_cnt < bcn_cnt)) {
2760 pwrpriv->lps_chk_cnt = 2;
2761 RTW_ERR(FUNC_ADPT_FMT" BCN_CNT:%d(%d) invalid\n",
2762 FUNC_ADPT_ARG(adapter), rx_bcn_cnt, bcn_cnt);
2763 }
2764 #endif
2765
2766 if (pwrpriv->lps_chk_cnt && --pwrpriv->lps_chk_cnt)
2767 enter_ps = _FALSE;
2768 else
2769 enter_ps = _TRUE;
2770 }
2771
2772 if (1) {
2773 RTW_INFO(FUNC_ADPT_FMT" tx_tp:%d [%d], rx_tp:%d [%d], bi_tp:%d [%d], enter_ps(%d):%s\n",
2774 FUNC_ADPT_ARG(adapter),
2775 tx_tp_mbits, pwrpriv->lps_tx_tp_th,
2776 rx_tp_mbits, pwrpriv->lps_rx_tp_th,
2777 bi_tp_mbits, pwrpriv->lps_bi_tp_th,
2778 pwrpriv->lps_chk_cnt,
2779 (enter_ps == _TRUE) ? "True" : "False");
2780 RTW_INFO(FUNC_ADPT_FMT" tx_pkt_cnt :%d [%d], rx_pkt_cnt :%d [%d]\n",
2781 FUNC_ADPT_ARG(adapter),
2782 pmlmepriv->LinkDetectInfo.NumTxOkInPeriod,
2783 pwrpriv->lps_tx_pkts,
2784 pmlmepriv->LinkDetectInfo.NumRxUnicastOkInPeriod,
2785 pwrpriv->lps_rx_pkts);
2786 if (!adapter->bsta_tp_dump)
2787 RTW_INFO(FUNC_ADPT_FMT" bcn_cnt:%d (per-%d second)\n",
2788 FUNC_ADPT_ARG(adapter),
2789 rx_bcn_cnt,
2790 2);
2791 }
2792
2793 if (enter_ps) {
2794 if (!from_timer)
2795 LPS_Enter(adapter, "TRAFFIC_IDLE");
2796 } else {
2797 if (!from_timer)
2798 LPS_Leave(adapter, "TRAFFIC_BUSY");
2799 else {
2800 #ifdef CONFIG_CONCURRENT_MODE
2801 #ifndef CONFIG_FW_MULTI_PORT_SUPPORT
2802 if (adapter->hw_port == HW_PORT0)
2803 #endif
2804 #endif
2805 rtw_lps_ctrl_wk_cmd(adapter, LPS_CTRL_TRAFFIC_BUSY, 0);
2806 }
2807 }
2808
2809 return enter_ps;
2810 }
2811 #endif
2812
_lps_chk_by_pkt_cnts(_adapter * padapter,u8 from_timer,u8 bBusyTraffic)2813 static u8 _lps_chk_by_pkt_cnts(_adapter *padapter, u8 from_timer, u8 bBusyTraffic)
2814 {
2815 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
2816 u8 bEnterPS = _FALSE;
2817
2818 /* check traffic for powersaving. */
2819 if (((pmlmepriv->LinkDetectInfo.NumRxUnicastOkInPeriod + pmlmepriv->LinkDetectInfo.NumTxOkInPeriod) > 8) ||
2820 #ifdef CONFIG_LPS_SLOW_TRANSITION
2821 (pmlmepriv->LinkDetectInfo.NumRxUnicastOkInPeriod > 2)
2822 #else /* CONFIG_LPS_SLOW_TRANSITION */
2823 (pmlmepriv->LinkDetectInfo.NumRxUnicastOkInPeriod > 4)
2824 #endif /* CONFIG_LPS_SLOW_TRANSITION */
2825 ) {
2826 #ifdef DBG_RX_COUNTER_DUMP
2827 if (padapter->dump_rx_cnt_mode & DUMP_DRV_TRX_COUNTER_DATA)
2828 RTW_INFO("(-)Tx = %d, Rx = %d\n", pmlmepriv->LinkDetectInfo.NumTxOkInPeriod, pmlmepriv->LinkDetectInfo.NumRxUnicastOkInPeriod);
2829 #endif
2830
2831 bEnterPS = _FALSE;
2832 #ifdef CONFIG_LPS_SLOW_TRANSITION
2833 if (bBusyTraffic == _TRUE) {
2834 if (pmlmepriv->LinkDetectInfo.TrafficTransitionCount <= 4)
2835 pmlmepriv->LinkDetectInfo.TrafficTransitionCount = 4;
2836
2837 pmlmepriv->LinkDetectInfo.TrafficTransitionCount++;
2838
2839 /* RTW_INFO("Set TrafficTransitionCount to %d\n", pmlmepriv->LinkDetectInfo.TrafficTransitionCount); */
2840
2841 if (pmlmepriv->LinkDetectInfo.TrafficTransitionCount > 30/*TrafficTransitionLevel*/)
2842 pmlmepriv->LinkDetectInfo.TrafficTransitionCount = 30;
2843 }
2844 #endif /* CONFIG_LPS_SLOW_TRANSITION */
2845 } else {
2846 #ifdef DBG_RX_COUNTER_DUMP
2847 if (padapter->dump_rx_cnt_mode & DUMP_DRV_TRX_COUNTER_DATA)
2848 RTW_INFO("(+)Tx = %d, Rx = %d\n", pmlmepriv->LinkDetectInfo.NumTxOkInPeriod, pmlmepriv->LinkDetectInfo.NumRxUnicastOkInPeriod);
2849 #endif
2850
2851 #ifdef CONFIG_LPS_SLOW_TRANSITION
2852 if (pmlmepriv->LinkDetectInfo.TrafficTransitionCount >= 2)
2853 pmlmepriv->LinkDetectInfo.TrafficTransitionCount -= 2;
2854 else
2855 pmlmepriv->LinkDetectInfo.TrafficTransitionCount = 0;
2856
2857 if (pmlmepriv->LinkDetectInfo.TrafficTransitionCount == 0)
2858 bEnterPS = _TRUE;
2859 #else /* CONFIG_LPS_SLOW_TRANSITION */
2860 bEnterPS = _TRUE;
2861 #endif /* CONFIG_LPS_SLOW_TRANSITION */
2862 }
2863
2864 #ifdef CONFIG_DYNAMIC_DTIM
2865 if (pmlmepriv->LinkDetectInfo.LowPowerTransitionCount == 8)
2866 bEnterPS = _FALSE;
2867
2868 RTW_INFO("LowPowerTransitionCount=%d\n", pmlmepriv->LinkDetectInfo.LowPowerTransitionCount);
2869 #endif /* CONFIG_DYNAMIC_DTIM */
2870
2871 /* LeisurePS only work in infra mode. */
2872 if (bEnterPS) {
2873 if (!from_timer) {
2874 #ifdef CONFIG_DYNAMIC_DTIM
2875 if (pmlmepriv->LinkDetectInfo.LowPowerTransitionCount < 8)
2876 adapter_to_pwrctl(padapter)->dtim = 1;
2877 else
2878 adapter_to_pwrctl(padapter)->dtim = 3;
2879 #endif /* CONFIG_DYNAMIC_DTIM */
2880 LPS_Enter(padapter, "TRAFFIC_IDLE");
2881 } else {
2882 /* do this at caller */
2883 /* rtw_lps_ctrl_wk_cmd(adapter, LPS_CTRL_ENTER, 0); */
2884 /* rtw_hal_dm_watchdog_in_lps(padapter); */
2885 }
2886
2887 #ifdef CONFIG_DYNAMIC_DTIM
2888 if (adapter_to_pwrctl(padapter)->bFwCurrentInPSMode == _TRUE)
2889 pmlmepriv->LinkDetectInfo.LowPowerTransitionCount++;
2890 #endif /* CONFIG_DYNAMIC_DTIM */
2891 } else {
2892 #ifdef CONFIG_DYNAMIC_DTIM
2893 if (pmlmepriv->LinkDetectInfo.LowPowerTransitionCount != 8)
2894 pmlmepriv->LinkDetectInfo.LowPowerTransitionCount = 0;
2895 else
2896 pmlmepriv->LinkDetectInfo.LowPowerTransitionCount++;
2897 #endif /* CONFIG_DYNAMIC_DTIM */
2898
2899 if (!from_timer)
2900 LPS_Leave(padapter, "TRAFFIC_BUSY");
2901 else {
2902 #ifdef CONFIG_CONCURRENT_MODE
2903 #ifndef CONFIG_FW_MULTI_PORT_SUPPORT
2904 if (padapter->hw_port == HW_PORT0)
2905 #endif
2906 #endif
2907 rtw_lps_ctrl_wk_cmd(padapter, LPS_CTRL_TRAFFIC_BUSY, 0);
2908 }
2909 }
2910
2911 return bEnterPS;
2912 }
2913 #endif /* CONFIG_LPS */
2914
2915 /* from_timer == 1 means driver is in LPS */
traffic_status_watchdog(_adapter * padapter,u8 from_timer)2916 u8 traffic_status_watchdog(_adapter *padapter, u8 from_timer)
2917 {
2918 u8 bEnterPS = _FALSE;
2919 u16 BusyThresholdHigh;
2920 u16 BusyThresholdLow;
2921 u16 BusyThreshold;
2922 u8 bBusyTraffic = _FALSE, bTxBusyTraffic = _FALSE, bRxBusyTraffic = _FALSE;
2923 u8 bHigherBusyTraffic = _FALSE, bHigherBusyRxTraffic = _FALSE, bHigherBusyTxTraffic = _FALSE;
2924
2925 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
2926 #ifdef CONFIG_TDLS
2927 struct tdls_info *ptdlsinfo = &(padapter->tdlsinfo);
2928 struct tdls_txmgmt txmgmt;
2929 u8 baddr[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
2930 #endif /* CONFIG_TDLS */
2931 #ifdef CONFIG_TRAFFIC_PROTECT
2932 RT_LINK_DETECT_T *link_detect = &pmlmepriv->LinkDetectInfo;
2933 #endif
2934
2935 #ifdef CONFIG_BT_COEXIST
2936 if (padapter->registrypriv.wifi_spec != 1) {
2937 BusyThresholdHigh = 25;
2938 BusyThresholdLow = 10;
2939 } else
2940 #endif /* CONFIG_BT_COEXIST */
2941 {
2942 BusyThresholdHigh = 100;
2943 BusyThresholdLow = 75;
2944 }
2945 BusyThreshold = BusyThresholdHigh;
2946
2947
2948 /* */
2949 /* Determine if our traffic is busy now */
2950 /* */
2951 if ((check_fwstate(pmlmepriv, WIFI_ASOC_STATE) == _TRUE)
2952 /*&& !MgntInitAdapterInProgress(pMgntInfo)*/) {
2953 /* if we raise bBusyTraffic in last watchdog, using lower threshold. */
2954 if (pmlmepriv->LinkDetectInfo.bBusyTraffic)
2955 BusyThreshold = BusyThresholdLow;
2956
2957 if (pmlmepriv->LinkDetectInfo.NumRxOkInPeriod > BusyThreshold ||
2958 pmlmepriv->LinkDetectInfo.NumTxOkInPeriod > BusyThreshold) {
2959 bBusyTraffic = _TRUE;
2960
2961 if (pmlmepriv->LinkDetectInfo.NumRxOkInPeriod > pmlmepriv->LinkDetectInfo.NumTxOkInPeriod)
2962 bRxBusyTraffic = _TRUE;
2963 else
2964 bTxBusyTraffic = _TRUE;
2965 }
2966
2967 /* Higher Tx/Rx data. */
2968 if (pmlmepriv->LinkDetectInfo.NumRxOkInPeriod > 4000 ||
2969 pmlmepriv->LinkDetectInfo.NumTxOkInPeriod > 4000) {
2970 bHigherBusyTraffic = _TRUE;
2971
2972 if (pmlmepriv->LinkDetectInfo.NumRxOkInPeriod > pmlmepriv->LinkDetectInfo.NumTxOkInPeriod)
2973 bHigherBusyRxTraffic = _TRUE;
2974 else
2975 bHigherBusyTxTraffic = _TRUE;
2976 }
2977
2978 #ifdef CONFIG_TRAFFIC_PROTECT
2979 #define TX_ACTIVE_TH 10
2980 #define RX_ACTIVE_TH 20
2981 #define TRAFFIC_PROTECT_PERIOD_MS 4500
2982
2983 if (link_detect->NumTxOkInPeriod > TX_ACTIVE_TH
2984 || link_detect->NumRxUnicastOkInPeriod > RX_ACTIVE_TH) {
2985
2986 RTW_INFO(FUNC_ADPT_FMT" acqiure wake_lock for %u ms(tx:%d,rx_unicast:%d)\n",
2987 FUNC_ADPT_ARG(padapter),
2988 TRAFFIC_PROTECT_PERIOD_MS,
2989 link_detect->NumTxOkInPeriod,
2990 link_detect->NumRxUnicastOkInPeriod);
2991
2992 rtw_lock_traffic_suspend_timeout(TRAFFIC_PROTECT_PERIOD_MS);
2993 }
2994 #endif
2995
2996 #ifdef CONFIG_TDLS
2997 #ifdef CONFIG_TDLS_AUTOSETUP
2998 /* TDLS_WATCHDOG_PERIOD * 2sec, periodically send */
2999 if (hal_chk_wl_func(padapter, WL_FUNC_TDLS) == _TRUE) {
3000 if ((ptdlsinfo->watchdog_count % TDLS_WATCHDOG_PERIOD) == 0) {
3001 _rtw_memcpy(txmgmt.peer, baddr, ETH_ALEN);
3002 issue_tdls_dis_req(padapter, &txmgmt);
3003 }
3004 ptdlsinfo->watchdog_count++;
3005 }
3006 #endif /* CONFIG_TDLS_AUTOSETUP */
3007 #endif /* CONFIG_TDLS */
3008
3009 #ifdef CONFIG_SUPPORT_STATIC_SMPS
3010 _ssmps_chk_by_tp(padapter, from_timer);
3011 #endif
3012 #ifdef CONFIG_CTRL_TXSS_BY_TP
3013 rtw_ctrl_tx_ss_by_tp(padapter, from_timer);
3014 #endif
3015
3016 #ifdef CONFIG_LPS
3017 if (adapter_to_pwrctl(padapter)->bLeisurePs && MLME_IS_STA(padapter)) {
3018 #ifdef CONFIG_LPS_CHK_BY_TP
3019 if (adapter_to_pwrctl(padapter)->lps_chk_by_tp)
3020 bEnterPS = _lps_chk_by_tp(padapter, from_timer);
3021 else
3022 #endif /*CONFIG_LPS_CHK_BY_TP*/
3023 bEnterPS = _lps_chk_by_pkt_cnts(padapter, from_timer, bBusyTraffic);
3024 }
3025 #endif /* CONFIG_LPS */
3026
3027 } else {
3028 #ifdef CONFIG_LPS
3029 if (!from_timer && rtw_mi_get_assoc_if_num(padapter) == 0)
3030 LPS_Leave(padapter, "NON_LINKED");
3031 #endif
3032 }
3033
3034 session_tracker_chk_cmd(padapter, NULL);
3035
3036 #ifdef CONFIG_BEAMFORMING
3037 #ifdef RTW_BEAMFORMING_VERSION_2
3038 rtw_bf_update_traffic(padapter);
3039 #endif /* RTW_BEAMFORMING_VERSION_2 */
3040 #endif /* CONFIG_BEAMFORMING */
3041
3042 pmlmepriv->LinkDetectInfo.NumRxOkInPeriod = 0;
3043 pmlmepriv->LinkDetectInfo.NumTxOkInPeriod = 0;
3044 pmlmepriv->LinkDetectInfo.NumRxUnicastOkInPeriod = 0;
3045 pmlmepriv->LinkDetectInfo.bBusyTraffic = bBusyTraffic;
3046 pmlmepriv->LinkDetectInfo.bTxBusyTraffic = bTxBusyTraffic;
3047 pmlmepriv->LinkDetectInfo.bRxBusyTraffic = bRxBusyTraffic;
3048 pmlmepriv->LinkDetectInfo.bHigherBusyTraffic = bHigherBusyTraffic;
3049 pmlmepriv->LinkDetectInfo.bHigherBusyRxTraffic = bHigherBusyRxTraffic;
3050 pmlmepriv->LinkDetectInfo.bHigherBusyTxTraffic = bHigherBusyTxTraffic;
3051
3052 return bEnterPS;
3053
3054 }
3055
3056 #ifdef CONFIG_AP_MODE
3057 /* for 11n Logo 4.2.31/4.2.32 */
dynamic_update_bcn_check(_adapter * padapter)3058 static void dynamic_update_bcn_check(_adapter *padapter)
3059 {
3060 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
3061 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
3062
3063 if (!padapter->registrypriv.wifi_spec)
3064 return;
3065
3066 if (!padapter->registrypriv.ht_enable || !is_supported_ht(padapter->registrypriv.wireless_mode))
3067 return;
3068
3069 if (!MLME_IS_AP(padapter))
3070 return;
3071
3072 if (pmlmeext->bstart_bss) {
3073 /* In 10 * 2 = 20s, there are no legacy AP, update HT info */
3074 static u8 count = 1;
3075
3076 if (count % 10 == 0) {
3077 count = 1;
3078 #ifdef CONFIG_80211N_HT
3079 if (_FALSE == ATOMIC_READ(&pmlmepriv->olbc)
3080 && _FALSE == ATOMIC_READ(&pmlmepriv->olbc_ht)) {
3081
3082 if (rtw_ht_operation_update(padapter) > 0) {
3083 update_beacon(padapter, _HT_CAPABILITY_IE_, NULL, _FALSE, 0);
3084 update_beacon(padapter, _HT_ADD_INFO_IE_, NULL, _TRUE, 0);
3085 }
3086 }
3087 #endif /* CONFIG_80211N_HT */
3088 }
3089
3090 #ifdef CONFIG_80211N_HT
3091 /* In 2s, there are any legacy AP, update HT info, and then reset count */
3092
3093 if (_FALSE != ATOMIC_READ(&pmlmepriv->olbc)
3094 && _FALSE != ATOMIC_READ(&pmlmepriv->olbc_ht)) {
3095
3096 if (rtw_ht_operation_update(padapter) > 0) {
3097 update_beacon(padapter, _HT_CAPABILITY_IE_, NULL, _FALSE, 0);
3098 update_beacon(padapter, _HT_ADD_INFO_IE_, NULL, _TRUE, 0);
3099
3100 }
3101 ATOMIC_SET(&pmlmepriv->olbc, _FALSE);
3102 ATOMIC_SET(&pmlmepriv->olbc_ht, _FALSE);
3103 count = 0;
3104 }
3105 #endif /* CONFIG_80211N_HT */
3106 count ++;
3107 }
3108 }
3109 #endif /* CONFIG_AP_MODE */
3110
rtw_iface_dynamic_chk_wk_hdl(_adapter * padapter)3111 void rtw_iface_dynamic_chk_wk_hdl(_adapter *padapter)
3112 {
3113 #ifdef CONFIG_AP_MODE
3114 #ifdef CONFIG_ACTIVE_KEEP_ALIVE_CHECK
3115 if (MLME_IS_AP(padapter) || MLME_IS_MESH(padapter)) {
3116 expire_timeout_chk(padapter);
3117 #ifdef CONFIG_RTW_MESH
3118 if (MLME_IS_MESH(padapter) && MLME_IS_ASOC(padapter))
3119 rtw_mesh_peer_status_chk(padapter);
3120 #endif
3121 }
3122 #endif /* CONFIG_ACTIVE_KEEP_ALIVE_CHECK */
3123
3124 dynamic_update_bcn_check(padapter);
3125
3126 #endif /* CONFIG_AP_MODE */
3127
3128 linked_status_chk(padapter, 0);
3129 traffic_status_watchdog(padapter, 0);
3130
3131 /* for debug purpose */
3132 _linked_info_dump(padapter);
3133
3134 #ifdef CONFIG_RTW_CFGVENDOR_RSSIMONITOR
3135 rtw_cfgvendor_rssi_monitor_evt(padapter);
3136 #endif
3137
3138
3139 }
rtw_dynamic_chk_wk_hdl(_adapter * padapter)3140 void rtw_dynamic_chk_wk_hdl(_adapter *padapter)
3141 {
3142 rtw_mi_dynamic_chk_wk_hdl(padapter);
3143 #ifdef CONFIG_MP_INCLUDED
3144 if (rtw_mp_mode_check(padapter) == _FALSE)
3145 #endif
3146 {
3147 #ifdef DBG_CONFIG_ERROR_DETECT
3148 rtw_hal_sreset_xmit_status_check(padapter);
3149 rtw_hal_sreset_linked_status_check(padapter);
3150 #endif
3151 }
3152
3153 /* if(check_fwstate(pmlmepriv, WIFI_UNDER_LINKING|WIFI_UNDER_SURVEY)==_FALSE) */
3154 {
3155 #ifdef DBG_RX_COUNTER_DUMP
3156 rtw_dump_rx_counters(padapter);
3157 #endif
3158 dm_DynamicUsbTxAgg(padapter, 0);
3159 }
3160 rtw_hal_dm_watchdog(padapter);
3161
3162 /* check_hw_pbc(padapter, pdrvextra_cmd->pbuf, pdrvextra_cmd->type); */
3163
3164 #ifdef CONFIG_BT_COEXIST
3165 /* BT-Coexist */
3166 rtw_btcoex_Handler(padapter);
3167 #endif
3168
3169 #ifdef CONFIG_RTW_MULTI_AP
3170 rtw_ch_util_rpt(padapter);
3171 #endif
3172
3173 #ifdef CONFIG_DFS_MASTER
3174 rtw_chset_chk_non_ocp_finish(adapter_to_rfctl(padapter));
3175 #endif
3176
3177 #ifdef CONFIG_IPS_CHECK_IN_WD
3178 /* always call rtw_ps_processor() at last one. */
3179 rtw_ps_processor(padapter);
3180 #endif
3181
3182 #ifdef CONFIG_MCC_MODE
3183 rtw_hal_mcc_sw_status_check(padapter);
3184 #endif /* CONFIG_MCC_MODE */
3185
3186 rtw_hal_periodic_tsf_update_chk(padapter);
3187 }
3188
3189 #ifdef CONFIG_LPS
3190 struct lps_ctrl_wk_parm {
3191 s8 lps_level;
3192 #ifdef CONFIG_LPS_1T1R
3193 s8 lps_1t1r;
3194 #endif
3195 };
3196
lps_ctrl_wk_hdl(_adapter * padapter,u8 lps_ctrl_type,u8 * buf)3197 void lps_ctrl_wk_hdl(_adapter *padapter, u8 lps_ctrl_type, u8 *buf)
3198 {
3199 struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(padapter);
3200 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
3201 struct lps_ctrl_wk_parm *parm = (struct lps_ctrl_wk_parm *)buf;
3202 u8 mstatus;
3203
3204 if ((check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) == _TRUE)
3205 || (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE) == _TRUE))
3206 return;
3207
3208 switch (lps_ctrl_type) {
3209 case LPS_CTRL_SCAN:
3210 /* RTW_INFO("LPS_CTRL_SCAN\n"); */
3211 #ifdef CONFIG_BT_COEXIST
3212 rtw_btcoex_ScanNotify(padapter, _TRUE);
3213 #endif /* CONFIG_BT_COEXIST */
3214 if (check_fwstate(pmlmepriv, WIFI_ASOC_STATE) == _TRUE) {
3215 /* connect */
3216 LPS_Leave(padapter, "LPS_CTRL_SCAN");
3217 }
3218 break;
3219 case LPS_CTRL_JOINBSS:
3220 /* RTW_INFO("LPS_CTRL_JOINBSS\n"); */
3221 LPS_Leave(padapter, "LPS_CTRL_JOINBSS");
3222 break;
3223 case LPS_CTRL_CONNECT:
3224 /* RTW_INFO("LPS_CTRL_CONNECT\n"); */
3225 mstatus = 1;/* connect */
3226 /* Reset LPS Setting */
3227 pwrpriv->LpsIdleCount = 0;
3228 rtw_hal_set_hwreg(padapter, HW_VAR_H2C_FW_JOINBSSRPT, (u8 *)(&mstatus));
3229 #ifdef CONFIG_BT_COEXIST
3230 rtw_btcoex_MediaStatusNotify(padapter, mstatus);
3231 #endif /* CONFIG_BT_COEXIST */
3232 break;
3233 case LPS_CTRL_DISCONNECT:
3234 /* RTW_INFO("LPS_CTRL_DISCONNECT\n"); */
3235 mstatus = 0;/* disconnect */
3236 #ifdef CONFIG_BT_COEXIST
3237 rtw_btcoex_MediaStatusNotify(padapter, mstatus);
3238 #endif /* CONFIG_BT_COEXIST */
3239 LPS_Leave(padapter, "LPS_CTRL_DISCONNECT");
3240 rtw_hal_set_hwreg(padapter, HW_VAR_H2C_FW_JOINBSSRPT, (u8 *)(&mstatus));
3241 break;
3242 case LPS_CTRL_SPECIAL_PACKET:
3243 /* RTW_INFO("LPS_CTRL_SPECIAL_PACKET\n"); */
3244 rtw_set_lps_deny(padapter, LPS_DELAY_MS);
3245 #ifdef CONFIG_BT_COEXIST
3246 rtw_btcoex_SpecialPacketNotify(padapter, PACKET_DHCP);
3247 #endif /* CONFIG_BT_COEXIST */
3248 LPS_Leave(padapter, "LPS_CTRL_SPECIAL_PACKET");
3249 break;
3250 case LPS_CTRL_LEAVE:
3251 LPS_Leave(padapter, "LPS_CTRL_LEAVE");
3252 break;
3253 case LPS_CTRL_LEAVE_SET_OPTION:
3254 LPS_Leave(padapter, "LPS_CTRL_LEAVE_SET_OPTION");
3255 if (parm) {
3256 if (parm->lps_level >= 0)
3257 pwrpriv->lps_level = parm->lps_level;
3258 #ifdef CONFIG_LPS_1T1R
3259 if (parm->lps_1t1r >= 0)
3260 pwrpriv->lps_1t1r = parm->lps_1t1r;
3261 #endif
3262 }
3263 break;
3264 case LPS_CTRL_LEAVE_CFG80211_PWRMGMT:
3265 LPS_Leave(padapter, "CFG80211_PWRMGMT");
3266 break;
3267 case LPS_CTRL_TRAFFIC_BUSY:
3268 LPS_Leave(padapter, "LPS_CTRL_TRAFFIC_BUSY");
3269 break;
3270 case LPS_CTRL_TX_TRAFFIC_LEAVE:
3271 LPS_Leave(padapter, "LPS_CTRL_TX_TRAFFIC_LEAVE");
3272 break;
3273 case LPS_CTRL_RX_TRAFFIC_LEAVE:
3274 LPS_Leave(padapter, "LPS_CTRL_RX_TRAFFIC_LEAVE");
3275 break;
3276 case LPS_CTRL_ENTER:
3277 LPS_Enter(padapter, "TRAFFIC_IDLE_1");
3278 break;
3279 default:
3280 break;
3281 }
3282
3283 }
3284
_rtw_lps_ctrl_wk_cmd(_adapter * adapter,u8 lps_ctrl_type,s8 lps_level,s8 lps_1t1r,u8 flags)3285 static u8 _rtw_lps_ctrl_wk_cmd(_adapter *adapter, u8 lps_ctrl_type, s8 lps_level, s8 lps_1t1r, u8 flags)
3286 {
3287 struct cmd_obj *cmdobj;
3288 struct drvextra_cmd_parm *parm;
3289 struct lps_ctrl_wk_parm *wk_parm = NULL;
3290 struct cmd_priv *pcmdpriv = &adapter->cmdpriv;
3291 struct submit_ctx sctx;
3292 u8 res = _SUCCESS;
3293
3294 if (lps_ctrl_type == LPS_CTRL_LEAVE_SET_OPTION) {
3295 wk_parm = rtw_zmalloc(sizeof(*wk_parm));
3296 if (wk_parm == NULL) {
3297 res = _FAIL;
3298 goto exit;
3299 }
3300 wk_parm->lps_level = lps_level;
3301 #ifdef CONFIG_LPS_1T1R
3302 wk_parm->lps_1t1r = lps_1t1r;
3303 #endif
3304 }
3305
3306 if (flags & RTW_CMDF_DIRECTLY) {
3307 /* no need to enqueue, do the cmd hdl directly */
3308 lps_ctrl_wk_hdl(adapter, lps_ctrl_type, (u8 *)wk_parm);
3309 if (wk_parm)
3310 rtw_mfree(wk_parm, sizeof(*wk_parm));
3311 } else {
3312 /* need enqueue, prepare cmd_obj and enqueue */
3313 parm = rtw_zmalloc(sizeof(*parm));
3314 if (parm == NULL) {
3315 if (wk_parm)
3316 rtw_mfree(wk_parm, sizeof(*wk_parm));
3317 res = _FAIL;
3318 goto exit;
3319 }
3320
3321 parm->ec_id = LPS_CTRL_WK_CID;
3322 parm->type = lps_ctrl_type;
3323 parm->size = wk_parm ? sizeof(*wk_parm) : 0;
3324 parm->pbuf = (u8 *)wk_parm;
3325
3326 cmdobj = rtw_zmalloc(sizeof(*cmdobj));
3327 if (cmdobj == NULL) {
3328 rtw_mfree(parm, sizeof(*parm));
3329 if (wk_parm)
3330 rtw_mfree(wk_parm, sizeof(*wk_parm));
3331 res = _FAIL;
3332 goto exit;
3333 }
3334
3335 init_h2fwcmd_w_parm_no_rsp(cmdobj, parm, CMD_SET_DRV_EXTRA);
3336
3337 if (flags & RTW_CMDF_WAIT_ACK) {
3338 cmdobj->sctx = &sctx;
3339 rtw_sctx_init(&sctx, 2000);
3340 }
3341
3342 res = rtw_enqueue_cmd(pcmdpriv, cmdobj);
3343
3344 if (res == _SUCCESS && (flags & RTW_CMDF_WAIT_ACK)) {
3345 rtw_sctx_wait(&sctx, __func__);
3346 _enter_critical_mutex(&pcmdpriv->sctx_mutex, NULL);
3347 if (sctx.status == RTW_SCTX_SUBMITTED)
3348 cmdobj->sctx = NULL;
3349 _exit_critical_mutex(&pcmdpriv->sctx_mutex, NULL);
3350 if (sctx.status != RTW_SCTX_DONE_SUCCESS)
3351 res = _FAIL;
3352 }
3353 }
3354
3355 exit:
3356 return res;
3357 }
3358
rtw_lps_ctrl_wk_cmd(_adapter * adapter,u8 lps_ctrl_type,u8 flags)3359 u8 rtw_lps_ctrl_wk_cmd(_adapter *adapter, u8 lps_ctrl_type, u8 flags)
3360 {
3361 return _rtw_lps_ctrl_wk_cmd(adapter, lps_ctrl_type, -1, -1, flags);
3362 }
3363
rtw_lps_ctrl_leave_set_level_cmd(_adapter * adapter,u8 lps_level,u8 flags)3364 u8 rtw_lps_ctrl_leave_set_level_cmd(_adapter *adapter, u8 lps_level, u8 flags)
3365 {
3366 return _rtw_lps_ctrl_wk_cmd(adapter, LPS_CTRL_LEAVE_SET_OPTION, lps_level, -1, flags);
3367 }
3368
3369 #ifdef CONFIG_LPS_1T1R
rtw_lps_ctrl_leave_set_1t1r_cmd(_adapter * adapter,u8 lps_1t1r,u8 flags)3370 u8 rtw_lps_ctrl_leave_set_1t1r_cmd(_adapter *adapter, u8 lps_1t1r, u8 flags)
3371 {
3372 return _rtw_lps_ctrl_wk_cmd(adapter, LPS_CTRL_LEAVE_SET_OPTION, -1, lps_1t1r, flags);
3373 }
3374 #endif
3375
rtw_dm_in_lps_hdl(_adapter * padapter)3376 void rtw_dm_in_lps_hdl(_adapter *padapter)
3377 {
3378 rtw_hal_set_hwreg(padapter, HW_VAR_DM_IN_LPS_LCLK, NULL);
3379 }
3380
rtw_dm_in_lps_wk_cmd(_adapter * padapter)3381 u8 rtw_dm_in_lps_wk_cmd(_adapter *padapter)
3382 {
3383 struct cmd_obj *ph2c;
3384 struct drvextra_cmd_parm *pdrvextra_cmd_parm;
3385 struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
3386 u8 res = _SUCCESS;
3387
3388
3389 ph2c = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
3390 if (ph2c == NULL) {
3391 res = _FAIL;
3392 goto exit;
3393 }
3394
3395 pdrvextra_cmd_parm = (struct drvextra_cmd_parm *)rtw_zmalloc(sizeof(struct drvextra_cmd_parm));
3396 if (pdrvextra_cmd_parm == NULL) {
3397 rtw_mfree((unsigned char *)ph2c, sizeof(struct cmd_obj));
3398 res = _FAIL;
3399 goto exit;
3400 }
3401
3402 pdrvextra_cmd_parm->ec_id = DM_IN_LPS_WK_CID;
3403 pdrvextra_cmd_parm->type = 0;
3404 pdrvextra_cmd_parm->size = 0;
3405 pdrvextra_cmd_parm->pbuf = NULL;
3406
3407 init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, CMD_SET_DRV_EXTRA);
3408
3409 res = rtw_enqueue_cmd(pcmdpriv, ph2c);
3410
3411 exit:
3412
3413 return res;
3414
3415 }
3416
rtw_lps_change_dtim_hdl(_adapter * padapter,u8 dtim)3417 void rtw_lps_change_dtim_hdl(_adapter *padapter, u8 dtim)
3418 {
3419 struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(padapter);
3420
3421 if (dtim <= 0 || dtim > 16)
3422 return;
3423
3424 #ifdef CONFIG_BT_COEXIST
3425 if (rtw_btcoex_IsBtControlLps(padapter) == _TRUE)
3426 return;
3427 #endif
3428
3429 #ifdef CONFIG_LPS_LCLK
3430 _enter_pwrlock(&pwrpriv->lock);
3431 #endif
3432
3433 if (pwrpriv->dtim != dtim) {
3434 RTW_INFO("change DTIM from %d to %d, bFwCurrentInPSMode=%d, ps_mode=%d\n", pwrpriv->dtim, dtim,
3435 pwrpriv->bFwCurrentInPSMode, pwrpriv->pwr_mode);
3436
3437 pwrpriv->dtim = dtim;
3438 }
3439
3440 if ((pwrpriv->bFwCurrentInPSMode == _TRUE) && (pwrpriv->pwr_mode > PS_MODE_ACTIVE)) {
3441 u8 ps_mode = pwrpriv->pwr_mode;
3442
3443 /* RTW_INFO("change DTIM from %d to %d, ps_mode=%d\n", pwrpriv->dtim, dtim, ps_mode); */
3444
3445 rtw_exec_lps(padapter, ps_mode);
3446 }
3447
3448 #ifdef CONFIG_LPS_LCLK
3449 _exit_pwrlock(&pwrpriv->lock);
3450 #endif
3451
3452 }
3453
3454 #endif
3455
rtw_lps_change_dtim_cmd(_adapter * padapter,u8 dtim)3456 u8 rtw_lps_change_dtim_cmd(_adapter *padapter, u8 dtim)
3457 {
3458 struct cmd_obj *ph2c;
3459 struct drvextra_cmd_parm *pdrvextra_cmd_parm;
3460 struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
3461 u8 res = _SUCCESS;
3462 /*
3463 #ifdef CONFIG_CONCURRENT_MODE
3464 if (padapter->hw_port != HW_PORT0)
3465 return res;
3466 #endif
3467 */
3468 {
3469 ph2c = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
3470 if (ph2c == NULL) {
3471 res = _FAIL;
3472 goto exit;
3473 }
3474
3475 pdrvextra_cmd_parm = (struct drvextra_cmd_parm *)rtw_zmalloc(sizeof(struct drvextra_cmd_parm));
3476 if (pdrvextra_cmd_parm == NULL) {
3477 rtw_mfree((unsigned char *)ph2c, sizeof(struct cmd_obj));
3478 res = _FAIL;
3479 goto exit;
3480 }
3481
3482 pdrvextra_cmd_parm->ec_id = LPS_CHANGE_DTIM_CID;
3483 pdrvextra_cmd_parm->type = dtim;
3484 pdrvextra_cmd_parm->size = 0;
3485 pdrvextra_cmd_parm->pbuf = NULL;
3486
3487 init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, CMD_SET_DRV_EXTRA);
3488
3489 res = rtw_enqueue_cmd(pcmdpriv, ph2c);
3490 }
3491
3492 exit:
3493
3494 return res;
3495
3496 }
3497
3498 #if (RATE_ADAPTIVE_SUPPORT == 1)
rpt_timer_setting_wk_hdl(_adapter * padapter,u16 minRptTime)3499 void rpt_timer_setting_wk_hdl(_adapter *padapter, u16 minRptTime)
3500 {
3501 rtw_hal_set_hwreg(padapter, HW_VAR_RPT_TIMER_SETTING, (u8 *)(&minRptTime));
3502 }
3503
rtw_rpt_timer_cfg_cmd(_adapter * padapter,u16 minRptTime)3504 u8 rtw_rpt_timer_cfg_cmd(_adapter *padapter, u16 minRptTime)
3505 {
3506 struct cmd_obj *ph2c;
3507 struct drvextra_cmd_parm *pdrvextra_cmd_parm;
3508 struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
3509
3510 u8 res = _SUCCESS;
3511
3512 ph2c = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
3513 if (ph2c == NULL) {
3514 res = _FAIL;
3515 goto exit;
3516 }
3517
3518 pdrvextra_cmd_parm = (struct drvextra_cmd_parm *)rtw_zmalloc(sizeof(struct drvextra_cmd_parm));
3519 if (pdrvextra_cmd_parm == NULL) {
3520 rtw_mfree((unsigned char *)ph2c, sizeof(struct cmd_obj));
3521 res = _FAIL;
3522 goto exit;
3523 }
3524
3525 pdrvextra_cmd_parm->ec_id = RTP_TIMER_CFG_WK_CID;
3526 pdrvextra_cmd_parm->type = minRptTime;
3527 pdrvextra_cmd_parm->size = 0;
3528 pdrvextra_cmd_parm->pbuf = NULL;
3529 init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, CMD_SET_DRV_EXTRA);
3530 res = rtw_enqueue_cmd(pcmdpriv, ph2c);
3531 exit:
3532
3533
3534 return res;
3535
3536 }
3537
3538 #endif
3539
3540 #ifdef CONFIG_ANTENNA_DIVERSITY
antenna_select_wk_hdl(_adapter * padapter,u8 antenna)3541 void antenna_select_wk_hdl(_adapter *padapter, u8 antenna)
3542 {
3543 rtw_hal_set_odm_var(padapter, HAL_ODM_ANTDIV_SELECT, &antenna, _TRUE);
3544 }
3545
rtw_antenna_select_cmd(_adapter * padapter,u8 antenna,u8 enqueue)3546 u8 rtw_antenna_select_cmd(_adapter *padapter, u8 antenna, u8 enqueue)
3547 {
3548 struct cmd_obj *ph2c;
3549 struct drvextra_cmd_parm *pdrvextra_cmd_parm;
3550 struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
3551 struct dvobj_priv *dvobj = adapter_to_dvobj(padapter);
3552 u8 bSupportAntDiv = _FALSE;
3553 u8 res = _SUCCESS;
3554 int i;
3555
3556 rtw_hal_get_def_var(padapter, HAL_DEF_IS_SUPPORT_ANT_DIV, &(bSupportAntDiv));
3557 if (_FALSE == bSupportAntDiv)
3558 return _FAIL;
3559
3560 for (i = 0; i < dvobj->iface_nums; i++) {
3561 if (rtw_linked_check(dvobj->padapters[i]))
3562 return _FAIL;
3563 }
3564
3565 if (_TRUE == enqueue) {
3566 ph2c = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
3567 if (ph2c == NULL) {
3568 res = _FAIL;
3569 goto exit;
3570 }
3571
3572 pdrvextra_cmd_parm = (struct drvextra_cmd_parm *)rtw_zmalloc(sizeof(struct drvextra_cmd_parm));
3573 if (pdrvextra_cmd_parm == NULL) {
3574 rtw_mfree((unsigned char *)ph2c, sizeof(struct cmd_obj));
3575 res = _FAIL;
3576 goto exit;
3577 }
3578
3579 pdrvextra_cmd_parm->ec_id = ANT_SELECT_WK_CID;
3580 pdrvextra_cmd_parm->type = antenna;
3581 pdrvextra_cmd_parm->size = 0;
3582 pdrvextra_cmd_parm->pbuf = NULL;
3583 init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, CMD_SET_DRV_EXTRA);
3584
3585 res = rtw_enqueue_cmd(pcmdpriv, ph2c);
3586 } else
3587 antenna_select_wk_hdl(padapter, antenna);
3588 exit:
3589
3590
3591 return res;
3592
3593 }
3594 #endif
3595
rtw_dm_ra_mask_hdl(_adapter * padapter,struct sta_info * psta)3596 void rtw_dm_ra_mask_hdl(_adapter *padapter, struct sta_info *psta)
3597 {
3598 if (psta)
3599 set_sta_rate(padapter, psta);
3600 }
3601
rtw_dm_ra_mask_wk_cmd(_adapter * padapter,u8 * psta)3602 u8 rtw_dm_ra_mask_wk_cmd(_adapter *padapter, u8 *psta)
3603 {
3604 struct cmd_obj *ph2c;
3605 struct drvextra_cmd_parm *pdrvextra_cmd_parm;
3606 struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
3607 u8 res = _SUCCESS;
3608
3609
3610 ph2c = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
3611 if (ph2c == NULL) {
3612 res = _FAIL;
3613 goto exit;
3614 }
3615
3616 pdrvextra_cmd_parm = (struct drvextra_cmd_parm *)rtw_zmalloc(sizeof(struct drvextra_cmd_parm));
3617 if (pdrvextra_cmd_parm == NULL) {
3618 rtw_mfree((unsigned char *)ph2c, sizeof(struct cmd_obj));
3619 res = _FAIL;
3620 goto exit;
3621 }
3622
3623 pdrvextra_cmd_parm->ec_id = DM_RA_MSK_WK_CID;
3624 pdrvextra_cmd_parm->type = 0;
3625 pdrvextra_cmd_parm->size = 0;
3626 pdrvextra_cmd_parm->pbuf = psta;
3627
3628 init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, CMD_SET_DRV_EXTRA);
3629
3630 res = rtw_enqueue_cmd(pcmdpriv, ph2c);
3631
3632 exit:
3633
3634 return res;
3635
3636 }
3637
power_saving_wk_hdl(_adapter * padapter)3638 void power_saving_wk_hdl(_adapter *padapter)
3639 {
3640 rtw_ps_processor(padapter);
3641 }
3642
3643 /* add for CONFIG_IEEE80211W, none 11w can use it */
reset_securitypriv_hdl(_adapter * padapter)3644 void reset_securitypriv_hdl(_adapter *padapter)
3645 {
3646 rtw_reset_securitypriv(padapter);
3647 }
3648
3649 #ifdef CONFIG_P2P
p2p_protocol_wk_cmd(_adapter * padapter,int intCmdType)3650 u8 p2p_protocol_wk_cmd(_adapter *padapter, int intCmdType)
3651 {
3652 struct cmd_obj *ph2c;
3653 struct drvextra_cmd_parm *pdrvextra_cmd_parm;
3654 struct wifidirect_info *pwdinfo = &(padapter->wdinfo);
3655 struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
3656 u8 res = _SUCCESS;
3657
3658
3659 if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE))
3660 return res;
3661
3662 ph2c = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
3663 if (ph2c == NULL) {
3664 res = _FAIL;
3665 goto exit;
3666 }
3667
3668 pdrvextra_cmd_parm = (struct drvextra_cmd_parm *)rtw_zmalloc(sizeof(struct drvextra_cmd_parm));
3669 if (pdrvextra_cmd_parm == NULL) {
3670 rtw_mfree((unsigned char *)ph2c, sizeof(struct cmd_obj));
3671 res = _FAIL;
3672 goto exit;
3673 }
3674
3675 pdrvextra_cmd_parm->ec_id = P2P_PROTO_WK_CID;
3676 pdrvextra_cmd_parm->type = intCmdType; /* As the command tppe. */
3677 pdrvextra_cmd_parm->size = 0;
3678 pdrvextra_cmd_parm->pbuf = NULL; /* Must be NULL here */
3679
3680 init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, CMD_SET_DRV_EXTRA);
3681
3682 res = rtw_enqueue_cmd(pcmdpriv, ph2c);
3683
3684 exit:
3685
3686
3687 return res;
3688
3689 }
3690 #endif /* CONFIG_P2P */
3691
3692 #ifdef CONFIG_IOCTL_CFG80211
rtw_alloc_roch_parm(_adapter * adapter,u64 cookie,struct wireless_dev * wdev,struct ieee80211_channel * ch,enum nl80211_channel_type ch_type,unsigned int duration,u8 flags)3693 static struct rtw_roch_parm *rtw_alloc_roch_parm(_adapter *adapter
3694 , u64 cookie, struct wireless_dev *wdev
3695 , struct ieee80211_channel *ch, enum nl80211_channel_type ch_type
3696 , unsigned int duration
3697 , u8 flags
3698 )
3699 {
3700 struct rtw_roch_parm *roch_parm;
3701 bool cancel = duration ? 0 : 1;
3702
3703 roch_parm = (struct rtw_roch_parm *)rtw_zmalloc(sizeof(struct rtw_roch_parm));
3704 if (!roch_parm)
3705 return NULL;
3706
3707 roch_parm->cookie = cookie;
3708 roch_parm->wdev = wdev;
3709 if (!cancel) {
3710 _rtw_memcpy(&roch_parm->ch, ch, sizeof(struct ieee80211_channel));
3711 roch_parm->ch_type = ch_type;
3712 roch_parm->duration = duration;
3713 }
3714
3715 return roch_parm;
3716 }
3717
rtw_roch_cmd(_adapter * adapter,u64 cookie,struct wireless_dev * wdev,struct ieee80211_channel * ch,enum nl80211_channel_type ch_type,unsigned int duration,u8 flags)3718 inline u8 rtw_roch_cmd(_adapter *adapter
3719 , u64 cookie, struct wireless_dev *wdev
3720 , struct ieee80211_channel *ch, enum nl80211_channel_type ch_type
3721 , unsigned int duration
3722 , u8 flags
3723 )
3724 {
3725 struct rtw_roch_parm *roch_parm;
3726
3727 roch_parm = rtw_alloc_roch_parm(adapter, cookie, wdev, ch, ch_type, duration, flags);
3728 if (!roch_parm)
3729 return _FAIL;
3730
3731 return rtw_roch_wk_cmd(adapter, ROCH_RO_CH_WK, roch_parm, flags);
3732 }
3733
rtw_cancel_roch_cmd(_adapter * adapter,u64 cookie,struct wireless_dev * wdev,u8 flags)3734 inline u8 rtw_cancel_roch_cmd(_adapter *adapter, u64 cookie, struct wireless_dev *wdev, u8 flags)
3735 {
3736 struct rtw_roch_parm *roch_parm;
3737
3738 roch_parm = rtw_alloc_roch_parm(adapter, cookie, wdev, NULL, 0, 0, flags);
3739 if (!roch_parm)
3740 return _FAIL;
3741
3742 return rtw_roch_wk_cmd(adapter, ROCH_CANCEL_RO_CH_WK, roch_parm, flags);
3743 }
3744
rtw_mgnt_tx_cmd(_adapter * adapter,u8 tx_ch,u8 no_cck,const u8 * buf,size_t len,int wait_ack,u8 flags)3745 inline u8 rtw_mgnt_tx_cmd(_adapter *adapter, u8 tx_ch, u8 no_cck, const u8 *buf, size_t len, int wait_ack, u8 flags)
3746 {
3747 struct cmd_obj *cmdobj;
3748 struct drvextra_cmd_parm *parm;
3749 struct mgnt_tx_parm *mgnt_parm;
3750 struct cmd_priv *pcmdpriv = &adapter->cmdpriv;
3751 struct submit_ctx sctx;
3752 u8 res = _SUCCESS;
3753
3754 mgnt_parm = (struct mgnt_tx_parm *)rtw_zmalloc(sizeof(struct mgnt_tx_parm));
3755 if (mgnt_parm == NULL) {
3756 res = _FAIL;
3757 goto exit;
3758 }
3759
3760 mgnt_parm->tx_ch = tx_ch;
3761 mgnt_parm->no_cck = no_cck;
3762 mgnt_parm->buf = buf;
3763 mgnt_parm->len = len;
3764 mgnt_parm->wait_ack = wait_ack;
3765
3766 if (flags & RTW_CMDF_DIRECTLY) {
3767 /* no need to enqueue, do the cmd hdl directly and free cmd parameter */
3768 if (H2C_SUCCESS != rtw_mgnt_tx_handler(adapter, (u8 *)mgnt_parm))
3769 res = _FAIL;
3770 rtw_mfree((u8 *)mgnt_parm, sizeof(*mgnt_parm));
3771 } else {
3772 /* need enqueue, prepare cmd_obj and enqueue */
3773 parm = (struct drvextra_cmd_parm *)rtw_zmalloc(sizeof(struct drvextra_cmd_parm));
3774 if (parm == NULL) {
3775 rtw_mfree((u8 *)mgnt_parm, sizeof(*mgnt_parm));
3776 res = _FAIL;
3777 goto exit;
3778 }
3779
3780 parm->ec_id = MGNT_TX_WK_CID;
3781 parm->type = 0;
3782 parm->size = sizeof(*mgnt_parm);
3783 parm->pbuf = (u8 *)mgnt_parm;
3784
3785 cmdobj = (struct cmd_obj *)rtw_zmalloc(sizeof(*cmdobj));
3786 if (cmdobj == NULL) {
3787 res = _FAIL;
3788 rtw_mfree((u8 *)mgnt_parm, sizeof(*mgnt_parm));
3789 rtw_mfree((u8 *)parm, sizeof(*parm));
3790 goto exit;
3791 }
3792
3793 init_h2fwcmd_w_parm_no_rsp(cmdobj, parm, CMD_SET_DRV_EXTRA);
3794
3795 if (flags & RTW_CMDF_WAIT_ACK) {
3796 cmdobj->sctx = &sctx;
3797 rtw_sctx_init(&sctx, 10 * 1000);
3798 }
3799
3800 res = rtw_enqueue_cmd(pcmdpriv, cmdobj);
3801
3802 if (res == _SUCCESS && (flags & RTW_CMDF_WAIT_ACK)) {
3803 rtw_sctx_wait(&sctx, __func__);
3804 _enter_critical_mutex(&pcmdpriv->sctx_mutex, NULL);
3805 if (sctx.status == RTW_SCTX_SUBMITTED)
3806 cmdobj->sctx = NULL;
3807 _exit_critical_mutex(&pcmdpriv->sctx_mutex, NULL);
3808 if (sctx.status != RTW_SCTX_DONE_SUCCESS)
3809 res = _FAIL;
3810 }
3811 }
3812
3813 exit:
3814 return res;
3815 }
3816 #endif
3817
rtw_ps_cmd(_adapter * padapter)3818 u8 rtw_ps_cmd(_adapter *padapter)
3819 {
3820 struct cmd_obj *ppscmd;
3821 struct drvextra_cmd_parm *pdrvextra_cmd_parm;
3822 struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
3823
3824 u8 res = _SUCCESS;
3825
3826 #ifdef CONFIG_CONCURRENT_MODE
3827 if (!is_primary_adapter(padapter))
3828 goto exit;
3829 #endif
3830
3831 ppscmd = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
3832 if (ppscmd == NULL) {
3833 res = _FAIL;
3834 goto exit;
3835 }
3836
3837 pdrvextra_cmd_parm = (struct drvextra_cmd_parm *)rtw_zmalloc(sizeof(struct drvextra_cmd_parm));
3838 if (pdrvextra_cmd_parm == NULL) {
3839 rtw_mfree((unsigned char *)ppscmd, sizeof(struct cmd_obj));
3840 res = _FAIL;
3841 goto exit;
3842 }
3843
3844 pdrvextra_cmd_parm->ec_id = POWER_SAVING_CTRL_WK_CID;
3845 pdrvextra_cmd_parm->type = 0;
3846 pdrvextra_cmd_parm->size = 0;
3847 pdrvextra_cmd_parm->pbuf = NULL;
3848 init_h2fwcmd_w_parm_no_rsp(ppscmd, pdrvextra_cmd_parm, CMD_SET_DRV_EXTRA);
3849
3850 res = rtw_enqueue_cmd(pcmdpriv, ppscmd);
3851
3852 exit:
3853
3854
3855 return res;
3856
3857 }
3858
3859 #if CONFIG_DFS
rtw_dfs_ch_switch_hdl(struct dvobj_priv * dvobj)3860 void rtw_dfs_ch_switch_hdl(struct dvobj_priv *dvobj)
3861 {
3862 struct rf_ctl_t *rfctl = dvobj_to_rfctl(dvobj);
3863 _adapter *pri_adapter = dvobj_get_primary_adapter(dvobj);
3864 struct mlme_ext_priv *pmlmeext = &pri_adapter->mlmeextpriv;
3865 u8 ifbmp_m = rtw_mi_get_ap_mesh_ifbmp(pri_adapter);
3866 u8 ifbmp_s = rtw_mi_get_ld_sta_ifbmp(pri_adapter);
3867 s16 req_ch;
3868 u8 req_bw = CHANNEL_WIDTH_20, req_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE, csa_timer = _FALSE;
3869 u8 need_discon = _FALSE;
3870
3871 rtw_hal_macid_sleep_all_used(pri_adapter);
3872
3873 if (rtw_chset_search_ch(rfctl->channel_set, rfctl->csa_ch) >= 0
3874 && !rtw_chset_is_ch_non_ocp(rfctl->channel_set, rfctl->csa_ch)
3875 ) {
3876 /* CSA channel available and valid */
3877 req_ch = rfctl->csa_ch;
3878 RTW_INFO("%s valid CSA ch%u\n", __func__, rfctl->csa_ch);
3879 csa_timer = _TRUE;
3880 } else if (ifbmp_m) {
3881 /* no available or valid CSA channel, having AP/MESH ifaces */
3882 req_ch = REQ_CH_NONE;
3883 need_discon = _TRUE;
3884 RTW_INFO("%s ch sel by AP/MESH ifaces\n", __func__);
3885 } else {
3886 /* no available or valid CSA channel and no AP/MESH ifaces */
3887 if (!IsSupported24G(dvobj_to_regsty(dvobj)->wireless_mode)
3888 #ifdef CONFIG_DFS_MASTER
3889 || rfctl->radar_detected
3890 #endif
3891 )
3892 req_ch = 36;
3893 else
3894 req_ch = 1;
3895 need_discon = _TRUE;
3896 RTW_INFO("%s switch to ch%d, then disconnect with AP\n", __func__, req_ch);
3897 }
3898
3899 if (!need_discon) {
3900 /* fault tolerant for AP */
3901 if(rfctl->csa_ch_width == 1 || rfctl->csa_ch_width == 2 || rfctl->csa_ch_width == 3) {
3902 if (rtw_get_offset_by_chbw(req_ch, CHANNEL_WIDTH_80, &req_offset)) {
3903 /* always use 80 Mhz to connect if ch/bw/offset is valid */
3904 req_bw = CHANNEL_WIDTH_80;
3905 } else {
3906 req_bw = CHANNEL_WIDTH_20;
3907 req_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
3908 }
3909 } else if(rfctl->csa_ch_offset == 1) {
3910 req_bw = CHANNEL_WIDTH_40;
3911 req_offset = HAL_PRIME_CHNL_OFFSET_LOWER;
3912 } else if(rfctl->csa_ch_offset == 3) {
3913 req_bw = CHANNEL_WIDTH_40;
3914 req_offset = HAL_PRIME_CHNL_OFFSET_UPPER;
3915 } else{
3916 req_bw = CHANNEL_WIDTH_20;
3917 req_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
3918 }
3919 }
3920
3921 RTW_INFO("req_ch=%d, req_bw=%d, req_offset=%d, ifbmp_m=0x%02x, ifbmp_s=0x%02x\n"
3922 , req_ch, req_bw, req_offset, ifbmp_m, ifbmp_s);
3923
3924 /* check all STA ifaces status */
3925 if (ifbmp_s) {
3926 _adapter *iface;
3927 int i;
3928
3929 for (i = 0; i < dvobj->iface_nums; i++) {
3930 iface = dvobj->padapters[i];
3931 if (!iface || !(ifbmp_s & BIT(iface->iface_id)))
3932 continue;
3933
3934 if (need_discon) {
3935 /* CSA channel not available or not valid, then disconnect */
3936 set_fwstate(&iface->mlmepriv, WIFI_OP_CH_SWITCHING);
3937 issue_deauth(iface, get_bssid(&iface->mlmepriv), WLAN_REASON_DEAUTH_LEAVING);
3938 } else {
3939 /* update STA mode ch/bw/offset */
3940 iface->mlmeextpriv.cur_channel = req_ch;
3941 iface->mlmeextpriv.cur_bwmode = req_bw;
3942 iface->mlmeextpriv.cur_ch_offset = req_offset;
3943 /* updaet STA mode DSConfig , ap mode will update in rtw_change_bss_chbw_cmd */
3944 iface->mlmepriv.cur_network.network.Configuration.DSConfig = req_ch;
3945 set_fwstate(&iface->mlmepriv, WIFI_CSA_UPDATE_BEACON);
3946
3947 #ifdef CONFIG_80211D
3948 if (iface->mlmepriv.recv_country_ie) {
3949 if (rtw_apply_recv_country_ie_cmd(iface, RTW_CMDF_DIRECTLY
3950 , req_ch > 14 ? BAND_ON_5G : BAND_ON_2_4G, req_ch
3951 , iface->mlmepriv.recv_country_ie) != _SUCCESS
3952 )
3953 RTW_WARN(FUNC_ADPT_FMT" rtw_apply_recv_country_ie_cmd() fail\n", FUNC_ADPT_ARG(iface));
3954 }
3955 #endif
3956 }
3957 }
3958 }
3959
3960 if (csa_timer) {
3961 RTW_INFO("pmlmeext->csa_timer 70 seconds\n");
3962 /* wait 70 seconds for receiving beacons */
3963 _set_timer(&pmlmeext->csa_timer, CAC_TIME_MS + 10000);
3964 }
3965
3966 #ifdef CONFIG_AP_MODE
3967 if (ifbmp_m) {
3968 u8 execlude = 0;
3969
3970 if (need_discon)
3971 execlude = ifbmp_s;
3972 /* trigger channel selection with consideraton of asoc STA ifaces */
3973 rtw_change_bss_chbw_cmd(dvobj_get_primary_adapter(dvobj), RTW_CMDF_DIRECTLY
3974 , ifbmp_m, execlude, req_ch, REQ_BW_ORI, REQ_OFFSET_NONE);
3975 } else
3976 #endif
3977 {
3978 /* no AP/MESH iface, switch DFS status and channel directly */
3979 rtw_warn_on(req_ch <= 0);
3980 #ifdef CONFIG_DFS_MASTER
3981 if (need_discon)
3982 rtw_dfs_rd_en_decision(pri_adapter, MLME_OPCH_SWITCH, ifbmp_s);
3983 else
3984 rtw_dfs_rd_en_decision(pri_adapter, MLME_OPCH_SWITCH, 0);
3985 #endif
3986 LeaveAllPowerSaveModeDirect(pri_adapter);
3987 set_channel_bwmode(pri_adapter, req_ch, req_offset, req_bw);
3988 /* update union ch/bw/offset for STA only */
3989 rtw_mi_update_union_chan_inf(pri_adapter, req_ch, req_offset, req_bw);
3990 rtw_rfctl_update_op_mode(rfctl, 0, 0);
3991 }
3992
3993 /* make asoc STA ifaces disconnect */
3994 if (ifbmp_s && need_discon) {
3995 _adapter *iface;
3996 int i;
3997
3998 for (i = 0; i < dvobj->iface_nums; i++) {
3999 iface = dvobj->padapters[i];
4000 if (!iface || !(ifbmp_s & BIT(iface->iface_id)))
4001 continue;
4002 rtw_disassoc_cmd(iface, 0, RTW_CMDF_DIRECTLY);
4003 rtw_indicate_disconnect(iface, 0, _FALSE);
4004 rtw_free_assoc_resources(iface, _TRUE);
4005 rtw_free_network_queue(iface, _TRUE);
4006 }
4007 }
4008
4009 rfctl->csa_ch = 0;
4010 rfctl->csa_switch_cnt = 0;
4011 rfctl->csa_ch_offset = 0;
4012 rfctl->csa_ch_width = 0;
4013 rfctl->csa_ch_freq_seg0 = 0;
4014 rfctl->csa_ch_freq_seg1 = 0;
4015
4016 rtw_hal_macid_wakeup_all_used(pri_adapter);
4017 rtw_mi_os_xmit_schedule(pri_adapter);
4018 }
4019 #endif /* CONFIG_DFS */
4020
4021 #ifdef CONFIG_AP_MODE
4022
rtw_chk_hi_queue_hdl(_adapter * padapter)4023 static void rtw_chk_hi_queue_hdl(_adapter *padapter)
4024 {
4025 struct sta_info *psta_bmc;
4026 struct sta_priv *pstapriv = &padapter->stapriv;
4027 systime start = rtw_get_current_time();
4028 u8 empty = _FALSE;
4029
4030 psta_bmc = rtw_get_bcmc_stainfo(padapter);
4031 if (!psta_bmc)
4032 return;
4033
4034 rtw_hal_get_hwreg(padapter, HW_VAR_CHK_HI_QUEUE_EMPTY, &empty);
4035
4036 while (_FALSE == empty && rtw_get_passing_time_ms(start) < rtw_get_wait_hiq_empty_ms()) {
4037 rtw_msleep_os(100);
4038 rtw_hal_get_hwreg(padapter, HW_VAR_CHK_HI_QUEUE_EMPTY, &empty);
4039 }
4040
4041 if (psta_bmc->sleepq_len == 0) {
4042 if (empty == _SUCCESS) {
4043 bool update_tim = _FALSE;
4044
4045 if (rtw_tim_map_is_set(padapter, pstapriv->tim_bitmap, 0))
4046 update_tim = _TRUE;
4047
4048 rtw_tim_map_clear(padapter, pstapriv->tim_bitmap, 0);
4049 rtw_tim_map_clear(padapter, pstapriv->sta_dz_bitmap, 0);
4050
4051 if (update_tim == _TRUE)
4052 _update_beacon(padapter, _TIM_IE_, NULL, _TRUE, 0,"bmc sleepq and HIQ empty");
4053 } else /* re check again */
4054 rtw_chk_hi_queue_cmd(padapter);
4055
4056 }
4057
4058 }
4059
rtw_chk_hi_queue_cmd(_adapter * padapter)4060 u8 rtw_chk_hi_queue_cmd(_adapter *padapter)
4061 {
4062 struct cmd_obj *ph2c;
4063 struct drvextra_cmd_parm *pdrvextra_cmd_parm;
4064 struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
4065 u8 res = _SUCCESS;
4066
4067 ph2c = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
4068 if (ph2c == NULL) {
4069 res = _FAIL;
4070 goto exit;
4071 }
4072
4073 pdrvextra_cmd_parm = (struct drvextra_cmd_parm *)rtw_zmalloc(sizeof(struct drvextra_cmd_parm));
4074 if (pdrvextra_cmd_parm == NULL) {
4075 rtw_mfree((unsigned char *)ph2c, sizeof(struct cmd_obj));
4076 res = _FAIL;
4077 goto exit;
4078 }
4079
4080 pdrvextra_cmd_parm->ec_id = CHECK_HIQ_WK_CID;
4081 pdrvextra_cmd_parm->type = 0;
4082 pdrvextra_cmd_parm->size = 0;
4083 pdrvextra_cmd_parm->pbuf = NULL;
4084
4085 init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, CMD_SET_DRV_EXTRA);
4086
4087 res = rtw_enqueue_cmd(pcmdpriv, ph2c);
4088
4089 exit:
4090
4091 return res;
4092
4093 }
4094
4095 #ifdef CONFIG_DFS_MASTER
rtw_dfs_rd_hdl(_adapter * adapter)4096 u8 rtw_dfs_rd_hdl(_adapter *adapter)
4097 {
4098 struct dvobj_priv *dvobj = adapter_to_dvobj(adapter);
4099 struct rf_ctl_t *rfctl = adapter_to_rfctl(adapter);
4100 u8 cch;
4101
4102 if (!rfctl->radar_detect_enabled)
4103 goto exit;
4104
4105 cch = rtw_get_center_ch(rfctl->radar_detect_ch, rfctl->radar_detect_bw, rfctl->radar_detect_offset);
4106
4107 if (dvobj->oper_channel != rfctl->radar_detect_ch
4108 || rtw_get_passing_time_ms(rtw_get_on_oper_ch_time(adapter)) < 300
4109 ) {
4110 /* offchannel, bypass radar detect */
4111 goto cac_status_chk;
4112 }
4113
4114 if (IS_CH_WAITING(rfctl) && !IS_UNDER_CAC(rfctl)) {
4115 /* non_ocp, bypass radar detect */
4116 goto cac_status_chk;
4117 }
4118
4119 if (!rfctl->dbg_dfs_fake_radar_detect_cnt
4120 && rtw_odm_radar_detect(adapter) != _TRUE)
4121 goto cac_status_chk;
4122
4123 if (!rfctl->dbg_dfs_fake_radar_detect_cnt
4124 && rfctl->dbg_dfs_radar_detect_trigger_non
4125 ) {
4126 /* radar detect debug mode, trigger no mlme flow */
4127 RTW_INFO("%s radar detected on test mode, trigger no mlme flow\n", __func__);
4128 goto cac_status_chk;
4129 }
4130
4131 if (rfctl->dbg_dfs_fake_radar_detect_cnt != 0) {
4132 RTW_INFO("%s fake radar detected, cnt:%d\n", __func__
4133 , rfctl->dbg_dfs_fake_radar_detect_cnt);
4134 rfctl->dbg_dfs_fake_radar_detect_cnt--;
4135 } else
4136 RTW_INFO("%s radar detected\n", __func__);
4137
4138 rfctl->radar_detected = 1;
4139
4140 rtw_chset_update_non_ocp(rfctl->channel_set
4141 , rfctl->radar_detect_ch, rfctl->radar_detect_bw, rfctl->radar_detect_offset);
4142
4143 if (IS_UNDER_CAC(rfctl))
4144 rtw_nlrtw_cac_abort_event(adapter, cch, rfctl->radar_detect_bw);
4145 rtw_nlrtw_radar_detect_event(adapter, cch, rfctl->radar_detect_bw);
4146
4147 rtw_dfs_ch_switch_hdl(dvobj);
4148
4149 if (rfctl->radar_detect_enabled)
4150 goto set_timer;
4151 goto exit;
4152
4153 cac_status_chk:
4154
4155 if (!IS_CAC_STOPPED(rfctl)
4156 && ((IS_UNDER_CAC(rfctl) && rfctl->cac_force_stop)
4157 || !IS_CH_WAITING(rfctl)
4158 )
4159 ) {
4160 u8 pause = 0x00;
4161
4162 rtw_hal_set_hwreg(adapter, HW_VAR_TXPAUSE, &pause);
4163 rfctl->cac_start_time = rfctl->cac_end_time = RTW_CAC_STOPPED;
4164 rtw_nlrtw_cac_finish_event(adapter, cch, rfctl->radar_detect_bw);
4165
4166 if (rtw_mi_check_fwstate(adapter, WIFI_UNDER_LINKING|WIFI_UNDER_SURVEY) == _FALSE) {
4167 u8 doiqk = _TRUE;
4168 u8 u_ch, u_bw, u_offset;
4169
4170 rtw_hal_set_hwreg(adapter , HW_VAR_DO_IQK , &doiqk);
4171
4172 if (rtw_mi_get_ch_setting_union(adapter, &u_ch, &u_bw, &u_offset))
4173 set_channel_bwmode(adapter, u_ch, u_offset, u_bw);
4174 else
4175 rtw_warn_on(1);
4176
4177 doiqk = _FALSE;
4178 rtw_hal_set_hwreg(adapter , HW_VAR_DO_IQK , &doiqk);
4179
4180 #ifdef CONFIG_AP_MODE
4181 ResumeTxBeacon(adapter);
4182 rtw_mi_tx_beacon_hdl(adapter);
4183 #endif
4184 }
4185 }
4186
4187 set_timer:
4188 _set_timer(&rfctl->radar_detect_timer
4189 , rtw_odm_radar_detect_polling_int_ms(dvobj));
4190
4191 exit:
4192 return H2C_SUCCESS;
4193 }
4194
rtw_dfs_rd_cmd(_adapter * adapter,bool enqueue)4195 u8 rtw_dfs_rd_cmd(_adapter *adapter, bool enqueue)
4196 {
4197 struct cmd_obj *cmdobj;
4198 struct drvextra_cmd_parm *parm;
4199 struct cmd_priv *cmdpriv = &adapter->cmdpriv;
4200 u8 res = _FAIL;
4201
4202 if (enqueue) {
4203 cmdobj = rtw_zmalloc(sizeof(struct cmd_obj));
4204 if (cmdobj == NULL)
4205 goto exit;
4206
4207 parm = rtw_zmalloc(sizeof(struct drvextra_cmd_parm));
4208 if (parm == NULL) {
4209 rtw_mfree(cmdobj, sizeof(struct cmd_obj));
4210 goto exit;
4211 }
4212
4213 parm->ec_id = DFS_RADAR_DETECT_WK_CID;
4214 parm->type = 0;
4215 parm->size = 0;
4216 parm->pbuf = NULL;
4217
4218 init_h2fwcmd_w_parm_no_rsp(cmdobj, parm, CMD_SET_DRV_EXTRA);
4219 res = rtw_enqueue_cmd(cmdpriv, cmdobj);
4220 } else {
4221 rtw_dfs_rd_hdl(adapter);
4222 res = _SUCCESS;
4223 }
4224
4225 exit:
4226 return res;
4227 }
4228
rtw_dfs_rd_timer_hdl(void * ctx)4229 void rtw_dfs_rd_timer_hdl(void *ctx)
4230 {
4231 struct rf_ctl_t *rfctl = (struct rf_ctl_t *)ctx;
4232 struct dvobj_priv *dvobj = rfctl_to_dvobj(rfctl);
4233
4234 rtw_dfs_rd_cmd(dvobj_get_primary_adapter(dvobj), _TRUE);
4235 }
4236
rtw_dfs_rd_enable(struct rf_ctl_t * rfctl,u8 ch,u8 bw,u8 offset,bool bypass_cac)4237 static void rtw_dfs_rd_enable(struct rf_ctl_t *rfctl, u8 ch, u8 bw, u8 offset, bool bypass_cac)
4238 {
4239 struct dvobj_priv *dvobj = rfctl_to_dvobj(rfctl);
4240 _adapter *adapter = dvobj_get_primary_adapter(dvobj);
4241
4242 RTW_INFO("%s on %u,%u,%u\n", __func__, ch, bw, offset);
4243
4244 if (bypass_cac)
4245 rfctl->cac_start_time = rfctl->cac_end_time = RTW_CAC_STOPPED;
4246 else if (rtw_is_cac_reset_needed(rfctl, ch, bw, offset) == _TRUE)
4247 rtw_reset_cac(rfctl, ch, bw, offset);
4248
4249 rfctl->radar_detect_by_others = _FALSE;
4250 rfctl->radar_detect_ch = ch;
4251 rfctl->radar_detect_bw = bw;
4252 rfctl->radar_detect_offset = offset;
4253
4254 rfctl->radar_detected = 0;
4255
4256 if (IS_CH_WAITING(rfctl))
4257 StopTxBeacon(adapter);
4258
4259 if (!rfctl->radar_detect_enabled) {
4260 RTW_INFO("%s set radar_detect_enabled\n", __func__);
4261 rfctl->radar_detect_enabled = 1;
4262 #ifdef CONFIG_LPS
4263 LPS_Leave(adapter, "RADAR_DETECT_EN");
4264 #endif
4265 _set_timer(&rfctl->radar_detect_timer
4266 , rtw_odm_radar_detect_polling_int_ms(dvobj));
4267
4268 if (rtw_rfctl_overlap_radar_detect_ch(rfctl)) {
4269 if (IS_CH_WAITING(rfctl)) {
4270 u8 pause = 0xFF;
4271
4272 rtw_hal_set_hwreg(adapter, HW_VAR_TXPAUSE, &pause);
4273 }
4274 rtw_odm_radar_detect_enable(adapter);
4275 }
4276 }
4277 }
4278
rtw_dfs_rd_disable(struct rf_ctl_t * rfctl,u8 ch,u8 bw,u8 offset,bool by_others)4279 static void rtw_dfs_rd_disable(struct rf_ctl_t *rfctl, u8 ch, u8 bw, u8 offset, bool by_others)
4280 {
4281 _adapter *adapter = dvobj_get_primary_adapter(rfctl_to_dvobj(rfctl));
4282
4283 rfctl->radar_detect_by_others = by_others;
4284
4285 if (rfctl->radar_detect_enabled) {
4286 bool overlap_radar_detect_ch = rtw_rfctl_overlap_radar_detect_ch(rfctl);
4287
4288 RTW_INFO("%s clear radar_detect_enabled\n", __func__);
4289
4290 rfctl->radar_detect_enabled = 0;
4291 rfctl->radar_detected = 0;
4292 rfctl->radar_detect_ch = 0;
4293 rfctl->radar_detect_bw = 0;
4294 rfctl->radar_detect_offset = 0;
4295 rfctl->cac_start_time = rfctl->cac_end_time = RTW_CAC_STOPPED;
4296 _cancel_timer_ex(&rfctl->radar_detect_timer);
4297
4298 if (rtw_mi_check_fwstate(adapter, WIFI_UNDER_LINKING|WIFI_UNDER_SURVEY) == _FALSE) {
4299 ResumeTxBeacon(adapter);
4300 rtw_mi_tx_beacon_hdl(adapter);
4301 }
4302
4303 if (overlap_radar_detect_ch) {
4304 u8 pause = 0x00;
4305
4306 rtw_hal_set_hwreg(adapter, HW_VAR_TXPAUSE, &pause);
4307 rtw_odm_radar_detect_disable(adapter);
4308 }
4309 }
4310
4311 if (by_others) {
4312 rfctl->radar_detect_ch = ch;
4313 rfctl->radar_detect_bw = bw;
4314 rfctl->radar_detect_offset = offset;
4315 } else {
4316 rfctl->radar_detect_ch = 0;
4317 rfctl->radar_detect_bw = 0;
4318 rfctl->radar_detect_offset = 0;
4319 }
4320 }
4321
rtw_dfs_rd_en_decision(_adapter * adapter,u8 mlme_act,u8 excl_ifbmp)4322 void rtw_dfs_rd_en_decision(_adapter *adapter, u8 mlme_act, u8 excl_ifbmp)
4323 {
4324 struct dvobj_priv *dvobj = adapter_to_dvobj(adapter);
4325 struct rf_ctl_t *rfctl = adapter_to_rfctl(adapter);
4326 struct mlme_ext_priv *mlmeext = &adapter->mlmeextpriv;
4327 struct mi_state mstate;
4328 u8 ifbmp;
4329 u8 u_ch, u_bw, u_offset;
4330 bool ld_sta_in_dfs = _FALSE;
4331 bool sync_ch = _FALSE; /* _FALSE: asign channel directly */
4332 bool needed = _FALSE;
4333
4334 if (mlme_act == MLME_OPCH_SWITCH
4335 || mlme_act == MLME_ACTION_NONE
4336 ) {
4337 ifbmp = ~excl_ifbmp;
4338 rtw_mi_status_by_ifbmp(dvobj, ifbmp, &mstate);
4339 rtw_mi_get_ch_setting_union_by_ifbmp(dvobj, ifbmp, &u_ch, &u_bw, &u_offset);
4340 } else {
4341 ifbmp = ~excl_ifbmp & ~BIT(adapter->iface_id);
4342 rtw_mi_status_by_ifbmp(dvobj, ifbmp, &mstate);
4343 rtw_mi_get_ch_setting_union_by_ifbmp(dvobj, ifbmp, &u_ch, &u_bw, &u_offset);
4344 if (u_ch != 0)
4345 sync_ch = _TRUE;
4346
4347 switch (mlme_act) {
4348 case MLME_STA_CONNECTING:
4349 MSTATE_STA_LG_NUM(&mstate)++;
4350 break;
4351 case MLME_STA_CONNECTED:
4352 MSTATE_STA_LD_NUM(&mstate)++;
4353 break;
4354 case MLME_STA_DISCONNECTED:
4355 break;
4356 #ifdef CONFIG_AP_MODE
4357 case MLME_AP_STARTED:
4358 MSTATE_AP_NUM(&mstate)++;
4359 break;
4360 case MLME_AP_STOPPED:
4361 break;
4362 #endif
4363 #ifdef CONFIG_RTW_MESH
4364 case MLME_MESH_STARTED:
4365 MSTATE_MESH_NUM(&mstate)++;
4366 break;
4367 case MLME_MESH_STOPPED:
4368 break;
4369 #endif
4370 default:
4371 rtw_warn_on(1);
4372 break;
4373 }
4374
4375 if (sync_ch == _TRUE) {
4376 if (!MLME_IS_OPCH_SW(adapter)) {
4377 if (!rtw_is_chbw_grouped(mlmeext->cur_channel, mlmeext->cur_bwmode, mlmeext->cur_ch_offset, u_ch, u_bw, u_offset)) {
4378 RTW_INFO(FUNC_ADPT_FMT" can't sync %u,%u,%u with %u,%u,%u\n", FUNC_ADPT_ARG(adapter)
4379 , mlmeext->cur_channel, mlmeext->cur_bwmode, mlmeext->cur_ch_offset, u_ch, u_bw, u_offset);
4380 goto apply;
4381 }
4382
4383 rtw_sync_chbw(&mlmeext->cur_channel, &mlmeext->cur_bwmode, &mlmeext->cur_ch_offset
4384 , &u_ch, &u_bw, &u_offset);
4385 }
4386 } else {
4387 u_ch = mlmeext->cur_channel;
4388 u_bw = mlmeext->cur_bwmode;
4389 u_offset = mlmeext->cur_ch_offset;
4390 }
4391 }
4392
4393 if (MSTATE_STA_LG_NUM(&mstate) > 0) {
4394 /* STA mode is linking */
4395 goto apply;
4396 }
4397
4398 if (MSTATE_STA_LD_NUM(&mstate) > 0) {
4399 if (rtw_chset_is_dfs_chbw(rfctl->channel_set, u_ch, u_bw, u_offset)) {
4400 /*
4401 * if operate as slave w/o radar detect,
4402 * rely on AP on which STA mode connects
4403 */
4404 if (IS_DFS_SLAVE_WITH_RD(rfctl) && !rtw_rfctl_dfs_domain_unknown(rfctl))
4405 needed = _TRUE;
4406 ld_sta_in_dfs = _TRUE;
4407 }
4408 goto apply;
4409 }
4410
4411 if (!MSTATE_AP_NUM(&mstate) && !MSTATE_MESH_NUM(&mstate)) {
4412 /* No working AP/Mesh mode */
4413 goto apply;
4414 }
4415
4416 if (rtw_chset_is_dfs_chbw(rfctl->channel_set, u_ch, u_bw, u_offset))
4417 needed = _TRUE;
4418
4419 apply:
4420
4421 RTW_INFO(FUNC_ADPT_FMT" needed:%d, mlme_act:%u, excl_ifbmp:0x%02x\n"
4422 , FUNC_ADPT_ARG(adapter), needed, mlme_act, excl_ifbmp);
4423 RTW_INFO(FUNC_ADPT_FMT" ld_sta_num:%u, lg_sta_num:%u, ap_num:%u, mesh_num:%u, %u,%u,%u\n"
4424 , FUNC_ADPT_ARG(adapter), MSTATE_STA_LD_NUM(&mstate), MSTATE_STA_LG_NUM(&mstate)
4425 , MSTATE_AP_NUM(&mstate), MSTATE_MESH_NUM(&mstate)
4426 , u_ch, u_bw, u_offset);
4427
4428 if (needed == _TRUE)
4429 rtw_dfs_rd_enable(rfctl, u_ch, u_bw, u_offset, ld_sta_in_dfs);
4430 else
4431 rtw_dfs_rd_disable(rfctl, u_ch, u_bw, u_offset, ld_sta_in_dfs);
4432 }
4433
rtw_dfs_rd_en_decision_cmd(_adapter * adapter)4434 u8 rtw_dfs_rd_en_decision_cmd(_adapter *adapter)
4435 {
4436 struct cmd_obj *cmdobj;
4437 struct drvextra_cmd_parm *parm;
4438 struct cmd_priv *cmdpriv = &adapter->cmdpriv;
4439 u8 res = _FAIL;
4440
4441 cmdobj = rtw_zmalloc(sizeof(struct cmd_obj));
4442 if (cmdobj == NULL)
4443 goto exit;
4444
4445 parm = rtw_zmalloc(sizeof(struct drvextra_cmd_parm));
4446 if (parm == NULL) {
4447 rtw_mfree(cmdobj, sizeof(struct cmd_obj));
4448 goto exit;
4449 }
4450
4451 parm->ec_id = DFS_RADAR_DETECT_EN_DEC_WK_CID;
4452 parm->type = 0;
4453 parm->size = 0;
4454 parm->pbuf = NULL;
4455
4456 init_h2fwcmd_w_parm_no_rsp(cmdobj, parm, CMD_SET_DRV_EXTRA);
4457 res = rtw_enqueue_cmd(cmdpriv, cmdobj);
4458
4459 exit:
4460 return res;
4461 }
4462 #endif /* CONFIG_DFS_MASTER */
4463
4464 #endif /* CONFIG_AP_MODE */
4465
4466 #ifdef CONFIG_BT_COEXIST
4467 struct btinfo {
4468 u8 cid;
4469 u8 len;
4470
4471 u8 bConnection:1;
4472 u8 bSCOeSCO:1;
4473 u8 bInQPage:1;
4474 u8 bACLBusy:1;
4475 u8 bSCOBusy:1;
4476 u8 bHID:1;
4477 u8 bA2DP:1;
4478 u8 bFTP:1;
4479
4480 u8 retry_cnt:4;
4481 u8 rsvd_34:1;
4482 u8 rsvd_35:1;
4483 u8 rsvd_36:1;
4484 u8 rsvd_37:1;
4485
4486 u8 rssi;
4487
4488 u8 rsvd_50:1;
4489 u8 rsvd_51:1;
4490 u8 rsvd_52:1;
4491 u8 rsvd_53:1;
4492 u8 rsvd_54:1;
4493 u8 rsvd_55:1;
4494 u8 eSCO_SCO:1;
4495 u8 Master_Slave:1;
4496
4497 u8 rsvd_6;
4498 u8 rsvd_7;
4499 };
4500
btinfo_evt_dump(void * sel,void * buf)4501 void btinfo_evt_dump(void *sel, void *buf)
4502 {
4503 struct btinfo *info = (struct btinfo *)buf;
4504
4505 RTW_PRINT_SEL(sel, "cid:0x%02x, len:%u\n", info->cid, info->len);
4506
4507 if (info->len > 2)
4508 RTW_PRINT_SEL(sel, "byte2:%s%s%s%s%s%s%s%s\n"
4509 , info->bConnection ? "bConnection " : ""
4510 , info->bSCOeSCO ? "bSCOeSCO " : ""
4511 , info->bInQPage ? "bInQPage " : ""
4512 , info->bACLBusy ? "bACLBusy " : ""
4513 , info->bSCOBusy ? "bSCOBusy " : ""
4514 , info->bHID ? "bHID " : ""
4515 , info->bA2DP ? "bA2DP " : ""
4516 , info->bFTP ? "bFTP" : ""
4517 );
4518
4519 if (info->len > 3)
4520 RTW_PRINT_SEL(sel, "retry_cnt:%u\n", info->retry_cnt);
4521
4522 if (info->len > 4)
4523 RTW_PRINT_SEL(sel, "rssi:%u\n", info->rssi);
4524
4525 if (info->len > 5)
4526 RTW_PRINT_SEL(sel, "byte5:%s%s\n"
4527 , info->eSCO_SCO ? "eSCO_SCO " : ""
4528 , info->Master_Slave ? "Master_Slave " : ""
4529 );
4530 }
4531
rtw_btinfo_hdl(_adapter * adapter,u8 * buf,u16 buf_len)4532 static void rtw_btinfo_hdl(_adapter *adapter, u8 *buf, u16 buf_len)
4533 {
4534 #define BTINFO_WIFI_FETCH 0x23
4535 #define BTINFO_BT_AUTO_RPT 0x27
4536 #ifdef CONFIG_BT_COEXIST_SOCKET_TRX
4537 struct btinfo_8761ATV *info = (struct btinfo_8761ATV *)buf;
4538 #else /* !CONFIG_BT_COEXIST_SOCKET_TRX */
4539 struct btinfo *info = (struct btinfo *)buf;
4540 #endif /* CONFIG_BT_COEXIST_SOCKET_TRX */
4541 u8 cmd_idx;
4542 u8 len;
4543
4544 cmd_idx = info->cid;
4545
4546 if (info->len > buf_len - 2) {
4547 rtw_warn_on(1);
4548 len = buf_len - 2;
4549 } else
4550 len = info->len;
4551
4552 /* #define DBG_PROC_SET_BTINFO_EVT */
4553 #ifdef DBG_PROC_SET_BTINFO_EVT
4554 #ifdef CONFIG_BT_COEXIST_SOCKET_TRX
4555 RTW_INFO("%s: btinfo[0]=%x,btinfo[1]=%x,btinfo[2]=%x,btinfo[3]=%x btinfo[4]=%x,btinfo[5]=%x,btinfo[6]=%x,btinfo[7]=%x\n"
4556 , __func__, buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7]);
4557 #else/* !CONFIG_BT_COEXIST_SOCKET_TRX */
4558 btinfo_evt_dump(RTW_DBGDUMP, info);
4559 #endif /* CONFIG_BT_COEXIST_SOCKET_TRX */
4560 #endif /* DBG_PROC_SET_BTINFO_EVT */
4561
4562 /* transform BT-FW btinfo to WiFI-FW C2H format and notify */
4563 if (cmd_idx == BTINFO_WIFI_FETCH)
4564 buf[1] = 0;
4565 else if (cmd_idx == BTINFO_BT_AUTO_RPT)
4566 buf[1] = 2;
4567 #ifdef CONFIG_BT_COEXIST_SOCKET_TRX
4568 else if (0x01 == cmd_idx || 0x02 == cmd_idx)
4569 buf[1] = buf[0];
4570 #endif /* CONFIG_BT_COEXIST_SOCKET_TRX */
4571 rtw_btcoex_BtInfoNotify(adapter , len + 1, &buf[1]);
4572 }
4573
rtw_btinfo_cmd(_adapter * adapter,u8 * buf,u16 len)4574 u8 rtw_btinfo_cmd(_adapter *adapter, u8 *buf, u16 len)
4575 {
4576 struct cmd_obj *ph2c;
4577 struct drvextra_cmd_parm *pdrvextra_cmd_parm;
4578 u8 *btinfo;
4579 struct cmd_priv *pcmdpriv = &adapter->cmdpriv;
4580 u8 res = _SUCCESS;
4581
4582 ph2c = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
4583 if (ph2c == NULL) {
4584 res = _FAIL;
4585 goto exit;
4586 }
4587
4588 pdrvextra_cmd_parm = (struct drvextra_cmd_parm *)rtw_zmalloc(sizeof(struct drvextra_cmd_parm));
4589 if (pdrvextra_cmd_parm == NULL) {
4590 rtw_mfree((u8 *)ph2c, sizeof(struct cmd_obj));
4591 res = _FAIL;
4592 goto exit;
4593 }
4594
4595 btinfo = rtw_zmalloc(len);
4596 if (btinfo == NULL) {
4597 rtw_mfree((u8 *)ph2c, sizeof(struct cmd_obj));
4598 rtw_mfree((u8 *)pdrvextra_cmd_parm, sizeof(struct drvextra_cmd_parm));
4599 res = _FAIL;
4600 goto exit;
4601 }
4602
4603 pdrvextra_cmd_parm->ec_id = BTINFO_WK_CID;
4604 pdrvextra_cmd_parm->type = 0;
4605 pdrvextra_cmd_parm->size = len;
4606 pdrvextra_cmd_parm->pbuf = btinfo;
4607
4608 _rtw_memcpy(btinfo, buf, len);
4609
4610 init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, CMD_SET_DRV_EXTRA);
4611
4612 res = rtw_enqueue_cmd(pcmdpriv, ph2c);
4613
4614 exit:
4615 return res;
4616 }
4617
rtw_btc_reduce_wl_txpwr_hdl(_adapter * adapter,u32 pwr_lvl)4618 static void rtw_btc_reduce_wl_txpwr_hdl(_adapter *adapter, u32 pwr_lvl)
4619 {
4620 rtw_btcoex_set_reduced_wl_pwr_lvl(adapter, pwr_lvl);
4621 rtw_btcoex_do_reduce_wl_pwr_lvl(adapter);
4622
4623 RTW_INFO(FUNC_ADPT_FMT ": BTC reduce WL TxPwr %d dB!\n",
4624 FUNC_ADPT_ARG(adapter), pwr_lvl);
4625 }
4626
rtw_btc_reduce_wl_txpwr_cmd(_adapter * adapter,u32 val)4627 u8 rtw_btc_reduce_wl_txpwr_cmd(_adapter *adapter, u32 val)
4628 {
4629 struct cmd_obj *pcmdobj;
4630 struct drvextra_cmd_parm *pdrvextra_cmd_parm;
4631 struct cmd_priv *pcmdpriv = &adapter->cmdpriv;
4632 u8 res = _SUCCESS;
4633
4634 pcmdobj = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
4635 if (pcmdobj == NULL) {
4636 res = _FAIL;
4637 goto exit;
4638 }
4639
4640 pdrvextra_cmd_parm = (struct drvextra_cmd_parm *)rtw_zmalloc(sizeof(struct drvextra_cmd_parm));
4641 if (pdrvextra_cmd_parm == NULL) {
4642 rtw_mfree((u8 *)pcmdobj, sizeof(struct cmd_obj));
4643 res = _FAIL;
4644 goto exit;
4645 }
4646
4647 pdrvextra_cmd_parm->ec_id = BTC_REDUCE_WL_TXPWR_CID;
4648 pdrvextra_cmd_parm->type = val;
4649 pdrvextra_cmd_parm->size = 0;
4650 pdrvextra_cmd_parm->pbuf = NULL;
4651
4652 init_h2fwcmd_w_parm_no_rsp(pcmdobj, pdrvextra_cmd_parm, CMD_SET_DRV_EXTRA);
4653
4654 res = rtw_enqueue_cmd(pcmdpriv, pcmdobj);
4655
4656 exit:
4657 return res;
4658 }
4659 #endif /* CONFIG_BT_COEXIST */
4660
rtw_test_h2c_cmd(_adapter * adapter,u8 * buf,u8 len)4661 u8 rtw_test_h2c_cmd(_adapter *adapter, u8 *buf, u8 len)
4662 {
4663 struct cmd_obj *pcmdobj;
4664 struct drvextra_cmd_parm *pdrvextra_cmd_parm;
4665 u8 *ph2c_content;
4666 struct cmd_priv *pcmdpriv = &adapter->cmdpriv;
4667 u8 res = _SUCCESS;
4668
4669 pcmdobj = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
4670 if (pcmdobj == NULL) {
4671 res = _FAIL;
4672 goto exit;
4673 }
4674
4675 pdrvextra_cmd_parm = (struct drvextra_cmd_parm *)rtw_zmalloc(sizeof(struct drvextra_cmd_parm));
4676 if (pdrvextra_cmd_parm == NULL) {
4677 rtw_mfree((u8 *)pcmdobj, sizeof(struct cmd_obj));
4678 res = _FAIL;
4679 goto exit;
4680 }
4681
4682 ph2c_content = rtw_zmalloc(len);
4683 if (ph2c_content == NULL) {
4684 rtw_mfree((u8 *)pcmdobj, sizeof(struct cmd_obj));
4685 rtw_mfree((u8 *)pdrvextra_cmd_parm, sizeof(struct drvextra_cmd_parm));
4686 res = _FAIL;
4687 goto exit;
4688 }
4689
4690 pdrvextra_cmd_parm->ec_id = TEST_H2C_CID;
4691 pdrvextra_cmd_parm->type = 0;
4692 pdrvextra_cmd_parm->size = len;
4693 pdrvextra_cmd_parm->pbuf = ph2c_content;
4694
4695 _rtw_memcpy(ph2c_content, buf, len);
4696
4697 init_h2fwcmd_w_parm_no_rsp(pcmdobj, pdrvextra_cmd_parm, CMD_SET_DRV_EXTRA);
4698
4699 res = rtw_enqueue_cmd(pcmdpriv, pcmdobj);
4700
4701 exit:
4702 return res;
4703 }
4704
4705 #ifdef CONFIG_MP_INCLUDED
rtw_mp_cmd_hdl(_adapter * padapter,u8 mp_cmd_id)4706 static s32 rtw_mp_cmd_hdl(_adapter *padapter, u8 mp_cmd_id)
4707 {
4708 HAL_DATA_TYPE *pHalData = GET_HAL_DATA(padapter);
4709 int ret = H2C_SUCCESS;
4710 uint status = _SUCCESS;
4711
4712 if (mp_cmd_id == MP_START) {
4713 if (padapter->registrypriv.mp_mode == 0) {
4714 rtw_intf_stop(padapter);
4715 rtw_hal_deinit(padapter);
4716 padapter->registrypriv.mp_mode = 1;
4717 #ifdef CONFIG_BT_COEXIST
4718 padapter->mppriv.CureFuseBTCoex = pHalData->EEPROMBluetoothCoexist;
4719 pHalData->EEPROMBluetoothCoexist = _FALSE;
4720 #endif
4721 #ifdef CONFIG_RF_POWER_TRIM
4722 if (!IS_HARDWARE_TYPE_8814A(padapter) && !IS_HARDWARE_TYPE_8822B(padapter)
4723 && !IS_HARDWARE_TYPE_8822C(padapter) && !IS_HARDWARE_TYPE_8723F(padapter)) {
4724 padapter->registrypriv.RegPwrTrimEnable = 1;
4725 rtw_hal_read_chip_info(padapter);
4726 }
4727 #endif /*CONFIG_RF_POWER_TRIM*/
4728 rtw_reset_drv_sw(padapter);
4729 #ifdef CONFIG_NEW_NETDEV_HDL
4730 if (!rtw_is_hw_init_completed(padapter)) {
4731 status = rtw_hal_init(padapter);
4732 if (status == _FAIL) {
4733 ret = H2C_REJECTED;
4734 goto exit;
4735 }
4736 rtw_hal_iface_init(padapter);
4737 }
4738 #else
4739 status = rtw_hal_init(padapter);
4740 if (status == _FAIL) {
4741 ret = H2C_REJECTED;
4742 goto exit;
4743 }
4744 #endif /*CONFIG_NEW_NETDEV_HDL*/
4745 #ifndef RTW_HALMAC
4746 rtw_intf_start(padapter);
4747 #endif /* !RTW_HALMAC */
4748 #ifdef RTW_HALMAC /*for New IC*/
4749 MPT_InitializeAdapter(padapter, 1);
4750 #endif /* CONFIG_MP_INCLUDED */
4751 }
4752
4753 if (padapter->registrypriv.mp_mode == 0) {
4754 ret = H2C_REJECTED;
4755 goto exit;
4756 }
4757
4758 if (padapter->mppriv.mode == MP_OFF) {
4759 if (mp_start_test(padapter) == _FAIL) {
4760 ret = H2C_REJECTED;
4761 goto exit;
4762 }
4763 padapter->mppriv.mode = MP_ON;
4764 MPT_PwrCtlDM(padapter, 0);
4765 }
4766 padapter->mppriv.bmac_filter = _FALSE;
4767 #ifdef CONFIG_RTL8723B
4768 #ifdef CONFIG_USB_HCI
4769 rtw_write32(padapter, 0x765, 0x0000);
4770 rtw_write32(padapter, 0x948, 0x0280);
4771 #else
4772 rtw_write32(padapter, 0x765, 0x0000);
4773 rtw_write32(padapter, 0x948, 0x0000);
4774 #endif
4775 #ifdef CONFIG_FOR_RTL8723BS_VQ0
4776 rtw_write32(padapter, 0x765, 0x0000);
4777 rtw_write32(padapter, 0x948, 0x0280);
4778 #endif
4779 rtw_write8(padapter, 0x66, 0x27); /*Open BT uart Log*/
4780 rtw_write8(padapter, 0xc50, 0x20); /*for RX init Gain*/
4781 #endif
4782 odm_write_dig(&pHalData->odmpriv, 0x20);
4783
4784 } else if (mp_cmd_id == MP_STOP) {
4785 if (padapter->registrypriv.mp_mode == 1) {
4786 MPT_DeInitAdapter(padapter);
4787 rtw_intf_stop(padapter);
4788 rtw_hal_deinit(padapter);
4789 padapter->registrypriv.mp_mode = 0;
4790 #ifdef CONFIG_BT_COEXIST
4791 pHalData->EEPROMBluetoothCoexist = padapter->mppriv.CureFuseBTCoex;
4792 #endif
4793 rtw_reset_drv_sw(padapter);
4794 #ifdef CONFIG_NEW_NETDEV_HDL
4795 if (!rtw_is_hw_init_completed(padapter)) {
4796 status = rtw_hal_init(padapter);
4797 if (status == _FAIL) {
4798 ret = H2C_REJECTED;
4799 goto exit;
4800 }
4801 rtw_hal_iface_init(padapter);
4802 }
4803 #else
4804 status = rtw_hal_init(padapter);
4805 if (status == _FAIL) {
4806 ret = H2C_REJECTED;
4807 goto exit;
4808 }
4809 #endif /*CONFIG_NEW_NETDEV_HDL*/
4810 #ifndef RTW_HALMAC
4811 rtw_intf_start(padapter);
4812 #endif /* !RTW_HALMAC */
4813 }
4814
4815 if (padapter->mppriv.mode != MP_OFF) {
4816 mp_stop_test(padapter);
4817 padapter->mppriv.mode = MP_OFF;
4818 }
4819
4820 } else {
4821 RTW_INFO(FUNC_ADPT_FMT"invalid id:%d\n", FUNC_ADPT_ARG(padapter), mp_cmd_id);
4822 ret = H2C_PARAMETERS_ERROR;
4823 rtw_warn_on(1);
4824 }
4825
4826 exit:
4827 return ret;
4828 }
4829
rtw_mp_cmd(_adapter * adapter,u8 mp_cmd_id,u8 flags)4830 u8 rtw_mp_cmd(_adapter *adapter, u8 mp_cmd_id, u8 flags)
4831 {
4832 struct cmd_obj *cmdobj;
4833 struct drvextra_cmd_parm *parm;
4834 struct cmd_priv *pcmdpriv = &adapter->cmdpriv;
4835 struct submit_ctx sctx;
4836 u8 res = _SUCCESS;
4837
4838 parm = (struct drvextra_cmd_parm *)rtw_zmalloc(sizeof(struct drvextra_cmd_parm));
4839 if (parm == NULL) {
4840 res = _FAIL;
4841 goto exit;
4842 }
4843
4844 parm->ec_id = MP_CMD_WK_CID;
4845 parm->type = mp_cmd_id;
4846 parm->size = 0;
4847 parm->pbuf = NULL;
4848
4849 if (flags & RTW_CMDF_DIRECTLY) {
4850 /* no need to enqueue, do the cmd hdl directly and free cmd parameter */
4851 if (H2C_SUCCESS != rtw_mp_cmd_hdl(adapter, mp_cmd_id))
4852 res = _FAIL;
4853 rtw_mfree((u8 *)parm, sizeof(*parm));
4854 } else {
4855 /* need enqueue, prepare cmd_obj and enqueue */
4856 cmdobj = (struct cmd_obj *)rtw_zmalloc(sizeof(*cmdobj));
4857 if (cmdobj == NULL) {
4858 res = _FAIL;
4859 rtw_mfree((u8 *)parm, sizeof(*parm));
4860 goto exit;
4861 }
4862
4863 init_h2fwcmd_w_parm_no_rsp(cmdobj, parm, CMD_SET_DRV_EXTRA);
4864
4865 if (flags & RTW_CMDF_WAIT_ACK) {
4866 cmdobj->sctx = &sctx;
4867 rtw_sctx_init(&sctx, 10 * 1000);
4868 }
4869
4870 res = rtw_enqueue_cmd(pcmdpriv, cmdobj);
4871
4872 if (res == _SUCCESS && (flags & RTW_CMDF_WAIT_ACK)) {
4873 rtw_sctx_wait(&sctx, __func__);
4874 _enter_critical_mutex(&pcmdpriv->sctx_mutex, NULL);
4875 if (sctx.status == RTW_SCTX_SUBMITTED)
4876 cmdobj->sctx = NULL;
4877 _exit_critical_mutex(&pcmdpriv->sctx_mutex, NULL);
4878 if (sctx.status != RTW_SCTX_DONE_SUCCESS)
4879 res = _FAIL;
4880 }
4881 }
4882
4883 exit:
4884 return res;
4885 }
4886 #endif /*CONFIG_MP_INCLUDED*/
4887
4888 #ifdef CONFIG_RTW_CUSTOMER_STR
rtw_customer_str_cmd_hdl(_adapter * adapter,u8 write,const u8 * cstr)4889 static s32 rtw_customer_str_cmd_hdl(_adapter *adapter, u8 write, const u8 *cstr)
4890 {
4891 int ret = H2C_SUCCESS;
4892
4893 if (write)
4894 ret = rtw_hal_h2c_customer_str_write(adapter, cstr);
4895 else
4896 ret = rtw_hal_h2c_customer_str_req(adapter);
4897
4898 return ret == _SUCCESS ? H2C_SUCCESS : H2C_REJECTED;
4899 }
4900
rtw_customer_str_cmd(_adapter * adapter,u8 write,const u8 * cstr)4901 static u8 rtw_customer_str_cmd(_adapter *adapter, u8 write, const u8 *cstr)
4902 {
4903 struct cmd_obj *cmdobj;
4904 struct drvextra_cmd_parm *parm;
4905 u8 *str = NULL;
4906 struct cmd_priv *pcmdpriv = &adapter->cmdpriv;
4907 struct submit_ctx sctx;
4908 u8 res = _SUCCESS;
4909
4910 parm = (struct drvextra_cmd_parm *)rtw_zmalloc(sizeof(struct drvextra_cmd_parm));
4911 if (parm == NULL) {
4912 res = _FAIL;
4913 goto exit;
4914 }
4915
4916 if (write) {
4917 str = rtw_zmalloc(RTW_CUSTOMER_STR_LEN);
4918 if (str == NULL) {
4919 rtw_mfree((u8 *)parm, sizeof(struct drvextra_cmd_parm));
4920 res = _FAIL;
4921 goto exit;
4922 }
4923 }
4924
4925 parm->ec_id = CUSTOMER_STR_WK_CID;
4926 parm->type = write;
4927 parm->size = write ? RTW_CUSTOMER_STR_LEN : 0;
4928 parm->pbuf = write ? str : NULL;
4929
4930 if (write)
4931 _rtw_memcpy(str, cstr, RTW_CUSTOMER_STR_LEN);
4932
4933 /* need enqueue, prepare cmd_obj and enqueue */
4934 cmdobj = (struct cmd_obj *)rtw_zmalloc(sizeof(*cmdobj));
4935 if (cmdobj == NULL) {
4936 res = _FAIL;
4937 rtw_mfree((u8 *)parm, sizeof(*parm));
4938 if (write)
4939 rtw_mfree(str, RTW_CUSTOMER_STR_LEN);
4940 goto exit;
4941 }
4942
4943 init_h2fwcmd_w_parm_no_rsp(cmdobj, parm, CMD_SET_DRV_EXTRA);
4944
4945 cmdobj->sctx = &sctx;
4946 rtw_sctx_init(&sctx, 2 * 1000);
4947
4948 res = rtw_enqueue_cmd(pcmdpriv, cmdobj);
4949
4950 if (res == _SUCCESS) {
4951 rtw_sctx_wait(&sctx, __func__);
4952 _enter_critical_mutex(&pcmdpriv->sctx_mutex, NULL);
4953 if (sctx.status == RTW_SCTX_SUBMITTED)
4954 cmdobj->sctx = NULL;
4955 _exit_critical_mutex(&pcmdpriv->sctx_mutex, NULL);
4956 if (sctx.status != RTW_SCTX_DONE_SUCCESS)
4957 res = _FAIL;
4958 }
4959
4960 exit:
4961 return res;
4962 }
4963
rtw_customer_str_req_cmd(_adapter * adapter)4964 inline u8 rtw_customer_str_req_cmd(_adapter *adapter)
4965 {
4966 return rtw_customer_str_cmd(adapter, 0, NULL);
4967 }
4968
rtw_customer_str_write_cmd(_adapter * adapter,const u8 * cstr)4969 inline u8 rtw_customer_str_write_cmd(_adapter *adapter, const u8 *cstr)
4970 {
4971 return rtw_customer_str_cmd(adapter, 1, cstr);
4972 }
4973 #endif /* CONFIG_RTW_CUSTOMER_STR */
4974
rtw_c2h_wk_cmd(PADAPTER padapter,u8 * pbuf,u16 length,u8 type)4975 u8 rtw_c2h_wk_cmd(PADAPTER padapter, u8 *pbuf, u16 length, u8 type)
4976 {
4977 struct cmd_obj *ph2c;
4978 struct drvextra_cmd_parm *pdrvextra_cmd_parm;
4979 struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
4980 u8 *extra_cmd_buf;
4981 u8 res = _SUCCESS;
4982
4983 ph2c = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
4984 if (ph2c == NULL) {
4985 res = _FAIL;
4986 goto exit;
4987 }
4988
4989 pdrvextra_cmd_parm = (struct drvextra_cmd_parm *)rtw_zmalloc(sizeof(struct drvextra_cmd_parm));
4990 if (pdrvextra_cmd_parm == NULL) {
4991 rtw_mfree((u8 *)ph2c, sizeof(struct cmd_obj));
4992 res = _FAIL;
4993 goto exit;
4994 }
4995
4996 extra_cmd_buf = rtw_zmalloc(length);
4997 if (extra_cmd_buf == NULL) {
4998 rtw_mfree((u8 *)ph2c, sizeof(struct cmd_obj));
4999 rtw_mfree((u8 *)pdrvextra_cmd_parm, sizeof(struct drvextra_cmd_parm));
5000 res = _FAIL;
5001 goto exit;
5002 }
5003
5004 _rtw_memcpy(extra_cmd_buf, pbuf, length);
5005 pdrvextra_cmd_parm->ec_id = C2H_WK_CID;
5006 pdrvextra_cmd_parm->type = type;
5007 pdrvextra_cmd_parm->size = length;
5008 pdrvextra_cmd_parm->pbuf = extra_cmd_buf;
5009
5010 init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, CMD_SET_DRV_EXTRA);
5011
5012 res = rtw_enqueue_cmd(pcmdpriv, ph2c);
5013
5014 exit:
5015 return res;
5016 }
5017
5018 #ifdef CONFIG_FW_C2H_REG
rtw_c2h_reg_wk_cmd(_adapter * adapter,u8 * c2h_evt)5019 inline u8 rtw_c2h_reg_wk_cmd(_adapter *adapter, u8 *c2h_evt)
5020 {
5021 return rtw_c2h_wk_cmd(adapter, c2h_evt, c2h_evt ? C2H_REG_LEN : 0, C2H_TYPE_REG);
5022 }
5023 #endif
5024
5025 #ifdef CONFIG_FW_C2H_PKT
rtw_c2h_packet_wk_cmd(_adapter * adapter,u8 * c2h_evt,u16 length)5026 inline u8 rtw_c2h_packet_wk_cmd(_adapter *adapter, u8 *c2h_evt, u16 length)
5027 {
5028 return rtw_c2h_wk_cmd(adapter, c2h_evt, length, C2H_TYPE_PKT);
5029 }
5030 #endif
5031
_rtw_run_in_thread_cmd(_adapter * adapter,void (* func)(void *),void * context,s32 timeout_ms)5032 static u8 _rtw_run_in_thread_cmd(_adapter *adapter, void (*func)(void *), void *context, s32 timeout_ms)
5033 {
5034 struct cmd_priv *cmdpriv = &adapter->cmdpriv;
5035 struct cmd_obj *cmdobj;
5036 struct RunInThread_param *parm;
5037 struct submit_ctx sctx;
5038 s32 res = _SUCCESS;
5039
5040 cmdobj = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
5041 if (NULL == cmdobj) {
5042 res = _FAIL;
5043 goto exit;
5044 }
5045
5046 parm = (struct RunInThread_param *)rtw_zmalloc(sizeof(struct RunInThread_param));
5047 if (NULL == parm) {
5048 rtw_mfree((u8 *)cmdobj, sizeof(struct cmd_obj));
5049 res = _FAIL;
5050 goto exit;
5051 }
5052
5053 parm->func = func;
5054 parm->context = context;
5055 init_h2fwcmd_w_parm_no_rsp(cmdobj, parm, CMD_RUN_INTHREAD);
5056
5057 if (timeout_ms >= 0) {
5058 cmdobj->sctx = &sctx;
5059 rtw_sctx_init(&sctx, timeout_ms);
5060 }
5061
5062 res = rtw_enqueue_cmd(cmdpriv, cmdobj);
5063
5064 if (res == _SUCCESS && timeout_ms >= 0) {
5065 rtw_sctx_wait(&sctx, __func__);
5066 _enter_critical_mutex(&cmdpriv->sctx_mutex, NULL);
5067 if (sctx.status == RTW_SCTX_SUBMITTED)
5068 cmdobj->sctx = NULL;
5069 _exit_critical_mutex(&cmdpriv->sctx_mutex, NULL);
5070 if (sctx.status != RTW_SCTX_DONE_SUCCESS)
5071 res = _FAIL;
5072 }
5073
5074 exit:
5075 return res;
5076 }
5077
rtw_run_in_thread_cmd(_adapter * adapter,void (* func)(void *),void * context)5078 u8 rtw_run_in_thread_cmd(_adapter *adapter, void (*func)(void *), void *context)
5079 {
5080 return _rtw_run_in_thread_cmd(adapter, func, context, -1);
5081 }
5082
rtw_run_in_thread_cmd_wait(_adapter * adapter,void (* func)(void *),void * context,s32 timeout_ms)5083 u8 rtw_run_in_thread_cmd_wait(_adapter *adapter, void (*func)(void *), void *context, s32 timeout_ms)
5084 {
5085 return _rtw_run_in_thread_cmd(adapter, func, context, timeout_ms);
5086 }
5087
5088 #ifdef CONFIG_FW_C2H_REG
c2h_evt_hdl(_adapter * adapter,u8 * c2h_evt,c2h_id_filter filter)5089 s32 c2h_evt_hdl(_adapter *adapter, u8 *c2h_evt, c2h_id_filter filter)
5090 {
5091 s32 ret = _FAIL;
5092 u8 buf[C2H_REG_LEN] = {0};
5093 u8 id, seq, plen;
5094 u8 *payload;
5095
5096 if (!c2h_evt) {
5097 /* No c2h event in cmd_obj, read c2h event before handling*/
5098 if (rtw_hal_c2h_evt_read(adapter, buf) != _SUCCESS)
5099 goto exit;
5100 c2h_evt = buf;
5101 }
5102
5103 rtw_hal_c2h_reg_hdr_parse(adapter, c2h_evt, &id, &seq, &plen, &payload);
5104
5105 if (filter && filter(adapter, id, seq, plen, payload) == _FALSE)
5106 goto exit;
5107
5108 ret = rtw_hal_c2h_handler(adapter, id, seq, plen, payload);
5109
5110 exit:
5111 return ret;
5112 }
5113 #endif /* CONFIG_FW_C2H_REG */
5114
session_tracker_cmd(_adapter * adapter,u8 cmd,struct sta_info * sta,u8 * local_naddr,u8 * local_port,u8 * remote_naddr,u8 * remote_port)5115 u8 session_tracker_cmd(_adapter *adapter, u8 cmd, struct sta_info *sta, u8 *local_naddr, u8 *local_port, u8 *remote_naddr, u8 *remote_port)
5116 {
5117 struct cmd_priv *cmdpriv = &adapter->cmdpriv;
5118 struct cmd_obj *cmdobj;
5119 struct drvextra_cmd_parm *cmd_parm;
5120 struct st_cmd_parm *st_parm;
5121 u8 res = _SUCCESS;
5122
5123 cmdobj = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
5124 if (cmdobj == NULL) {
5125 res = _FAIL;
5126 goto exit;
5127 }
5128
5129 cmd_parm = (struct drvextra_cmd_parm *)rtw_zmalloc(sizeof(struct drvextra_cmd_parm));
5130 if (cmd_parm == NULL) {
5131 rtw_mfree((u8 *)cmdobj, sizeof(struct cmd_obj));
5132 res = _FAIL;
5133 goto exit;
5134 }
5135
5136 st_parm = (struct st_cmd_parm *)rtw_zmalloc(sizeof(struct st_cmd_parm));
5137 if (st_parm == NULL) {
5138 rtw_mfree((u8 *)cmdobj, sizeof(struct cmd_obj));
5139 rtw_mfree((u8 *)cmd_parm, sizeof(struct drvextra_cmd_parm));
5140 res = _FAIL;
5141 goto exit;
5142 }
5143
5144 st_parm->cmd = cmd;
5145 st_parm->sta = sta;
5146 if (cmd != ST_CMD_CHK) {
5147 _rtw_memcpy(&st_parm->local_naddr, local_naddr, 4);
5148 _rtw_memcpy(&st_parm->local_port, local_port, 2);
5149 _rtw_memcpy(&st_parm->remote_naddr, remote_naddr, 4);
5150 _rtw_memcpy(&st_parm->remote_port, remote_port, 2);
5151 }
5152
5153 cmd_parm->ec_id = SESSION_TRACKER_WK_CID;
5154 cmd_parm->type = 0;
5155 cmd_parm->size = sizeof(struct st_cmd_parm);
5156 cmd_parm->pbuf = (u8 *)st_parm;
5157 init_h2fwcmd_w_parm_no_rsp(cmdobj, cmd_parm, CMD_SET_DRV_EXTRA);
5158 cmdobj->no_io = 1;
5159
5160 res = rtw_enqueue_cmd(cmdpriv, cmdobj);
5161
5162 exit:
5163 return res;
5164 }
5165
session_tracker_chk_cmd(_adapter * adapter,struct sta_info * sta)5166 inline u8 session_tracker_chk_cmd(_adapter *adapter, struct sta_info *sta)
5167 {
5168 return session_tracker_cmd(adapter, ST_CMD_CHK, sta, NULL, NULL, NULL, NULL);
5169 }
5170
session_tracker_add_cmd(_adapter * adapter,struct sta_info * sta,u8 * local_naddr,u8 * local_port,u8 * remote_naddr,u8 * remote_port)5171 inline u8 session_tracker_add_cmd(_adapter *adapter, struct sta_info *sta, u8 *local_naddr, u8 *local_port, u8 *remote_naddr, u8 *remote_port)
5172 {
5173 return session_tracker_cmd(adapter, ST_CMD_ADD, sta, local_naddr, local_port, remote_naddr, remote_port);
5174 }
5175
session_tracker_del_cmd(_adapter * adapter,struct sta_info * sta,u8 * local_naddr,u8 * local_port,u8 * remote_naddr,u8 * remote_port)5176 inline u8 session_tracker_del_cmd(_adapter *adapter, struct sta_info *sta, u8 *local_naddr, u8 *local_port, u8 *remote_naddr, u8 *remote_port)
5177 {
5178 return session_tracker_cmd(adapter, ST_CMD_DEL, sta, local_naddr, local_port, remote_naddr, remote_port);
5179 }
5180
session_tracker_chk_for_sta(_adapter * adapter,struct sta_info * sta)5181 void session_tracker_chk_for_sta(_adapter *adapter, struct sta_info *sta)
5182 {
5183 struct st_ctl_t *st_ctl = &sta->st_ctl;
5184 int i;
5185 _irqL irqL;
5186 _list *plist, *phead, *pnext;
5187 _list dlist;
5188 struct session_tracker *st = NULL;
5189 u8 op_wfd_mode = MIRACAST_DISABLED;
5190
5191 if (DBG_SESSION_TRACKER)
5192 RTW_INFO(FUNC_ADPT_FMT" sta:%p\n", FUNC_ADPT_ARG(adapter), sta);
5193
5194 if (!(sta->state & WIFI_ASOC_STATE))
5195 goto exit;
5196
5197 for (i = 0; i < SESSION_TRACKER_REG_ID_NUM; i++) {
5198 if (st_ctl->reg[i].s_proto != 0)
5199 break;
5200 }
5201 if (i >= SESSION_TRACKER_REG_ID_NUM)
5202 goto chk_sta;
5203
5204 _rtw_init_listhead(&dlist);
5205
5206 _enter_critical_bh(&st_ctl->tracker_q.lock, &irqL);
5207
5208 phead = &st_ctl->tracker_q.queue;
5209 plist = get_next(phead);
5210 pnext = get_next(plist);
5211 while (rtw_end_of_queue_search(phead, plist) == _FALSE) {
5212 st = LIST_CONTAINOR(plist, struct session_tracker, list);
5213 plist = pnext;
5214 pnext = get_next(pnext);
5215
5216 if (st->status != ST_STATUS_ESTABLISH
5217 && rtw_get_passing_time_ms(st->set_time) > ST_EXPIRE_MS
5218 ) {
5219 rtw_list_delete(&st->list);
5220 rtw_list_insert_tail(&st->list, &dlist);
5221 }
5222
5223 /* TODO: check OS for status update */
5224 if (st->status == ST_STATUS_CHECK)
5225 st->status = ST_STATUS_ESTABLISH;
5226
5227 if (st->status != ST_STATUS_ESTABLISH)
5228 continue;
5229
5230 #ifdef CONFIG_WFD
5231 if (0)
5232 RTW_INFO(FUNC_ADPT_FMT" local:%u, remote:%u, rtsp:%u, %u, %u\n", FUNC_ADPT_ARG(adapter)
5233 , ntohs(st->local_port), ntohs(st->remote_port), adapter->wfd_info.rtsp_ctrlport, adapter->wfd_info.tdls_rtsp_ctrlport
5234 , adapter->wfd_info.peer_rtsp_ctrlport);
5235 if (ntohs(st->local_port) == adapter->wfd_info.rtsp_ctrlport)
5236 op_wfd_mode |= MIRACAST_SINK;
5237 if (ntohs(st->local_port) == adapter->wfd_info.tdls_rtsp_ctrlport)
5238 op_wfd_mode |= MIRACAST_SINK;
5239 if (ntohs(st->remote_port) == adapter->wfd_info.peer_rtsp_ctrlport)
5240 op_wfd_mode |= MIRACAST_SOURCE;
5241 #endif
5242 }
5243
5244 _exit_critical_bh(&st_ctl->tracker_q.lock, &irqL);
5245
5246 plist = get_next(&dlist);
5247 while (rtw_end_of_queue_search(&dlist, plist) == _FALSE) {
5248 st = LIST_CONTAINOR(plist, struct session_tracker, list);
5249 plist = get_next(plist);
5250 rtw_mfree((u8 *)st, sizeof(struct session_tracker));
5251 }
5252
5253 chk_sta:
5254 if (STA_OP_WFD_MODE(sta) != op_wfd_mode) {
5255 STA_SET_OP_WFD_MODE(sta, op_wfd_mode);
5256 rtw_sta_media_status_rpt_cmd(adapter, sta, 1);
5257 }
5258
5259 exit:
5260 return;
5261 }
5262
session_tracker_chk_for_adapter(_adapter * adapter)5263 void session_tracker_chk_for_adapter(_adapter *adapter)
5264 {
5265 struct sta_priv *stapriv = &adapter->stapriv;
5266 struct sta_info *sta;
5267 int i;
5268 _irqL irqL;
5269 _list *plist, *phead;
5270 u8 op_wfd_mode = MIRACAST_DISABLED;
5271
5272 _enter_critical_bh(&stapriv->sta_hash_lock, &irqL);
5273
5274 for (i = 0; i < NUM_STA; i++) {
5275 phead = &(stapriv->sta_hash[i]);
5276 plist = get_next(phead);
5277
5278 while ((rtw_end_of_queue_search(phead, plist)) == _FALSE) {
5279 sta = LIST_CONTAINOR(plist, struct sta_info, hash_list);
5280 plist = get_next(plist);
5281
5282 session_tracker_chk_for_sta(adapter, sta);
5283
5284 op_wfd_mode |= STA_OP_WFD_MODE(sta);
5285 }
5286 }
5287
5288 _exit_critical_bh(&stapriv->sta_hash_lock, &irqL);
5289
5290 #ifdef CONFIG_WFD
5291 adapter->wfd_info.op_wfd_mode = MIRACAST_MODE_REVERSE(op_wfd_mode);
5292 #endif
5293 }
5294
session_tracker_cmd_hdl(_adapter * adapter,struct st_cmd_parm * parm)5295 void session_tracker_cmd_hdl(_adapter *adapter, struct st_cmd_parm *parm)
5296 {
5297 u8 cmd = parm->cmd;
5298 struct sta_info *sta = parm->sta;
5299
5300 if (cmd == ST_CMD_CHK) {
5301 if (sta)
5302 session_tracker_chk_for_sta(adapter, sta);
5303 else
5304 session_tracker_chk_for_adapter(adapter);
5305
5306 goto exit;
5307
5308 } else if (cmd == ST_CMD_ADD || cmd == ST_CMD_DEL) {
5309 struct st_ctl_t *st_ctl;
5310 u32 local_naddr = parm->local_naddr;
5311 u16 local_port = parm->local_port;
5312 u32 remote_naddr = parm->remote_naddr;
5313 u16 remote_port = parm->remote_port;
5314 struct session_tracker *st = NULL;
5315 _irqL irqL;
5316 _list *plist, *phead;
5317 u8 free_st = 0;
5318 u8 alloc_st = 0;
5319
5320 if (DBG_SESSION_TRACKER)
5321 RTW_INFO(FUNC_ADPT_FMT" cmd:%u, sta:%p, local:"IP_FMT":"PORT_FMT", remote:"IP_FMT":"PORT_FMT"\n"
5322 , FUNC_ADPT_ARG(adapter), cmd, sta
5323 , IP_ARG(&local_naddr), PORT_ARG(&local_port)
5324 , IP_ARG(&remote_naddr), PORT_ARG(&remote_port)
5325 );
5326
5327 if (!(sta->state & WIFI_ASOC_STATE))
5328 goto exit;
5329
5330 st_ctl = &sta->st_ctl;
5331
5332 _enter_critical_bh(&st_ctl->tracker_q.lock, &irqL);
5333
5334 phead = &st_ctl->tracker_q.queue;
5335 plist = get_next(phead);
5336 while (rtw_end_of_queue_search(phead, plist) == _FALSE) {
5337 st = LIST_CONTAINOR(plist, struct session_tracker, list);
5338
5339 if (st->local_naddr == local_naddr
5340 && st->local_port == local_port
5341 && st->remote_naddr == remote_naddr
5342 && st->remote_port == remote_port)
5343 break;
5344
5345 plist = get_next(plist);
5346 }
5347
5348 if (rtw_end_of_queue_search(phead, plist) == _TRUE)
5349 st = NULL;
5350
5351 switch (cmd) {
5352 case ST_CMD_DEL:
5353 if (st) {
5354 rtw_list_delete(plist);
5355 free_st = 1;
5356 }
5357 goto unlock;
5358 case ST_CMD_ADD:
5359 if (!st)
5360 alloc_st = 1;
5361 }
5362
5363 unlock:
5364 _exit_critical_bh(&st_ctl->tracker_q.lock, &irqL);
5365
5366 if (free_st) {
5367 rtw_mfree((u8 *)st, sizeof(struct session_tracker));
5368 goto exit;
5369 }
5370
5371 if (alloc_st) {
5372 st = (struct session_tracker *)rtw_zmalloc(sizeof(struct session_tracker));
5373 if (!st)
5374 goto exit;
5375
5376 st->local_naddr = local_naddr;
5377 st->local_port = local_port;
5378 st->remote_naddr = remote_naddr;
5379 st->remote_port = remote_port;
5380 st->set_time = rtw_get_current_time();
5381 st->status = ST_STATUS_CHECK;
5382
5383 _enter_critical_bh(&st_ctl->tracker_q.lock, &irqL);
5384 rtw_list_insert_tail(&st->list, phead);
5385 _exit_critical_bh(&st_ctl->tracker_q.lock, &irqL);
5386 }
5387 }
5388
5389 exit:
5390 return;
5391 }
5392
5393 #if defined(CONFIG_RTW_MESH) && defined(RTW_PER_CMD_SUPPORT_FW)
rtw_req_per_cmd_hdl(_adapter * adapter)5394 static s32 rtw_req_per_cmd_hdl(_adapter *adapter)
5395 {
5396 struct dvobj_priv *dvobj = adapter_to_dvobj(adapter);
5397 struct macid_ctl_t *macid_ctl = dvobj_to_macidctl(dvobj);
5398 struct macid_bmp req_macid_bmp, *macid_bmp;
5399 u8 i, ret = _FAIL;
5400
5401 macid_bmp = &macid_ctl->if_g[adapter->iface_id];
5402 _rtw_memcpy(&req_macid_bmp, macid_bmp, sizeof(struct macid_bmp));
5403
5404 /* Clear none mesh's macid */
5405 for (i = 0; i < macid_ctl->num; i++) {
5406 u8 role;
5407 role = GET_H2CCMD_MSRRPT_PARM_ROLE(&macid_ctl->h2c_msr[i]);
5408 if (role != H2C_MSR_ROLE_MESH)
5409 rtw_macid_map_clr(&req_macid_bmp, i);
5410 }
5411
5412 /* group_macid: always be 0 in NIC, so only pass macid_bitmap.m0
5413 * rpt_type: 0 includes all info in 1, use 0 for now
5414 * macid_bitmap: pass m0 only for NIC
5415 */
5416 ret = rtw_hal_set_req_per_rpt_cmd(adapter, 0, 0, req_macid_bmp.m0);
5417
5418 return ret;
5419 }
5420
rtw_req_per_cmd(_adapter * adapter)5421 u8 rtw_req_per_cmd(_adapter *adapter)
5422 {
5423 struct cmd_obj *cmdobj;
5424 struct drvextra_cmd_parm *parm;
5425 struct cmd_priv *pcmdpriv = &adapter->cmdpriv;
5426 struct submit_ctx sctx;
5427 u8 res = _SUCCESS;
5428
5429 parm = (struct drvextra_cmd_parm *)rtw_zmalloc(sizeof(struct drvextra_cmd_parm));
5430 if (parm == NULL) {
5431 res = _FAIL;
5432 goto exit;
5433 }
5434
5435 parm->ec_id = REQ_PER_CMD_WK_CID;
5436 parm->type = 0;
5437 parm->size = 0;
5438 parm->pbuf = NULL;
5439
5440 cmdobj = (struct cmd_obj *)rtw_zmalloc(sizeof(*cmdobj));
5441 if (cmdobj == NULL) {
5442 res = _FAIL;
5443 rtw_mfree((u8 *)parm, sizeof(*parm));
5444 goto exit;
5445 }
5446
5447 init_h2fwcmd_w_parm_no_rsp(cmdobj, parm, CMD_SET_DRV_EXTRA);
5448
5449 res = rtw_enqueue_cmd(pcmdpriv, cmdobj);
5450
5451 exit:
5452 return res;
5453 }
5454 #endif
5455
5456
rtw_ac_parm_cmd_hdl(_adapter * padapter,u8 * _ac_parm_buf,int ac_type)5457 void rtw_ac_parm_cmd_hdl(_adapter *padapter, u8 *_ac_parm_buf, int ac_type)
5458 {
5459
5460 u32 ac_parm_buf;
5461
5462 _rtw_memcpy(&ac_parm_buf, _ac_parm_buf, sizeof(ac_parm_buf));
5463 switch (ac_type) {
5464 case XMIT_VO_QUEUE:
5465 RTW_INFO(FUNC_NDEV_FMT" AC_VO = 0x%08x\n", FUNC_ADPT_ARG(padapter), (unsigned int) ac_parm_buf);
5466 rtw_hal_set_hwreg(padapter, HW_VAR_AC_PARAM_VO, (u8 *)(&ac_parm_buf));
5467 break;
5468
5469 case XMIT_VI_QUEUE:
5470 RTW_INFO(FUNC_NDEV_FMT" AC_VI = 0x%08x\n", FUNC_ADPT_ARG(padapter), (unsigned int) ac_parm_buf);
5471 rtw_hal_set_hwreg(padapter, HW_VAR_AC_PARAM_VI, (u8 *)(&ac_parm_buf));
5472 break;
5473
5474 case XMIT_BE_QUEUE:
5475 RTW_INFO(FUNC_NDEV_FMT" AC_BE = 0x%08x\n", FUNC_ADPT_ARG(padapter), (unsigned int) ac_parm_buf);
5476 rtw_hal_set_hwreg(padapter, HW_VAR_AC_PARAM_BE, (u8 *)(&ac_parm_buf));
5477 break;
5478
5479 case XMIT_BK_QUEUE:
5480 RTW_INFO(FUNC_NDEV_FMT" AC_BK = 0x%08x\n", FUNC_ADPT_ARG(padapter), (unsigned int) ac_parm_buf);
5481 rtw_hal_set_hwreg(padapter, HW_VAR_AC_PARAM_BK, (u8 *)(&ac_parm_buf));
5482 break;
5483
5484 default:
5485 break;
5486 }
5487
5488 }
5489
5490
rtw_drvextra_cmd_hdl(_adapter * padapter,unsigned char * pbuf)5491 u8 rtw_drvextra_cmd_hdl(_adapter *padapter, unsigned char *pbuf)
5492 {
5493 int ret = H2C_SUCCESS;
5494 struct drvextra_cmd_parm *pdrvextra_cmd;
5495
5496 if (!pbuf)
5497 return H2C_PARAMETERS_ERROR;
5498
5499 pdrvextra_cmd = (struct drvextra_cmd_parm *)pbuf;
5500
5501 switch (pdrvextra_cmd->ec_id) {
5502 case STA_MSTATUS_RPT_WK_CID:
5503 rtw_sta_media_status_rpt_cmd_hdl(padapter, (struct sta_media_status_rpt_cmd_parm *)pdrvextra_cmd->pbuf);
5504 break;
5505
5506 case DYNAMIC_CHK_WK_CID:/*only primary padapter go to this cmd, but execute dynamic_chk_wk_hdl() for two interfaces */
5507 rtw_dynamic_chk_wk_hdl(padapter);
5508 break;
5509 case POWER_SAVING_CTRL_WK_CID:
5510 power_saving_wk_hdl(padapter);
5511 break;
5512 #ifdef CONFIG_LPS
5513 case LPS_CTRL_WK_CID:
5514 lps_ctrl_wk_hdl(padapter, (u8)pdrvextra_cmd->type, pdrvextra_cmd->pbuf);
5515 break;
5516 case DM_IN_LPS_WK_CID:
5517 rtw_dm_in_lps_hdl(padapter);
5518 break;
5519 case LPS_CHANGE_DTIM_CID:
5520 rtw_lps_change_dtim_hdl(padapter, (u8)pdrvextra_cmd->type);
5521 break;
5522 #endif
5523 #if (RATE_ADAPTIVE_SUPPORT == 1)
5524 case RTP_TIMER_CFG_WK_CID:
5525 rpt_timer_setting_wk_hdl(padapter, pdrvextra_cmd->type);
5526 break;
5527 #endif
5528 #ifdef CONFIG_ANTENNA_DIVERSITY
5529 case ANT_SELECT_WK_CID:
5530 antenna_select_wk_hdl(padapter, pdrvextra_cmd->type);
5531 break;
5532 #endif
5533 #ifdef CONFIG_P2P_PS
5534 case P2P_PS_WK_CID:
5535 p2p_ps_wk_hdl(padapter, pdrvextra_cmd->type);
5536 break;
5537 #endif
5538 #ifdef CONFIG_P2P
5539 case P2P_PROTO_WK_CID:
5540 /*
5541 * Commented by Albert 2011/07/01
5542 * I used the type_size as the type command
5543 */
5544 ret = p2p_protocol_wk_hdl(padapter, pdrvextra_cmd->type, pdrvextra_cmd->pbuf);
5545 break;
5546 #endif
5547 #ifdef CONFIG_AP_MODE
5548 case CHECK_HIQ_WK_CID:
5549 rtw_chk_hi_queue_hdl(padapter);
5550 break;
5551 #endif
5552 /* add for CONFIG_IEEE80211W, none 11w can use it */
5553 case RESET_SECURITYPRIV:
5554 reset_securitypriv_hdl(padapter);
5555 break;
5556 case FREE_ASSOC_RESOURCES:
5557 free_assoc_resources_hdl(padapter, (u8)pdrvextra_cmd->type);
5558 break;
5559 case C2H_WK_CID:
5560 switch (pdrvextra_cmd->type) {
5561 #ifdef CONFIG_FW_C2H_REG
5562 case C2H_TYPE_REG:
5563 c2h_evt_hdl(padapter, pdrvextra_cmd->pbuf, NULL);
5564 break;
5565 #endif
5566 #ifdef CONFIG_FW_C2H_PKT
5567 case C2H_TYPE_PKT:
5568 rtw_hal_c2h_pkt_hdl(padapter, pdrvextra_cmd->pbuf, pdrvextra_cmd->size);
5569 break;
5570 #endif
5571 default:
5572 RTW_ERR("unknown C2H type:%d\n", pdrvextra_cmd->type);
5573 rtw_warn_on(1);
5574 break;
5575 }
5576 break;
5577 #ifdef CONFIG_BEAMFORMING
5578 case BEAMFORMING_WK_CID:
5579 beamforming_wk_hdl(padapter, pdrvextra_cmd->type, pdrvextra_cmd->pbuf);
5580 break;
5581 #endif
5582 case DM_RA_MSK_WK_CID:
5583 rtw_dm_ra_mask_hdl(padapter, (struct sta_info *)pdrvextra_cmd->pbuf);
5584 break;
5585 #ifdef CONFIG_BT_COEXIST
5586 case BTINFO_WK_CID:
5587 rtw_btinfo_hdl(padapter, pdrvextra_cmd->pbuf, pdrvextra_cmd->size);
5588 break;
5589 case BTC_REDUCE_WL_TXPWR_CID:
5590 rtw_btc_reduce_wl_txpwr_hdl(padapter, pdrvextra_cmd->type);
5591 break;
5592 #endif
5593 #ifdef CONFIG_DFS_MASTER
5594 case DFS_RADAR_DETECT_WK_CID:
5595 rtw_dfs_rd_hdl(padapter);
5596 break;
5597 case DFS_RADAR_DETECT_EN_DEC_WK_CID:
5598 rtw_dfs_rd_en_decision(padapter, MLME_ACTION_NONE, 0);
5599 break;
5600 #endif
5601 case SESSION_TRACKER_WK_CID:
5602 session_tracker_cmd_hdl(padapter, (struct st_cmd_parm *)pdrvextra_cmd->pbuf);
5603 break;
5604 case EN_HW_UPDATE_TSF_WK_CID:
5605 rtw_hal_set_hwreg(padapter, HW_VAR_EN_HW_UPDATE_TSF, NULL);
5606 break;
5607 case PERIOD_TSF_UPDATE_END_WK_CID:
5608 rtw_hal_periodic_tsf_update_chk(padapter);
5609 break;
5610 case TEST_H2C_CID:
5611 rtw_hal_fill_h2c_cmd(padapter, pdrvextra_cmd->pbuf[0], pdrvextra_cmd->size - 1, &pdrvextra_cmd->pbuf[1]);
5612 break;
5613 case MP_CMD_WK_CID:
5614 #ifdef CONFIG_MP_INCLUDED
5615 ret = rtw_mp_cmd_hdl(padapter, pdrvextra_cmd->type);
5616 #endif
5617 break;
5618 #ifdef CONFIG_RTW_CUSTOMER_STR
5619 case CUSTOMER_STR_WK_CID:
5620 ret = rtw_customer_str_cmd_hdl(padapter, pdrvextra_cmd->type, pdrvextra_cmd->pbuf);
5621 break;
5622 #endif
5623
5624 #ifdef CONFIG_RTW_REPEATER_SON
5625 case RSON_SCAN_WK_CID:
5626 rtw_rson_scan_cmd_hdl(padapter, pdrvextra_cmd->type);
5627 break;
5628 #endif
5629
5630 #ifdef CONFIG_IOCTL_CFG80211
5631 case MGNT_TX_WK_CID:
5632 ret = rtw_mgnt_tx_handler(padapter, pdrvextra_cmd->pbuf);
5633 break;
5634 #endif /* CONFIG_IOCTL_CFG80211 */
5635
5636 #if (defined(CONFIG_P2P) && defined(CONFIG_CONCURRENT_MODE)) || defined(CONFIG_IOCTL_CFG80211)
5637 case ROCH_WK_CID:
5638 ret = rtw_roch_wk_hdl(padapter, pdrvextra_cmd->type, pdrvextra_cmd->pbuf);
5639 break;
5640 #endif /* (defined(CONFIG_P2P) && defined(CONFIG_CONCURRENT_MODE)) || defined(CONFIG_IOCTL_CFG80211) */
5641
5642 #ifdef CONFIG_MCC_MODE
5643 case MCC_CMD_WK_CID:
5644 ret = rtw_mcc_cmd_hdl(padapter, pdrvextra_cmd->type, pdrvextra_cmd->pbuf);
5645 break;
5646 #endif /* CONFIG_MCC_MODE */
5647 #if defined(CONFIG_RTW_MESH) && defined(RTW_PER_CMD_SUPPORT_FW)
5648 case REQ_PER_CMD_WK_CID:
5649 ret = rtw_req_per_cmd_hdl(padapter);
5650 break;
5651 #endif
5652 #ifdef CONFIG_SUPPORT_STATIC_SMPS
5653 case SSMPS_WK_CID :
5654 rtw_ssmps_wk_hdl(padapter, (struct ssmps_cmd_parm *)pdrvextra_cmd->pbuf);
5655 break;
5656 #endif
5657 #ifdef CONFIG_CTRL_TXSS_BY_TP
5658 case TXSS_WK_CID :
5659 rtw_ctrl_txss_wk_hdl(padapter, (struct txss_cmd_parm *)pdrvextra_cmd->pbuf);
5660 break;
5661 #endif
5662 case AC_PARM_CMD_WK_CID:
5663 rtw_ac_parm_cmd_hdl(padapter, pdrvextra_cmd->pbuf, pdrvextra_cmd->type);
5664 break;
5665 #ifdef CONFIG_AP_MODE
5666 case STOP_AP_WK_CID:
5667 stop_ap_hdl(padapter);
5668 break;
5669 #endif
5670 #ifdef CONFIG_RTW_TOKEN_BASED_XMIT
5671 case TBTX_CONTROL_TX_WK_CID:
5672 tx_control_hdl(padapter);
5673 break;
5674 #endif
5675 default:
5676 break;
5677 }
5678
5679 if (pdrvextra_cmd->pbuf && pdrvextra_cmd->size > 0)
5680 rtw_mfree(pdrvextra_cmd->pbuf, pdrvextra_cmd->size);
5681
5682 return ret;
5683 }
5684
rtw_survey_cmd_callback(_adapter * padapter,struct cmd_obj * pcmd)5685 void rtw_survey_cmd_callback(_adapter *padapter , struct cmd_obj *pcmd)
5686 {
5687 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
5688
5689
5690 if (pcmd->res == H2C_DROPPED) {
5691 /* TODO: cancel timer and do timeout handler directly... */
5692 /* need to make timeout handlerOS independent */
5693 mlme_set_scan_to_timer(pmlmepriv, 1);
5694 } else if (pcmd->res != H2C_SUCCESS) {
5695 mlme_set_scan_to_timer(pmlmepriv, 1);
5696 }
5697
5698 /* free cmd */
5699 rtw_free_cmd_obj(pcmd);
5700
5701 }
rtw_disassoc_cmd_callback(_adapter * padapter,struct cmd_obj * pcmd)5702 void rtw_disassoc_cmd_callback(_adapter *padapter, struct cmd_obj *pcmd)
5703 {
5704 _irqL irqL;
5705 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
5706
5707
5708 if (pcmd->res != H2C_SUCCESS) {
5709 _enter_critical_bh(&pmlmepriv->lock, &irqL);
5710 set_fwstate(pmlmepriv, WIFI_ASOC_STATE);
5711 _exit_critical_bh(&pmlmepriv->lock, &irqL);
5712 goto exit;
5713 }
5714 #ifdef CONFIG_BR_EXT
5715 else /* clear bridge database */
5716 nat25_db_cleanup(padapter);
5717 #endif /* CONFIG_BR_EXT */
5718
5719 /* free cmd */
5720 rtw_free_cmd_obj(pcmd);
5721
5722 exit:
5723 return;
5724 }
5725
rtw_joinbss_cmd_callback(_adapter * padapter,struct cmd_obj * pcmd)5726 void rtw_joinbss_cmd_callback(_adapter *padapter, struct cmd_obj *pcmd)
5727 {
5728 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
5729
5730
5731 if (pcmd->res == H2C_DROPPED) {
5732 /* TODO: cancel timer and do timeout handler directly... */
5733 /* need to make timeout handlerOS independent */
5734 _set_timer(&pmlmepriv->assoc_timer, 1);
5735 } else if (pcmd->res != H2C_SUCCESS)
5736 _set_timer(&pmlmepriv->assoc_timer, 1);
5737
5738 rtw_free_cmd_obj(pcmd);
5739
5740 }
5741
rtw_create_ibss_post_hdl(_adapter * padapter,int status)5742 void rtw_create_ibss_post_hdl(_adapter *padapter, int status)
5743 {
5744 _irqL irqL;
5745 struct wlan_network *pwlan = NULL;
5746 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
5747 WLAN_BSSID_EX *pdev_network = &padapter->registrypriv.dev_network;
5748 struct wlan_network *mlme_cur_network = &(pmlmepriv->cur_network);
5749
5750 if (status != H2C_SUCCESS)
5751 _set_timer(&pmlmepriv->assoc_timer, 1);
5752
5753 _cancel_timer_ex(&pmlmepriv->assoc_timer);
5754
5755 _enter_critical_bh(&pmlmepriv->lock, &irqL);
5756
5757 {
5758 _irqL irqL;
5759
5760 pwlan = _rtw_alloc_network(pmlmepriv);
5761 _enter_critical_bh(&(pmlmepriv->scanned_queue.lock), &irqL);
5762 if (pwlan == NULL) {
5763 pwlan = rtw_get_oldest_wlan_network(&pmlmepriv->scanned_queue);
5764 if (pwlan == NULL) {
5765 _exit_critical_bh(&(pmlmepriv->scanned_queue.lock), &irqL);
5766 goto createbss_cmd_fail;
5767 }
5768 pwlan->last_scanned = rtw_get_current_time();
5769 } else
5770 rtw_list_insert_tail(&(pwlan->list), &pmlmepriv->scanned_queue.queue);
5771
5772 pdev_network->Length = get_WLAN_BSSID_EX_sz(pdev_network);
5773 _rtw_memcpy(&(pwlan->network), pdev_network, pdev_network->Length);
5774 /* pwlan->fixed = _TRUE; */
5775
5776 /* copy pdev_network information to pmlmepriv->cur_network */
5777 _rtw_memcpy(&mlme_cur_network->network, pdev_network, (get_WLAN_BSSID_EX_sz(pdev_network)));
5778
5779 #if 0
5780 /* reset DSConfig */
5781 mlme_cur_network->network.Configuration.DSConfig = (u32)rtw_ch2freq(pdev_network->Configuration.DSConfig);
5782 #endif
5783
5784 _clr_fwstate_(pmlmepriv, WIFI_UNDER_LINKING);
5785 _exit_critical_bh(&(pmlmepriv->scanned_queue.lock), &irqL);
5786 /* we will set WIFI_ASOC_STATE when there is one more sat to join us (rtw_stassoc_event_callback) */
5787 }
5788
5789 createbss_cmd_fail:
5790 _exit_critical_bh(&pmlmepriv->lock, &irqL);
5791 return;
5792 }
5793
5794
5795
rtw_setstaKey_cmdrsp_callback(_adapter * padapter,struct cmd_obj * pcmd)5796 void rtw_setstaKey_cmdrsp_callback(_adapter *padapter , struct cmd_obj *pcmd)
5797 {
5798
5799 struct sta_priv *pstapriv = &padapter->stapriv;
5800 struct set_stakey_rsp *psetstakey_rsp = (struct set_stakey_rsp *)(pcmd->rsp);
5801 struct sta_info *psta = rtw_get_stainfo(pstapriv, psetstakey_rsp->addr);
5802
5803
5804 if (psta == NULL) {
5805 goto exit;
5806 }
5807
5808 /* psta->cmn.aid = psta->cmn.mac_id = psetstakey_rsp->keyid; */ /* CAM_ID(CAM_ENTRY) */
5809
5810 exit:
5811
5812 rtw_free_cmd_obj(pcmd);
5813
5814
5815 }
5816
rtw_getrttbl_cmd_cmdrsp_callback(_adapter * padapter,struct cmd_obj * pcmd)5817 void rtw_getrttbl_cmd_cmdrsp_callback(_adapter *padapter, struct cmd_obj *pcmd)
5818 {
5819
5820 rtw_free_cmd_obj(pcmd);
5821 #ifdef CONFIG_MP_INCLUDED
5822 if (padapter->registrypriv.mp_mode == 1)
5823 padapter->mppriv.workparam.bcompleted = _TRUE;
5824 #endif
5825
5826
5827 }
5828
set_txq_params_cmd(_adapter * adapter,u32 ac_parm,u8 ac_type)5829 u8 set_txq_params_cmd(_adapter *adapter, u32 ac_parm, u8 ac_type)
5830 {
5831 struct cmd_obj *cmdobj;
5832 struct drvextra_cmd_parm *pdrvextra_cmd_parm;
5833 struct cmd_priv *pcmdpriv = &adapter->cmdpriv;
5834 u8 *ac_parm_buf = NULL;
5835 u8 sz;
5836 u8 res = _SUCCESS;
5837
5838
5839 cmdobj = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
5840 if (cmdobj == NULL) {
5841 res = _FAIL;
5842 goto exit;
5843 }
5844
5845 pdrvextra_cmd_parm = (struct drvextra_cmd_parm *)rtw_zmalloc(sizeof(struct drvextra_cmd_parm));
5846 if (pdrvextra_cmd_parm == NULL) {
5847 rtw_mfree((u8 *)cmdobj, sizeof(struct cmd_obj));
5848 res = _FAIL;
5849 goto exit;
5850 }
5851
5852 sz = sizeof(ac_parm);
5853 ac_parm_buf = rtw_zmalloc(sz);
5854 if (ac_parm_buf == NULL) {
5855 rtw_mfree((u8 *)cmdobj, sizeof(struct cmd_obj));
5856 rtw_mfree((u8 *)pdrvextra_cmd_parm, sizeof(struct drvextra_cmd_parm));
5857 res = _FAIL;
5858 goto exit;
5859 }
5860
5861 pdrvextra_cmd_parm->ec_id = AC_PARM_CMD_WK_CID;
5862 pdrvextra_cmd_parm->type = ac_type;
5863 pdrvextra_cmd_parm->size = sz;
5864 pdrvextra_cmd_parm->pbuf = ac_parm_buf;
5865
5866 _rtw_memcpy(ac_parm_buf, &ac_parm, sz);
5867
5868 init_h2fwcmd_w_parm_no_rsp(cmdobj, pdrvextra_cmd_parm, CMD_SET_DRV_EXTRA);
5869 res = rtw_enqueue_cmd(pcmdpriv, cmdobj);
5870
5871 exit:
5872 return res;
5873 }
5874
5875 /* Driver writes beacon length to REG for FW adjusting beacon receive time */
5876 #ifdef CONFIG_WRITE_BCN_LEN_TO_FW
rtw_write_bcnlen_to_fw_cmd(_adapter * padapter,u16 bcn_len)5877 u8 rtw_write_bcnlen_to_fw_cmd(_adapter *padapter, u16 bcn_len)
5878 {
5879 struct cmd_obj *pcmd;
5880 struct write_bcnlen_param *parm;
5881 struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
5882 u8 res = _SUCCESS;
5883
5884 pcmd = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
5885 if (pcmd == NULL) {
5886 res = _FAIL;
5887 goto exit;
5888 }
5889
5890 parm = (struct write_bcnlen_param *)rtw_zmalloc(sizeof(struct write_bcnlen_param));
5891 if (parm == NULL) {
5892 rtw_mfree((unsigned char *)pcmd, sizeof(struct cmd_obj));
5893 res = _FAIL;
5894 goto exit;
5895 }
5896
5897 parm->bcn_len = bcn_len;
5898 init_h2fwcmd_w_parm_no_rsp(pcmd, parm, CMD_WRITE_BCN_LEN);
5899 res = rtw_enqueue_cmd(pcmdpriv, pcmd);
5900
5901 exit:
5902 return res;
5903 }
5904 #endif /* CONFIG_WRITE_BCN_LEN_TO_FW */
5905
rtw_reqtxrpt_cmd(_adapter * adapter,u8 macid)5906 u8 rtw_reqtxrpt_cmd(_adapter *adapter, u8 macid)
5907 {
5908 struct cmd_obj *cmdobj;
5909 struct reqtxrpt_param *parm;
5910 struct cmd_priv *pcmdpriv = &adapter->cmdpriv;
5911 struct submit_ctx sctx;
5912 u8 flags = RTW_CMDF_WAIT_ACK;
5913 u8 res = _FAIL;
5914
5915 /* prepare cmd parameter */
5916 parm = rtw_zmalloc(sizeof(*parm));
5917 if (parm == NULL)
5918 goto exit;
5919 parm->macid = macid;
5920
5921 /* need enqueue, prepare cmd_obj and enqueue */
5922 cmdobj = rtw_zmalloc(sizeof(*cmdobj));
5923 if (cmdobj == NULL) {
5924 rtw_mfree((u8 *)parm, sizeof(*parm));
5925 goto exit;
5926 }
5927
5928 init_h2fwcmd_w_parm_no_rsp(cmdobj, parm, CMD_REQ_TXRPT);
5929
5930 if (flags & RTW_CMDF_WAIT_ACK) {
5931 cmdobj->sctx = &sctx;
5932 rtw_sctx_init(&sctx, 2000);
5933 }
5934
5935 res = rtw_enqueue_cmd(pcmdpriv, cmdobj);
5936
5937 if (res == _SUCCESS && (flags & RTW_CMDF_WAIT_ACK)) {
5938 rtw_sctx_wait(&sctx, __func__);
5939 _enter_critical_mutex(&pcmdpriv->sctx_mutex, NULL);
5940 if (sctx.status == RTW_SCTX_SUBMITTED)
5941 cmdobj->sctx = NULL;
5942 _exit_critical_mutex(&pcmdpriv->sctx_mutex, NULL);
5943 if (sctx.status != RTW_SCTX_DONE_SUCCESS)
5944 res = _FAIL;
5945 }
5946
5947 exit:
5948 return res;
5949 }
5950
5951