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 && !MLME_IS_OPCH_SW(adapter)
4345 && CHK_MLME_STATE(adapter, WIFI_UNDER_LINKING | WIFI_ASOC_STATE))
4346 sync_ch = _TRUE;
4347
4348 switch (mlme_act) {
4349 case MLME_STA_CONNECTING:
4350 MSTATE_STA_LG_NUM(&mstate)++;
4351 break;
4352 case MLME_STA_CONNECTED:
4353 MSTATE_STA_LD_NUM(&mstate)++;
4354 break;
4355 case MLME_STA_DISCONNECTED:
4356 break;
4357 #ifdef CONFIG_AP_MODE
4358 case MLME_AP_STARTED:
4359 MSTATE_AP_NUM(&mstate)++;
4360 break;
4361 case MLME_AP_STOPPED:
4362 break;
4363 #endif
4364 #ifdef CONFIG_RTW_MESH
4365 case MLME_MESH_STARTED:
4366 MSTATE_MESH_NUM(&mstate)++;
4367 break;
4368 case MLME_MESH_STOPPED:
4369 break;
4370 #endif
4371 default:
4372 rtw_warn_on(1);
4373 break;
4374 }
4375
4376 if (sync_ch == _TRUE) {
4377 if (!rtw_is_chbw_grouped(mlmeext->cur_channel, mlmeext->cur_bwmode, mlmeext->cur_ch_offset, u_ch, u_bw, u_offset)) {
4378 RTW_WARN(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 } else {
4386 u_ch = mlmeext->cur_channel;
4387 u_bw = mlmeext->cur_bwmode;
4388 u_offset = mlmeext->cur_ch_offset;
4389 }
4390 }
4391
4392 if (MSTATE_STA_LG_NUM(&mstate) > 0) {
4393 /* STA mode is linking */
4394 goto apply;
4395 }
4396
4397 if (MSTATE_STA_LD_NUM(&mstate) > 0) {
4398 if (rtw_chset_is_dfs_chbw(rfctl->channel_set, u_ch, u_bw, u_offset)) {
4399 /*
4400 * if operate as slave w/o radar detect,
4401 * rely on AP on which STA mode connects
4402 */
4403 if (IS_DFS_SLAVE_WITH_RD(rfctl) && !rtw_rfctl_dfs_domain_unknown(rfctl))
4404 needed = _TRUE;
4405 ld_sta_in_dfs = _TRUE;
4406 }
4407 goto apply;
4408 }
4409
4410 if (!MSTATE_AP_NUM(&mstate) && !MSTATE_MESH_NUM(&mstate)) {
4411 /* No working AP/Mesh mode */
4412 goto apply;
4413 }
4414
4415 if (rtw_chset_is_dfs_chbw(rfctl->channel_set, u_ch, u_bw, u_offset))
4416 needed = _TRUE;
4417
4418 apply:
4419
4420 RTW_INFO(FUNC_ADPT_FMT" needed:%d, mlme_act:%u, excl_ifbmp:0x%02x\n"
4421 , FUNC_ADPT_ARG(adapter), needed, mlme_act, excl_ifbmp);
4422 RTW_INFO(FUNC_ADPT_FMT" ld_sta_num:%u, lg_sta_num:%u, ap_num:%u, mesh_num:%u, %u,%u,%u\n"
4423 , FUNC_ADPT_ARG(adapter), MSTATE_STA_LD_NUM(&mstate), MSTATE_STA_LG_NUM(&mstate)
4424 , MSTATE_AP_NUM(&mstate), MSTATE_MESH_NUM(&mstate)
4425 , u_ch, u_bw, u_offset);
4426
4427 if (needed == _TRUE)
4428 rtw_dfs_rd_enable(rfctl, u_ch, u_bw, u_offset, ld_sta_in_dfs);
4429 else
4430 rtw_dfs_rd_disable(rfctl, u_ch, u_bw, u_offset, ld_sta_in_dfs);
4431 }
4432
rtw_dfs_rd_en_decision_cmd(_adapter * adapter)4433 u8 rtw_dfs_rd_en_decision_cmd(_adapter *adapter)
4434 {
4435 struct cmd_obj *cmdobj;
4436 struct drvextra_cmd_parm *parm;
4437 struct cmd_priv *cmdpriv = &adapter->cmdpriv;
4438 u8 res = _FAIL;
4439
4440 cmdobj = rtw_zmalloc(sizeof(struct cmd_obj));
4441 if (cmdobj == NULL)
4442 goto exit;
4443
4444 parm = rtw_zmalloc(sizeof(struct drvextra_cmd_parm));
4445 if (parm == NULL) {
4446 rtw_mfree(cmdobj, sizeof(struct cmd_obj));
4447 goto exit;
4448 }
4449
4450 parm->ec_id = DFS_RADAR_DETECT_EN_DEC_WK_CID;
4451 parm->type = 0;
4452 parm->size = 0;
4453 parm->pbuf = NULL;
4454
4455 init_h2fwcmd_w_parm_no_rsp(cmdobj, parm, CMD_SET_DRV_EXTRA);
4456 res = rtw_enqueue_cmd(cmdpriv, cmdobj);
4457
4458 exit:
4459 return res;
4460 }
4461 #endif /* CONFIG_DFS_MASTER */
4462
4463 #endif /* CONFIG_AP_MODE */
4464
4465 #ifdef CONFIG_BT_COEXIST
4466 struct btinfo {
4467 u8 cid;
4468 u8 len;
4469
4470 u8 bConnection:1;
4471 u8 bSCOeSCO:1;
4472 u8 bInQPage:1;
4473 u8 bACLBusy:1;
4474 u8 bSCOBusy:1;
4475 u8 bHID:1;
4476 u8 bA2DP:1;
4477 u8 bFTP:1;
4478
4479 u8 retry_cnt:4;
4480 u8 rsvd_34:1;
4481 u8 rsvd_35:1;
4482 u8 rsvd_36:1;
4483 u8 rsvd_37:1;
4484
4485 u8 rssi;
4486
4487 u8 rsvd_50:1;
4488 u8 rsvd_51:1;
4489 u8 rsvd_52:1;
4490 u8 rsvd_53:1;
4491 u8 rsvd_54:1;
4492 u8 rsvd_55:1;
4493 u8 eSCO_SCO:1;
4494 u8 Master_Slave:1;
4495
4496 u8 rsvd_6;
4497 u8 rsvd_7;
4498 };
4499
btinfo_evt_dump(void * sel,void * buf)4500 void btinfo_evt_dump(void *sel, void *buf)
4501 {
4502 struct btinfo *info = (struct btinfo *)buf;
4503
4504 RTW_PRINT_SEL(sel, "cid:0x%02x, len:%u\n", info->cid, info->len);
4505
4506 if (info->len > 2)
4507 RTW_PRINT_SEL(sel, "byte2:%s%s%s%s%s%s%s%s\n"
4508 , info->bConnection ? "bConnection " : ""
4509 , info->bSCOeSCO ? "bSCOeSCO " : ""
4510 , info->bInQPage ? "bInQPage " : ""
4511 , info->bACLBusy ? "bACLBusy " : ""
4512 , info->bSCOBusy ? "bSCOBusy " : ""
4513 , info->bHID ? "bHID " : ""
4514 , info->bA2DP ? "bA2DP " : ""
4515 , info->bFTP ? "bFTP" : ""
4516 );
4517
4518 if (info->len > 3)
4519 RTW_PRINT_SEL(sel, "retry_cnt:%u\n", info->retry_cnt);
4520
4521 if (info->len > 4)
4522 RTW_PRINT_SEL(sel, "rssi:%u\n", info->rssi);
4523
4524 if (info->len > 5)
4525 RTW_PRINT_SEL(sel, "byte5:%s%s\n"
4526 , info->eSCO_SCO ? "eSCO_SCO " : ""
4527 , info->Master_Slave ? "Master_Slave " : ""
4528 );
4529 }
4530
rtw_btinfo_hdl(_adapter * adapter,u8 * buf,u16 buf_len)4531 static void rtw_btinfo_hdl(_adapter *adapter, u8 *buf, u16 buf_len)
4532 {
4533 #define BTINFO_WIFI_FETCH 0x23
4534 #define BTINFO_BT_AUTO_RPT 0x27
4535 #ifdef CONFIG_BT_COEXIST_SOCKET_TRX
4536 struct btinfo_8761ATV *info = (struct btinfo_8761ATV *)buf;
4537 #else /* !CONFIG_BT_COEXIST_SOCKET_TRX */
4538 struct btinfo *info = (struct btinfo *)buf;
4539 #endif /* CONFIG_BT_COEXIST_SOCKET_TRX */
4540 u8 cmd_idx;
4541 u8 len;
4542
4543 cmd_idx = info->cid;
4544
4545 if (info->len > buf_len - 2) {
4546 rtw_warn_on(1);
4547 len = buf_len - 2;
4548 } else
4549 len = info->len;
4550
4551 /* #define DBG_PROC_SET_BTINFO_EVT */
4552 #ifdef DBG_PROC_SET_BTINFO_EVT
4553 #ifdef CONFIG_BT_COEXIST_SOCKET_TRX
4554 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"
4555 , __func__, buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7]);
4556 #else/* !CONFIG_BT_COEXIST_SOCKET_TRX */
4557 btinfo_evt_dump(RTW_DBGDUMP, info);
4558 #endif /* CONFIG_BT_COEXIST_SOCKET_TRX */
4559 #endif /* DBG_PROC_SET_BTINFO_EVT */
4560
4561 /* transform BT-FW btinfo to WiFI-FW C2H format and notify */
4562 if (cmd_idx == BTINFO_WIFI_FETCH)
4563 buf[1] = 0;
4564 else if (cmd_idx == BTINFO_BT_AUTO_RPT)
4565 buf[1] = 2;
4566 #ifdef CONFIG_BT_COEXIST_SOCKET_TRX
4567 else if (0x01 == cmd_idx || 0x02 == cmd_idx)
4568 buf[1] = buf[0];
4569 #endif /* CONFIG_BT_COEXIST_SOCKET_TRX */
4570 rtw_btcoex_BtInfoNotify(adapter , len + 1, &buf[1]);
4571 }
4572
rtw_btinfo_cmd(_adapter * adapter,u8 * buf,u16 len)4573 u8 rtw_btinfo_cmd(_adapter *adapter, u8 *buf, u16 len)
4574 {
4575 struct cmd_obj *ph2c;
4576 struct drvextra_cmd_parm *pdrvextra_cmd_parm;
4577 u8 *btinfo;
4578 struct cmd_priv *pcmdpriv = &adapter->cmdpriv;
4579 u8 res = _SUCCESS;
4580
4581 ph2c = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
4582 if (ph2c == NULL) {
4583 res = _FAIL;
4584 goto exit;
4585 }
4586
4587 pdrvextra_cmd_parm = (struct drvextra_cmd_parm *)rtw_zmalloc(sizeof(struct drvextra_cmd_parm));
4588 if (pdrvextra_cmd_parm == NULL) {
4589 rtw_mfree((u8 *)ph2c, sizeof(struct cmd_obj));
4590 res = _FAIL;
4591 goto exit;
4592 }
4593
4594 btinfo = rtw_zmalloc(len);
4595 if (btinfo == NULL) {
4596 rtw_mfree((u8 *)ph2c, sizeof(struct cmd_obj));
4597 rtw_mfree((u8 *)pdrvextra_cmd_parm, sizeof(struct drvextra_cmd_parm));
4598 res = _FAIL;
4599 goto exit;
4600 }
4601
4602 pdrvextra_cmd_parm->ec_id = BTINFO_WK_CID;
4603 pdrvextra_cmd_parm->type = 0;
4604 pdrvextra_cmd_parm->size = len;
4605 pdrvextra_cmd_parm->pbuf = btinfo;
4606
4607 _rtw_memcpy(btinfo, buf, len);
4608
4609 init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, CMD_SET_DRV_EXTRA);
4610
4611 res = rtw_enqueue_cmd(pcmdpriv, ph2c);
4612
4613 exit:
4614 return res;
4615 }
4616
rtw_btc_reduce_wl_txpwr_hdl(_adapter * adapter,u32 pwr_lvl)4617 static void rtw_btc_reduce_wl_txpwr_hdl(_adapter *adapter, u32 pwr_lvl)
4618 {
4619 rtw_btcoex_set_reduced_wl_pwr_lvl(adapter, pwr_lvl);
4620 rtw_btcoex_do_reduce_wl_pwr_lvl(adapter);
4621
4622 RTW_INFO(FUNC_ADPT_FMT ": BTC reduce WL TxPwr %d dB!\n",
4623 FUNC_ADPT_ARG(adapter), pwr_lvl);
4624 }
4625
rtw_btc_reduce_wl_txpwr_cmd(_adapter * adapter,u32 val)4626 u8 rtw_btc_reduce_wl_txpwr_cmd(_adapter *adapter, u32 val)
4627 {
4628 struct cmd_obj *pcmdobj;
4629 struct drvextra_cmd_parm *pdrvextra_cmd_parm;
4630 struct cmd_priv *pcmdpriv = &adapter->cmdpriv;
4631 u8 res = _SUCCESS;
4632
4633 pcmdobj = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
4634 if (pcmdobj == NULL) {
4635 res = _FAIL;
4636 goto exit;
4637 }
4638
4639 pdrvextra_cmd_parm = (struct drvextra_cmd_parm *)rtw_zmalloc(sizeof(struct drvextra_cmd_parm));
4640 if (pdrvextra_cmd_parm == NULL) {
4641 rtw_mfree((u8 *)pcmdobj, sizeof(struct cmd_obj));
4642 res = _FAIL;
4643 goto exit;
4644 }
4645
4646 pdrvextra_cmd_parm->ec_id = BTC_REDUCE_WL_TXPWR_CID;
4647 pdrvextra_cmd_parm->type = val;
4648 pdrvextra_cmd_parm->size = 0;
4649 pdrvextra_cmd_parm->pbuf = NULL;
4650
4651 init_h2fwcmd_w_parm_no_rsp(pcmdobj, pdrvextra_cmd_parm, CMD_SET_DRV_EXTRA);
4652
4653 res = rtw_enqueue_cmd(pcmdpriv, pcmdobj);
4654
4655 exit:
4656 return res;
4657 }
4658 #endif /* CONFIG_BT_COEXIST */
4659
rtw_test_h2c_cmd(_adapter * adapter,u8 * buf,u8 len)4660 u8 rtw_test_h2c_cmd(_adapter *adapter, u8 *buf, u8 len)
4661 {
4662 struct cmd_obj *pcmdobj;
4663 struct drvextra_cmd_parm *pdrvextra_cmd_parm;
4664 u8 *ph2c_content;
4665 struct cmd_priv *pcmdpriv = &adapter->cmdpriv;
4666 u8 res = _SUCCESS;
4667
4668 pcmdobj = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
4669 if (pcmdobj == NULL) {
4670 res = _FAIL;
4671 goto exit;
4672 }
4673
4674 pdrvextra_cmd_parm = (struct drvextra_cmd_parm *)rtw_zmalloc(sizeof(struct drvextra_cmd_parm));
4675 if (pdrvextra_cmd_parm == NULL) {
4676 rtw_mfree((u8 *)pcmdobj, sizeof(struct cmd_obj));
4677 res = _FAIL;
4678 goto exit;
4679 }
4680
4681 ph2c_content = rtw_zmalloc(len);
4682 if (ph2c_content == NULL) {
4683 rtw_mfree((u8 *)pcmdobj, sizeof(struct cmd_obj));
4684 rtw_mfree((u8 *)pdrvextra_cmd_parm, sizeof(struct drvextra_cmd_parm));
4685 res = _FAIL;
4686 goto exit;
4687 }
4688
4689 pdrvextra_cmd_parm->ec_id = TEST_H2C_CID;
4690 pdrvextra_cmd_parm->type = 0;
4691 pdrvextra_cmd_parm->size = len;
4692 pdrvextra_cmd_parm->pbuf = ph2c_content;
4693
4694 _rtw_memcpy(ph2c_content, buf, len);
4695
4696 init_h2fwcmd_w_parm_no_rsp(pcmdobj, pdrvextra_cmd_parm, CMD_SET_DRV_EXTRA);
4697
4698 res = rtw_enqueue_cmd(pcmdpriv, pcmdobj);
4699
4700 exit:
4701 return res;
4702 }
4703
4704 #ifdef CONFIG_MP_INCLUDED
rtw_mp_cmd_hdl(_adapter * padapter,u8 mp_cmd_id)4705 static s32 rtw_mp_cmd_hdl(_adapter *padapter, u8 mp_cmd_id)
4706 {
4707 HAL_DATA_TYPE *pHalData = GET_HAL_DATA(padapter);
4708 int ret = H2C_SUCCESS;
4709 uint status = _SUCCESS;
4710
4711 if (mp_cmd_id == MP_START) {
4712 if (padapter->registrypriv.mp_mode == 0) {
4713 rtw_intf_stop(padapter);
4714 rtw_hal_deinit(padapter);
4715 padapter->registrypriv.mp_mode = 1;
4716 #ifdef CONFIG_BT_COEXIST
4717 padapter->mppriv.CureFuseBTCoex = pHalData->EEPROMBluetoothCoexist;
4718 pHalData->EEPROMBluetoothCoexist = _FALSE;
4719 #endif
4720 #ifdef CONFIG_RF_POWER_TRIM
4721 if (!IS_HARDWARE_TYPE_8814A(padapter) && !IS_HARDWARE_TYPE_8822B(padapter)
4722 && !IS_HARDWARE_TYPE_8822C(padapter) && !IS_HARDWARE_TYPE_8723F(padapter)) {
4723 padapter->registrypriv.RegPwrTrimEnable = 1;
4724 rtw_hal_read_chip_info(padapter);
4725 }
4726 #endif /*CONFIG_RF_POWER_TRIM*/
4727 rtw_reset_drv_sw(padapter);
4728 #ifdef CONFIG_NEW_NETDEV_HDL
4729 if (!rtw_is_hw_init_completed(padapter)) {
4730 status = rtw_hal_init(padapter);
4731 if (status == _FAIL) {
4732 ret = H2C_REJECTED;
4733 goto exit;
4734 }
4735 rtw_hal_iface_init(padapter);
4736 }
4737 #else
4738 status = rtw_hal_init(padapter);
4739 if (status == _FAIL) {
4740 ret = H2C_REJECTED;
4741 goto exit;
4742 }
4743 #endif /*CONFIG_NEW_NETDEV_HDL*/
4744 #ifndef RTW_HALMAC
4745 rtw_intf_start(padapter);
4746 #endif /* !RTW_HALMAC */
4747 #ifdef RTW_HALMAC /*for New IC*/
4748 MPT_InitializeAdapter(padapter, 1);
4749 #endif /* CONFIG_MP_INCLUDED */
4750 }
4751
4752 if (padapter->registrypriv.mp_mode == 0) {
4753 ret = H2C_REJECTED;
4754 goto exit;
4755 }
4756
4757 if (padapter->mppriv.mode == MP_OFF) {
4758 if (mp_start_test(padapter) == _FAIL) {
4759 ret = H2C_REJECTED;
4760 goto exit;
4761 }
4762 padapter->mppriv.mode = MP_ON;
4763 MPT_PwrCtlDM(padapter, 0);
4764 }
4765 padapter->mppriv.bmac_filter = _FALSE;
4766 #ifdef CONFIG_RTL8723B
4767 #ifdef CONFIG_USB_HCI
4768 rtw_write32(padapter, 0x765, 0x0000);
4769 rtw_write32(padapter, 0x948, 0x0280);
4770 #else
4771 rtw_write32(padapter, 0x765, 0x0000);
4772 rtw_write32(padapter, 0x948, 0x0000);
4773 #endif
4774 #ifdef CONFIG_FOR_RTL8723BS_VQ0
4775 rtw_write32(padapter, 0x765, 0x0000);
4776 rtw_write32(padapter, 0x948, 0x0280);
4777 #endif
4778 rtw_write8(padapter, 0x66, 0x27); /*Open BT uart Log*/
4779 rtw_write8(padapter, 0xc50, 0x20); /*for RX init Gain*/
4780 #endif
4781 odm_write_dig(&pHalData->odmpriv, 0x20);
4782
4783 } else if (mp_cmd_id == MP_STOP) {
4784 if (padapter->registrypriv.mp_mode == 1) {
4785 MPT_DeInitAdapter(padapter);
4786 rtw_intf_stop(padapter);
4787 rtw_hal_deinit(padapter);
4788 padapter->registrypriv.mp_mode = 0;
4789 #ifdef CONFIG_BT_COEXIST
4790 pHalData->EEPROMBluetoothCoexist = padapter->mppriv.CureFuseBTCoex;
4791 #endif
4792 rtw_reset_drv_sw(padapter);
4793 #ifdef CONFIG_NEW_NETDEV_HDL
4794 if (!rtw_is_hw_init_completed(padapter)) {
4795 status = rtw_hal_init(padapter);
4796 if (status == _FAIL) {
4797 ret = H2C_REJECTED;
4798 goto exit;
4799 }
4800 rtw_hal_iface_init(padapter);
4801 }
4802 #else
4803 status = rtw_hal_init(padapter);
4804 if (status == _FAIL) {
4805 ret = H2C_REJECTED;
4806 goto exit;
4807 }
4808 #endif /*CONFIG_NEW_NETDEV_HDL*/
4809 #ifndef RTW_HALMAC
4810 rtw_intf_start(padapter);
4811 #endif /* !RTW_HALMAC */
4812 }
4813
4814 if (padapter->mppriv.mode != MP_OFF) {
4815 mp_stop_test(padapter);
4816 padapter->mppriv.mode = MP_OFF;
4817 }
4818
4819 } else {
4820 RTW_INFO(FUNC_ADPT_FMT"invalid id:%d\n", FUNC_ADPT_ARG(padapter), mp_cmd_id);
4821 ret = H2C_PARAMETERS_ERROR;
4822 rtw_warn_on(1);
4823 }
4824
4825 exit:
4826 return ret;
4827 }
4828
rtw_mp_cmd(_adapter * adapter,u8 mp_cmd_id,u8 flags)4829 u8 rtw_mp_cmd(_adapter *adapter, u8 mp_cmd_id, u8 flags)
4830 {
4831 struct cmd_obj *cmdobj;
4832 struct drvextra_cmd_parm *parm;
4833 struct cmd_priv *pcmdpriv = &adapter->cmdpriv;
4834 struct submit_ctx sctx;
4835 u8 res = _SUCCESS;
4836
4837 parm = (struct drvextra_cmd_parm *)rtw_zmalloc(sizeof(struct drvextra_cmd_parm));
4838 if (parm == NULL) {
4839 res = _FAIL;
4840 goto exit;
4841 }
4842
4843 parm->ec_id = MP_CMD_WK_CID;
4844 parm->type = mp_cmd_id;
4845 parm->size = 0;
4846 parm->pbuf = NULL;
4847
4848 if (flags & RTW_CMDF_DIRECTLY) {
4849 /* no need to enqueue, do the cmd hdl directly and free cmd parameter */
4850 if (H2C_SUCCESS != rtw_mp_cmd_hdl(adapter, mp_cmd_id))
4851 res = _FAIL;
4852 rtw_mfree((u8 *)parm, sizeof(*parm));
4853 } else {
4854 /* need enqueue, prepare cmd_obj and enqueue */
4855 cmdobj = (struct cmd_obj *)rtw_zmalloc(sizeof(*cmdobj));
4856 if (cmdobj == NULL) {
4857 res = _FAIL;
4858 rtw_mfree((u8 *)parm, sizeof(*parm));
4859 goto exit;
4860 }
4861
4862 init_h2fwcmd_w_parm_no_rsp(cmdobj, parm, CMD_SET_DRV_EXTRA);
4863
4864 if (flags & RTW_CMDF_WAIT_ACK) {
4865 cmdobj->sctx = &sctx;
4866 rtw_sctx_init(&sctx, 10 * 1000);
4867 }
4868
4869 res = rtw_enqueue_cmd(pcmdpriv, cmdobj);
4870
4871 if (res == _SUCCESS && (flags & RTW_CMDF_WAIT_ACK)) {
4872 rtw_sctx_wait(&sctx, __func__);
4873 _enter_critical_mutex(&pcmdpriv->sctx_mutex, NULL);
4874 if (sctx.status == RTW_SCTX_SUBMITTED)
4875 cmdobj->sctx = NULL;
4876 _exit_critical_mutex(&pcmdpriv->sctx_mutex, NULL);
4877 if (sctx.status != RTW_SCTX_DONE_SUCCESS)
4878 res = _FAIL;
4879 }
4880 }
4881
4882 exit:
4883 return res;
4884 }
4885 #endif /*CONFIG_MP_INCLUDED*/
4886
4887 #ifdef CONFIG_RTW_CUSTOMER_STR
rtw_customer_str_cmd_hdl(_adapter * adapter,u8 write,const u8 * cstr)4888 static s32 rtw_customer_str_cmd_hdl(_adapter *adapter, u8 write, const u8 *cstr)
4889 {
4890 int ret = H2C_SUCCESS;
4891
4892 if (write)
4893 ret = rtw_hal_h2c_customer_str_write(adapter, cstr);
4894 else
4895 ret = rtw_hal_h2c_customer_str_req(adapter);
4896
4897 return ret == _SUCCESS ? H2C_SUCCESS : H2C_REJECTED;
4898 }
4899
rtw_customer_str_cmd(_adapter * adapter,u8 write,const u8 * cstr)4900 static u8 rtw_customer_str_cmd(_adapter *adapter, u8 write, const u8 *cstr)
4901 {
4902 struct cmd_obj *cmdobj;
4903 struct drvextra_cmd_parm *parm;
4904 u8 *str = NULL;
4905 struct cmd_priv *pcmdpriv = &adapter->cmdpriv;
4906 struct submit_ctx sctx;
4907 u8 res = _SUCCESS;
4908
4909 parm = (struct drvextra_cmd_parm *)rtw_zmalloc(sizeof(struct drvextra_cmd_parm));
4910 if (parm == NULL) {
4911 res = _FAIL;
4912 goto exit;
4913 }
4914
4915 if (write) {
4916 str = rtw_zmalloc(RTW_CUSTOMER_STR_LEN);
4917 if (str == NULL) {
4918 rtw_mfree((u8 *)parm, sizeof(struct drvextra_cmd_parm));
4919 res = _FAIL;
4920 goto exit;
4921 }
4922 }
4923
4924 parm->ec_id = CUSTOMER_STR_WK_CID;
4925 parm->type = write;
4926 parm->size = write ? RTW_CUSTOMER_STR_LEN : 0;
4927 parm->pbuf = write ? str : NULL;
4928
4929 if (write)
4930 _rtw_memcpy(str, cstr, RTW_CUSTOMER_STR_LEN);
4931
4932 /* need enqueue, prepare cmd_obj and enqueue */
4933 cmdobj = (struct cmd_obj *)rtw_zmalloc(sizeof(*cmdobj));
4934 if (cmdobj == NULL) {
4935 res = _FAIL;
4936 rtw_mfree((u8 *)parm, sizeof(*parm));
4937 if (write)
4938 rtw_mfree(str, RTW_CUSTOMER_STR_LEN);
4939 goto exit;
4940 }
4941
4942 init_h2fwcmd_w_parm_no_rsp(cmdobj, parm, CMD_SET_DRV_EXTRA);
4943
4944 cmdobj->sctx = &sctx;
4945 rtw_sctx_init(&sctx, 2 * 1000);
4946
4947 res = rtw_enqueue_cmd(pcmdpriv, cmdobj);
4948
4949 if (res == _SUCCESS) {
4950 rtw_sctx_wait(&sctx, __func__);
4951 _enter_critical_mutex(&pcmdpriv->sctx_mutex, NULL);
4952 if (sctx.status == RTW_SCTX_SUBMITTED)
4953 cmdobj->sctx = NULL;
4954 _exit_critical_mutex(&pcmdpriv->sctx_mutex, NULL);
4955 if (sctx.status != RTW_SCTX_DONE_SUCCESS)
4956 res = _FAIL;
4957 }
4958
4959 exit:
4960 return res;
4961 }
4962
rtw_customer_str_req_cmd(_adapter * adapter)4963 inline u8 rtw_customer_str_req_cmd(_adapter *adapter)
4964 {
4965 return rtw_customer_str_cmd(adapter, 0, NULL);
4966 }
4967
rtw_customer_str_write_cmd(_adapter * adapter,const u8 * cstr)4968 inline u8 rtw_customer_str_write_cmd(_adapter *adapter, const u8 *cstr)
4969 {
4970 return rtw_customer_str_cmd(adapter, 1, cstr);
4971 }
4972 #endif /* CONFIG_RTW_CUSTOMER_STR */
4973
rtw_c2h_wk_cmd(PADAPTER padapter,u8 * pbuf,u16 length,u8 type)4974 u8 rtw_c2h_wk_cmd(PADAPTER padapter, u8 *pbuf, u16 length, u8 type)
4975 {
4976 struct cmd_obj *ph2c;
4977 struct drvextra_cmd_parm *pdrvextra_cmd_parm;
4978 struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
4979 u8 *extra_cmd_buf;
4980 u8 res = _SUCCESS;
4981
4982 ph2c = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
4983 if (ph2c == NULL) {
4984 res = _FAIL;
4985 goto exit;
4986 }
4987
4988 pdrvextra_cmd_parm = (struct drvextra_cmd_parm *)rtw_zmalloc(sizeof(struct drvextra_cmd_parm));
4989 if (pdrvextra_cmd_parm == NULL) {
4990 rtw_mfree((u8 *)ph2c, sizeof(struct cmd_obj));
4991 res = _FAIL;
4992 goto exit;
4993 }
4994
4995 extra_cmd_buf = rtw_zmalloc(length);
4996 if (extra_cmd_buf == NULL) {
4997 rtw_mfree((u8 *)ph2c, sizeof(struct cmd_obj));
4998 rtw_mfree((u8 *)pdrvextra_cmd_parm, sizeof(struct drvextra_cmd_parm));
4999 res = _FAIL;
5000 goto exit;
5001 }
5002
5003 _rtw_memcpy(extra_cmd_buf, pbuf, length);
5004 pdrvextra_cmd_parm->ec_id = C2H_WK_CID;
5005 pdrvextra_cmd_parm->type = type;
5006 pdrvextra_cmd_parm->size = length;
5007 pdrvextra_cmd_parm->pbuf = extra_cmd_buf;
5008
5009 init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, CMD_SET_DRV_EXTRA);
5010
5011 res = rtw_enqueue_cmd(pcmdpriv, ph2c);
5012
5013 exit:
5014 return res;
5015 }
5016
5017 #ifdef CONFIG_FW_C2H_REG
rtw_c2h_reg_wk_cmd(_adapter * adapter,u8 * c2h_evt)5018 inline u8 rtw_c2h_reg_wk_cmd(_adapter *adapter, u8 *c2h_evt)
5019 {
5020 return rtw_c2h_wk_cmd(adapter, c2h_evt, c2h_evt ? C2H_REG_LEN : 0, C2H_TYPE_REG);
5021 }
5022 #endif
5023
5024 #ifdef CONFIG_FW_C2H_PKT
rtw_c2h_packet_wk_cmd(_adapter * adapter,u8 * c2h_evt,u16 length)5025 inline u8 rtw_c2h_packet_wk_cmd(_adapter *adapter, u8 *c2h_evt, u16 length)
5026 {
5027 return rtw_c2h_wk_cmd(adapter, c2h_evt, length, C2H_TYPE_PKT);
5028 }
5029 #endif
5030
_rtw_run_in_thread_cmd(_adapter * adapter,void (* func)(void *),void * context,s32 timeout_ms)5031 static u8 _rtw_run_in_thread_cmd(_adapter *adapter, void (*func)(void *), void *context, s32 timeout_ms)
5032 {
5033 struct cmd_priv *cmdpriv = &adapter->cmdpriv;
5034 struct cmd_obj *cmdobj;
5035 struct RunInThread_param *parm;
5036 struct submit_ctx sctx;
5037 s32 res = _SUCCESS;
5038
5039 cmdobj = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
5040 if (NULL == cmdobj) {
5041 res = _FAIL;
5042 goto exit;
5043 }
5044
5045 parm = (struct RunInThread_param *)rtw_zmalloc(sizeof(struct RunInThread_param));
5046 if (NULL == parm) {
5047 rtw_mfree((u8 *)cmdobj, sizeof(struct cmd_obj));
5048 res = _FAIL;
5049 goto exit;
5050 }
5051
5052 parm->func = func;
5053 parm->context = context;
5054 init_h2fwcmd_w_parm_no_rsp(cmdobj, parm, CMD_RUN_INTHREAD);
5055
5056 if (timeout_ms >= 0) {
5057 cmdobj->sctx = &sctx;
5058 rtw_sctx_init(&sctx, timeout_ms);
5059 }
5060
5061 res = rtw_enqueue_cmd(cmdpriv, cmdobj);
5062
5063 if (res == _SUCCESS && timeout_ms >= 0) {
5064 rtw_sctx_wait(&sctx, __func__);
5065 _enter_critical_mutex(&cmdpriv->sctx_mutex, NULL);
5066 if (sctx.status == RTW_SCTX_SUBMITTED)
5067 cmdobj->sctx = NULL;
5068 _exit_critical_mutex(&cmdpriv->sctx_mutex, NULL);
5069 if (sctx.status != RTW_SCTX_DONE_SUCCESS)
5070 res = _FAIL;
5071 }
5072
5073 exit:
5074 return res;
5075 }
5076
rtw_run_in_thread_cmd(_adapter * adapter,void (* func)(void *),void * context)5077 u8 rtw_run_in_thread_cmd(_adapter *adapter, void (*func)(void *), void *context)
5078 {
5079 return _rtw_run_in_thread_cmd(adapter, func, context, -1);
5080 }
5081
rtw_run_in_thread_cmd_wait(_adapter * adapter,void (* func)(void *),void * context,s32 timeout_ms)5082 u8 rtw_run_in_thread_cmd_wait(_adapter *adapter, void (*func)(void *), void *context, s32 timeout_ms)
5083 {
5084 return _rtw_run_in_thread_cmd(adapter, func, context, timeout_ms);
5085 }
5086
5087 #ifdef CONFIG_FW_C2H_REG
c2h_evt_hdl(_adapter * adapter,u8 * c2h_evt,c2h_id_filter filter)5088 s32 c2h_evt_hdl(_adapter *adapter, u8 *c2h_evt, c2h_id_filter filter)
5089 {
5090 s32 ret = _FAIL;
5091 u8 buf[C2H_REG_LEN] = {0};
5092 u8 id, seq, plen;
5093 u8 *payload;
5094
5095 if (!c2h_evt) {
5096 /* No c2h event in cmd_obj, read c2h event before handling*/
5097 if (rtw_hal_c2h_evt_read(adapter, buf) != _SUCCESS)
5098 goto exit;
5099 c2h_evt = buf;
5100 }
5101
5102 rtw_hal_c2h_reg_hdr_parse(adapter, c2h_evt, &id, &seq, &plen, &payload);
5103
5104 if (filter && filter(adapter, id, seq, plen, payload) == _FALSE)
5105 goto exit;
5106
5107 ret = rtw_hal_c2h_handler(adapter, id, seq, plen, payload);
5108
5109 exit:
5110 return ret;
5111 }
5112 #endif /* CONFIG_FW_C2H_REG */
5113
session_tracker_cmd(_adapter * adapter,u8 cmd,struct sta_info * sta,u8 * local_naddr,u8 * local_port,u8 * remote_naddr,u8 * remote_port)5114 u8 session_tracker_cmd(_adapter *adapter, u8 cmd, struct sta_info *sta, u8 *local_naddr, u8 *local_port, u8 *remote_naddr, u8 *remote_port)
5115 {
5116 struct cmd_priv *cmdpriv = &adapter->cmdpriv;
5117 struct cmd_obj *cmdobj;
5118 struct drvextra_cmd_parm *cmd_parm;
5119 struct st_cmd_parm *st_parm;
5120 u8 res = _SUCCESS;
5121
5122 cmdobj = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
5123 if (cmdobj == NULL) {
5124 res = _FAIL;
5125 goto exit;
5126 }
5127
5128 cmd_parm = (struct drvextra_cmd_parm *)rtw_zmalloc(sizeof(struct drvextra_cmd_parm));
5129 if (cmd_parm == NULL) {
5130 rtw_mfree((u8 *)cmdobj, sizeof(struct cmd_obj));
5131 res = _FAIL;
5132 goto exit;
5133 }
5134
5135 st_parm = (struct st_cmd_parm *)rtw_zmalloc(sizeof(struct st_cmd_parm));
5136 if (st_parm == NULL) {
5137 rtw_mfree((u8 *)cmdobj, sizeof(struct cmd_obj));
5138 rtw_mfree((u8 *)cmd_parm, sizeof(struct drvextra_cmd_parm));
5139 res = _FAIL;
5140 goto exit;
5141 }
5142
5143 st_parm->cmd = cmd;
5144 st_parm->sta = sta;
5145 if (cmd != ST_CMD_CHK) {
5146 _rtw_memcpy(&st_parm->local_naddr, local_naddr, 4);
5147 _rtw_memcpy(&st_parm->local_port, local_port, 2);
5148 _rtw_memcpy(&st_parm->remote_naddr, remote_naddr, 4);
5149 _rtw_memcpy(&st_parm->remote_port, remote_port, 2);
5150 }
5151
5152 cmd_parm->ec_id = SESSION_TRACKER_WK_CID;
5153 cmd_parm->type = 0;
5154 cmd_parm->size = sizeof(struct st_cmd_parm);
5155 cmd_parm->pbuf = (u8 *)st_parm;
5156 init_h2fwcmd_w_parm_no_rsp(cmdobj, cmd_parm, CMD_SET_DRV_EXTRA);
5157 cmdobj->no_io = 1;
5158
5159 res = rtw_enqueue_cmd(cmdpriv, cmdobj);
5160
5161 exit:
5162 return res;
5163 }
5164
session_tracker_chk_cmd(_adapter * adapter,struct sta_info * sta)5165 inline u8 session_tracker_chk_cmd(_adapter *adapter, struct sta_info *sta)
5166 {
5167 return session_tracker_cmd(adapter, ST_CMD_CHK, sta, NULL, NULL, NULL, NULL);
5168 }
5169
session_tracker_add_cmd(_adapter * adapter,struct sta_info * sta,u8 * local_naddr,u8 * local_port,u8 * remote_naddr,u8 * remote_port)5170 inline u8 session_tracker_add_cmd(_adapter *adapter, struct sta_info *sta, u8 *local_naddr, u8 *local_port, u8 *remote_naddr, u8 *remote_port)
5171 {
5172 return session_tracker_cmd(adapter, ST_CMD_ADD, sta, local_naddr, local_port, remote_naddr, remote_port);
5173 }
5174
session_tracker_del_cmd(_adapter * adapter,struct sta_info * sta,u8 * local_naddr,u8 * local_port,u8 * remote_naddr,u8 * remote_port)5175 inline u8 session_tracker_del_cmd(_adapter *adapter, struct sta_info *sta, u8 *local_naddr, u8 *local_port, u8 *remote_naddr, u8 *remote_port)
5176 {
5177 return session_tracker_cmd(adapter, ST_CMD_DEL, sta, local_naddr, local_port, remote_naddr, remote_port);
5178 }
5179
session_tracker_chk_for_sta(_adapter * adapter,struct sta_info * sta)5180 void session_tracker_chk_for_sta(_adapter *adapter, struct sta_info *sta)
5181 {
5182 struct st_ctl_t *st_ctl = &sta->st_ctl;
5183 int i;
5184 _irqL irqL;
5185 _list *plist, *phead, *pnext;
5186 _list dlist;
5187 struct session_tracker *st = NULL;
5188 u8 op_wfd_mode = MIRACAST_DISABLED;
5189
5190 if (DBG_SESSION_TRACKER)
5191 RTW_INFO(FUNC_ADPT_FMT" sta:%p\n", FUNC_ADPT_ARG(adapter), sta);
5192
5193 if (!(sta->state & WIFI_ASOC_STATE))
5194 goto exit;
5195
5196 for (i = 0; i < SESSION_TRACKER_REG_ID_NUM; i++) {
5197 if (st_ctl->reg[i].s_proto != 0)
5198 break;
5199 }
5200 if (i >= SESSION_TRACKER_REG_ID_NUM)
5201 goto chk_sta;
5202
5203 _rtw_init_listhead(&dlist);
5204
5205 _enter_critical_bh(&st_ctl->tracker_q.lock, &irqL);
5206
5207 phead = &st_ctl->tracker_q.queue;
5208 plist = get_next(phead);
5209 pnext = get_next(plist);
5210 while (rtw_end_of_queue_search(phead, plist) == _FALSE) {
5211 st = LIST_CONTAINOR(plist, struct session_tracker, list);
5212 plist = pnext;
5213 pnext = get_next(pnext);
5214
5215 if (st->status != ST_STATUS_ESTABLISH
5216 && rtw_get_passing_time_ms(st->set_time) > ST_EXPIRE_MS
5217 ) {
5218 rtw_list_delete(&st->list);
5219 rtw_list_insert_tail(&st->list, &dlist);
5220 }
5221
5222 /* TODO: check OS for status update */
5223 if (st->status == ST_STATUS_CHECK)
5224 st->status = ST_STATUS_ESTABLISH;
5225
5226 if (st->status != ST_STATUS_ESTABLISH)
5227 continue;
5228
5229 #ifdef CONFIG_WFD
5230 if (0)
5231 RTW_INFO(FUNC_ADPT_FMT" local:%u, remote:%u, rtsp:%u, %u, %u\n", FUNC_ADPT_ARG(adapter)
5232 , ntohs(st->local_port), ntohs(st->remote_port), adapter->wfd_info.rtsp_ctrlport, adapter->wfd_info.tdls_rtsp_ctrlport
5233 , adapter->wfd_info.peer_rtsp_ctrlport);
5234 if (ntohs(st->local_port) == adapter->wfd_info.rtsp_ctrlport)
5235 op_wfd_mode |= MIRACAST_SINK;
5236 if (ntohs(st->local_port) == adapter->wfd_info.tdls_rtsp_ctrlport)
5237 op_wfd_mode |= MIRACAST_SINK;
5238 if (ntohs(st->remote_port) == adapter->wfd_info.peer_rtsp_ctrlport)
5239 op_wfd_mode |= MIRACAST_SOURCE;
5240 #endif
5241 }
5242
5243 _exit_critical_bh(&st_ctl->tracker_q.lock, &irqL);
5244
5245 plist = get_next(&dlist);
5246 while (rtw_end_of_queue_search(&dlist, plist) == _FALSE) {
5247 st = LIST_CONTAINOR(plist, struct session_tracker, list);
5248 plist = get_next(plist);
5249 rtw_mfree((u8 *)st, sizeof(struct session_tracker));
5250 }
5251
5252 chk_sta:
5253 if (STA_OP_WFD_MODE(sta) != op_wfd_mode) {
5254 STA_SET_OP_WFD_MODE(sta, op_wfd_mode);
5255 rtw_sta_media_status_rpt_cmd(adapter, sta, 1);
5256 }
5257
5258 exit:
5259 return;
5260 }
5261
session_tracker_chk_for_adapter(_adapter * adapter)5262 void session_tracker_chk_for_adapter(_adapter *adapter)
5263 {
5264 struct sta_priv *stapriv = &adapter->stapriv;
5265 struct sta_info *sta;
5266 int i;
5267 _irqL irqL;
5268 _list *plist, *phead;
5269 u8 op_wfd_mode = MIRACAST_DISABLED;
5270
5271 _enter_critical_bh(&stapriv->sta_hash_lock, &irqL);
5272
5273 for (i = 0; i < NUM_STA; i++) {
5274 phead = &(stapriv->sta_hash[i]);
5275 plist = get_next(phead);
5276
5277 while ((rtw_end_of_queue_search(phead, plist)) == _FALSE) {
5278 sta = LIST_CONTAINOR(plist, struct sta_info, hash_list);
5279 plist = get_next(plist);
5280
5281 session_tracker_chk_for_sta(adapter, sta);
5282
5283 op_wfd_mode |= STA_OP_WFD_MODE(sta);
5284 }
5285 }
5286
5287 _exit_critical_bh(&stapriv->sta_hash_lock, &irqL);
5288
5289 #ifdef CONFIG_WFD
5290 adapter->wfd_info.op_wfd_mode = MIRACAST_MODE_REVERSE(op_wfd_mode);
5291 #endif
5292 }
5293
session_tracker_cmd_hdl(_adapter * adapter,struct st_cmd_parm * parm)5294 void session_tracker_cmd_hdl(_adapter *adapter, struct st_cmd_parm *parm)
5295 {
5296 u8 cmd = parm->cmd;
5297 struct sta_info *sta = parm->sta;
5298
5299 if (cmd == ST_CMD_CHK) {
5300 if (sta)
5301 session_tracker_chk_for_sta(adapter, sta);
5302 else
5303 session_tracker_chk_for_adapter(adapter);
5304
5305 goto exit;
5306
5307 } else if (cmd == ST_CMD_ADD || cmd == ST_CMD_DEL) {
5308 struct st_ctl_t *st_ctl;
5309 u32 local_naddr = parm->local_naddr;
5310 u16 local_port = parm->local_port;
5311 u32 remote_naddr = parm->remote_naddr;
5312 u16 remote_port = parm->remote_port;
5313 struct session_tracker *st = NULL;
5314 _irqL irqL;
5315 _list *plist, *phead;
5316 u8 free_st = 0;
5317 u8 alloc_st = 0;
5318
5319 if (DBG_SESSION_TRACKER)
5320 RTW_INFO(FUNC_ADPT_FMT" cmd:%u, sta:%p, local:"IP_FMT":"PORT_FMT", remote:"IP_FMT":"PORT_FMT"\n"
5321 , FUNC_ADPT_ARG(adapter), cmd, sta
5322 , IP_ARG(&local_naddr), PORT_ARG(&local_port)
5323 , IP_ARG(&remote_naddr), PORT_ARG(&remote_port)
5324 );
5325
5326 if (!(sta->state & WIFI_ASOC_STATE))
5327 goto exit;
5328
5329 st_ctl = &sta->st_ctl;
5330
5331 _enter_critical_bh(&st_ctl->tracker_q.lock, &irqL);
5332
5333 phead = &st_ctl->tracker_q.queue;
5334 plist = get_next(phead);
5335 while (rtw_end_of_queue_search(phead, plist) == _FALSE) {
5336 st = LIST_CONTAINOR(plist, struct session_tracker, list);
5337
5338 if (st->local_naddr == local_naddr
5339 && st->local_port == local_port
5340 && st->remote_naddr == remote_naddr
5341 && st->remote_port == remote_port)
5342 break;
5343
5344 plist = get_next(plist);
5345 }
5346
5347 if (rtw_end_of_queue_search(phead, plist) == _TRUE)
5348 st = NULL;
5349
5350 switch (cmd) {
5351 case ST_CMD_DEL:
5352 if (st) {
5353 rtw_list_delete(plist);
5354 free_st = 1;
5355 }
5356 goto unlock;
5357 case ST_CMD_ADD:
5358 if (!st)
5359 alloc_st = 1;
5360 }
5361
5362 unlock:
5363 _exit_critical_bh(&st_ctl->tracker_q.lock, &irqL);
5364
5365 if (free_st) {
5366 rtw_mfree((u8 *)st, sizeof(struct session_tracker));
5367 goto exit;
5368 }
5369
5370 if (alloc_st) {
5371 st = (struct session_tracker *)rtw_zmalloc(sizeof(struct session_tracker));
5372 if (!st)
5373 goto exit;
5374
5375 st->local_naddr = local_naddr;
5376 st->local_port = local_port;
5377 st->remote_naddr = remote_naddr;
5378 st->remote_port = remote_port;
5379 st->set_time = rtw_get_current_time();
5380 st->status = ST_STATUS_CHECK;
5381
5382 _enter_critical_bh(&st_ctl->tracker_q.lock, &irqL);
5383 rtw_list_insert_tail(&st->list, phead);
5384 _exit_critical_bh(&st_ctl->tracker_q.lock, &irqL);
5385 }
5386 }
5387
5388 exit:
5389 return;
5390 }
5391
5392 #if defined(CONFIG_RTW_MESH) && defined(RTW_PER_CMD_SUPPORT_FW)
rtw_req_per_cmd_hdl(_adapter * adapter)5393 static s32 rtw_req_per_cmd_hdl(_adapter *adapter)
5394 {
5395 struct dvobj_priv *dvobj = adapter_to_dvobj(adapter);
5396 struct macid_ctl_t *macid_ctl = dvobj_to_macidctl(dvobj);
5397 struct macid_bmp req_macid_bmp, *macid_bmp;
5398 u8 i, ret = _FAIL;
5399
5400 macid_bmp = &macid_ctl->if_g[adapter->iface_id];
5401 _rtw_memcpy(&req_macid_bmp, macid_bmp, sizeof(struct macid_bmp));
5402
5403 /* Clear none mesh's macid */
5404 for (i = 0; i < macid_ctl->num; i++) {
5405 u8 role;
5406 role = GET_H2CCMD_MSRRPT_PARM_ROLE(&macid_ctl->h2c_msr[i]);
5407 if (role != H2C_MSR_ROLE_MESH)
5408 rtw_macid_map_clr(&req_macid_bmp, i);
5409 }
5410
5411 /* group_macid: always be 0 in NIC, so only pass macid_bitmap.m0
5412 * rpt_type: 0 includes all info in 1, use 0 for now
5413 * macid_bitmap: pass m0 only for NIC
5414 */
5415 ret = rtw_hal_set_req_per_rpt_cmd(adapter, 0, 0, req_macid_bmp.m0);
5416
5417 return ret;
5418 }
5419
rtw_req_per_cmd(_adapter * adapter)5420 u8 rtw_req_per_cmd(_adapter *adapter)
5421 {
5422 struct cmd_obj *cmdobj;
5423 struct drvextra_cmd_parm *parm;
5424 struct cmd_priv *pcmdpriv = &adapter->cmdpriv;
5425 struct submit_ctx sctx;
5426 u8 res = _SUCCESS;
5427
5428 parm = (struct drvextra_cmd_parm *)rtw_zmalloc(sizeof(struct drvextra_cmd_parm));
5429 if (parm == NULL) {
5430 res = _FAIL;
5431 goto exit;
5432 }
5433
5434 parm->ec_id = REQ_PER_CMD_WK_CID;
5435 parm->type = 0;
5436 parm->size = 0;
5437 parm->pbuf = NULL;
5438
5439 cmdobj = (struct cmd_obj *)rtw_zmalloc(sizeof(*cmdobj));
5440 if (cmdobj == NULL) {
5441 res = _FAIL;
5442 rtw_mfree((u8 *)parm, sizeof(*parm));
5443 goto exit;
5444 }
5445
5446 init_h2fwcmd_w_parm_no_rsp(cmdobj, parm, CMD_SET_DRV_EXTRA);
5447
5448 res = rtw_enqueue_cmd(pcmdpriv, cmdobj);
5449
5450 exit:
5451 return res;
5452 }
5453 #endif
5454
5455
rtw_ac_parm_cmd_hdl(_adapter * padapter,u8 * _ac_parm_buf,int ac_type)5456 void rtw_ac_parm_cmd_hdl(_adapter *padapter, u8 *_ac_parm_buf, int ac_type)
5457 {
5458
5459 u32 ac_parm_buf;
5460
5461 _rtw_memcpy(&ac_parm_buf, _ac_parm_buf, sizeof(ac_parm_buf));
5462 switch (ac_type) {
5463 case XMIT_VO_QUEUE:
5464 RTW_INFO(FUNC_NDEV_FMT" AC_VO = 0x%08x\n", FUNC_ADPT_ARG(padapter), (unsigned int) ac_parm_buf);
5465 rtw_hal_set_hwreg(padapter, HW_VAR_AC_PARAM_VO, (u8 *)(&ac_parm_buf));
5466 break;
5467
5468 case XMIT_VI_QUEUE:
5469 RTW_INFO(FUNC_NDEV_FMT" AC_VI = 0x%08x\n", FUNC_ADPT_ARG(padapter), (unsigned int) ac_parm_buf);
5470 rtw_hal_set_hwreg(padapter, HW_VAR_AC_PARAM_VI, (u8 *)(&ac_parm_buf));
5471 break;
5472
5473 case XMIT_BE_QUEUE:
5474 RTW_INFO(FUNC_NDEV_FMT" AC_BE = 0x%08x\n", FUNC_ADPT_ARG(padapter), (unsigned int) ac_parm_buf);
5475 rtw_hal_set_hwreg(padapter, HW_VAR_AC_PARAM_BE, (u8 *)(&ac_parm_buf));
5476 break;
5477
5478 case XMIT_BK_QUEUE:
5479 RTW_INFO(FUNC_NDEV_FMT" AC_BK = 0x%08x\n", FUNC_ADPT_ARG(padapter), (unsigned int) ac_parm_buf);
5480 rtw_hal_set_hwreg(padapter, HW_VAR_AC_PARAM_BK, (u8 *)(&ac_parm_buf));
5481 break;
5482
5483 default:
5484 break;
5485 }
5486
5487 }
5488
5489
rtw_drvextra_cmd_hdl(_adapter * padapter,unsigned char * pbuf)5490 u8 rtw_drvextra_cmd_hdl(_adapter *padapter, unsigned char *pbuf)
5491 {
5492 int ret = H2C_SUCCESS;
5493 struct drvextra_cmd_parm *pdrvextra_cmd;
5494
5495 if (!pbuf)
5496 return H2C_PARAMETERS_ERROR;
5497
5498 pdrvextra_cmd = (struct drvextra_cmd_parm *)pbuf;
5499
5500 switch (pdrvextra_cmd->ec_id) {
5501 case STA_MSTATUS_RPT_WK_CID:
5502 rtw_sta_media_status_rpt_cmd_hdl(padapter, (struct sta_media_status_rpt_cmd_parm *)pdrvextra_cmd->pbuf);
5503 break;
5504
5505 case DYNAMIC_CHK_WK_CID:/*only primary padapter go to this cmd, but execute dynamic_chk_wk_hdl() for two interfaces */
5506 rtw_dynamic_chk_wk_hdl(padapter);
5507 break;
5508 case POWER_SAVING_CTRL_WK_CID:
5509 power_saving_wk_hdl(padapter);
5510 break;
5511 #ifdef CONFIG_LPS
5512 case LPS_CTRL_WK_CID:
5513 lps_ctrl_wk_hdl(padapter, (u8)pdrvextra_cmd->type, pdrvextra_cmd->pbuf);
5514 break;
5515 case DM_IN_LPS_WK_CID:
5516 rtw_dm_in_lps_hdl(padapter);
5517 break;
5518 case LPS_CHANGE_DTIM_CID:
5519 rtw_lps_change_dtim_hdl(padapter, (u8)pdrvextra_cmd->type);
5520 break;
5521 #endif
5522 #if (RATE_ADAPTIVE_SUPPORT == 1)
5523 case RTP_TIMER_CFG_WK_CID:
5524 rpt_timer_setting_wk_hdl(padapter, pdrvextra_cmd->type);
5525 break;
5526 #endif
5527 #ifdef CONFIG_ANTENNA_DIVERSITY
5528 case ANT_SELECT_WK_CID:
5529 antenna_select_wk_hdl(padapter, pdrvextra_cmd->type);
5530 break;
5531 #endif
5532 #ifdef CONFIG_P2P_PS
5533 case P2P_PS_WK_CID:
5534 p2p_ps_wk_hdl(padapter, pdrvextra_cmd->type);
5535 break;
5536 #endif
5537 #ifdef CONFIG_P2P
5538 case P2P_PROTO_WK_CID:
5539 /*
5540 * Commented by Albert 2011/07/01
5541 * I used the type_size as the type command
5542 */
5543 ret = p2p_protocol_wk_hdl(padapter, pdrvextra_cmd->type, pdrvextra_cmd->pbuf);
5544 break;
5545 #endif
5546 #ifdef CONFIG_AP_MODE
5547 case CHECK_HIQ_WK_CID:
5548 rtw_chk_hi_queue_hdl(padapter);
5549 break;
5550 #endif
5551 /* add for CONFIG_IEEE80211W, none 11w can use it */
5552 case RESET_SECURITYPRIV:
5553 reset_securitypriv_hdl(padapter);
5554 break;
5555 case FREE_ASSOC_RESOURCES:
5556 free_assoc_resources_hdl(padapter, (u8)pdrvextra_cmd->type);
5557 break;
5558 case C2H_WK_CID:
5559 switch (pdrvextra_cmd->type) {
5560 #ifdef CONFIG_FW_C2H_REG
5561 case C2H_TYPE_REG:
5562 c2h_evt_hdl(padapter, pdrvextra_cmd->pbuf, NULL);
5563 break;
5564 #endif
5565 #ifdef CONFIG_FW_C2H_PKT
5566 case C2H_TYPE_PKT:
5567 rtw_hal_c2h_pkt_hdl(padapter, pdrvextra_cmd->pbuf, pdrvextra_cmd->size);
5568 break;
5569 #endif
5570 default:
5571 RTW_ERR("unknown C2H type:%d\n", pdrvextra_cmd->type);
5572 rtw_warn_on(1);
5573 break;
5574 }
5575 break;
5576 #ifdef CONFIG_BEAMFORMING
5577 case BEAMFORMING_WK_CID:
5578 beamforming_wk_hdl(padapter, pdrvextra_cmd->type, pdrvextra_cmd->pbuf);
5579 break;
5580 #endif
5581 case DM_RA_MSK_WK_CID:
5582 rtw_dm_ra_mask_hdl(padapter, (struct sta_info *)pdrvextra_cmd->pbuf);
5583 break;
5584 #ifdef CONFIG_BT_COEXIST
5585 case BTINFO_WK_CID:
5586 rtw_btinfo_hdl(padapter, pdrvextra_cmd->pbuf, pdrvextra_cmd->size);
5587 break;
5588 case BTC_REDUCE_WL_TXPWR_CID:
5589 rtw_btc_reduce_wl_txpwr_hdl(padapter, pdrvextra_cmd->type);
5590 break;
5591 #endif
5592 #ifdef CONFIG_DFS_MASTER
5593 case DFS_RADAR_DETECT_WK_CID:
5594 rtw_dfs_rd_hdl(padapter);
5595 break;
5596 case DFS_RADAR_DETECT_EN_DEC_WK_CID:
5597 rtw_dfs_rd_en_decision(padapter, MLME_ACTION_NONE, 0);
5598 break;
5599 #endif
5600 case SESSION_TRACKER_WK_CID:
5601 session_tracker_cmd_hdl(padapter, (struct st_cmd_parm *)pdrvextra_cmd->pbuf);
5602 break;
5603 case EN_HW_UPDATE_TSF_WK_CID:
5604 rtw_hal_set_hwreg(padapter, HW_VAR_EN_HW_UPDATE_TSF, NULL);
5605 break;
5606 case PERIOD_TSF_UPDATE_END_WK_CID:
5607 rtw_hal_periodic_tsf_update_chk(padapter);
5608 break;
5609 case TEST_H2C_CID:
5610 rtw_hal_fill_h2c_cmd(padapter, pdrvextra_cmd->pbuf[0], pdrvextra_cmd->size - 1, &pdrvextra_cmd->pbuf[1]);
5611 break;
5612 case MP_CMD_WK_CID:
5613 #ifdef CONFIG_MP_INCLUDED
5614 ret = rtw_mp_cmd_hdl(padapter, pdrvextra_cmd->type);
5615 #endif
5616 break;
5617 #ifdef CONFIG_RTW_CUSTOMER_STR
5618 case CUSTOMER_STR_WK_CID:
5619 ret = rtw_customer_str_cmd_hdl(padapter, pdrvextra_cmd->type, pdrvextra_cmd->pbuf);
5620 break;
5621 #endif
5622
5623 #ifdef CONFIG_RTW_REPEATER_SON
5624 case RSON_SCAN_WK_CID:
5625 rtw_rson_scan_cmd_hdl(padapter, pdrvextra_cmd->type);
5626 break;
5627 #endif
5628
5629 #ifdef CONFIG_IOCTL_CFG80211
5630 case MGNT_TX_WK_CID:
5631 ret = rtw_mgnt_tx_handler(padapter, pdrvextra_cmd->pbuf);
5632 break;
5633 #endif /* CONFIG_IOCTL_CFG80211 */
5634
5635 #if (defined(CONFIG_P2P) && defined(CONFIG_CONCURRENT_MODE)) || defined(CONFIG_IOCTL_CFG80211)
5636 case ROCH_WK_CID:
5637 ret = rtw_roch_wk_hdl(padapter, pdrvextra_cmd->type, pdrvextra_cmd->pbuf);
5638 break;
5639 #endif /* (defined(CONFIG_P2P) && defined(CONFIG_CONCURRENT_MODE)) || defined(CONFIG_IOCTL_CFG80211) */
5640
5641 #ifdef CONFIG_MCC_MODE
5642 case MCC_CMD_WK_CID:
5643 ret = rtw_mcc_cmd_hdl(padapter, pdrvextra_cmd->type, pdrvextra_cmd->pbuf);
5644 break;
5645 #endif /* CONFIG_MCC_MODE */
5646 #if defined(CONFIG_RTW_MESH) && defined(RTW_PER_CMD_SUPPORT_FW)
5647 case REQ_PER_CMD_WK_CID:
5648 ret = rtw_req_per_cmd_hdl(padapter);
5649 break;
5650 #endif
5651 #ifdef CONFIG_SUPPORT_STATIC_SMPS
5652 case SSMPS_WK_CID :
5653 rtw_ssmps_wk_hdl(padapter, (struct ssmps_cmd_parm *)pdrvextra_cmd->pbuf);
5654 break;
5655 #endif
5656 #ifdef CONFIG_CTRL_TXSS_BY_TP
5657 case TXSS_WK_CID :
5658 rtw_ctrl_txss_wk_hdl(padapter, (struct txss_cmd_parm *)pdrvextra_cmd->pbuf);
5659 break;
5660 #endif
5661 case AC_PARM_CMD_WK_CID:
5662 rtw_ac_parm_cmd_hdl(padapter, pdrvextra_cmd->pbuf, pdrvextra_cmd->type);
5663 break;
5664 #ifdef CONFIG_AP_MODE
5665 case STOP_AP_WK_CID:
5666 stop_ap_hdl(padapter);
5667 break;
5668 #endif
5669 #ifdef CONFIG_RTW_TOKEN_BASED_XMIT
5670 case TBTX_CONTROL_TX_WK_CID:
5671 tx_control_hdl(padapter);
5672 break;
5673 #endif
5674 default:
5675 break;
5676 }
5677
5678 if (pdrvextra_cmd->pbuf && pdrvextra_cmd->size > 0)
5679 rtw_mfree(pdrvextra_cmd->pbuf, pdrvextra_cmd->size);
5680
5681 return ret;
5682 }
5683
rtw_survey_cmd_callback(_adapter * padapter,struct cmd_obj * pcmd)5684 void rtw_survey_cmd_callback(_adapter *padapter , struct cmd_obj *pcmd)
5685 {
5686 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
5687
5688
5689 if (pcmd->res == H2C_DROPPED) {
5690 /* TODO: cancel timer and do timeout handler directly... */
5691 /* need to make timeout handlerOS independent */
5692 mlme_set_scan_to_timer(pmlmepriv, 1);
5693 } else if (pcmd->res != H2C_SUCCESS) {
5694 mlme_set_scan_to_timer(pmlmepriv, 1);
5695 }
5696
5697 /* free cmd */
5698 rtw_free_cmd_obj(pcmd);
5699
5700 }
rtw_disassoc_cmd_callback(_adapter * padapter,struct cmd_obj * pcmd)5701 void rtw_disassoc_cmd_callback(_adapter *padapter, struct cmd_obj *pcmd)
5702 {
5703 _irqL irqL;
5704 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
5705
5706
5707 if (pcmd->res != H2C_SUCCESS) {
5708 _enter_critical_bh(&pmlmepriv->lock, &irqL);
5709 set_fwstate(pmlmepriv, WIFI_ASOC_STATE);
5710 _exit_critical_bh(&pmlmepriv->lock, &irqL);
5711 goto exit;
5712 }
5713 #ifdef CONFIG_BR_EXT
5714 else /* clear bridge database */
5715 nat25_db_cleanup(padapter);
5716 #endif /* CONFIG_BR_EXT */
5717
5718 /* free cmd */
5719 rtw_free_cmd_obj(pcmd);
5720
5721 exit:
5722 return;
5723 }
5724
rtw_joinbss_cmd_callback(_adapter * padapter,struct cmd_obj * pcmd)5725 void rtw_joinbss_cmd_callback(_adapter *padapter, struct cmd_obj *pcmd)
5726 {
5727 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
5728
5729
5730 if (pcmd->res == H2C_DROPPED) {
5731 /* TODO: cancel timer and do timeout handler directly... */
5732 /* need to make timeout handlerOS independent */
5733 _set_timer(&pmlmepriv->assoc_timer, 1);
5734 } else if (pcmd->res != H2C_SUCCESS)
5735 _set_timer(&pmlmepriv->assoc_timer, 1);
5736
5737 rtw_free_cmd_obj(pcmd);
5738
5739 }
5740
rtw_create_ibss_post_hdl(_adapter * padapter,int status)5741 void rtw_create_ibss_post_hdl(_adapter *padapter, int status)
5742 {
5743 _irqL irqL;
5744 struct wlan_network *pwlan = NULL;
5745 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
5746 WLAN_BSSID_EX *pdev_network = &padapter->registrypriv.dev_network;
5747 struct wlan_network *mlme_cur_network = &(pmlmepriv->cur_network);
5748
5749 if (status != H2C_SUCCESS)
5750 _set_timer(&pmlmepriv->assoc_timer, 1);
5751
5752 _cancel_timer_ex(&pmlmepriv->assoc_timer);
5753
5754 _enter_critical_bh(&pmlmepriv->lock, &irqL);
5755
5756 {
5757 _irqL irqL;
5758
5759 pwlan = _rtw_alloc_network(pmlmepriv);
5760 _enter_critical_bh(&(pmlmepriv->scanned_queue.lock), &irqL);
5761 if (pwlan == NULL) {
5762 pwlan = rtw_get_oldest_wlan_network(&pmlmepriv->scanned_queue);
5763 if (pwlan == NULL) {
5764 _exit_critical_bh(&(pmlmepriv->scanned_queue.lock), &irqL);
5765 goto createbss_cmd_fail;
5766 }
5767 pwlan->last_scanned = rtw_get_current_time();
5768 } else
5769 rtw_list_insert_tail(&(pwlan->list), &pmlmepriv->scanned_queue.queue);
5770
5771 pdev_network->Length = get_WLAN_BSSID_EX_sz(pdev_network);
5772 _rtw_memcpy(&(pwlan->network), pdev_network, pdev_network->Length);
5773 /* pwlan->fixed = _TRUE; */
5774
5775 /* copy pdev_network information to pmlmepriv->cur_network */
5776 _rtw_memcpy(&mlme_cur_network->network, pdev_network, (get_WLAN_BSSID_EX_sz(pdev_network)));
5777
5778 #if 0
5779 /* reset DSConfig */
5780 mlme_cur_network->network.Configuration.DSConfig = (u32)rtw_ch2freq(pdev_network->Configuration.DSConfig);
5781 #endif
5782
5783 _clr_fwstate_(pmlmepriv, WIFI_UNDER_LINKING);
5784 _exit_critical_bh(&(pmlmepriv->scanned_queue.lock), &irqL);
5785 /* we will set WIFI_ASOC_STATE when there is one more sat to join us (rtw_stassoc_event_callback) */
5786 }
5787
5788 createbss_cmd_fail:
5789 _exit_critical_bh(&pmlmepriv->lock, &irqL);
5790 return;
5791 }
5792
5793
5794
rtw_setstaKey_cmdrsp_callback(_adapter * padapter,struct cmd_obj * pcmd)5795 void rtw_setstaKey_cmdrsp_callback(_adapter *padapter , struct cmd_obj *pcmd)
5796 {
5797
5798 struct sta_priv *pstapriv = &padapter->stapriv;
5799 struct set_stakey_rsp *psetstakey_rsp = (struct set_stakey_rsp *)(pcmd->rsp);
5800 struct sta_info *psta = rtw_get_stainfo(pstapriv, psetstakey_rsp->addr);
5801
5802
5803 if (psta == NULL) {
5804 goto exit;
5805 }
5806
5807 /* psta->cmn.aid = psta->cmn.mac_id = psetstakey_rsp->keyid; */ /* CAM_ID(CAM_ENTRY) */
5808
5809 exit:
5810
5811 rtw_free_cmd_obj(pcmd);
5812
5813
5814 }
5815
rtw_getrttbl_cmd_cmdrsp_callback(_adapter * padapter,struct cmd_obj * pcmd)5816 void rtw_getrttbl_cmd_cmdrsp_callback(_adapter *padapter, struct cmd_obj *pcmd)
5817 {
5818
5819 rtw_free_cmd_obj(pcmd);
5820 #ifdef CONFIG_MP_INCLUDED
5821 if (padapter->registrypriv.mp_mode == 1)
5822 padapter->mppriv.workparam.bcompleted = _TRUE;
5823 #endif
5824
5825
5826 }
5827
set_txq_params_cmd(_adapter * adapter,u32 ac_parm,u8 ac_type)5828 u8 set_txq_params_cmd(_adapter *adapter, u32 ac_parm, u8 ac_type)
5829 {
5830 struct cmd_obj *cmdobj;
5831 struct drvextra_cmd_parm *pdrvextra_cmd_parm;
5832 struct cmd_priv *pcmdpriv = &adapter->cmdpriv;
5833 u8 *ac_parm_buf = NULL;
5834 u8 sz;
5835 u8 res = _SUCCESS;
5836
5837
5838 cmdobj = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
5839 if (cmdobj == NULL) {
5840 res = _FAIL;
5841 goto exit;
5842 }
5843
5844 pdrvextra_cmd_parm = (struct drvextra_cmd_parm *)rtw_zmalloc(sizeof(struct drvextra_cmd_parm));
5845 if (pdrvextra_cmd_parm == NULL) {
5846 rtw_mfree((u8 *)cmdobj, sizeof(struct cmd_obj));
5847 res = _FAIL;
5848 goto exit;
5849 }
5850
5851 sz = sizeof(ac_parm);
5852 ac_parm_buf = rtw_zmalloc(sz);
5853 if (ac_parm_buf == NULL) {
5854 rtw_mfree((u8 *)cmdobj, sizeof(struct cmd_obj));
5855 rtw_mfree((u8 *)pdrvextra_cmd_parm, sizeof(struct drvextra_cmd_parm));
5856 res = _FAIL;
5857 goto exit;
5858 }
5859
5860 pdrvextra_cmd_parm->ec_id = AC_PARM_CMD_WK_CID;
5861 pdrvextra_cmd_parm->type = ac_type;
5862 pdrvextra_cmd_parm->size = sz;
5863 pdrvextra_cmd_parm->pbuf = ac_parm_buf;
5864
5865 _rtw_memcpy(ac_parm_buf, &ac_parm, sz);
5866
5867 init_h2fwcmd_w_parm_no_rsp(cmdobj, pdrvextra_cmd_parm, CMD_SET_DRV_EXTRA);
5868 res = rtw_enqueue_cmd(pcmdpriv, cmdobj);
5869
5870 exit:
5871 return res;
5872 }
5873
5874 /* Driver writes beacon length to REG for FW adjusting beacon receive time */
5875 #ifdef CONFIG_WRITE_BCN_LEN_TO_FW
rtw_write_bcnlen_to_fw_cmd(_adapter * padapter,u16 bcn_len)5876 u8 rtw_write_bcnlen_to_fw_cmd(_adapter *padapter, u16 bcn_len)
5877 {
5878 struct cmd_obj *pcmd;
5879 struct write_bcnlen_param *parm;
5880 struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
5881 u8 res = _SUCCESS;
5882
5883 pcmd = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
5884 if (pcmd == NULL) {
5885 res = _FAIL;
5886 goto exit;
5887 }
5888
5889 parm = (struct write_bcnlen_param *)rtw_zmalloc(sizeof(struct write_bcnlen_param));
5890 if (parm == NULL) {
5891 rtw_mfree((unsigned char *)pcmd, sizeof(struct cmd_obj));
5892 res = _FAIL;
5893 goto exit;
5894 }
5895
5896 parm->bcn_len = bcn_len;
5897 init_h2fwcmd_w_parm_no_rsp(pcmd, parm, CMD_WRITE_BCN_LEN);
5898 res = rtw_enqueue_cmd(pcmdpriv, pcmd);
5899
5900 exit:
5901 return res;
5902 }
5903 #endif /* CONFIG_WRITE_BCN_LEN_TO_FW */
5904
rtw_reqtxrpt_cmd(_adapter * adapter,u8 macid)5905 u8 rtw_reqtxrpt_cmd(_adapter *adapter, u8 macid)
5906 {
5907 struct cmd_obj *cmdobj;
5908 struct reqtxrpt_param *parm;
5909 struct cmd_priv *pcmdpriv = &adapter->cmdpriv;
5910 struct submit_ctx sctx;
5911 u8 flags = RTW_CMDF_WAIT_ACK;
5912 u8 res = _FAIL;
5913
5914 /* prepare cmd parameter */
5915 parm = rtw_zmalloc(sizeof(*parm));
5916 if (parm == NULL)
5917 goto exit;
5918 parm->macid = macid;
5919
5920 /* need enqueue, prepare cmd_obj and enqueue */
5921 cmdobj = rtw_zmalloc(sizeof(*cmdobj));
5922 if (cmdobj == NULL) {
5923 rtw_mfree((u8 *)parm, sizeof(*parm));
5924 goto exit;
5925 }
5926
5927 init_h2fwcmd_w_parm_no_rsp(cmdobj, parm, CMD_REQ_TXRPT);
5928
5929 if (flags & RTW_CMDF_WAIT_ACK) {
5930 cmdobj->sctx = &sctx;
5931 rtw_sctx_init(&sctx, 2000);
5932 }
5933
5934 res = rtw_enqueue_cmd(pcmdpriv, cmdobj);
5935
5936 if (res == _SUCCESS && (flags & RTW_CMDF_WAIT_ACK)) {
5937 rtw_sctx_wait(&sctx, __func__);
5938 _enter_critical_mutex(&pcmdpriv->sctx_mutex, NULL);
5939 if (sctx.status == RTW_SCTX_SUBMITTED)
5940 cmdobj->sctx = NULL;
5941 _exit_critical_mutex(&pcmdpriv->sctx_mutex, NULL);
5942 if (sctx.status != RTW_SCTX_DONE_SUCCESS)
5943 res = _FAIL;
5944 }
5945
5946 exit:
5947 return res;
5948 }
5949
5950