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
rtw_joinbss_cmd(_adapter * padapter,struct wlan_network * pnetwork)991 u8 rtw_joinbss_cmd(_adapter *padapter, struct wlan_network *pnetwork)
992 {
993 u8 *auth, res = _SUCCESS;
994 uint t_len = 0;
995 WLAN_BSSID_EX *psecnetwork;
996 struct cmd_obj *pcmd;
997 struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
998 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
999 struct qos_priv *pqospriv = &pmlmepriv->qospriv;
1000 struct security_priv *psecuritypriv = &padapter->securitypriv;
1001 struct registry_priv *pregistrypriv = &padapter->registrypriv;
1002 #ifdef CONFIG_80211N_HT
1003 struct ht_priv *phtpriv = &pmlmepriv->htpriv;
1004 #endif /* CONFIG_80211N_HT */
1005 #ifdef CONFIG_80211AC_VHT
1006 struct vht_priv *pvhtpriv = &pmlmepriv->vhtpriv;
1007 #endif /* CONFIG_80211AC_VHT */
1008 NDIS_802_11_NETWORK_INFRASTRUCTURE ndis_network_mode = pnetwork->network.InfrastructureMode;
1009 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
1010 struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
1011 struct rf_ctl_t *rfctl = adapter_to_rfctl(padapter);
1012 u32 tmp_len;
1013 u8 *ptmp = NULL;
1014
1015 rtw_led_control(padapter, LED_CTL_START_TO_LINK);
1016
1017 pcmd = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
1018 if (pcmd == NULL) {
1019 res = _FAIL;
1020 goto exit;
1021 }
1022 #if 0
1023 /* for IEs is pointer */
1024 t_len = sizeof(u32) + sizeof(NDIS_802_11_MAC_ADDRESS) + 2 +
1025 sizeof(NDIS_802_11_SSID) + sizeof(u32) +
1026 sizeof(NDIS_802_11_RSSI) + sizeof(NDIS_802_11_NETWORK_TYPE) +
1027 sizeof(NDIS_802_11_CONFIGURATION) +
1028 sizeof(NDIS_802_11_NETWORK_INFRASTRUCTURE) +
1029 sizeof(NDIS_802_11_RATES_EX) + sizeof(WLAN_PHY_INFO) + sizeof(u32) + MAX_IE_SZ;
1030 #endif
1031 /* for IEs is fix buf size */
1032 t_len = sizeof(WLAN_BSSID_EX);
1033
1034
1035 /* for hidden ap to set fw_state here */
1036 if (check_fwstate(pmlmepriv, WIFI_STATION_STATE | WIFI_ADHOC_STATE) != _TRUE) {
1037 switch (ndis_network_mode) {
1038 case Ndis802_11IBSS:
1039 set_fwstate(pmlmepriv, WIFI_ADHOC_STATE);
1040 break;
1041
1042 case Ndis802_11Infrastructure:
1043 set_fwstate(pmlmepriv, WIFI_STATION_STATE);
1044 break;
1045
1046 default:
1047 rtw_warn_on(1);
1048 break;
1049 }
1050 }
1051
1052 pmlmeinfo->assoc_AP_vendor = check_assoc_AP(pnetwork->network.IEs, pnetwork->network.IELength);
1053
1054 #ifdef CONFIG_80211AC_VHT
1055 /* save AP beamform_cap info for BCM IOT issue */
1056 if (pmlmeinfo->assoc_AP_vendor == HT_IOT_PEER_BROADCOM)
1057 get_vht_bf_cap(pnetwork->network.IEs,
1058 pnetwork->network.IELength,
1059 &pvhtpriv->ap_bf_cap);
1060 #endif
1061 /*
1062 Modified by Arvin 2015/05/13
1063 Solution for allocating a new WLAN_BSSID_EX to avoid race condition issue between disconnect and joinbss
1064 */
1065 psecnetwork = (WLAN_BSSID_EX *)rtw_zmalloc(sizeof(WLAN_BSSID_EX));
1066 if (psecnetwork == NULL) {
1067 if (pcmd != NULL)
1068 rtw_mfree((unsigned char *)pcmd, sizeof(struct cmd_obj));
1069
1070 res = _FAIL;
1071
1072
1073 goto exit;
1074 }
1075
1076 _rtw_memset(psecnetwork, 0, t_len);
1077
1078 _rtw_memcpy(psecnetwork, &pnetwork->network, get_WLAN_BSSID_EX_sz(&pnetwork->network));
1079
1080 auth = &psecuritypriv->authenticator_ie[0];
1081 psecuritypriv->authenticator_ie[0] = (unsigned char)psecnetwork->IELength;
1082
1083 if ((psecnetwork->IELength - 12) < (256 - 1))
1084 _rtw_memcpy(&psecuritypriv->authenticator_ie[1], &psecnetwork->IEs[12], psecnetwork->IELength - 12);
1085 else
1086 _rtw_memcpy(&psecuritypriv->authenticator_ie[1], &psecnetwork->IEs[12], (256 - 1));
1087
1088 psecnetwork->IELength = 0;
1089 /* Added by Albert 2009/02/18 */
1090 /* If the the driver wants to use the bssid to create the connection. */
1091 /* If not, we have to copy the connecting AP's MAC address to it so that */
1092 /* the driver just has the bssid information for PMKIDList searching. */
1093
1094 if (pmlmepriv->assoc_by_bssid == _FALSE)
1095 _rtw_memcpy(&pmlmepriv->assoc_bssid[0], &pnetwork->network.MacAddress[0], ETH_ALEN);
1096
1097 /* copy fixed ie */
1098 _rtw_memcpy(psecnetwork->IEs, pnetwork->network.IEs, 12);
1099 psecnetwork->IELength = 12;
1100
1101 psecnetwork->IELength += rtw_restruct_sec_ie(padapter, psecnetwork->IEs + psecnetwork->IELength);
1102
1103
1104 pqospriv->qos_option = 0;
1105
1106 if (pregistrypriv->wmm_enable) {
1107 #ifdef CONFIG_WMMPS_STA
1108 rtw_uapsd_use_default_setting(padapter);
1109 #endif /* CONFIG_WMMPS_STA */
1110 tmp_len = rtw_restruct_wmm_ie(padapter, &pnetwork->network.IEs[0], &psecnetwork->IEs[0], pnetwork->network.IELength, psecnetwork->IELength);
1111
1112 if (psecnetwork->IELength != tmp_len) {
1113 psecnetwork->IELength = tmp_len;
1114 pqospriv->qos_option = 1; /* There is WMM IE in this corresp. beacon */
1115 } else {
1116 pqospriv->qos_option = 0;/* There is no WMM IE in this corresp. beacon */
1117 }
1118 }
1119
1120 #ifdef CONFIG_80211N_HT
1121 phtpriv->ht_option = _FALSE;
1122 if (pregistrypriv->ht_enable && is_supported_ht(pregistrypriv->wireless_mode)) {
1123 ptmp = rtw_get_ie(&pnetwork->network.IEs[12], _HT_CAPABILITY_IE_, &tmp_len, pnetwork->network.IELength - 12);
1124 if (ptmp && tmp_len > 0) {
1125 /* Added by Albert 2010/06/23 */
1126 /* For the WEP mode, we will use the bg mode to do the connection to avoid some IOT issue. */
1127 /* Especially for Realtek 8192u SoftAP. */
1128 if ((padapter->securitypriv.dot11PrivacyAlgrthm != _WEP40_) &&
1129 (padapter->securitypriv.dot11PrivacyAlgrthm != _WEP104_) &&
1130 (padapter->securitypriv.dot11PrivacyAlgrthm != _TKIP_)) {
1131 rtw_ht_use_default_setting(padapter);
1132
1133 /* rtw_restructure_ht_ie */
1134 rtw_restructure_ht_ie(padapter, &pnetwork->network.IEs[12], &psecnetwork->IEs[0],
1135 pnetwork->network.IELength - 12, &psecnetwork->IELength,
1136 pnetwork->network.Configuration.DSConfig);
1137 }
1138 }
1139 }
1140
1141 #ifdef CONFIG_80211AC_VHT
1142 pvhtpriv->vht_option = _FALSE;
1143 if (phtpriv->ht_option
1144 && REGSTY_IS_11AC_ENABLE(pregistrypriv)
1145 && is_supported_vht(pregistrypriv->wireless_mode)
1146 && (!rfctl->country_ent || COUNTRY_CHPLAN_EN_11AC(rfctl->country_ent))
1147 ) {
1148 u8 vht_enable = 0;
1149
1150 if (pnetwork->network.Configuration.DSConfig > 14)
1151 vht_enable = 1;
1152 else if ((REGSTY_IS_11AC_24G_ENABLE(pregistrypriv)) && (padapter->registrypriv.wifi_spec == 0))
1153 vht_enable = 1;
1154
1155 if (vht_enable == 1)
1156 rtw_restructure_vht_ie(padapter, &pnetwork->network.IEs[0], &psecnetwork->IEs[0],
1157 pnetwork->network.IELength, &psecnetwork->IELength);
1158 }
1159 #endif
1160 #endif /* CONFIG_80211N_HT */
1161
1162 rtw_append_extended_cap(padapter, &psecnetwork->IEs[0], &psecnetwork->IELength);
1163
1164 #ifdef CONFIG_RTW_80211R
1165 rtw_ft_validate_akm_type(padapter, pnetwork);
1166 #endif
1167
1168 #if 0
1169 psecuritypriv->supplicant_ie[0] = (u8)psecnetwork->IELength;
1170
1171 if (psecnetwork->IELength < (256 - 1))
1172 _rtw_memcpy(&psecuritypriv->supplicant_ie[1], &psecnetwork->IEs[0], psecnetwork->IELength);
1173 else
1174 _rtw_memcpy(&psecuritypriv->supplicant_ie[1], &psecnetwork->IEs[0], (256 - 1));
1175 #endif
1176
1177 pcmd->cmdsz = sizeof(WLAN_BSSID_EX);
1178
1179 _rtw_init_listhead(&pcmd->list);
1180 pcmd->cmdcode = CMD_JOINBSS;/* _JoinBss_CMD_ */
1181 pcmd->parmbuf = (unsigned char *)psecnetwork;
1182 pcmd->rsp = NULL;
1183 pcmd->rspsz = 0;
1184
1185 res = rtw_enqueue_cmd(pcmdpriv, pcmd);
1186
1187 exit:
1188
1189
1190 return res;
1191 }
1192
rtw_disassoc_cmd(_adapter * padapter,u32 deauth_timeout_ms,int flags)1193 u8 rtw_disassoc_cmd(_adapter *padapter, u32 deauth_timeout_ms, int flags) /* for sta_mode */
1194 {
1195 struct cmd_obj *cmdobj = NULL;
1196 struct disconnect_parm *param = NULL;
1197 struct cmd_priv *cmdpriv = &padapter->cmdpriv;
1198 struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
1199 struct submit_ctx sctx;
1200 u8 res = _SUCCESS;
1201
1202 /* prepare cmd parameter */
1203 param = (struct disconnect_parm *)rtw_zmalloc(sizeof(*param));
1204 if (param == NULL) {
1205 res = _FAIL;
1206 goto exit;
1207 }
1208 param->deauth_timeout_ms = deauth_timeout_ms;
1209
1210 if (flags & RTW_CMDF_DIRECTLY) {
1211 /* no need to enqueue, do the cmd hdl directly and free cmd parameter */
1212 if (disconnect_hdl(padapter, (u8 *)param) != H2C_SUCCESS)
1213 res = _FAIL;
1214 rtw_mfree((u8 *)param, sizeof(*param));
1215
1216 } else {
1217 cmdobj = (struct cmd_obj *)rtw_zmalloc(sizeof(*cmdobj));
1218 if (cmdobj == NULL) {
1219 res = _FAIL;
1220 rtw_mfree((u8 *)param, sizeof(*param));
1221 goto exit;
1222 }
1223 init_h2fwcmd_w_parm_no_rsp(cmdobj, param, CMD_DISCONNECT);
1224 if (flags & RTW_CMDF_WAIT_ACK) {
1225 cmdobj->sctx = &sctx;
1226 rtw_sctx_init(&sctx, 2000);
1227 }
1228 res = rtw_enqueue_cmd(cmdpriv, cmdobj);
1229 if (res == _SUCCESS && (flags & RTW_CMDF_WAIT_ACK)) {
1230 rtw_sctx_wait(&sctx, __func__);
1231 _enter_critical_mutex(&pcmdpriv->sctx_mutex, NULL);
1232 if (sctx.status == RTW_SCTX_SUBMITTED)
1233 cmdobj->sctx = NULL;
1234 _exit_critical_mutex(&pcmdpriv->sctx_mutex, NULL);
1235 }
1236 }
1237
1238 exit:
1239
1240
1241 return res;
1242 }
1243
1244 #ifdef CONFIG_AP_MODE
rtw_stop_ap_cmd(_adapter * adapter,u8 flags)1245 u8 rtw_stop_ap_cmd(_adapter *adapter, u8 flags)
1246 {
1247 struct cmd_obj *cmdobj;
1248 struct drvextra_cmd_parm *parm;
1249 struct cmd_priv *pcmdpriv = &adapter->cmdpriv;
1250 struct submit_ctx sctx;
1251 u8 res = _SUCCESS;
1252
1253 if (flags & RTW_CMDF_DIRECTLY) {
1254 /* no need to enqueue, do the cmd hdl directly and free cmd parameter */
1255 if (H2C_SUCCESS != stop_ap_hdl(adapter))
1256 res = _FAIL;
1257 } else {
1258 parm = (struct drvextra_cmd_parm *)rtw_zmalloc(sizeof(struct drvextra_cmd_parm));
1259 if (parm == NULL) {
1260 res = _FAIL;
1261 goto exit;
1262 }
1263
1264 parm->ec_id = STOP_AP_WK_CID;
1265 parm->type = 0;
1266 parm->size = 0;
1267 parm->pbuf = NULL;
1268
1269 /* need enqueue, prepare cmd_obj and enqueue */
1270 cmdobj = (struct cmd_obj *)rtw_zmalloc(sizeof(*cmdobj));
1271 if (cmdobj == NULL) {
1272 res = _FAIL;
1273 goto exit;
1274 }
1275
1276 init_h2fwcmd_w_parm_no_rsp(cmdobj, parm, CMD_SET_DRV_EXTRA);
1277
1278 if (flags & RTW_CMDF_WAIT_ACK) {
1279 cmdobj->sctx = &sctx;
1280 rtw_sctx_init(&sctx, 2000);
1281 }
1282
1283 res = rtw_enqueue_cmd(pcmdpriv, cmdobj);
1284
1285 if (res == _SUCCESS && (flags & RTW_CMDF_WAIT_ACK)) {
1286 rtw_sctx_wait(&sctx, __func__);
1287 _enter_critical_mutex(&pcmdpriv->sctx_mutex, NULL);
1288 if (sctx.status == RTW_SCTX_SUBMITTED)
1289 cmdobj->sctx = NULL;
1290 _exit_critical_mutex(&pcmdpriv->sctx_mutex, NULL);
1291 }
1292 }
1293 exit:
1294 return res;
1295 }
1296 #endif /* CONFIG_AP_MODE */
1297
1298 #ifdef CONFIG_RTW_TOKEN_BASED_XMIT
rtw_tx_control_cmd(_adapter * adapter)1299 u8 rtw_tx_control_cmd(_adapter *adapter)
1300 {
1301 struct cmd_obj *ph2c;
1302 struct drvextra_cmd_parm *pdrvextra_cmd_parm;
1303 struct cmd_priv *pcmdpriv = &adapter->cmdpriv;
1304
1305 u8 res = _SUCCESS;
1306
1307 ph2c = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
1308 if (ph2c == NULL){
1309 res = _FAIL;
1310 goto exit;
1311 }
1312
1313 pdrvextra_cmd_parm = (struct drvextra_cmd_parm *)rtw_zmalloc(sizeof(struct drvextra_cmd_parm));
1314 if (pdrvextra_cmd_parm == NULL) {
1315 rtw_mfree((unsigned char *)ph2c, sizeof(struct cmd_obj));
1316 res = _FAIL;
1317 goto exit;
1318 }
1319
1320 pdrvextra_cmd_parm->ec_id = TBTX_CONTROL_TX_WK_CID;
1321 pdrvextra_cmd_parm->type = 0;
1322 pdrvextra_cmd_parm->size = 0;
1323 pdrvextra_cmd_parm->pbuf = NULL;
1324 init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, CMD_SET_DRV_EXTRA);
1325
1326 res = rtw_enqueue_cmd(pcmdpriv, ph2c);
1327
1328 exit:
1329 return res;
1330 }
1331 #endif
1332
rtw_setopmode_cmd(_adapter * adapter,NDIS_802_11_NETWORK_INFRASTRUCTURE networktype,u8 flags)1333 u8 rtw_setopmode_cmd(_adapter *adapter, NDIS_802_11_NETWORK_INFRASTRUCTURE networktype, u8 flags)
1334 {
1335 struct cmd_obj *cmdobj;
1336 struct setopmode_parm *parm;
1337 struct cmd_priv *pcmdpriv = &adapter->cmdpriv;
1338 struct submit_ctx sctx;
1339 u8 res = _SUCCESS;
1340
1341 /* prepare cmd parameter */
1342 parm = (struct setopmode_parm *)rtw_zmalloc(sizeof(*parm));
1343 if (parm == NULL) {
1344 res = _FAIL;
1345 goto exit;
1346 }
1347 parm->mode = (u8)networktype;
1348
1349 if (flags & RTW_CMDF_DIRECTLY) {
1350 /* no need to enqueue, do the cmd hdl directly and free cmd parameter */
1351 if (H2C_SUCCESS != setopmode_hdl(adapter, (u8 *)parm))
1352 res = _FAIL;
1353 rtw_mfree((u8 *)parm, sizeof(*parm));
1354 } else {
1355 /* need enqueue, prepare cmd_obj and enqueue */
1356 cmdobj = (struct cmd_obj *)rtw_zmalloc(sizeof(*cmdobj));
1357 if (cmdobj == NULL) {
1358 res = _FAIL;
1359 rtw_mfree((u8 *)parm, sizeof(*parm));
1360 goto exit;
1361 }
1362
1363 init_h2fwcmd_w_parm_no_rsp(cmdobj, parm, CMD_SET_OPMODE);
1364
1365 if (flags & RTW_CMDF_WAIT_ACK) {
1366 cmdobj->sctx = &sctx;
1367 rtw_sctx_init(&sctx, 2000);
1368 }
1369
1370 res = rtw_enqueue_cmd(pcmdpriv, cmdobj);
1371
1372 if (res == _SUCCESS && (flags & RTW_CMDF_WAIT_ACK)) {
1373 rtw_sctx_wait(&sctx, __func__);
1374 _enter_critical_mutex(&pcmdpriv->sctx_mutex, NULL);
1375 if (sctx.status == RTW_SCTX_SUBMITTED)
1376 cmdobj->sctx = NULL;
1377 _exit_critical_mutex(&pcmdpriv->sctx_mutex, NULL);
1378 }
1379 }
1380
1381 exit:
1382 return res;
1383 }
1384
rtw_setstakey_cmd(_adapter * padapter,struct sta_info * sta,u8 key_type,bool enqueue)1385 u8 rtw_setstakey_cmd(_adapter *padapter, struct sta_info *sta, u8 key_type, bool enqueue)
1386 {
1387 struct cmd_obj *ph2c;
1388 struct set_stakey_parm *psetstakey_para;
1389 struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
1390 struct set_stakey_rsp *psetstakey_rsp = NULL;
1391
1392 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1393 struct security_priv *psecuritypriv = &padapter->securitypriv;
1394 u8 key_len =16;
1395 u8 res = _SUCCESS;
1396
1397
1398 psetstakey_para = (struct set_stakey_parm *)rtw_zmalloc(sizeof(struct set_stakey_parm));
1399 if (psetstakey_para == NULL) {
1400 res = _FAIL;
1401 goto exit;
1402 }
1403
1404 _rtw_memcpy(psetstakey_para->addr, sta->cmn.mac_addr, ETH_ALEN);
1405
1406 if (check_fwstate(pmlmepriv, WIFI_STATION_STATE))
1407 psetstakey_para->algorithm = (unsigned char) psecuritypriv->dot11PrivacyAlgrthm;
1408 else
1409 GET_ENCRY_ALGO(psecuritypriv, sta, psetstakey_para->algorithm, _FALSE);
1410
1411 if ((psetstakey_para->algorithm == _GCMP_256_) || (psetstakey_para->algorithm == _CCMP_256_))
1412 key_len = 32;
1413
1414 if (key_type == GROUP_KEY) {
1415 _rtw_memcpy(&psetstakey_para->key, &psecuritypriv->dot118021XGrpKey[psecuritypriv->dot118021XGrpKeyid].skey, key_len);
1416 psetstakey_para->gk = 1;
1417 } else if (key_type == UNICAST_KEY)
1418 _rtw_memcpy(&psetstakey_para->key, &sta->dot118021x_UncstKey, key_len);
1419 #ifdef CONFIG_TDLS
1420 else if (key_type == TDLS_KEY) {
1421 _rtw_memcpy(&psetstakey_para->key, sta->tpk.tk, key_len);
1422 psetstakey_para->algorithm = (u8)sta->dot118021XPrivacy;
1423 }
1424 #endif /* CONFIG_TDLS */
1425
1426 /* jeff: set this becasue at least sw key is ready */
1427 padapter->securitypriv.busetkipkey = _TRUE;
1428
1429 if (enqueue) {
1430 ph2c = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
1431 if (ph2c == NULL) {
1432 rtw_mfree((u8 *) psetstakey_para, sizeof(struct set_stakey_parm));
1433 res = _FAIL;
1434 goto exit;
1435 }
1436
1437 psetstakey_rsp = (struct set_stakey_rsp *)rtw_zmalloc(sizeof(struct set_stakey_rsp));
1438 if (psetstakey_rsp == NULL) {
1439 rtw_mfree((u8 *) ph2c, sizeof(struct cmd_obj));
1440 rtw_mfree((u8 *) psetstakey_para, sizeof(struct set_stakey_parm));
1441 res = _FAIL;
1442 goto exit;
1443 }
1444
1445 init_h2fwcmd_w_parm_no_rsp(ph2c, psetstakey_para, CMD_SET_STAKEY);
1446 ph2c->rsp = (u8 *) psetstakey_rsp;
1447 ph2c->rspsz = sizeof(struct set_stakey_rsp);
1448 res = rtw_enqueue_cmd(pcmdpriv, ph2c);
1449 } else {
1450 set_stakey_hdl(padapter, (u8 *)psetstakey_para);
1451 rtw_mfree((u8 *) psetstakey_para, sizeof(struct set_stakey_parm));
1452 }
1453 exit:
1454
1455
1456 return res;
1457 }
1458
rtw_clearstakey_cmd(_adapter * padapter,struct sta_info * sta,u8 enqueue)1459 u8 rtw_clearstakey_cmd(_adapter *padapter, struct sta_info *sta, u8 enqueue)
1460 {
1461 struct cmd_obj *ph2c;
1462 struct set_stakey_parm *psetstakey_para;
1463 struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
1464 struct set_stakey_rsp *psetstakey_rsp = NULL;
1465 s16 cam_id = 0;
1466 u8 res = _SUCCESS;
1467
1468 if (!sta) {
1469 RTW_ERR("%s sta == NULL\n", __func__);
1470 goto exit;
1471 }
1472
1473 if (!enqueue) {
1474 while ((cam_id = rtw_camid_search(padapter, sta->cmn.mac_addr, -1, -1)) >= 0) {
1475 RTW_PRINT("clear key for addr:"MAC_FMT", camid:%d\n", MAC_ARG(sta->cmn.mac_addr), cam_id);
1476 clear_cam_entry(padapter, cam_id);
1477 rtw_camid_free(padapter, cam_id);
1478 }
1479 } else {
1480 ph2c = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
1481 if (ph2c == NULL) {
1482 res = _FAIL;
1483 goto exit;
1484 }
1485
1486 psetstakey_para = (struct set_stakey_parm *)rtw_zmalloc(sizeof(struct set_stakey_parm));
1487 if (psetstakey_para == NULL) {
1488 rtw_mfree((u8 *) ph2c, sizeof(struct cmd_obj));
1489 res = _FAIL;
1490 goto exit;
1491 }
1492
1493 psetstakey_rsp = (struct set_stakey_rsp *)rtw_zmalloc(sizeof(struct set_stakey_rsp));
1494 if (psetstakey_rsp == NULL) {
1495 rtw_mfree((u8 *) ph2c, sizeof(struct cmd_obj));
1496 rtw_mfree((u8 *) psetstakey_para, sizeof(struct set_stakey_parm));
1497 res = _FAIL;
1498 goto exit;
1499 }
1500
1501 init_h2fwcmd_w_parm_no_rsp(ph2c, psetstakey_para, CMD_SET_STAKEY);
1502 ph2c->rsp = (u8 *) psetstakey_rsp;
1503 ph2c->rspsz = sizeof(struct set_stakey_rsp);
1504
1505 _rtw_memcpy(psetstakey_para->addr, sta->cmn.mac_addr, ETH_ALEN);
1506
1507 psetstakey_para->algorithm = _NO_PRIVACY_;
1508
1509 res = rtw_enqueue_cmd(pcmdpriv, ph2c);
1510
1511 }
1512
1513 exit:
1514
1515
1516 return res;
1517 }
1518
rtw_addbareq_cmd(_adapter * padapter,u8 tid,u8 * addr)1519 u8 rtw_addbareq_cmd(_adapter *padapter, u8 tid, u8 *addr)
1520 {
1521 struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
1522 struct cmd_obj *ph2c;
1523 struct addBaReq_parm *paddbareq_parm;
1524
1525 u8 res = _SUCCESS;
1526
1527
1528 ph2c = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
1529 if (ph2c == NULL) {
1530 res = _FAIL;
1531 goto exit;
1532 }
1533
1534 paddbareq_parm = (struct addBaReq_parm *)rtw_zmalloc(sizeof(struct addBaReq_parm));
1535 if (paddbareq_parm == NULL) {
1536 rtw_mfree((unsigned char *)ph2c, sizeof(struct cmd_obj));
1537 res = _FAIL;
1538 goto exit;
1539 }
1540
1541 paddbareq_parm->tid = tid;
1542 _rtw_memcpy(paddbareq_parm->addr, addr, ETH_ALEN);
1543
1544 init_h2fwcmd_w_parm_no_rsp(ph2c, paddbareq_parm, CMD_ADD_BAREQ);
1545
1546 /* RTW_INFO("rtw_addbareq_cmd, tid=%d\n", tid); */
1547
1548 /* rtw_enqueue_cmd(pcmdpriv, ph2c); */
1549 res = rtw_enqueue_cmd(pcmdpriv, ph2c);
1550
1551 exit:
1552
1553
1554 return res;
1555 }
1556
rtw_addbarsp_cmd(_adapter * padapter,u8 * addr,u16 tid,u8 status,u8 size,u16 start_seq)1557 u8 rtw_addbarsp_cmd(_adapter *padapter, u8 *addr, u16 tid, u8 status, u8 size, u16 start_seq)
1558 {
1559 struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
1560 struct cmd_obj *ph2c;
1561 struct addBaRsp_parm *paddBaRsp_parm;
1562 u8 res = _SUCCESS;
1563
1564
1565 ph2c = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
1566 if (ph2c == NULL) {
1567 res = _FAIL;
1568 goto exit;
1569 }
1570
1571 paddBaRsp_parm = (struct addBaRsp_parm *)rtw_zmalloc(sizeof(struct addBaRsp_parm));
1572
1573 if (paddBaRsp_parm == NULL) {
1574 rtw_mfree((unsigned char *)ph2c, sizeof(struct cmd_obj));
1575 res = _FAIL;
1576 goto exit;
1577 }
1578
1579 _rtw_memcpy(paddBaRsp_parm->addr, addr, ETH_ALEN);
1580 paddBaRsp_parm->tid = tid;
1581 paddBaRsp_parm->status = status;
1582 paddBaRsp_parm->size = size;
1583 paddBaRsp_parm->start_seq = start_seq;
1584
1585 init_h2fwcmd_w_parm_no_rsp(ph2c, paddBaRsp_parm, CMD_ADD_BARSP);
1586
1587 res = rtw_enqueue_cmd(pcmdpriv, ph2c);
1588
1589 exit:
1590
1591
1592 return res;
1593 }
1594 /* add for CONFIG_IEEE80211W, none 11w can use it */
rtw_reset_securitypriv_cmd(_adapter * padapter)1595 u8 rtw_reset_securitypriv_cmd(_adapter *padapter)
1596 {
1597 struct cmd_obj *ph2c;
1598 struct drvextra_cmd_parm *pdrvextra_cmd_parm;
1599 struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
1600 u8 res = _SUCCESS;
1601
1602
1603 ph2c = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
1604 if (ph2c == NULL) {
1605 res = _FAIL;
1606 goto exit;
1607 }
1608
1609 pdrvextra_cmd_parm = (struct drvextra_cmd_parm *)rtw_zmalloc(sizeof(struct drvextra_cmd_parm));
1610 if (pdrvextra_cmd_parm == NULL) {
1611 rtw_mfree((unsigned char *)ph2c, sizeof(struct cmd_obj));
1612 res = _FAIL;
1613 goto exit;
1614 }
1615
1616 pdrvextra_cmd_parm->ec_id = RESET_SECURITYPRIV;
1617 pdrvextra_cmd_parm->type = 0;
1618 pdrvextra_cmd_parm->size = 0;
1619 pdrvextra_cmd_parm->pbuf = NULL;
1620
1621 init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, CMD_SET_DRV_EXTRA);
1622
1623
1624 /* rtw_enqueue_cmd(pcmdpriv, ph2c); */
1625 res = rtw_enqueue_cmd(pcmdpriv, ph2c);
1626
1627 exit:
1628
1629
1630 return res;
1631
1632 }
1633
free_assoc_resources_hdl(_adapter * padapter,u8 lock_scanned_queue)1634 void free_assoc_resources_hdl(_adapter *padapter, u8 lock_scanned_queue)
1635 {
1636 rtw_free_assoc_resources(padapter, lock_scanned_queue);
1637 }
1638
rtw_free_assoc_resources_cmd(_adapter * padapter,u8 lock_scanned_queue,int flags)1639 u8 rtw_free_assoc_resources_cmd(_adapter *padapter, u8 lock_scanned_queue, int flags)
1640 {
1641 struct cmd_obj *cmd;
1642 struct drvextra_cmd_parm *pdrvextra_cmd_parm;
1643 struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
1644 struct submit_ctx sctx;
1645 u8 res = _SUCCESS;
1646
1647 if (flags & RTW_CMDF_DIRECTLY) {
1648 free_assoc_resources_hdl(padapter, lock_scanned_queue);
1649 }
1650 else {
1651 cmd = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
1652 if (cmd == NULL) {
1653 res = _FAIL;
1654 goto exit;
1655 }
1656
1657 pdrvextra_cmd_parm = (struct drvextra_cmd_parm *)rtw_zmalloc(sizeof(struct drvextra_cmd_parm));
1658 if (pdrvextra_cmd_parm == NULL) {
1659 rtw_mfree((unsigned char *)cmd, sizeof(struct cmd_obj));
1660 res = _FAIL;
1661 goto exit;
1662 }
1663
1664 pdrvextra_cmd_parm->ec_id = FREE_ASSOC_RESOURCES;
1665 pdrvextra_cmd_parm->type = lock_scanned_queue;
1666 pdrvextra_cmd_parm->size = 0;
1667 pdrvextra_cmd_parm->pbuf = NULL;
1668
1669 init_h2fwcmd_w_parm_no_rsp(cmd, pdrvextra_cmd_parm, CMD_SET_DRV_EXTRA);
1670 if (flags & RTW_CMDF_WAIT_ACK) {
1671 cmd->sctx = &sctx;
1672 rtw_sctx_init(&sctx, 2000);
1673 }
1674
1675 res = rtw_enqueue_cmd(pcmdpriv, cmd);
1676
1677 if (res == _SUCCESS && (flags & RTW_CMDF_WAIT_ACK)) {
1678 rtw_sctx_wait(&sctx, __func__);
1679 _enter_critical_mutex(&pcmdpriv->sctx_mutex, NULL);
1680 if (sctx.status == RTW_SCTX_SUBMITTED)
1681 cmd->sctx = NULL;
1682 _exit_critical_mutex(&pcmdpriv->sctx_mutex, NULL);
1683 }
1684 }
1685 exit:
1686 return res;
1687
1688 }
1689
rtw_dynamic_chk_wk_cmd(_adapter * padapter)1690 u8 rtw_dynamic_chk_wk_cmd(_adapter *padapter)
1691 {
1692 struct cmd_obj *ph2c;
1693 struct drvextra_cmd_parm *pdrvextra_cmd_parm;
1694 struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
1695 u8 res = _SUCCESS;
1696
1697
1698 /* only primary padapter does this cmd */
1699
1700 ph2c = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
1701 if (ph2c == NULL) {
1702 res = _FAIL;
1703 goto exit;
1704 }
1705
1706 pdrvextra_cmd_parm = (struct drvextra_cmd_parm *)rtw_zmalloc(sizeof(struct drvextra_cmd_parm));
1707 if (pdrvextra_cmd_parm == NULL) {
1708 rtw_mfree((unsigned char *)ph2c, sizeof(struct cmd_obj));
1709 res = _FAIL;
1710 goto exit;
1711 }
1712
1713 pdrvextra_cmd_parm->ec_id = DYNAMIC_CHK_WK_CID;
1714 pdrvextra_cmd_parm->type = 0;
1715 pdrvextra_cmd_parm->size = 0;
1716 pdrvextra_cmd_parm->pbuf = NULL;
1717 init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, CMD_SET_DRV_EXTRA);
1718
1719
1720 /* rtw_enqueue_cmd(pcmdpriv, ph2c); */
1721 res = rtw_enqueue_cmd(pcmdpriv, ph2c);
1722
1723 exit:
1724
1725
1726 return res;
1727
1728 }
1729
rtw_iqk_cmd(_adapter * padapter,u8 flags)1730 u8 rtw_iqk_cmd(_adapter *padapter, u8 flags)
1731 {
1732 struct cmd_obj *pcmdobj;
1733 struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
1734 struct submit_ctx sctx;
1735 u8 res = _SUCCESS;
1736
1737 if (flags & RTW_CMDF_DIRECTLY) {
1738 /* no need to enqueue, do the cmd hdl */
1739 rtw_iqk_hdl(padapter, NULL);
1740 } else {
1741 /* need enqueue, prepare cmd_obj and enqueue */
1742 pcmdobj = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
1743 if (pcmdobj == NULL) {
1744 res = _FAIL;
1745 goto exit;
1746 }
1747
1748 init_h2fwcmd_w_parm_no_parm_rsp(pcmdobj, CMD_DO_IQK);
1749
1750 if (flags & RTW_CMDF_WAIT_ACK) {
1751 pcmdobj->sctx = &sctx;
1752 rtw_sctx_init(&sctx, 10 * 1000);
1753 }
1754
1755 res = rtw_enqueue_cmd(pcmdpriv, pcmdobj);
1756
1757 if (res == _SUCCESS && (flags & RTW_CMDF_WAIT_ACK)) {
1758 rtw_sctx_wait(&sctx, __func__);
1759 _enter_critical_mutex(&pcmdpriv->sctx_mutex, NULL);
1760 if (sctx.status == RTW_SCTX_SUBMITTED)
1761 pcmdobj->sctx = NULL;
1762 _exit_critical_mutex(&pcmdpriv->sctx_mutex, NULL);
1763 }
1764 }
1765
1766 exit:
1767
1768 return res;
1769 }
1770
rtw_set_chbw_cmd(_adapter * padapter,u8 ch,u8 bw,u8 ch_offset,u8 flags)1771 u8 rtw_set_chbw_cmd(_adapter *padapter, u8 ch, u8 bw, u8 ch_offset, u8 flags)
1772 {
1773 struct cmd_obj *pcmdobj;
1774 struct set_ch_parm *set_ch_parm;
1775 struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
1776 struct submit_ctx sctx;
1777 u8 res = _SUCCESS;
1778
1779
1780 RTW_INFO(FUNC_NDEV_FMT" ch:%u, bw:%u, ch_offset:%u\n",
1781 FUNC_NDEV_ARG(padapter->pnetdev), ch, bw, ch_offset);
1782
1783 /* check input parameter */
1784
1785 /* prepare cmd parameter */
1786 set_ch_parm = (struct set_ch_parm *)rtw_zmalloc(sizeof(*set_ch_parm));
1787 if (set_ch_parm == NULL) {
1788 res = _FAIL;
1789 goto exit;
1790 }
1791 set_ch_parm->ch = ch;
1792 set_ch_parm->bw = bw;
1793 set_ch_parm->ch_offset = ch_offset;
1794
1795 if (flags & RTW_CMDF_DIRECTLY) {
1796 /* no need to enqueue, do the cmd hdl directly and free cmd parameter */
1797 if (H2C_SUCCESS != rtw_set_chbw_hdl(padapter, (u8 *)set_ch_parm))
1798 res = _FAIL;
1799
1800 rtw_mfree((u8 *)set_ch_parm, sizeof(*set_ch_parm));
1801 } else {
1802 /* need enqueue, prepare cmd_obj and enqueue */
1803 pcmdobj = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
1804 if (pcmdobj == NULL) {
1805 rtw_mfree((u8 *)set_ch_parm, sizeof(*set_ch_parm));
1806 res = _FAIL;
1807 goto exit;
1808 }
1809
1810 init_h2fwcmd_w_parm_no_rsp(pcmdobj, set_ch_parm, CMD_SET_CHANNEL);
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 /* do something based on res... */
1829
1830 exit:
1831
1832 RTW_INFO(FUNC_NDEV_FMT" res:%u\n", FUNC_NDEV_ARG(padapter->pnetdev), res);
1833
1834
1835 return res;
1836 }
1837
_rtw_set_chplan_cmd(_adapter * adapter,int flags,u8 chplan,const struct country_chplan * country_ent,enum regd_src_t regd_src,u8 swconfig)1838 static u8 _rtw_set_chplan_cmd(_adapter *adapter, int flags, u8 chplan, const struct country_chplan *country_ent, enum regd_src_t regd_src, u8 swconfig)
1839 {
1840 struct cmd_obj *cmdobj;
1841 struct SetChannelPlan_param *parm;
1842 struct cmd_priv *pcmdpriv = &adapter->cmdpriv;
1843 struct submit_ctx sctx;
1844 u8 res = _SUCCESS;
1845
1846 /* check if allow software config */
1847 if (swconfig && rtw_hal_is_disable_sw_channel_plan(adapter) == _TRUE) {
1848 res = _FAIL;
1849 goto exit;
1850 }
1851
1852 /* if country_entry is provided, replace chplan */
1853 if (country_ent)
1854 chplan = country_ent->chplan;
1855
1856 /* check input parameter */
1857 if (regd_src == REGD_SRC_RTK_PRIV && !rtw_is_channel_plan_valid(chplan)) {
1858 res = _FAIL;
1859 goto exit;
1860 }
1861
1862 /* prepare cmd parameter */
1863 parm = (struct SetChannelPlan_param *)rtw_zmalloc(sizeof(*parm));
1864 if (parm == NULL) {
1865 res = _FAIL;
1866 goto exit;
1867 }
1868 parm->regd_src = regd_src;
1869 parm->country_ent = country_ent;
1870 parm->channel_plan = chplan;
1871
1872 if (flags & RTW_CMDF_DIRECTLY) {
1873 /* no need to enqueue, do the cmd hdl directly and free cmd parameter */
1874 if (H2C_SUCCESS != rtw_set_chplan_hdl(adapter, (u8 *)parm))
1875 res = _FAIL;
1876 rtw_mfree((u8 *)parm, sizeof(*parm));
1877 } else {
1878 /* need enqueue, prepare cmd_obj and enqueue */
1879 cmdobj = (struct cmd_obj *)rtw_zmalloc(sizeof(*cmdobj));
1880 if (cmdobj == NULL) {
1881 res = _FAIL;
1882 rtw_mfree((u8 *)parm, sizeof(*parm));
1883 goto exit;
1884 }
1885
1886 init_h2fwcmd_w_parm_no_rsp(cmdobj, parm, CMD_SET_CHANPLAN);
1887
1888 if (flags & RTW_CMDF_WAIT_ACK) {
1889 cmdobj->sctx = &sctx;
1890 rtw_sctx_init(&sctx, 2000);
1891 }
1892
1893 res = rtw_enqueue_cmd(pcmdpriv, cmdobj);
1894
1895 if (res == _SUCCESS && (flags & RTW_CMDF_WAIT_ACK)) {
1896 rtw_sctx_wait(&sctx, __func__);
1897 _enter_critical_mutex(&pcmdpriv->sctx_mutex, NULL);
1898 if (sctx.status == RTW_SCTX_SUBMITTED)
1899 cmdobj->sctx = NULL;
1900 _exit_critical_mutex(&pcmdpriv->sctx_mutex, NULL);
1901 if (sctx.status != RTW_SCTX_DONE_SUCCESS)
1902 res = _FAIL;
1903 }
1904
1905 /* allow set channel plan when cmd_thread is not running */
1906 if (res != _SUCCESS && (flags & RTW_CMDF_WAIT_ACK)) {
1907 parm = (struct SetChannelPlan_param *)rtw_zmalloc(sizeof(*parm));
1908 if (parm == NULL) {
1909 res = _FAIL;
1910 goto exit;
1911 }
1912 parm->regd_src = regd_src;
1913 parm->country_ent = country_ent;
1914 parm->channel_plan = chplan;
1915
1916 if (H2C_SUCCESS != rtw_set_chplan_hdl(adapter, (u8 *)parm))
1917 res = _FAIL;
1918 else
1919 res = _SUCCESS;
1920 rtw_mfree((u8 *)parm, sizeof(*parm));
1921 }
1922 }
1923
1924 exit:
1925 return res;
1926 }
1927
rtw_set_chplan_cmd(_adapter * adapter,int flags,u8 chplan,u8 swconfig)1928 inline u8 rtw_set_chplan_cmd(_adapter *adapter, int flags, u8 chplan, u8 swconfig)
1929 {
1930 return _rtw_set_chplan_cmd(adapter, flags, chplan, NULL, REGD_SRC_RTK_PRIV, swconfig);
1931 }
1932
rtw_set_country_cmd(_adapter * adapter,int flags,const char * country_code,u8 swconfig)1933 inline u8 rtw_set_country_cmd(_adapter *adapter, int flags, const char *country_code, u8 swconfig)
1934 {
1935 const struct country_chplan *ent;
1936
1937 if (is_alpha(country_code[0]) == _FALSE
1938 || is_alpha(country_code[1]) == _FALSE
1939 ) {
1940 RTW_PRINT("%s input country_code is not alpha2\n", __func__);
1941 return _FAIL;
1942 }
1943
1944 ent = rtw_get_chplan_from_country(country_code);
1945
1946 if (ent == NULL) {
1947 RTW_PRINT("%s unsupported country_code:\"%c%c\"\n", __func__, country_code[0], country_code[1]);
1948 return _FAIL;
1949 }
1950
1951 RTW_PRINT("%s country_code:\"%c%c\" mapping to chplan:0x%02x\n", __func__, country_code[0], country_code[1], ent->chplan);
1952
1953 return _rtw_set_chplan_cmd(adapter, flags, RTW_CHPLAN_UNSPECIFIED, ent, REGD_SRC_RTK_PRIV, swconfig);
1954 }
1955
1956 #ifdef CONFIG_REGD_SRC_FROM_OS
rtw_sync_os_regd_cmd(_adapter * adapter,int flags,const char * country_code,u8 dfs_region)1957 inline u8 rtw_sync_os_regd_cmd(_adapter *adapter, int flags, const char *country_code, u8 dfs_region)
1958 {
1959 struct country_chplan *ent;
1960 const struct country_chplan *rtk_ent;
1961
1962 /* allocate entry for regd source out of driver */
1963 ent = rtw_malloc(sizeof(*ent));
1964 if (ent == NULL)
1965 return _FAIL;
1966
1967 rtk_ent = rtw_get_chplan_from_country(country_code);
1968
1969 _rtw_memcpy(ent->alpha2, country_code, 2);
1970
1971 /*
1972 * Regulation follows OS, the internal txpwr limit selection is searched by alpha2
1973 * "00" => WW, others use string mapping
1974 * When no matching txpwr limit selection is found, use
1975 * 1. txpwr lmit selection associated with alpha2 inside driver regulation database
1976 * 2. WW when driver has no support of this alpha2
1977 */
1978
1979 ent->chplan = rtk_ent ? rtk_ent->chplan : RTW_CHPLAN_UNSPECIFIED;
1980 ent->txpwr_lmt_override = rtk_ent ? rtk_ent->txpwr_lmt_override : TXPWR_LMT_DEF;
1981 #if defined(CONFIG_80211AC_VHT) || defined(CONFIG_80211AX_HE)
1982 ent->proto_en = CCHPLAN_PROTO_EN_ALL;
1983 #endif
1984
1985 /* TODO: dfs_region */
1986
1987 return _rtw_set_chplan_cmd(adapter, flags, RTW_CHPLAN_UNSPECIFIED, ent, REGD_SRC_OS, 1);
1988 }
1989 #endif /* CONFIG_REGD_SRC_FROM_OS */
1990
rtw_get_chplan_cmd(_adapter * adapter,int flags,struct get_chplan_resp ** resp)1991 u8 rtw_get_chplan_cmd(_adapter *adapter, int flags, struct get_chplan_resp **resp)
1992 {
1993 struct cmd_obj *cmdobj;
1994 struct get_channel_plan_param *parm;
1995 struct cmd_priv *pcmdpriv = &adapter->cmdpriv;
1996 struct submit_ctx sctx;
1997 u8 res = _FAIL;
1998
1999 if (!(flags & (RTW_CMDF_DIRECTLY | RTW_CMDF_WAIT_ACK)))
2000 goto exit;
2001
2002 /* prepare cmd parameter */
2003 parm = rtw_zmalloc(sizeof(*parm));
2004 if (parm == NULL)
2005 goto exit;
2006 parm->resp = resp;
2007
2008 if (flags & RTW_CMDF_DIRECTLY) {
2009 /* no need to enqueue, do the cmd hdl directly and free cmd parameter */
2010 if (H2C_SUCCESS == rtw_get_chplan_hdl(adapter, (u8 *)parm))
2011 res = _SUCCESS;
2012 rtw_mfree((u8 *)parm, sizeof(*parm));
2013 } else {
2014 /* need enqueue, prepare cmd_obj and enqueue */
2015 cmdobj = (struct cmd_obj *)rtw_zmalloc(sizeof(*cmdobj));
2016 if (cmdobj == NULL) {
2017 rtw_mfree((u8 *)parm, sizeof(*parm));
2018 goto exit;
2019 }
2020
2021 init_h2fwcmd_w_parm_no_rsp(cmdobj, parm, CMD_GET_CHANPLAN);
2022
2023 if (flags & RTW_CMDF_WAIT_ACK) {
2024 cmdobj->sctx = &sctx;
2025 rtw_sctx_init(&sctx, 2000);
2026 }
2027
2028 res = rtw_enqueue_cmd(pcmdpriv, cmdobj);
2029
2030 if (res == _SUCCESS && (flags & RTW_CMDF_WAIT_ACK)) {
2031 rtw_sctx_wait(&sctx, __func__);
2032 _enter_critical_mutex(&pcmdpriv->sctx_mutex, NULL);
2033 if (sctx.status == RTW_SCTX_SUBMITTED)
2034 cmdobj->sctx = NULL;
2035 _exit_critical_mutex(&pcmdpriv->sctx_mutex, NULL);
2036 if (sctx.status != RTW_SCTX_DONE_SUCCESS)
2037 res = _FAIL;
2038 }
2039
2040 /* allow get channel plan when cmd_thread is not running */
2041 if (res != _SUCCESS && (flags & RTW_CMDF_WAIT_ACK)) {
2042 parm = rtw_zmalloc(sizeof(*parm));
2043 if (parm == NULL)
2044 goto exit;
2045 parm->resp = resp;
2046
2047 if (H2C_SUCCESS == rtw_get_chplan_hdl(adapter, (u8 *)parm))
2048 res = _SUCCESS;
2049
2050 rtw_mfree((u8 *)parm, sizeof(*parm));
2051 }
2052 }
2053
2054 exit:
2055 return res;
2056 }
2057
rtw_led_blink_cmd(_adapter * padapter,void * pLed)2058 u8 rtw_led_blink_cmd(_adapter *padapter, void *pLed)
2059 {
2060 struct cmd_obj *pcmdobj;
2061 struct LedBlink_param *ledBlink_param;
2062 struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
2063
2064 u8 res = _SUCCESS;
2065
2066
2067
2068 pcmdobj = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
2069 if (pcmdobj == NULL) {
2070 res = _FAIL;
2071 goto exit;
2072 }
2073
2074 ledBlink_param = (struct LedBlink_param *)rtw_zmalloc(sizeof(struct LedBlink_param));
2075 if (ledBlink_param == NULL) {
2076 rtw_mfree((u8 *)pcmdobj, sizeof(struct cmd_obj));
2077 res = _FAIL;
2078 goto exit;
2079 }
2080
2081 ledBlink_param->pLed = pLed;
2082
2083 init_h2fwcmd_w_parm_no_rsp(pcmdobj, ledBlink_param, CMD_LEDBLINK);
2084 res = rtw_enqueue_cmd(pcmdpriv, pcmdobj);
2085
2086 exit:
2087
2088
2089 return res;
2090 }
2091
rtw_set_csa_cmd(_adapter * adapter)2092 u8 rtw_set_csa_cmd(_adapter *adapter)
2093 {
2094 struct cmd_obj *cmdobj;
2095 struct cmd_priv *cmdpriv = &adapter->cmdpriv;
2096 u8 res = _SUCCESS;
2097
2098 cmdobj = rtw_zmalloc(sizeof(struct cmd_obj));
2099 if (cmdobj == NULL) {
2100 res = _FAIL;
2101 goto exit;
2102 }
2103
2104 init_h2fwcmd_w_parm_no_parm_rsp(cmdobj, CMD_SET_CHANSWITCH);
2105 res = rtw_enqueue_cmd(cmdpriv, cmdobj);
2106
2107 exit:
2108 return res;
2109 }
2110
rtw_tdls_cmd(_adapter * padapter,u8 * addr,u8 option)2111 u8 rtw_tdls_cmd(_adapter *padapter, u8 *addr, u8 option)
2112 {
2113 u8 res = _SUCCESS;
2114 #ifdef CONFIG_TDLS
2115 struct cmd_obj *pcmdobj;
2116 struct TDLSoption_param *TDLSoption;
2117 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
2118 struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
2119
2120 pcmdobj = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
2121 if (pcmdobj == NULL) {
2122 res = _FAIL;
2123 goto exit;
2124 }
2125
2126 TDLSoption = (struct TDLSoption_param *)rtw_zmalloc(sizeof(struct TDLSoption_param));
2127 if (TDLSoption == NULL) {
2128 rtw_mfree((u8 *)pcmdobj, sizeof(struct cmd_obj));
2129 res = _FAIL;
2130 goto exit;
2131 }
2132
2133 _rtw_spinlock(&(padapter->tdlsinfo.cmd_lock));
2134 if (addr != NULL)
2135 _rtw_memcpy(TDLSoption->addr, addr, 6);
2136 TDLSoption->option = option;
2137 _rtw_spinunlock(&(padapter->tdlsinfo.cmd_lock));
2138 init_h2fwcmd_w_parm_no_rsp(pcmdobj, TDLSoption, CMD_TDLS);
2139 res = rtw_enqueue_cmd(pcmdpriv, pcmdobj);
2140
2141 exit:
2142 #endif /* CONFIG_TDLS */
2143
2144 return res;
2145 }
2146
rtw_enable_hw_update_tsf_cmd(_adapter * padapter)2147 u8 rtw_enable_hw_update_tsf_cmd(_adapter *padapter)
2148 {
2149 struct cmd_obj *ph2c;
2150 struct drvextra_cmd_parm *pdrvextra_cmd_parm;
2151 struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
2152 u8 res = _SUCCESS;
2153
2154
2155 ph2c = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
2156 if (ph2c == NULL) {
2157 res = _FAIL;
2158 goto exit;
2159 }
2160
2161 pdrvextra_cmd_parm = (struct drvextra_cmd_parm *)rtw_zmalloc(sizeof(struct drvextra_cmd_parm));
2162 if (pdrvextra_cmd_parm == NULL) {
2163 rtw_mfree((unsigned char *)ph2c, sizeof(struct cmd_obj));
2164 res = _FAIL;
2165 goto exit;
2166 }
2167
2168 pdrvextra_cmd_parm->ec_id = EN_HW_UPDATE_TSF_WK_CID;
2169 pdrvextra_cmd_parm->type = 0;
2170 pdrvextra_cmd_parm->size = 0;
2171 pdrvextra_cmd_parm->pbuf = NULL;
2172
2173 init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, CMD_SET_DRV_EXTRA);
2174
2175 res = rtw_enqueue_cmd(pcmdpriv, ph2c);
2176
2177 exit:
2178 return res;
2179 }
2180
rtw_periodic_tsf_update_end_cmd(_adapter * adapter)2181 u8 rtw_periodic_tsf_update_end_cmd(_adapter *adapter)
2182 {
2183 struct cmd_obj *cmdobj;
2184 struct drvextra_cmd_parm *parm;
2185 struct cmd_priv *cmdpriv = &adapter->cmdpriv;
2186 u8 res = _SUCCESS;
2187
2188 cmdobj = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
2189 if (cmdobj == NULL) {
2190 res = _FAIL;
2191 goto exit;
2192 }
2193
2194 parm = (struct drvextra_cmd_parm *)rtw_zmalloc(sizeof(struct drvextra_cmd_parm));
2195 if (parm == NULL) {
2196 rtw_mfree((unsigned char *)cmdobj, sizeof(struct cmd_obj));
2197 res = _FAIL;
2198 goto exit;
2199 }
2200
2201 parm->ec_id = PERIOD_TSF_UPDATE_END_WK_CID;
2202 parm->type = 0;
2203 parm->size = 0;
2204 parm->pbuf = NULL;
2205
2206 init_h2fwcmd_w_parm_no_rsp(cmdobj, parm, CMD_SET_DRV_EXTRA);
2207
2208 res = rtw_enqueue_cmd(cmdpriv, cmdobj);
2209
2210 exit:
2211 return res;
2212 }
rtw_ssmps_wk_hdl(_adapter * adapter,struct ssmps_cmd_parm * ssmp_param)2213 u8 rtw_ssmps_wk_hdl(_adapter *adapter, struct ssmps_cmd_parm *ssmp_param)
2214 {
2215 u8 res = _SUCCESS;
2216 struct sta_info *sta = ssmp_param->sta;
2217 u8 smps = ssmp_param->smps;
2218
2219 if (sta == NULL)
2220 return _FALSE;
2221
2222 if (smps)
2223 rtw_ssmps_enter(adapter, sta);
2224 else
2225 rtw_ssmps_leave(adapter, sta);
2226 return res;
2227 }
2228
rtw_ssmps_wk_cmd(_adapter * adapter,struct sta_info * sta,u8 smps,u8 enqueue)2229 u8 rtw_ssmps_wk_cmd(_adapter *adapter, struct sta_info *sta, u8 smps, u8 enqueue)
2230 {
2231 struct cmd_obj *cmdobj;
2232 struct drvextra_cmd_parm *cmd_parm;
2233 struct ssmps_cmd_parm *ssmp_param;
2234 struct cmd_priv *pcmdpriv = &adapter->cmdpriv;
2235 u8 res = _SUCCESS;
2236
2237 if (enqueue) {
2238 cmdobj = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
2239 if (cmdobj == NULL) {
2240 res = _FAIL;
2241 goto exit;
2242 }
2243
2244 cmd_parm = (struct drvextra_cmd_parm *)rtw_zmalloc(sizeof(struct drvextra_cmd_parm));
2245 if (cmd_parm == NULL) {
2246 rtw_mfree((unsigned char *)cmdobj, sizeof(struct cmd_obj));
2247 res = _FAIL;
2248 goto exit;
2249 }
2250
2251 ssmp_param = (struct ssmps_cmd_parm *)rtw_zmalloc(sizeof(struct ssmps_cmd_parm));
2252 if (ssmp_param == NULL) {
2253 rtw_mfree((u8 *)cmdobj, sizeof(struct cmd_obj));
2254 rtw_mfree((u8 *)cmd_parm, sizeof(struct drvextra_cmd_parm));
2255 res = _FAIL;
2256 goto exit;
2257 }
2258
2259 ssmp_param->smps = smps;
2260 ssmp_param->sta = sta;
2261
2262 cmd_parm->ec_id = SSMPS_WK_CID;
2263 cmd_parm->type = 0;
2264 cmd_parm->size = sizeof(struct ssmps_cmd_parm);
2265 cmd_parm->pbuf = (u8 *)ssmp_param;
2266
2267 init_h2fwcmd_w_parm_no_rsp(cmdobj, cmd_parm, CMD_SET_DRV_EXTRA);
2268
2269 res = rtw_enqueue_cmd(pcmdpriv, cmdobj);
2270 } else {
2271 struct ssmps_cmd_parm tmp_ssmp_param;
2272
2273 tmp_ssmp_param.smps = smps;
2274 tmp_ssmp_param.sta = sta;
2275 rtw_ssmps_wk_hdl(adapter, &tmp_ssmp_param);
2276 }
2277
2278 exit:
2279 return res;
2280 }
2281
2282 #ifdef CONFIG_SUPPORT_STATIC_SMPS
_ssmps_chk_by_tp(_adapter * adapter,u8 from_timer)2283 u8 _ssmps_chk_by_tp(_adapter *adapter, u8 from_timer)
2284 {
2285 u8 enter_smps = _FALSE;
2286 struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
2287 struct mlme_ext_priv *pmlmeext = &(adapter->mlmeextpriv);
2288 struct sta_priv *pstapriv = &adapter->stapriv;
2289 struct sta_info *psta;
2290 u32 tx_tp_mbits, rx_tp_mbits;
2291
2292 if (!MLME_IS_STA(adapter) ||
2293 !hal_is_mimo_support(adapter) ||
2294 !pmlmeext->ssmps_en ||
2295 (pmlmeext->cur_channel > 14)
2296 )
2297 return enter_smps;
2298
2299 psta = rtw_get_stainfo(pstapriv, get_bssid(pmlmepriv));
2300 if (psta == NULL) {
2301 RTW_ERR(ADPT_FMT" sta == NULL\n", ADPT_ARG(adapter));
2302 rtw_warn_on(1);
2303 return enter_smps;
2304 }
2305
2306 if (psta->cmn.mimo_type == RF_1T1R)
2307 return enter_smps;
2308
2309 tx_tp_mbits = psta->sta_stats.tx_tp_kbits >> 10;
2310 rx_tp_mbits = psta->sta_stats.rx_tp_kbits >> 10;
2311
2312 #ifdef DBG_STATIC_SMPS
2313 if (pmlmeext->ssmps_test) {
2314 enter_smps = (pmlmeext->ssmps_test_en == 1) ? _TRUE : _FALSE;
2315 }
2316 else
2317 #endif
2318 {
2319 if ((tx_tp_mbits <= pmlmeext->ssmps_tx_tp_th) &&
2320 (rx_tp_mbits <= pmlmeext->ssmps_rx_tp_th))
2321 enter_smps = _TRUE;
2322 else
2323 enter_smps = _FALSE;
2324 }
2325
2326 if (1) {
2327 RTW_INFO(FUNC_ADPT_FMT" tx_tp:%d [%d], rx_tp:%d [%d] , SSMPS enter :%s\n",
2328 FUNC_ADPT_ARG(adapter),
2329 tx_tp_mbits, pmlmeext->ssmps_tx_tp_th,
2330 rx_tp_mbits, pmlmeext->ssmps_rx_tp_th,
2331 (enter_smps == _TRUE) ? "True" : "False");
2332 #ifdef DBG_STATIC_SMPS
2333 RTW_INFO(FUNC_ADPT_FMT" test:%d test_en:%d\n",
2334 FUNC_ADPT_ARG(adapter),
2335 pmlmeext->ssmps_test,
2336 pmlmeext->ssmps_test_en);
2337 #endif
2338 }
2339
2340 if (enter_smps) {
2341 if (!from_timer && psta->cmn.sm_ps != SM_PS_STATIC)
2342 rtw_ssmps_enter(adapter, psta);
2343 } else {
2344 if (!from_timer && psta->cmn.sm_ps != SM_PS_DISABLE)
2345 rtw_ssmps_leave(adapter, psta);
2346 else {
2347 u8 ps_change = _FALSE;
2348
2349 if (enter_smps && psta->cmn.sm_ps != SM_PS_STATIC)
2350 ps_change = _TRUE;
2351 else if (!enter_smps && psta->cmn.sm_ps != SM_PS_DISABLE)
2352 ps_change = _TRUE;
2353
2354 if (ps_change)
2355 rtw_ssmps_wk_cmd(adapter, psta, enter_smps, 1);
2356 }
2357 }
2358
2359 return enter_smps;
2360 }
2361 #endif /*CONFIG_SUPPORT_STATIC_SMPS*/
2362
2363 #ifdef CONFIG_CTRL_TXSS_BY_TP
rtw_ctrl_txss_update_mimo_type(_adapter * adapter,struct sta_info * sta)2364 void rtw_ctrl_txss_update_mimo_type(_adapter *adapter, struct sta_info *sta)
2365 {
2366 struct mlme_ext_priv *pmlmeext = &(adapter->mlmeextpriv);
2367
2368 pmlmeext->txss_momi_type_bk = sta->cmn.mimo_type;
2369 }
2370
rtw_ctrl_txss(_adapter * adapter,struct sta_info * sta,bool tx_1ss)2371 u8 rtw_ctrl_txss(_adapter *adapter, struct sta_info *sta, bool tx_1ss)
2372 {
2373 struct mlme_ext_priv *pmlmeext = &(adapter->mlmeextpriv);
2374 struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(adapter);
2375 u8 lps_changed = _FALSE;
2376 u8 rst = _SUCCESS;
2377
2378 if (pmlmeext->txss_1ss == tx_1ss)
2379 return _FALSE;
2380
2381 if (pwrpriv->bLeisurePs && pwrpriv->pwr_mode != PS_MODE_ACTIVE) {
2382 lps_changed = _TRUE;
2383 LPS_Leave(adapter, "LPS_CTRL_TXSS");
2384 }
2385
2386 RTW_INFO(ADPT_FMT" STA [" MAC_FMT "] set tx to %d ss\n",
2387 ADPT_ARG(adapter), MAC_ARG(sta->cmn.mac_addr),
2388 (tx_1ss) ? 1 : rtw_get_sta_tx_nss(adapter, sta));
2389
2390 /*ra re-registed*/
2391 sta->cmn.mimo_type = (tx_1ss) ? RF_1T1R : pmlmeext->txss_momi_type_bk;
2392 rtw_phydm_ra_registed(adapter, sta);
2393
2394 /*configure trx mode*/
2395 rtw_phydm_trx_cfg(adapter, tx_1ss);
2396 pmlmeext->txss_1ss = tx_1ss;
2397
2398 if (lps_changed)
2399 LPS_Enter(adapter, "LPS_CTRL_TXSS");
2400
2401 return rst;
2402 }
2403
rtw_ctrl_txss_wk_hdl(_adapter * adapter,struct txss_cmd_parm * txss_param)2404 u8 rtw_ctrl_txss_wk_hdl(_adapter *adapter, struct txss_cmd_parm *txss_param)
2405 {
2406 if (!txss_param->sta)
2407 return _FALSE;
2408
2409 return rtw_ctrl_txss(adapter, txss_param->sta, txss_param->tx_1ss);
2410 }
2411
rtw_ctrl_txss_wk_cmd(_adapter * adapter,struct sta_info * sta,bool tx_1ss,u8 flag)2412 u8 rtw_ctrl_txss_wk_cmd(_adapter *adapter, struct sta_info *sta, bool tx_1ss, u8 flag)
2413 {
2414 struct cmd_obj *cmdobj;
2415 struct drvextra_cmd_parm *cmd_parm;
2416 struct txss_cmd_parm *txss_param;
2417 struct cmd_priv *pcmdpriv = &adapter->cmdpriv;
2418 struct submit_ctx sctx;
2419 u8 res = _SUCCESS;
2420
2421 txss_param = (struct txss_cmd_parm *)rtw_zmalloc(sizeof(struct txss_cmd_parm));
2422 if (txss_param == NULL) {
2423 res = _FAIL;
2424 goto exit;
2425 }
2426
2427 txss_param->tx_1ss = tx_1ss;
2428 txss_param->sta = sta;
2429
2430 if (flag & RTW_CMDF_DIRECTLY) {
2431 res = rtw_ctrl_txss_wk_hdl(adapter, txss_param);
2432 rtw_mfree((u8 *)txss_param, sizeof(*txss_param));
2433 } else {
2434 cmdobj = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
2435 if (cmdobj == NULL) {
2436 res = _FAIL;
2437 goto exit;
2438 }
2439
2440 cmd_parm = (struct drvextra_cmd_parm *)rtw_zmalloc(sizeof(struct drvextra_cmd_parm));
2441 if (cmd_parm == NULL) {
2442 rtw_mfree((u8 *)cmdobj, sizeof(struct cmd_obj));
2443 res = _FAIL;
2444 goto exit;
2445 }
2446
2447 cmd_parm->ec_id = TXSS_WK_CID;
2448 cmd_parm->type = 0;
2449 cmd_parm->size = sizeof(struct txss_cmd_parm);
2450 cmd_parm->pbuf = (u8 *)txss_param;
2451
2452 init_h2fwcmd_w_parm_no_rsp(cmdobj, cmd_parm, CMD_SET_DRV_EXTRA);
2453
2454 if (flag & RTW_CMDF_WAIT_ACK) {
2455 cmdobj->sctx = &sctx;
2456 rtw_sctx_init(&sctx, 10 * 1000);
2457 }
2458
2459 res = rtw_enqueue_cmd(pcmdpriv, cmdobj);
2460 if (res == _SUCCESS && (flag & RTW_CMDF_WAIT_ACK)) {
2461 rtw_sctx_wait(&sctx, __func__);
2462 _enter_critical_mutex(&pcmdpriv->sctx_mutex, NULL);
2463 if (sctx.status == RTW_SCTX_SUBMITTED)
2464 cmdobj->sctx = NULL;
2465 _exit_critical_mutex(&pcmdpriv->sctx_mutex, NULL);
2466 if (sctx.status != RTW_SCTX_DONE_SUCCESS)
2467 res = _FAIL;
2468 }
2469 }
2470
2471 exit:
2472 return res;
2473 }
2474
rtw_ctrl_tx_ss_by_tp(_adapter * adapter,u8 from_timer)2475 void rtw_ctrl_tx_ss_by_tp(_adapter *adapter, u8 from_timer)
2476 {
2477 bool tx_1ss = _FALSE; /*change tx from 2ss to 1ss*/
2478 struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
2479 struct mlme_ext_priv *pmlmeext = &(adapter->mlmeextpriv);
2480 struct sta_priv *pstapriv = &adapter->stapriv;
2481 struct sta_info *psta;
2482 u32 tx_tp_mbits;
2483
2484 if (!MLME_IS_STA(adapter) ||
2485 !hal_is_mimo_support(adapter) ||
2486 !pmlmeext->txss_ctrl_en
2487 )
2488 return;
2489
2490 psta = rtw_get_stainfo(pstapriv, get_bssid(pmlmepriv));
2491 if (psta == NULL) {
2492 RTW_ERR(ADPT_FMT" sta == NULL\n", ADPT_ARG(adapter));
2493 rtw_warn_on(1);
2494 return;
2495 }
2496
2497 tx_tp_mbits = psta->sta_stats.tx_tp_kbits >> 10;
2498 if (tx_tp_mbits >= pmlmeext->txss_tp_th) {
2499 tx_1ss = _FALSE;
2500 } else {
2501 if (pmlmeext->txss_tp_chk_cnt && --pmlmeext->txss_tp_chk_cnt)
2502 tx_1ss = _FALSE;
2503 else
2504 tx_1ss = _TRUE;
2505 }
2506
2507 if (1) {
2508 RTW_INFO(FUNC_ADPT_FMT" tx_tp:%d [%d] tx_1ss(%d):%s\n",
2509 FUNC_ADPT_ARG(adapter),
2510 tx_tp_mbits, pmlmeext->txss_tp_th,
2511 pmlmeext->txss_tp_chk_cnt,
2512 (tx_1ss == _TRUE) ? "True" : "False");
2513 }
2514
2515 if (pmlmeext->txss_1ss != tx_1ss) {
2516 if (from_timer)
2517 rtw_ctrl_txss_wk_cmd(adapter, psta, tx_1ss, 0);
2518 else
2519 rtw_ctrl_txss(adapter, psta, tx_1ss);
2520 }
2521 }
2522 #ifdef DBG_CTRL_TXSS
dbg_ctrl_txss(_adapter * adapter,bool tx_1ss)2523 void dbg_ctrl_txss(_adapter *adapter, bool tx_1ss)
2524 {
2525 struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
2526 struct mlme_ext_priv *pmlmeext = &(adapter->mlmeextpriv);
2527 struct sta_priv *pstapriv = &adapter->stapriv;
2528 struct sta_info *psta;
2529
2530 if (!MLME_IS_STA(adapter) ||
2531 !hal_is_mimo_support(adapter)
2532 )
2533 return;
2534
2535 psta = rtw_get_stainfo(pstapriv, get_bssid(pmlmepriv));
2536 if (psta == NULL) {
2537 RTW_ERR(ADPT_FMT" sta == NULL\n", ADPT_ARG(adapter));
2538 rtw_warn_on(1);
2539 return;
2540 }
2541
2542 rtw_ctrl_txss(adapter, psta, tx_1ss);
2543 }
2544 #endif
2545 #endif /*CONFIG_CTRL_TXSS_BY_TP*/
2546
2547 #ifdef CONFIG_LPS
2548 #ifdef CONFIG_LPS_CHK_BY_TP
2549 #ifdef LPS_BCN_CNT_MONITOR
_bcn_cnt_expected(struct sta_info * psta)2550 static u8 _bcn_cnt_expected(struct sta_info *psta)
2551 {
2552 _adapter *adapter = psta->padapter;
2553 struct mlme_ext_priv *pmlmeext = &adapter->mlmeextpriv;
2554 struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
2555 u8 dtim = rtw_get_bcn_dtim_period(adapter);
2556 u8 bcn_cnt = 0;
2557
2558 if ((pmlmeinfo->bcn_interval !=0) && (dtim != 0))
2559 bcn_cnt = 2000 / pmlmeinfo->bcn_interval / dtim * 4 / 5; /*2s*/
2560 if (0)
2561 RTW_INFO("%s bcn_cnt:%d\n", __func__, bcn_cnt);
2562
2563 if (bcn_cnt == 0) {
2564 RTW_ERR(FUNC_ADPT_FMT" bcn_cnt == 0\n", FUNC_ADPT_ARG(adapter));
2565 rtw_warn_on(1);
2566 }
2567
2568 return bcn_cnt;
2569 }
2570 #endif
_lps_chk_by_tp(_adapter * adapter,u8 from_timer)2571 u8 _lps_chk_by_tp(_adapter *adapter, u8 from_timer)
2572 {
2573 u8 enter_ps = _FALSE;
2574 struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
2575 struct sta_priv *pstapriv = &adapter->stapriv;
2576 struct sta_info *psta;
2577 struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(adapter);
2578 u32 tx_tp_mbits, rx_tp_mbits, bi_tp_mbits;
2579 u8 rx_bcn_cnt;
2580
2581 psta = rtw_get_stainfo(pstapriv, get_bssid(pmlmepriv));
2582 if (psta == NULL) {
2583 RTW_ERR(ADPT_FMT" sta == NULL\n", ADPT_ARG(adapter));
2584 rtw_warn_on(1);
2585 return enter_ps;
2586 }
2587
2588 rx_bcn_cnt = rtw_get_bcn_cnt(psta->padapter);
2589 psta->sta_stats.acc_tx_bytes = psta->sta_stats.tx_bytes;
2590 psta->sta_stats.acc_rx_bytes = psta->sta_stats.rx_bytes;
2591
2592 #if 1
2593 tx_tp_mbits = psta->sta_stats.tx_tp_kbits >> 10;
2594 rx_tp_mbits = psta->sta_stats.rx_tp_kbits >> 10;
2595 bi_tp_mbits = tx_tp_mbits + rx_tp_mbits;
2596 #else
2597 tx_tp_mbits = psta->sta_stats.smooth_tx_tp_kbits >> 10;
2598 rx_tp_mbits = psta->sta_stats.smooth_rx_tp_kbits >> 10;
2599 bi_tp_mbits = tx_tp_mbits + rx_tp_mbits;
2600 #endif
2601
2602 if ((bi_tp_mbits >= pwrpriv->lps_bi_tp_th) ||
2603 (tx_tp_mbits >= pwrpriv->lps_tx_tp_th) ||
2604 (rx_tp_mbits >= pwrpriv->lps_rx_tp_th)) {
2605 enter_ps = _FALSE;
2606 pwrpriv->lps_chk_cnt = pwrpriv->lps_chk_cnt_th;
2607 }
2608 else {
2609 #ifdef LPS_BCN_CNT_MONITOR
2610 u8 bcn_cnt = _bcn_cnt_expected(psta);
2611
2612 if (bcn_cnt && (rx_bcn_cnt < bcn_cnt)) {
2613 pwrpriv->lps_chk_cnt = 2;
2614 RTW_ERR(FUNC_ADPT_FMT" BCN_CNT:%d(%d) invalid\n",
2615 FUNC_ADPT_ARG(adapter), rx_bcn_cnt, bcn_cnt);
2616 }
2617 #endif
2618
2619 if (pwrpriv->lps_chk_cnt && --pwrpriv->lps_chk_cnt)
2620 enter_ps = _FALSE;
2621 else
2622 enter_ps = _TRUE;
2623 }
2624
2625 if (1) {
2626 RTW_INFO(FUNC_ADPT_FMT" tx_tp:%d [%d], rx_tp:%d [%d], bi_tp:%d [%d], enter_ps(%d):%s\n",
2627 FUNC_ADPT_ARG(adapter),
2628 tx_tp_mbits, pwrpriv->lps_tx_tp_th,
2629 rx_tp_mbits, pwrpriv->lps_rx_tp_th,
2630 bi_tp_mbits, pwrpriv->lps_bi_tp_th,
2631 pwrpriv->lps_chk_cnt,
2632 (enter_ps == _TRUE) ? "True" : "False");
2633 RTW_INFO(FUNC_ADPT_FMT" tx_pkt_cnt :%d [%d], rx_pkt_cnt :%d [%d]\n",
2634 FUNC_ADPT_ARG(adapter),
2635 pmlmepriv->LinkDetectInfo.NumTxOkInPeriod,
2636 pwrpriv->lps_tx_pkts,
2637 pmlmepriv->LinkDetectInfo.NumRxUnicastOkInPeriod,
2638 pwrpriv->lps_rx_pkts);
2639 if (!adapter->bsta_tp_dump)
2640 RTW_INFO(FUNC_ADPT_FMT" bcn_cnt:%d (per-%d second)\n",
2641 FUNC_ADPT_ARG(adapter),
2642 rx_bcn_cnt,
2643 2);
2644 }
2645
2646 if (enter_ps) {
2647 if (!from_timer)
2648 LPS_Enter(adapter, "TRAFFIC_IDLE");
2649 } else {
2650 if (!from_timer)
2651 LPS_Leave(adapter, "TRAFFIC_BUSY");
2652 else {
2653 #ifdef CONFIG_CONCURRENT_MODE
2654 #ifndef CONFIG_FW_MULTI_PORT_SUPPORT
2655 if (adapter->hw_port == HW_PORT0)
2656 #endif
2657 #endif
2658 rtw_lps_ctrl_wk_cmd(adapter, LPS_CTRL_TRAFFIC_BUSY, 0);
2659 }
2660 }
2661
2662 return enter_ps;
2663 }
2664 #endif
2665
_lps_chk_by_pkt_cnts(_adapter * padapter,u8 from_timer,u8 bBusyTraffic)2666 static u8 _lps_chk_by_pkt_cnts(_adapter *padapter, u8 from_timer, u8 bBusyTraffic)
2667 {
2668 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
2669 u8 bEnterPS = _FALSE;
2670
2671 /* check traffic for powersaving. */
2672 if (((pmlmepriv->LinkDetectInfo.NumRxUnicastOkInPeriod + pmlmepriv->LinkDetectInfo.NumTxOkInPeriod) > 8) ||
2673 #ifdef CONFIG_LPS_SLOW_TRANSITION
2674 (pmlmepriv->LinkDetectInfo.NumRxUnicastOkInPeriod > 2)
2675 #else /* CONFIG_LPS_SLOW_TRANSITION */
2676 (pmlmepriv->LinkDetectInfo.NumRxUnicastOkInPeriod > 4)
2677 #endif /* CONFIG_LPS_SLOW_TRANSITION */
2678 ) {
2679 #ifdef DBG_RX_COUNTER_DUMP
2680 if (padapter->dump_rx_cnt_mode & DUMP_DRV_TRX_COUNTER_DATA)
2681 RTW_INFO("(-)Tx = %d, Rx = %d\n", pmlmepriv->LinkDetectInfo.NumTxOkInPeriod, pmlmepriv->LinkDetectInfo.NumRxUnicastOkInPeriod);
2682 #endif
2683
2684 bEnterPS = _FALSE;
2685 #ifdef CONFIG_LPS_SLOW_TRANSITION
2686 if (bBusyTraffic == _TRUE) {
2687 if (pmlmepriv->LinkDetectInfo.TrafficTransitionCount <= 4)
2688 pmlmepriv->LinkDetectInfo.TrafficTransitionCount = 4;
2689
2690 pmlmepriv->LinkDetectInfo.TrafficTransitionCount++;
2691
2692 /* RTW_INFO("Set TrafficTransitionCount to %d\n", pmlmepriv->LinkDetectInfo.TrafficTransitionCount); */
2693
2694 if (pmlmepriv->LinkDetectInfo.TrafficTransitionCount > 30/*TrafficTransitionLevel*/)
2695 pmlmepriv->LinkDetectInfo.TrafficTransitionCount = 30;
2696 }
2697 #endif /* CONFIG_LPS_SLOW_TRANSITION */
2698 } else {
2699 #ifdef DBG_RX_COUNTER_DUMP
2700 if (padapter->dump_rx_cnt_mode & DUMP_DRV_TRX_COUNTER_DATA)
2701 RTW_INFO("(+)Tx = %d, Rx = %d\n", pmlmepriv->LinkDetectInfo.NumTxOkInPeriod, pmlmepriv->LinkDetectInfo.NumRxUnicastOkInPeriod);
2702 #endif
2703
2704 #ifdef CONFIG_LPS_SLOW_TRANSITION
2705 if (pmlmepriv->LinkDetectInfo.TrafficTransitionCount >= 2)
2706 pmlmepriv->LinkDetectInfo.TrafficTransitionCount -= 2;
2707 else
2708 pmlmepriv->LinkDetectInfo.TrafficTransitionCount = 0;
2709
2710 if (pmlmepriv->LinkDetectInfo.TrafficTransitionCount == 0)
2711 bEnterPS = _TRUE;
2712 #else /* CONFIG_LPS_SLOW_TRANSITION */
2713 bEnterPS = _TRUE;
2714 #endif /* CONFIG_LPS_SLOW_TRANSITION */
2715 }
2716
2717 #ifdef CONFIG_DYNAMIC_DTIM
2718 if (pmlmepriv->LinkDetectInfo.LowPowerTransitionCount == 8)
2719 bEnterPS = _FALSE;
2720
2721 RTW_INFO("LowPowerTransitionCount=%d\n", pmlmepriv->LinkDetectInfo.LowPowerTransitionCount);
2722 #endif /* CONFIG_DYNAMIC_DTIM */
2723
2724 /* LeisurePS only work in infra mode. */
2725 if (bEnterPS) {
2726 if (!from_timer) {
2727 #ifdef CONFIG_DYNAMIC_DTIM
2728 if (pmlmepriv->LinkDetectInfo.LowPowerTransitionCount < 8)
2729 adapter_to_pwrctl(padapter)->dtim = 1;
2730 else
2731 adapter_to_pwrctl(padapter)->dtim = 3;
2732 #endif /* CONFIG_DYNAMIC_DTIM */
2733 LPS_Enter(padapter, "TRAFFIC_IDLE");
2734 } else {
2735 /* do this at caller */
2736 /* rtw_lps_ctrl_wk_cmd(adapter, LPS_CTRL_ENTER, 0); */
2737 /* rtw_hal_dm_watchdog_in_lps(padapter); */
2738 }
2739
2740 #ifdef CONFIG_DYNAMIC_DTIM
2741 if (adapter_to_pwrctl(padapter)->bFwCurrentInPSMode == _TRUE)
2742 pmlmepriv->LinkDetectInfo.LowPowerTransitionCount++;
2743 #endif /* CONFIG_DYNAMIC_DTIM */
2744 } else {
2745 #ifdef CONFIG_DYNAMIC_DTIM
2746 if (pmlmepriv->LinkDetectInfo.LowPowerTransitionCount != 8)
2747 pmlmepriv->LinkDetectInfo.LowPowerTransitionCount = 0;
2748 else
2749 pmlmepriv->LinkDetectInfo.LowPowerTransitionCount++;
2750 #endif /* CONFIG_DYNAMIC_DTIM */
2751
2752 if (!from_timer)
2753 LPS_Leave(padapter, "TRAFFIC_BUSY");
2754 else {
2755 #ifdef CONFIG_CONCURRENT_MODE
2756 #ifndef CONFIG_FW_MULTI_PORT_SUPPORT
2757 if (padapter->hw_port == HW_PORT0)
2758 #endif
2759 #endif
2760 rtw_lps_ctrl_wk_cmd(padapter, LPS_CTRL_TRAFFIC_BUSY, 0);
2761 }
2762 }
2763
2764 return bEnterPS;
2765 }
2766 #endif /* CONFIG_LPS */
2767
2768 /* from_timer == 1 means driver is in LPS */
traffic_status_watchdog(_adapter * padapter,u8 from_timer)2769 u8 traffic_status_watchdog(_adapter *padapter, u8 from_timer)
2770 {
2771 u8 bEnterPS = _FALSE;
2772 u16 BusyThresholdHigh;
2773 u16 BusyThresholdLow;
2774 u16 BusyThreshold;
2775 u8 bBusyTraffic = _FALSE, bTxBusyTraffic = _FALSE, bRxBusyTraffic = _FALSE;
2776 u8 bHigherBusyTraffic = _FALSE, bHigherBusyRxTraffic = _FALSE, bHigherBusyTxTraffic = _FALSE;
2777
2778 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
2779 #ifdef CONFIG_TDLS
2780 struct tdls_info *ptdlsinfo = &(padapter->tdlsinfo);
2781 struct tdls_txmgmt txmgmt;
2782 u8 baddr[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
2783 #endif /* CONFIG_TDLS */
2784 #ifdef CONFIG_TRAFFIC_PROTECT
2785 RT_LINK_DETECT_T *link_detect = &pmlmepriv->LinkDetectInfo;
2786 #endif
2787
2788 #ifdef CONFIG_BT_COEXIST
2789 if (padapter->registrypriv.wifi_spec != 1) {
2790 BusyThresholdHigh = 25;
2791 BusyThresholdLow = 10;
2792 } else
2793 #endif /* CONFIG_BT_COEXIST */
2794 {
2795 BusyThresholdHigh = 100;
2796 BusyThresholdLow = 75;
2797 }
2798 BusyThreshold = BusyThresholdHigh;
2799
2800
2801 /* */
2802 /* Determine if our traffic is busy now */
2803 /* */
2804 if ((check_fwstate(pmlmepriv, WIFI_ASOC_STATE) == _TRUE)
2805 /*&& !MgntInitAdapterInProgress(pMgntInfo)*/) {
2806 /* if we raise bBusyTraffic in last watchdog, using lower threshold. */
2807 if (pmlmepriv->LinkDetectInfo.bBusyTraffic)
2808 BusyThreshold = BusyThresholdLow;
2809
2810 if (pmlmepriv->LinkDetectInfo.NumRxOkInPeriod > BusyThreshold ||
2811 pmlmepriv->LinkDetectInfo.NumTxOkInPeriod > BusyThreshold) {
2812 bBusyTraffic = _TRUE;
2813
2814 if (pmlmepriv->LinkDetectInfo.NumRxOkInPeriod > pmlmepriv->LinkDetectInfo.NumTxOkInPeriod)
2815 bRxBusyTraffic = _TRUE;
2816 else
2817 bTxBusyTraffic = _TRUE;
2818 }
2819
2820 /* Higher Tx/Rx data. */
2821 if (pmlmepriv->LinkDetectInfo.NumRxOkInPeriod > 4000 ||
2822 pmlmepriv->LinkDetectInfo.NumTxOkInPeriod > 4000) {
2823 bHigherBusyTraffic = _TRUE;
2824
2825 if (pmlmepriv->LinkDetectInfo.NumRxOkInPeriod > pmlmepriv->LinkDetectInfo.NumTxOkInPeriod)
2826 bHigherBusyRxTraffic = _TRUE;
2827 else
2828 bHigherBusyTxTraffic = _TRUE;
2829 }
2830
2831 #ifdef CONFIG_TRAFFIC_PROTECT
2832 #define TX_ACTIVE_TH 10
2833 #define RX_ACTIVE_TH 20
2834 #define TRAFFIC_PROTECT_PERIOD_MS 4500
2835
2836 if (link_detect->NumTxOkInPeriod > TX_ACTIVE_TH
2837 || link_detect->NumRxUnicastOkInPeriod > RX_ACTIVE_TH) {
2838
2839 RTW_INFO(FUNC_ADPT_FMT" acqiure wake_lock for %u ms(tx:%d,rx_unicast:%d)\n",
2840 FUNC_ADPT_ARG(padapter),
2841 TRAFFIC_PROTECT_PERIOD_MS,
2842 link_detect->NumTxOkInPeriod,
2843 link_detect->NumRxUnicastOkInPeriod);
2844
2845 rtw_lock_traffic_suspend_timeout(TRAFFIC_PROTECT_PERIOD_MS);
2846 }
2847 #endif
2848
2849 #ifdef CONFIG_TDLS
2850 #ifdef CONFIG_TDLS_AUTOSETUP
2851 /* TDLS_WATCHDOG_PERIOD * 2sec, periodically send */
2852 if (hal_chk_wl_func(padapter, WL_FUNC_TDLS) == _TRUE) {
2853 if ((ptdlsinfo->watchdog_count % TDLS_WATCHDOG_PERIOD) == 0) {
2854 _rtw_memcpy(txmgmt.peer, baddr, ETH_ALEN);
2855 issue_tdls_dis_req(padapter, &txmgmt);
2856 }
2857 ptdlsinfo->watchdog_count++;
2858 }
2859 #endif /* CONFIG_TDLS_AUTOSETUP */
2860 #endif /* CONFIG_TDLS */
2861
2862 #ifdef CONFIG_SUPPORT_STATIC_SMPS
2863 _ssmps_chk_by_tp(padapter, from_timer);
2864 #endif
2865 #ifdef CONFIG_CTRL_TXSS_BY_TP
2866 rtw_ctrl_tx_ss_by_tp(padapter, from_timer);
2867 #endif
2868
2869 #ifdef CONFIG_LPS
2870 if (adapter_to_pwrctl(padapter)->bLeisurePs && MLME_IS_STA(padapter)) {
2871 #ifdef CONFIG_LPS_CHK_BY_TP
2872 if (adapter_to_pwrctl(padapter)->lps_chk_by_tp)
2873 bEnterPS = _lps_chk_by_tp(padapter, from_timer);
2874 else
2875 #endif /*CONFIG_LPS_CHK_BY_TP*/
2876 bEnterPS = _lps_chk_by_pkt_cnts(padapter, from_timer, bBusyTraffic);
2877 }
2878 #endif /* CONFIG_LPS */
2879
2880 } else {
2881 #ifdef CONFIG_LPS
2882 if (!from_timer && rtw_mi_get_assoc_if_num(padapter) == 0)
2883 LPS_Leave(padapter, "NON_LINKED");
2884 #endif
2885 }
2886
2887 session_tracker_chk_cmd(padapter, NULL);
2888
2889 #ifdef CONFIG_BEAMFORMING
2890 #ifdef RTW_BEAMFORMING_VERSION_2
2891 rtw_bf_update_traffic(padapter);
2892 #endif /* RTW_BEAMFORMING_VERSION_2 */
2893 #endif /* CONFIG_BEAMFORMING */
2894
2895 pmlmepriv->LinkDetectInfo.NumRxOkInPeriod = 0;
2896 pmlmepriv->LinkDetectInfo.NumTxOkInPeriod = 0;
2897 pmlmepriv->LinkDetectInfo.NumRxUnicastOkInPeriod = 0;
2898 pmlmepriv->LinkDetectInfo.bBusyTraffic = bBusyTraffic;
2899 pmlmepriv->LinkDetectInfo.bTxBusyTraffic = bTxBusyTraffic;
2900 pmlmepriv->LinkDetectInfo.bRxBusyTraffic = bRxBusyTraffic;
2901 pmlmepriv->LinkDetectInfo.bHigherBusyTraffic = bHigherBusyTraffic;
2902 pmlmepriv->LinkDetectInfo.bHigherBusyRxTraffic = bHigherBusyRxTraffic;
2903 pmlmepriv->LinkDetectInfo.bHigherBusyTxTraffic = bHigherBusyTxTraffic;
2904
2905 return bEnterPS;
2906
2907 }
2908
2909 #ifdef CONFIG_AP_MODE
2910 /* for 11n Logo 4.2.31/4.2.32 */
dynamic_update_bcn_check(_adapter * padapter)2911 static void dynamic_update_bcn_check(_adapter *padapter)
2912 {
2913 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
2914 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
2915
2916 if (!padapter->registrypriv.wifi_spec)
2917 return;
2918
2919 if (!padapter->registrypriv.ht_enable || !is_supported_ht(padapter->registrypriv.wireless_mode))
2920 return;
2921
2922 if (!MLME_IS_AP(padapter))
2923 return;
2924
2925 if (pmlmeext->bstart_bss) {
2926 /* In 10 * 2 = 20s, there are no legacy AP, update HT info */
2927 static u8 count = 1;
2928
2929 if (count % 10 == 0) {
2930 count = 1;
2931 #ifdef CONFIG_80211N_HT
2932 if (_FALSE == ATOMIC_READ(&pmlmepriv->olbc)
2933 && _FALSE == ATOMIC_READ(&pmlmepriv->olbc_ht)) {
2934
2935 if (rtw_ht_operation_update(padapter) > 0) {
2936 update_beacon(padapter, _HT_CAPABILITY_IE_, NULL, _FALSE, 0);
2937 update_beacon(padapter, _HT_ADD_INFO_IE_, NULL, _TRUE, 0);
2938 }
2939 }
2940 #endif /* CONFIG_80211N_HT */
2941 }
2942
2943 #ifdef CONFIG_80211N_HT
2944 /* In 2s, there are any legacy AP, update HT info, and then reset count */
2945
2946 if (_FALSE != ATOMIC_READ(&pmlmepriv->olbc)
2947 && _FALSE != ATOMIC_READ(&pmlmepriv->olbc_ht)) {
2948
2949 if (rtw_ht_operation_update(padapter) > 0) {
2950 update_beacon(padapter, _HT_CAPABILITY_IE_, NULL, _FALSE, 0);
2951 update_beacon(padapter, _HT_ADD_INFO_IE_, NULL, _TRUE, 0);
2952
2953 }
2954 ATOMIC_SET(&pmlmepriv->olbc, _FALSE);
2955 ATOMIC_SET(&pmlmepriv->olbc_ht, _FALSE);
2956 count = 0;
2957 }
2958 #endif /* CONFIG_80211N_HT */
2959 count ++;
2960 }
2961 }
2962 #endif /* CONFIG_AP_MODE */
2963
rtw_iface_dynamic_chk_wk_hdl(_adapter * padapter)2964 void rtw_iface_dynamic_chk_wk_hdl(_adapter *padapter)
2965 {
2966 #ifdef CONFIG_AP_MODE
2967 #ifdef CONFIG_ACTIVE_KEEP_ALIVE_CHECK
2968 if (MLME_IS_AP(padapter) || MLME_IS_MESH(padapter)) {
2969 expire_timeout_chk(padapter);
2970 #ifdef CONFIG_RTW_MESH
2971 if (MLME_IS_MESH(padapter) && MLME_IS_ASOC(padapter))
2972 rtw_mesh_peer_status_chk(padapter);
2973 #endif
2974 }
2975 #endif /* CONFIG_ACTIVE_KEEP_ALIVE_CHECK */
2976
2977 dynamic_update_bcn_check(padapter);
2978
2979 #endif /* CONFIG_AP_MODE */
2980
2981 linked_status_chk(padapter, 0);
2982 traffic_status_watchdog(padapter, 0);
2983
2984 /* for debug purpose */
2985 _linked_info_dump(padapter);
2986
2987 #ifdef CONFIG_RTW_CFGVENDOR_RSSIMONITOR
2988 rtw_cfgvendor_rssi_monitor_evt(padapter);
2989 #endif
2990
2991
2992 }
rtw_dynamic_chk_wk_hdl(_adapter * padapter)2993 void rtw_dynamic_chk_wk_hdl(_adapter *padapter)
2994 {
2995 rtw_mi_dynamic_chk_wk_hdl(padapter);
2996 #ifdef CONFIG_MP_INCLUDED
2997 if (rtw_mp_mode_check(padapter) == _FALSE)
2998 #endif
2999 {
3000 #ifdef DBG_CONFIG_ERROR_DETECT
3001 rtw_hal_sreset_xmit_status_check(padapter);
3002 rtw_hal_sreset_linked_status_check(padapter);
3003 #endif
3004 }
3005
3006 /* if(check_fwstate(pmlmepriv, WIFI_UNDER_LINKING|WIFI_UNDER_SURVEY)==_FALSE) */
3007 {
3008 #ifdef DBG_RX_COUNTER_DUMP
3009 rtw_dump_rx_counters(padapter);
3010 #endif
3011 dm_DynamicUsbTxAgg(padapter, 0);
3012 }
3013 rtw_hal_dm_watchdog(padapter);
3014
3015 /* check_hw_pbc(padapter, pdrvextra_cmd->pbuf, pdrvextra_cmd->type); */
3016
3017 #ifdef CONFIG_BT_COEXIST
3018 /* BT-Coexist */
3019 rtw_btcoex_Handler(padapter);
3020 #endif
3021
3022 #ifdef CONFIG_RTW_MULTI_AP
3023 rtw_ch_util_rpt(padapter);
3024 #endif
3025
3026 #ifdef CONFIG_DFS_MASTER
3027 rtw_chset_chk_non_ocp_finish(adapter_to_rfctl(padapter));
3028 #endif
3029
3030 #ifdef CONFIG_IPS_CHECK_IN_WD
3031 /* always call rtw_ps_processor() at last one. */
3032 rtw_ps_processor(padapter);
3033 #endif
3034
3035 #ifdef CONFIG_MCC_MODE
3036 rtw_hal_mcc_sw_status_check(padapter);
3037 #endif /* CONFIG_MCC_MODE */
3038
3039 rtw_hal_periodic_tsf_update_chk(padapter);
3040 }
3041
3042 #ifdef CONFIG_LPS
3043 struct lps_ctrl_wk_parm {
3044 s8 lps_level;
3045 #ifdef CONFIG_LPS_1T1R
3046 s8 lps_1t1r;
3047 #endif
3048 };
3049
lps_ctrl_wk_hdl(_adapter * padapter,u8 lps_ctrl_type,u8 * buf)3050 void lps_ctrl_wk_hdl(_adapter *padapter, u8 lps_ctrl_type, u8 *buf)
3051 {
3052 struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(padapter);
3053 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
3054 struct lps_ctrl_wk_parm *parm = (struct lps_ctrl_wk_parm *)buf;
3055 u8 mstatus;
3056
3057 if ((check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) == _TRUE)
3058 || (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE) == _TRUE))
3059 return;
3060
3061 switch (lps_ctrl_type) {
3062 case LPS_CTRL_SCAN:
3063 /* RTW_INFO("LPS_CTRL_SCAN\n"); */
3064 #ifdef CONFIG_BT_COEXIST
3065 rtw_btcoex_ScanNotify(padapter, _TRUE);
3066 #endif /* CONFIG_BT_COEXIST */
3067 if (check_fwstate(pmlmepriv, WIFI_ASOC_STATE) == _TRUE) {
3068 /* connect */
3069 LPS_Leave(padapter, "LPS_CTRL_SCAN");
3070 }
3071 break;
3072 case LPS_CTRL_JOINBSS:
3073 /* RTW_INFO("LPS_CTRL_JOINBSS\n"); */
3074 LPS_Leave(padapter, "LPS_CTRL_JOINBSS");
3075 break;
3076 case LPS_CTRL_CONNECT:
3077 /* RTW_INFO("LPS_CTRL_CONNECT\n"); */
3078 mstatus = 1;/* connect */
3079 /* Reset LPS Setting */
3080 pwrpriv->LpsIdleCount = 0;
3081 rtw_hal_set_hwreg(padapter, HW_VAR_H2C_FW_JOINBSSRPT, (u8 *)(&mstatus));
3082 #ifdef CONFIG_BT_COEXIST
3083 rtw_btcoex_MediaStatusNotify(padapter, mstatus);
3084 #endif /* CONFIG_BT_COEXIST */
3085 break;
3086 case LPS_CTRL_DISCONNECT:
3087 /* RTW_INFO("LPS_CTRL_DISCONNECT\n"); */
3088 mstatus = 0;/* disconnect */
3089 #ifdef CONFIG_BT_COEXIST
3090 rtw_btcoex_MediaStatusNotify(padapter, mstatus);
3091 #endif /* CONFIG_BT_COEXIST */
3092 LPS_Leave(padapter, "LPS_CTRL_DISCONNECT");
3093 rtw_hal_set_hwreg(padapter, HW_VAR_H2C_FW_JOINBSSRPT, (u8 *)(&mstatus));
3094 break;
3095 case LPS_CTRL_SPECIAL_PACKET:
3096 /* RTW_INFO("LPS_CTRL_SPECIAL_PACKET\n"); */
3097 rtw_set_lps_deny(padapter, LPS_DELAY_MS);
3098 #ifdef CONFIG_BT_COEXIST
3099 rtw_btcoex_SpecialPacketNotify(padapter, PACKET_DHCP);
3100 #endif /* CONFIG_BT_COEXIST */
3101 LPS_Leave(padapter, "LPS_CTRL_SPECIAL_PACKET");
3102 break;
3103 case LPS_CTRL_LEAVE:
3104 LPS_Leave(padapter, "LPS_CTRL_LEAVE");
3105 break;
3106 case LPS_CTRL_LEAVE_SET_OPTION:
3107 LPS_Leave(padapter, "LPS_CTRL_LEAVE_SET_OPTION");
3108 if (parm) {
3109 if (parm->lps_level >= 0)
3110 pwrpriv->lps_level = parm->lps_level;
3111 #ifdef CONFIG_LPS_1T1R
3112 if (parm->lps_1t1r >= 0)
3113 pwrpriv->lps_1t1r = parm->lps_1t1r;
3114 #endif
3115 }
3116 break;
3117 case LPS_CTRL_LEAVE_CFG80211_PWRMGMT:
3118 LPS_Leave(padapter, "CFG80211_PWRMGMT");
3119 break;
3120 case LPS_CTRL_TRAFFIC_BUSY:
3121 LPS_Leave(padapter, "LPS_CTRL_TRAFFIC_BUSY");
3122 break;
3123 case LPS_CTRL_TX_TRAFFIC_LEAVE:
3124 LPS_Leave(padapter, "LPS_CTRL_TX_TRAFFIC_LEAVE");
3125 break;
3126 case LPS_CTRL_RX_TRAFFIC_LEAVE:
3127 LPS_Leave(padapter, "LPS_CTRL_RX_TRAFFIC_LEAVE");
3128 break;
3129 case LPS_CTRL_ENTER:
3130 LPS_Enter(padapter, "TRAFFIC_IDLE_1");
3131 break;
3132 default:
3133 break;
3134 }
3135
3136 }
3137
_rtw_lps_ctrl_wk_cmd(_adapter * adapter,u8 lps_ctrl_type,s8 lps_level,s8 lps_1t1r,u8 flags)3138 static u8 _rtw_lps_ctrl_wk_cmd(_adapter *adapter, u8 lps_ctrl_type, s8 lps_level, s8 lps_1t1r, u8 flags)
3139 {
3140 struct cmd_obj *cmdobj;
3141 struct drvextra_cmd_parm *parm;
3142 struct lps_ctrl_wk_parm *wk_parm = NULL;
3143 struct cmd_priv *pcmdpriv = &adapter->cmdpriv;
3144 struct submit_ctx sctx;
3145 u8 res = _SUCCESS;
3146
3147 if (lps_ctrl_type == LPS_CTRL_LEAVE_SET_OPTION) {
3148 wk_parm = rtw_zmalloc(sizeof(*wk_parm));
3149 if (wk_parm == NULL) {
3150 res = _FAIL;
3151 goto exit;
3152 }
3153 wk_parm->lps_level = lps_level;
3154 #ifdef CONFIG_LPS_1T1R
3155 wk_parm->lps_1t1r = lps_1t1r;
3156 #endif
3157 }
3158
3159 if (flags & RTW_CMDF_DIRECTLY) {
3160 /* no need to enqueue, do the cmd hdl directly */
3161 lps_ctrl_wk_hdl(adapter, lps_ctrl_type, (u8 *)wk_parm);
3162 if (wk_parm)
3163 rtw_mfree(wk_parm, sizeof(*wk_parm));
3164 } else {
3165 /* need enqueue, prepare cmd_obj and enqueue */
3166 parm = rtw_zmalloc(sizeof(*parm));
3167 if (parm == NULL) {
3168 if (wk_parm)
3169 rtw_mfree(wk_parm, sizeof(*wk_parm));
3170 res = _FAIL;
3171 goto exit;
3172 }
3173
3174 parm->ec_id = LPS_CTRL_WK_CID;
3175 parm->type = lps_ctrl_type;
3176 parm->size = wk_parm ? sizeof(*wk_parm) : 0;
3177 parm->pbuf = (u8 *)wk_parm;
3178
3179 cmdobj = rtw_zmalloc(sizeof(*cmdobj));
3180 if (cmdobj == NULL) {
3181 rtw_mfree(parm, sizeof(*parm));
3182 if (wk_parm)
3183 rtw_mfree(wk_parm, sizeof(*wk_parm));
3184 res = _FAIL;
3185 goto exit;
3186 }
3187
3188 init_h2fwcmd_w_parm_no_rsp(cmdobj, parm, CMD_SET_DRV_EXTRA);
3189
3190 if (flags & RTW_CMDF_WAIT_ACK) {
3191 cmdobj->sctx = &sctx;
3192 rtw_sctx_init(&sctx, 2000);
3193 }
3194
3195 res = rtw_enqueue_cmd(pcmdpriv, cmdobj);
3196
3197 if (res == _SUCCESS && (flags & RTW_CMDF_WAIT_ACK)) {
3198 rtw_sctx_wait(&sctx, __func__);
3199 _enter_critical_mutex(&pcmdpriv->sctx_mutex, NULL);
3200 if (sctx.status == RTW_SCTX_SUBMITTED)
3201 cmdobj->sctx = NULL;
3202 _exit_critical_mutex(&pcmdpriv->sctx_mutex, NULL);
3203 if (sctx.status != RTW_SCTX_DONE_SUCCESS)
3204 res = _FAIL;
3205 }
3206 }
3207
3208 exit:
3209 return res;
3210 }
3211
rtw_lps_ctrl_wk_cmd(_adapter * adapter,u8 lps_ctrl_type,u8 flags)3212 u8 rtw_lps_ctrl_wk_cmd(_adapter *adapter, u8 lps_ctrl_type, u8 flags)
3213 {
3214 return _rtw_lps_ctrl_wk_cmd(adapter, lps_ctrl_type, -1, -1, flags);
3215 }
3216
rtw_lps_ctrl_leave_set_level_cmd(_adapter * adapter,u8 lps_level,u8 flags)3217 u8 rtw_lps_ctrl_leave_set_level_cmd(_adapter *adapter, u8 lps_level, u8 flags)
3218 {
3219 return _rtw_lps_ctrl_wk_cmd(adapter, LPS_CTRL_LEAVE_SET_OPTION, lps_level, -1, flags);
3220 }
3221
3222 #ifdef CONFIG_LPS_1T1R
rtw_lps_ctrl_leave_set_1t1r_cmd(_adapter * adapter,u8 lps_1t1r,u8 flags)3223 u8 rtw_lps_ctrl_leave_set_1t1r_cmd(_adapter *adapter, u8 lps_1t1r, u8 flags)
3224 {
3225 return _rtw_lps_ctrl_wk_cmd(adapter, LPS_CTRL_LEAVE_SET_OPTION, -1, lps_1t1r, flags);
3226 }
3227 #endif
3228
rtw_dm_in_lps_hdl(_adapter * padapter)3229 void rtw_dm_in_lps_hdl(_adapter *padapter)
3230 {
3231 rtw_hal_set_hwreg(padapter, HW_VAR_DM_IN_LPS_LCLK, NULL);
3232 }
3233
rtw_dm_in_lps_wk_cmd(_adapter * padapter)3234 u8 rtw_dm_in_lps_wk_cmd(_adapter *padapter)
3235 {
3236 struct cmd_obj *ph2c;
3237 struct drvextra_cmd_parm *pdrvextra_cmd_parm;
3238 struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
3239 u8 res = _SUCCESS;
3240
3241
3242 ph2c = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
3243 if (ph2c == NULL) {
3244 res = _FAIL;
3245 goto exit;
3246 }
3247
3248 pdrvextra_cmd_parm = (struct drvextra_cmd_parm *)rtw_zmalloc(sizeof(struct drvextra_cmd_parm));
3249 if (pdrvextra_cmd_parm == NULL) {
3250 rtw_mfree((unsigned char *)ph2c, sizeof(struct cmd_obj));
3251 res = _FAIL;
3252 goto exit;
3253 }
3254
3255 pdrvextra_cmd_parm->ec_id = DM_IN_LPS_WK_CID;
3256 pdrvextra_cmd_parm->type = 0;
3257 pdrvextra_cmd_parm->size = 0;
3258 pdrvextra_cmd_parm->pbuf = NULL;
3259
3260 init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, CMD_SET_DRV_EXTRA);
3261
3262 res = rtw_enqueue_cmd(pcmdpriv, ph2c);
3263
3264 exit:
3265
3266 return res;
3267
3268 }
3269
rtw_lps_change_dtim_hdl(_adapter * padapter,u8 dtim)3270 void rtw_lps_change_dtim_hdl(_adapter *padapter, u8 dtim)
3271 {
3272 struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(padapter);
3273
3274 if (dtim <= 0 || dtim > 16)
3275 return;
3276
3277 #ifdef CONFIG_BT_COEXIST
3278 if (rtw_btcoex_IsBtControlLps(padapter) == _TRUE)
3279 return;
3280 #endif
3281
3282 #ifdef CONFIG_LPS_LCLK
3283 _enter_pwrlock(&pwrpriv->lock);
3284 #endif
3285
3286 if (pwrpriv->dtim != dtim) {
3287 RTW_INFO("change DTIM from %d to %d, bFwCurrentInPSMode=%d, ps_mode=%d\n", pwrpriv->dtim, dtim,
3288 pwrpriv->bFwCurrentInPSMode, pwrpriv->pwr_mode);
3289
3290 pwrpriv->dtim = dtim;
3291 }
3292
3293 if ((pwrpriv->bFwCurrentInPSMode == _TRUE) && (pwrpriv->pwr_mode > PS_MODE_ACTIVE)) {
3294 u8 ps_mode = pwrpriv->pwr_mode;
3295
3296 /* RTW_INFO("change DTIM from %d to %d, ps_mode=%d\n", pwrpriv->dtim, dtim, ps_mode); */
3297
3298 rtw_exec_lps(padapter, ps_mode);
3299 }
3300
3301 #ifdef CONFIG_LPS_LCLK
3302 _exit_pwrlock(&pwrpriv->lock);
3303 #endif
3304
3305 }
3306
3307 #endif
3308
rtw_lps_change_dtim_cmd(_adapter * padapter,u8 dtim)3309 u8 rtw_lps_change_dtim_cmd(_adapter *padapter, u8 dtim)
3310 {
3311 struct cmd_obj *ph2c;
3312 struct drvextra_cmd_parm *pdrvextra_cmd_parm;
3313 struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
3314 u8 res = _SUCCESS;
3315 /*
3316 #ifdef CONFIG_CONCURRENT_MODE
3317 if (padapter->hw_port != HW_PORT0)
3318 return res;
3319 #endif
3320 */
3321 {
3322 ph2c = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
3323 if (ph2c == NULL) {
3324 res = _FAIL;
3325 goto exit;
3326 }
3327
3328 pdrvextra_cmd_parm = (struct drvextra_cmd_parm *)rtw_zmalloc(sizeof(struct drvextra_cmd_parm));
3329 if (pdrvextra_cmd_parm == NULL) {
3330 rtw_mfree((unsigned char *)ph2c, sizeof(struct cmd_obj));
3331 res = _FAIL;
3332 goto exit;
3333 }
3334
3335 pdrvextra_cmd_parm->ec_id = LPS_CHANGE_DTIM_CID;
3336 pdrvextra_cmd_parm->type = dtim;
3337 pdrvextra_cmd_parm->size = 0;
3338 pdrvextra_cmd_parm->pbuf = NULL;
3339
3340 init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, CMD_SET_DRV_EXTRA);
3341
3342 res = rtw_enqueue_cmd(pcmdpriv, ph2c);
3343 }
3344
3345 exit:
3346
3347 return res;
3348
3349 }
3350
3351 #if (RATE_ADAPTIVE_SUPPORT == 1)
rpt_timer_setting_wk_hdl(_adapter * padapter,u16 minRptTime)3352 void rpt_timer_setting_wk_hdl(_adapter *padapter, u16 minRptTime)
3353 {
3354 rtw_hal_set_hwreg(padapter, HW_VAR_RPT_TIMER_SETTING, (u8 *)(&minRptTime));
3355 }
3356
rtw_rpt_timer_cfg_cmd(_adapter * padapter,u16 minRptTime)3357 u8 rtw_rpt_timer_cfg_cmd(_adapter *padapter, u16 minRptTime)
3358 {
3359 struct cmd_obj *ph2c;
3360 struct drvextra_cmd_parm *pdrvextra_cmd_parm;
3361 struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
3362
3363 u8 res = _SUCCESS;
3364
3365 ph2c = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
3366 if (ph2c == NULL) {
3367 res = _FAIL;
3368 goto exit;
3369 }
3370
3371 pdrvextra_cmd_parm = (struct drvextra_cmd_parm *)rtw_zmalloc(sizeof(struct drvextra_cmd_parm));
3372 if (pdrvextra_cmd_parm == NULL) {
3373 rtw_mfree((unsigned char *)ph2c, sizeof(struct cmd_obj));
3374 res = _FAIL;
3375 goto exit;
3376 }
3377
3378 pdrvextra_cmd_parm->ec_id = RTP_TIMER_CFG_WK_CID;
3379 pdrvextra_cmd_parm->type = minRptTime;
3380 pdrvextra_cmd_parm->size = 0;
3381 pdrvextra_cmd_parm->pbuf = NULL;
3382 init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, CMD_SET_DRV_EXTRA);
3383 res = rtw_enqueue_cmd(pcmdpriv, ph2c);
3384 exit:
3385
3386
3387 return res;
3388
3389 }
3390
3391 #endif
3392
3393 #ifdef CONFIG_ANTENNA_DIVERSITY
antenna_select_wk_hdl(_adapter * padapter,u8 antenna)3394 void antenna_select_wk_hdl(_adapter *padapter, u8 antenna)
3395 {
3396 rtw_hal_set_odm_var(padapter, HAL_ODM_ANTDIV_SELECT, &antenna, _TRUE);
3397 }
3398
rtw_antenna_select_cmd(_adapter * padapter,u8 antenna,u8 enqueue)3399 u8 rtw_antenna_select_cmd(_adapter *padapter, u8 antenna, u8 enqueue)
3400 {
3401 struct cmd_obj *ph2c;
3402 struct drvextra_cmd_parm *pdrvextra_cmd_parm;
3403 struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
3404 struct dvobj_priv *dvobj = adapter_to_dvobj(padapter);
3405 u8 bSupportAntDiv = _FALSE;
3406 u8 res = _SUCCESS;
3407 int i;
3408
3409 rtw_hal_get_def_var(padapter, HAL_DEF_IS_SUPPORT_ANT_DIV, &(bSupportAntDiv));
3410 if (_FALSE == bSupportAntDiv)
3411 return _FAIL;
3412
3413 for (i = 0; i < dvobj->iface_nums; i++) {
3414 if (rtw_linked_check(dvobj->padapters[i]))
3415 return _FAIL;
3416 }
3417
3418 if (_TRUE == enqueue) {
3419 ph2c = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
3420 if (ph2c == NULL) {
3421 res = _FAIL;
3422 goto exit;
3423 }
3424
3425 pdrvextra_cmd_parm = (struct drvextra_cmd_parm *)rtw_zmalloc(sizeof(struct drvextra_cmd_parm));
3426 if (pdrvextra_cmd_parm == NULL) {
3427 rtw_mfree((unsigned char *)ph2c, sizeof(struct cmd_obj));
3428 res = _FAIL;
3429 goto exit;
3430 }
3431
3432 pdrvextra_cmd_parm->ec_id = ANT_SELECT_WK_CID;
3433 pdrvextra_cmd_parm->type = antenna;
3434 pdrvextra_cmd_parm->size = 0;
3435 pdrvextra_cmd_parm->pbuf = NULL;
3436 init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, CMD_SET_DRV_EXTRA);
3437
3438 res = rtw_enqueue_cmd(pcmdpriv, ph2c);
3439 } else
3440 antenna_select_wk_hdl(padapter, antenna);
3441 exit:
3442
3443
3444 return res;
3445
3446 }
3447 #endif
3448
rtw_dm_ra_mask_hdl(_adapter * padapter,struct sta_info * psta)3449 void rtw_dm_ra_mask_hdl(_adapter *padapter, struct sta_info *psta)
3450 {
3451 if (psta)
3452 set_sta_rate(padapter, psta);
3453 }
3454
rtw_dm_ra_mask_wk_cmd(_adapter * padapter,u8 * psta)3455 u8 rtw_dm_ra_mask_wk_cmd(_adapter *padapter, u8 *psta)
3456 {
3457 struct cmd_obj *ph2c;
3458 struct drvextra_cmd_parm *pdrvextra_cmd_parm;
3459 struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
3460 u8 res = _SUCCESS;
3461
3462
3463 ph2c = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
3464 if (ph2c == NULL) {
3465 res = _FAIL;
3466 goto exit;
3467 }
3468
3469 pdrvextra_cmd_parm = (struct drvextra_cmd_parm *)rtw_zmalloc(sizeof(struct drvextra_cmd_parm));
3470 if (pdrvextra_cmd_parm == NULL) {
3471 rtw_mfree((unsigned char *)ph2c, sizeof(struct cmd_obj));
3472 res = _FAIL;
3473 goto exit;
3474 }
3475
3476 pdrvextra_cmd_parm->ec_id = DM_RA_MSK_WK_CID;
3477 pdrvextra_cmd_parm->type = 0;
3478 pdrvextra_cmd_parm->size = 0;
3479 pdrvextra_cmd_parm->pbuf = psta;
3480
3481 init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, CMD_SET_DRV_EXTRA);
3482
3483 res = rtw_enqueue_cmd(pcmdpriv, ph2c);
3484
3485 exit:
3486
3487 return res;
3488
3489 }
3490
power_saving_wk_hdl(_adapter * padapter)3491 void power_saving_wk_hdl(_adapter *padapter)
3492 {
3493 rtw_ps_processor(padapter);
3494 }
3495
3496 /* add for CONFIG_IEEE80211W, none 11w can use it */
reset_securitypriv_hdl(_adapter * padapter)3497 void reset_securitypriv_hdl(_adapter *padapter)
3498 {
3499 rtw_reset_securitypriv(padapter);
3500 }
3501
3502 #ifdef CONFIG_P2P
p2p_protocol_wk_cmd(_adapter * padapter,int intCmdType)3503 u8 p2p_protocol_wk_cmd(_adapter *padapter, int intCmdType)
3504 {
3505 struct cmd_obj *ph2c;
3506 struct drvextra_cmd_parm *pdrvextra_cmd_parm;
3507 struct wifidirect_info *pwdinfo = &(padapter->wdinfo);
3508 struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
3509 u8 res = _SUCCESS;
3510
3511
3512 if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE))
3513 return res;
3514
3515 ph2c = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
3516 if (ph2c == NULL) {
3517 res = _FAIL;
3518 goto exit;
3519 }
3520
3521 pdrvextra_cmd_parm = (struct drvextra_cmd_parm *)rtw_zmalloc(sizeof(struct drvextra_cmd_parm));
3522 if (pdrvextra_cmd_parm == NULL) {
3523 rtw_mfree((unsigned char *)ph2c, sizeof(struct cmd_obj));
3524 res = _FAIL;
3525 goto exit;
3526 }
3527
3528 pdrvextra_cmd_parm->ec_id = P2P_PROTO_WK_CID;
3529 pdrvextra_cmd_parm->type = intCmdType; /* As the command tppe. */
3530 pdrvextra_cmd_parm->size = 0;
3531 pdrvextra_cmd_parm->pbuf = NULL; /* Must be NULL here */
3532
3533 init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, CMD_SET_DRV_EXTRA);
3534
3535 res = rtw_enqueue_cmd(pcmdpriv, ph2c);
3536
3537 exit:
3538
3539
3540 return res;
3541
3542 }
3543 #endif /* CONFIG_P2P */
3544
3545 #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)3546 static struct rtw_roch_parm *rtw_alloc_roch_parm(_adapter *adapter
3547 , u64 cookie, struct wireless_dev *wdev
3548 , struct ieee80211_channel *ch, enum nl80211_channel_type ch_type
3549 , unsigned int duration
3550 , u8 flags
3551 )
3552 {
3553 struct rtw_roch_parm *roch_parm;
3554 bool cancel = duration ? 0 : 1;
3555
3556 roch_parm = (struct rtw_roch_parm *)rtw_zmalloc(sizeof(struct rtw_roch_parm));
3557 if (!roch_parm)
3558 return NULL;
3559
3560 roch_parm->cookie = cookie;
3561 roch_parm->wdev = wdev;
3562 if (!cancel) {
3563 _rtw_memcpy(&roch_parm->ch, ch, sizeof(struct ieee80211_channel));
3564 roch_parm->ch_type = ch_type;
3565 roch_parm->duration = duration;
3566 }
3567
3568 return roch_parm;
3569 }
3570
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)3571 inline u8 rtw_roch_cmd(_adapter *adapter
3572 , u64 cookie, struct wireless_dev *wdev
3573 , struct ieee80211_channel *ch, enum nl80211_channel_type ch_type
3574 , unsigned int duration
3575 , u8 flags
3576 )
3577 {
3578 struct rtw_roch_parm *roch_parm;
3579
3580 roch_parm = rtw_alloc_roch_parm(adapter, cookie, wdev, ch, ch_type, duration, flags);
3581 if (!roch_parm)
3582 return _FAIL;
3583
3584 return rtw_roch_wk_cmd(adapter, ROCH_RO_CH_WK, roch_parm, flags);
3585 }
3586
rtw_cancel_roch_cmd(_adapter * adapter,u64 cookie,struct wireless_dev * wdev,u8 flags)3587 inline u8 rtw_cancel_roch_cmd(_adapter *adapter, u64 cookie, struct wireless_dev *wdev, u8 flags)
3588 {
3589 struct rtw_roch_parm *roch_parm;
3590
3591 roch_parm = rtw_alloc_roch_parm(adapter, cookie, wdev, NULL, 0, 0, flags);
3592 if (!roch_parm)
3593 return _FAIL;
3594
3595 return rtw_roch_wk_cmd(adapter, ROCH_CANCEL_RO_CH_WK, roch_parm, flags);
3596 }
3597
rtw_mgnt_tx_cmd(_adapter * adapter,u8 tx_ch,u8 no_cck,const u8 * buf,size_t len,int wait_ack,u8 flags)3598 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)
3599 {
3600 struct cmd_obj *cmdobj;
3601 struct drvextra_cmd_parm *parm;
3602 struct mgnt_tx_parm *mgnt_parm;
3603 struct cmd_priv *pcmdpriv = &adapter->cmdpriv;
3604 struct submit_ctx sctx;
3605 u8 res = _SUCCESS;
3606
3607 mgnt_parm = (struct mgnt_tx_parm *)rtw_zmalloc(sizeof(struct mgnt_tx_parm));
3608 if (mgnt_parm == NULL) {
3609 res = _FAIL;
3610 goto exit;
3611 }
3612
3613 mgnt_parm->tx_ch = tx_ch;
3614 mgnt_parm->no_cck = no_cck;
3615 mgnt_parm->buf = buf;
3616 mgnt_parm->len = len;
3617 mgnt_parm->wait_ack = wait_ack;
3618
3619 if (flags & RTW_CMDF_DIRECTLY) {
3620 /* no need to enqueue, do the cmd hdl directly and free cmd parameter */
3621 if (H2C_SUCCESS != rtw_mgnt_tx_handler(adapter, (u8 *)mgnt_parm))
3622 res = _FAIL;
3623 rtw_mfree((u8 *)mgnt_parm, sizeof(*mgnt_parm));
3624 } else {
3625 /* need enqueue, prepare cmd_obj and enqueue */
3626 parm = (struct drvextra_cmd_parm *)rtw_zmalloc(sizeof(struct drvextra_cmd_parm));
3627 if (parm == NULL) {
3628 rtw_mfree((u8 *)mgnt_parm, sizeof(*mgnt_parm));
3629 res = _FAIL;
3630 goto exit;
3631 }
3632
3633 parm->ec_id = MGNT_TX_WK_CID;
3634 parm->type = 0;
3635 parm->size = sizeof(*mgnt_parm);
3636 parm->pbuf = (u8 *)mgnt_parm;
3637
3638 cmdobj = (struct cmd_obj *)rtw_zmalloc(sizeof(*cmdobj));
3639 if (cmdobj == NULL) {
3640 res = _FAIL;
3641 rtw_mfree((u8 *)mgnt_parm, sizeof(*mgnt_parm));
3642 rtw_mfree((u8 *)parm, sizeof(*parm));
3643 goto exit;
3644 }
3645
3646 init_h2fwcmd_w_parm_no_rsp(cmdobj, parm, CMD_SET_DRV_EXTRA);
3647
3648 if (flags & RTW_CMDF_WAIT_ACK) {
3649 cmdobj->sctx = &sctx;
3650 rtw_sctx_init(&sctx, 10 * 1000);
3651 }
3652
3653 res = rtw_enqueue_cmd(pcmdpriv, cmdobj);
3654
3655 if (res == _SUCCESS && (flags & RTW_CMDF_WAIT_ACK)) {
3656 rtw_sctx_wait(&sctx, __func__);
3657 _enter_critical_mutex(&pcmdpriv->sctx_mutex, NULL);
3658 if (sctx.status == RTW_SCTX_SUBMITTED)
3659 cmdobj->sctx = NULL;
3660 _exit_critical_mutex(&pcmdpriv->sctx_mutex, NULL);
3661 if (sctx.status != RTW_SCTX_DONE_SUCCESS)
3662 res = _FAIL;
3663 }
3664 }
3665
3666 exit:
3667 return res;
3668 }
3669 #endif
3670
rtw_ps_cmd(_adapter * padapter)3671 u8 rtw_ps_cmd(_adapter *padapter)
3672 {
3673 struct cmd_obj *ppscmd;
3674 struct drvextra_cmd_parm *pdrvextra_cmd_parm;
3675 struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
3676
3677 u8 res = _SUCCESS;
3678
3679 #ifdef CONFIG_CONCURRENT_MODE
3680 if (!is_primary_adapter(padapter))
3681 goto exit;
3682 #endif
3683
3684 ppscmd = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
3685 if (ppscmd == NULL) {
3686 res = _FAIL;
3687 goto exit;
3688 }
3689
3690 pdrvextra_cmd_parm = (struct drvextra_cmd_parm *)rtw_zmalloc(sizeof(struct drvextra_cmd_parm));
3691 if (pdrvextra_cmd_parm == NULL) {
3692 rtw_mfree((unsigned char *)ppscmd, sizeof(struct cmd_obj));
3693 res = _FAIL;
3694 goto exit;
3695 }
3696
3697 pdrvextra_cmd_parm->ec_id = POWER_SAVING_CTRL_WK_CID;
3698 pdrvextra_cmd_parm->type = 0;
3699 pdrvextra_cmd_parm->size = 0;
3700 pdrvextra_cmd_parm->pbuf = NULL;
3701 init_h2fwcmd_w_parm_no_rsp(ppscmd, pdrvextra_cmd_parm, CMD_SET_DRV_EXTRA);
3702
3703 res = rtw_enqueue_cmd(pcmdpriv, ppscmd);
3704
3705 exit:
3706
3707
3708 return res;
3709
3710 }
3711
3712 #if CONFIG_DFS
rtw_dfs_ch_switch_hdl(struct dvobj_priv * dvobj)3713 void rtw_dfs_ch_switch_hdl(struct dvobj_priv *dvobj)
3714 {
3715 struct rf_ctl_t *rfctl = dvobj_to_rfctl(dvobj);
3716 _adapter *pri_adapter = dvobj_get_primary_adapter(dvobj);
3717 struct mlme_ext_priv *pmlmeext = &pri_adapter->mlmeextpriv;
3718 u8 ifbmp_m = rtw_mi_get_ap_mesh_ifbmp(pri_adapter);
3719 u8 ifbmp_s = rtw_mi_get_ld_sta_ifbmp(pri_adapter);
3720 s16 req_ch;
3721 u8 req_bw = CHANNEL_WIDTH_20, req_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
3722
3723 rtw_hal_macid_sleep_all_used(pri_adapter);
3724
3725 if (rtw_chset_search_ch(rfctl->channel_set, rfctl->csa_ch) >= 0
3726 && !rtw_chset_is_ch_non_ocp(rfctl->channel_set, rfctl->csa_ch)
3727 ) {
3728 /* CSA channel available and valid */
3729 req_ch = rfctl->csa_ch;
3730 RTW_INFO("%s valid CSA ch%u\n", __func__, rfctl->csa_ch);
3731 } else if (ifbmp_m) {
3732 /* no available or valid CSA channel, having AP/MESH ifaces */
3733 req_ch = REQ_CH_NONE;
3734 RTW_INFO("%s ch sel by AP/MESH ifaces\n", __func__);
3735 } else {
3736 /* no available or valid CSA channel and no AP/MESH ifaces */
3737 if (!IsSupported24G(dvobj_to_regsty(dvobj)->wireless_mode)
3738 #ifdef CONFIG_DFS_MASTER
3739 || rfctl->radar_detected
3740 #endif
3741 )
3742 req_ch = 36;
3743 else
3744 req_ch = 1;
3745 RTW_INFO("%s switch to ch%d\n", __func__, req_ch);
3746 }
3747
3748 /* only support 80 Mhz so far */
3749 if(rfctl->csa_ch_width == 1 || rfctl->csa_ch_width == 2 || rfctl->csa_ch_width == 3) {
3750 if (rtw_get_offset_by_chbw(req_ch, CHANNEL_WIDTH_80, &req_offset)) {
3751 req_bw = CHANNEL_WIDTH_80;
3752 } else {
3753 req_bw = CHANNEL_WIDTH_20;
3754 req_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
3755 }
3756 } else if(rfctl->csa_ch_offset == 1) {
3757 req_bw = CHANNEL_WIDTH_40;
3758 req_offset = HAL_PRIME_CHNL_OFFSET_LOWER;
3759 } else if(rfctl->csa_ch_offset == 3) {
3760 req_bw = CHANNEL_WIDTH_40;
3761 req_offset = HAL_PRIME_CHNL_OFFSET_UPPER;
3762 } else{
3763 req_bw = CHANNEL_WIDTH_20;
3764 req_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
3765 }
3766
3767 RTW_INFO("req_ch=%d, req_bw=%d, req_offset=%d, ifbmp_m=0x%02x, ifbmp_s=0x%02x\n"
3768 , req_ch, req_bw, req_offset, ifbmp_m, ifbmp_s);
3769
3770 /* update ch, bw, offset for all asoc STA ifaces */
3771 if (ifbmp_s) {
3772 _adapter *iface;
3773 int i;
3774
3775 for (i = 0; i < dvobj->iface_nums; i++) {
3776 iface = dvobj->padapters[i];
3777 if (!iface || !(ifbmp_s & BIT(iface->iface_id)))
3778 continue;
3779
3780 /* update STA mode ch/bw/offset */
3781 iface->mlmeextpriv.cur_channel = req_ch;
3782 iface->mlmeextpriv.cur_bwmode = req_bw;
3783 iface->mlmeextpriv.cur_ch_offset = req_offset;
3784 /* updaet STA mode DSConfig , ap mode will update in rtw_change_bss_chbw_cmd */
3785 iface->mlmepriv.cur_network.network.Configuration.DSConfig = req_ch;
3786 set_fwstate(&iface->mlmepriv, WIFI_CSA_UPDATE_BEACON);
3787
3788 }
3789 }
3790
3791 if (rfctl->csa_ch > 0) {
3792 RTW_INFO("pmlmeext->csa_timer 70 seconds\n");
3793 /* wait 70 seconds for receiving beacons */
3794 _set_timer(&pmlmeext->csa_timer, CAC_TIME_MS + 10000);
3795 }
3796
3797 #ifdef CONFIG_AP_MODE
3798 if (ifbmp_m) {
3799 /* trigger channel selection with consideraton of asoc STA ifaces */
3800 rtw_change_bss_chbw_cmd(dvobj_get_primary_adapter(dvobj), RTW_CMDF_DIRECTLY
3801 , ifbmp_m, 0, req_ch, REQ_BW_ORI, REQ_OFFSET_NONE);
3802 } else
3803 #endif
3804 {
3805 /* no AP/MESH iface, switch DFS status and channel directly */
3806 rtw_warn_on(req_ch <= 0);
3807 #ifdef CONFIG_DFS_MASTER
3808 rtw_dfs_rd_en_decision(pri_adapter, MLME_OPCH_SWITCH, 0);
3809 #endif
3810 LeaveAllPowerSaveModeDirect(pri_adapter);
3811 set_channel_bwmode(pri_adapter, req_ch, req_offset, req_bw);
3812 /* update union ch/bw/offset for STA only */
3813 rtw_mi_update_union_chan_inf(pri_adapter, req_ch, req_offset, req_bw);
3814 rtw_rfctl_update_op_mode(rfctl, 0, 0);
3815 }
3816
3817 rfctl->csa_ch = 0;
3818 rfctl->csa_switch_cnt = 0;
3819 rfctl->csa_ch_offset = 0;
3820 rfctl->csa_ch_width = 0;
3821 rfctl->csa_ch_freq_seg0 = 0;
3822 rfctl->csa_ch_freq_seg1 = 0;
3823
3824 rtw_hal_macid_wakeup_all_used(pri_adapter);
3825 rtw_mi_os_xmit_schedule(pri_adapter);
3826 }
3827 #endif /* CONFIG_DFS */
3828
3829 #ifdef CONFIG_AP_MODE
3830
rtw_chk_hi_queue_hdl(_adapter * padapter)3831 static void rtw_chk_hi_queue_hdl(_adapter *padapter)
3832 {
3833 struct sta_info *psta_bmc;
3834 struct sta_priv *pstapriv = &padapter->stapriv;
3835 systime start = rtw_get_current_time();
3836 u8 empty = _FALSE;
3837
3838 psta_bmc = rtw_get_bcmc_stainfo(padapter);
3839 if (!psta_bmc)
3840 return;
3841
3842 rtw_hal_get_hwreg(padapter, HW_VAR_CHK_HI_QUEUE_EMPTY, &empty);
3843
3844 while (_FALSE == empty && rtw_get_passing_time_ms(start) < rtw_get_wait_hiq_empty_ms()) {
3845 rtw_msleep_os(100);
3846 rtw_hal_get_hwreg(padapter, HW_VAR_CHK_HI_QUEUE_EMPTY, &empty);
3847 }
3848
3849 if (psta_bmc->sleepq_len == 0) {
3850 if (empty == _SUCCESS) {
3851 bool update_tim = _FALSE;
3852
3853 if (rtw_tim_map_is_set(padapter, pstapriv->tim_bitmap, 0))
3854 update_tim = _TRUE;
3855
3856 rtw_tim_map_clear(padapter, pstapriv->tim_bitmap, 0);
3857 rtw_tim_map_clear(padapter, pstapriv->sta_dz_bitmap, 0);
3858
3859 if (update_tim == _TRUE)
3860 _update_beacon(padapter, _TIM_IE_, NULL, _TRUE, 0,"bmc sleepq and HIQ empty");
3861 } else /* re check again */
3862 rtw_chk_hi_queue_cmd(padapter);
3863
3864 }
3865
3866 }
3867
rtw_chk_hi_queue_cmd(_adapter * padapter)3868 u8 rtw_chk_hi_queue_cmd(_adapter *padapter)
3869 {
3870 struct cmd_obj *ph2c;
3871 struct drvextra_cmd_parm *pdrvextra_cmd_parm;
3872 struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
3873 u8 res = _SUCCESS;
3874
3875 ph2c = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
3876 if (ph2c == NULL) {
3877 res = _FAIL;
3878 goto exit;
3879 }
3880
3881 pdrvextra_cmd_parm = (struct drvextra_cmd_parm *)rtw_zmalloc(sizeof(struct drvextra_cmd_parm));
3882 if (pdrvextra_cmd_parm == NULL) {
3883 rtw_mfree((unsigned char *)ph2c, sizeof(struct cmd_obj));
3884 res = _FAIL;
3885 goto exit;
3886 }
3887
3888 pdrvextra_cmd_parm->ec_id = CHECK_HIQ_WK_CID;
3889 pdrvextra_cmd_parm->type = 0;
3890 pdrvextra_cmd_parm->size = 0;
3891 pdrvextra_cmd_parm->pbuf = NULL;
3892
3893 init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, CMD_SET_DRV_EXTRA);
3894
3895 res = rtw_enqueue_cmd(pcmdpriv, ph2c);
3896
3897 exit:
3898
3899 return res;
3900
3901 }
3902
3903 #ifdef CONFIG_DFS_MASTER
rtw_dfs_rd_hdl(_adapter * adapter)3904 u8 rtw_dfs_rd_hdl(_adapter *adapter)
3905 {
3906 struct dvobj_priv *dvobj = adapter_to_dvobj(adapter);
3907 struct rf_ctl_t *rfctl = adapter_to_rfctl(adapter);
3908 u8 cch;
3909
3910 if (!rfctl->radar_detect_enabled)
3911 goto exit;
3912
3913 cch = rtw_get_center_ch(rfctl->radar_detect_ch, rfctl->radar_detect_bw, rfctl->radar_detect_offset);
3914
3915 if (dvobj->oper_channel != rfctl->radar_detect_ch
3916 || rtw_get_passing_time_ms(rtw_get_on_oper_ch_time(adapter)) < 300
3917 ) {
3918 /* offchannel, bypass radar detect */
3919 goto cac_status_chk;
3920 }
3921
3922 if (IS_CH_WAITING(rfctl) && !IS_UNDER_CAC(rfctl)) {
3923 /* non_ocp, bypass radar detect */
3924 goto cac_status_chk;
3925 }
3926
3927 if (!rfctl->dbg_dfs_fake_radar_detect_cnt
3928 && rtw_odm_radar_detect(adapter) != _TRUE)
3929 goto cac_status_chk;
3930
3931 if (!rfctl->dbg_dfs_fake_radar_detect_cnt
3932 && rfctl->dbg_dfs_radar_detect_trigger_non
3933 ) {
3934 /* radar detect debug mode, trigger no mlme flow */
3935 RTW_INFO("%s radar detected on test mode, trigger no mlme flow\n", __func__);
3936 goto cac_status_chk;
3937 }
3938
3939 if (rfctl->dbg_dfs_fake_radar_detect_cnt != 0) {
3940 RTW_INFO("%s fake radar detected, cnt:%d\n", __func__
3941 , rfctl->dbg_dfs_fake_radar_detect_cnt);
3942 rfctl->dbg_dfs_fake_radar_detect_cnt--;
3943 } else
3944 RTW_INFO("%s radar detected\n", __func__);
3945
3946 rfctl->radar_detected = 1;
3947
3948 rtw_chset_update_non_ocp(rfctl->channel_set
3949 , rfctl->radar_detect_ch, rfctl->radar_detect_bw, rfctl->radar_detect_offset);
3950
3951 if (IS_UNDER_CAC(rfctl))
3952 rtw_nlrtw_cac_abort_event(adapter, cch, rfctl->radar_detect_bw);
3953 rtw_nlrtw_radar_detect_event(adapter, cch, rfctl->radar_detect_bw);
3954
3955 rtw_dfs_ch_switch_hdl(dvobj);
3956
3957 if (rfctl->radar_detect_enabled)
3958 goto set_timer;
3959 goto exit;
3960
3961 cac_status_chk:
3962
3963 if (!IS_CAC_STOPPED(rfctl)
3964 && ((IS_UNDER_CAC(rfctl) && rfctl->cac_force_stop)
3965 || !IS_CH_WAITING(rfctl)
3966 )
3967 ) {
3968 u8 pause = 0x00;
3969
3970 rtw_hal_set_hwreg(adapter, HW_VAR_TXPAUSE, &pause);
3971 rfctl->cac_start_time = rfctl->cac_end_time = RTW_CAC_STOPPED;
3972 rtw_nlrtw_cac_finish_event(adapter, cch, rfctl->radar_detect_bw);
3973
3974 if (rtw_mi_check_fwstate(adapter, WIFI_UNDER_LINKING|WIFI_UNDER_SURVEY) == _FALSE) {
3975 u8 doiqk = _TRUE;
3976 u8 u_ch, u_bw, u_offset;
3977
3978 rtw_hal_set_hwreg(adapter , HW_VAR_DO_IQK , &doiqk);
3979
3980 if (rtw_mi_get_ch_setting_union(adapter, &u_ch, &u_bw, &u_offset))
3981 set_channel_bwmode(adapter, u_ch, u_offset, u_bw);
3982 else
3983 rtw_warn_on(1);
3984
3985 doiqk = _FALSE;
3986 rtw_hal_set_hwreg(adapter , HW_VAR_DO_IQK , &doiqk);
3987
3988 #ifdef CONFIG_AP_MODE
3989 ResumeTxBeacon(adapter);
3990 rtw_mi_tx_beacon_hdl(adapter);
3991 #endif
3992 }
3993 }
3994
3995 set_timer:
3996 _set_timer(&rfctl->radar_detect_timer
3997 , rtw_odm_radar_detect_polling_int_ms(dvobj));
3998
3999 exit:
4000 return H2C_SUCCESS;
4001 }
4002
rtw_dfs_rd_cmd(_adapter * adapter,bool enqueue)4003 u8 rtw_dfs_rd_cmd(_adapter *adapter, bool enqueue)
4004 {
4005 struct cmd_obj *cmdobj;
4006 struct drvextra_cmd_parm *parm;
4007 struct cmd_priv *cmdpriv = &adapter->cmdpriv;
4008 u8 res = _FAIL;
4009
4010 if (enqueue) {
4011 cmdobj = rtw_zmalloc(sizeof(struct cmd_obj));
4012 if (cmdobj == NULL)
4013 goto exit;
4014
4015 parm = rtw_zmalloc(sizeof(struct drvextra_cmd_parm));
4016 if (parm == NULL) {
4017 rtw_mfree(cmdobj, sizeof(struct cmd_obj));
4018 goto exit;
4019 }
4020
4021 parm->ec_id = DFS_RADAR_DETECT_WK_CID;
4022 parm->type = 0;
4023 parm->size = 0;
4024 parm->pbuf = NULL;
4025
4026 init_h2fwcmd_w_parm_no_rsp(cmdobj, parm, CMD_SET_DRV_EXTRA);
4027 res = rtw_enqueue_cmd(cmdpriv, cmdobj);
4028 } else {
4029 rtw_dfs_rd_hdl(adapter);
4030 res = _SUCCESS;
4031 }
4032
4033 exit:
4034 return res;
4035 }
4036
rtw_dfs_rd_timer_hdl(void * ctx)4037 void rtw_dfs_rd_timer_hdl(void *ctx)
4038 {
4039 struct rf_ctl_t *rfctl = (struct rf_ctl_t *)ctx;
4040 struct dvobj_priv *dvobj = rfctl_to_dvobj(rfctl);
4041
4042 rtw_dfs_rd_cmd(dvobj_get_primary_adapter(dvobj), _TRUE);
4043 }
4044
rtw_dfs_rd_enable(struct rf_ctl_t * rfctl,u8 ch,u8 bw,u8 offset,bool bypass_cac)4045 static void rtw_dfs_rd_enable(struct rf_ctl_t *rfctl, u8 ch, u8 bw, u8 offset, bool bypass_cac)
4046 {
4047 struct dvobj_priv *dvobj = rfctl_to_dvobj(rfctl);
4048 _adapter *adapter = dvobj_get_primary_adapter(dvobj);
4049
4050 RTW_INFO("%s on %u,%u,%u\n", __func__, ch, bw, offset);
4051
4052 if (bypass_cac)
4053 rfctl->cac_start_time = rfctl->cac_end_time = RTW_CAC_STOPPED;
4054 else if (rtw_is_cac_reset_needed(rfctl, ch, bw, offset) == _TRUE)
4055 rtw_reset_cac(rfctl, ch, bw, offset);
4056
4057 rfctl->radar_detect_by_others = _FALSE;
4058 rfctl->radar_detect_ch = ch;
4059 rfctl->radar_detect_bw = bw;
4060 rfctl->radar_detect_offset = offset;
4061
4062 rfctl->radar_detected = 0;
4063
4064 if (IS_CH_WAITING(rfctl))
4065 StopTxBeacon(adapter);
4066
4067 if (!rfctl->radar_detect_enabled) {
4068 RTW_INFO("%s set radar_detect_enabled\n", __func__);
4069 rfctl->radar_detect_enabled = 1;
4070 #ifdef CONFIG_LPS
4071 LPS_Leave(adapter, "RADAR_DETECT_EN");
4072 #endif
4073 _set_timer(&rfctl->radar_detect_timer
4074 , rtw_odm_radar_detect_polling_int_ms(dvobj));
4075
4076 if (rtw_rfctl_overlap_radar_detect_ch(rfctl)) {
4077 if (IS_CH_WAITING(rfctl)) {
4078 u8 pause = 0xFF;
4079
4080 rtw_hal_set_hwreg(adapter, HW_VAR_TXPAUSE, &pause);
4081 }
4082 rtw_odm_radar_detect_enable(adapter);
4083 }
4084 }
4085 }
4086
rtw_dfs_rd_disable(struct rf_ctl_t * rfctl,u8 ch,u8 bw,u8 offset,bool by_others)4087 static void rtw_dfs_rd_disable(struct rf_ctl_t *rfctl, u8 ch, u8 bw, u8 offset, bool by_others)
4088 {
4089 _adapter *adapter = dvobj_get_primary_adapter(rfctl_to_dvobj(rfctl));
4090
4091 rfctl->radar_detect_by_others = by_others;
4092
4093 if (rfctl->radar_detect_enabled) {
4094 bool overlap_radar_detect_ch = rtw_rfctl_overlap_radar_detect_ch(rfctl);
4095
4096 RTW_INFO("%s clear radar_detect_enabled\n", __func__);
4097
4098 rfctl->radar_detect_enabled = 0;
4099 rfctl->radar_detected = 0;
4100 rfctl->radar_detect_ch = 0;
4101 rfctl->radar_detect_bw = 0;
4102 rfctl->radar_detect_offset = 0;
4103 rfctl->cac_start_time = rfctl->cac_end_time = RTW_CAC_STOPPED;
4104 _cancel_timer_ex(&rfctl->radar_detect_timer);
4105
4106 if (rtw_mi_check_fwstate(adapter, WIFI_UNDER_LINKING|WIFI_UNDER_SURVEY) == _FALSE) {
4107 ResumeTxBeacon(adapter);
4108 rtw_mi_tx_beacon_hdl(adapter);
4109 }
4110
4111 if (overlap_radar_detect_ch) {
4112 u8 pause = 0x00;
4113
4114 rtw_hal_set_hwreg(adapter, HW_VAR_TXPAUSE, &pause);
4115 rtw_odm_radar_detect_disable(adapter);
4116 }
4117 }
4118
4119 if (by_others) {
4120 rfctl->radar_detect_ch = ch;
4121 rfctl->radar_detect_bw = bw;
4122 rfctl->radar_detect_offset = offset;
4123 } else {
4124 rfctl->radar_detect_ch = 0;
4125 rfctl->radar_detect_bw = 0;
4126 rfctl->radar_detect_offset = 0;
4127 }
4128 }
4129
rtw_dfs_rd_en_decision(_adapter * adapter,u8 mlme_act,u8 excl_ifbmp)4130 void rtw_dfs_rd_en_decision(_adapter *adapter, u8 mlme_act, u8 excl_ifbmp)
4131 {
4132 struct dvobj_priv *dvobj = adapter_to_dvobj(adapter);
4133 struct rf_ctl_t *rfctl = adapter_to_rfctl(adapter);
4134 struct mlme_ext_priv *mlmeext = &adapter->mlmeextpriv;
4135 struct mi_state mstate;
4136 u8 ifbmp;
4137 u8 u_ch, u_bw, u_offset;
4138 bool ld_sta_in_dfs = _FALSE;
4139 bool sync_ch = _FALSE; /* _FALSE: asign channel directly */
4140 bool needed = _FALSE;
4141
4142 if (mlme_act == MLME_OPCH_SWITCH
4143 || mlme_act == MLME_ACTION_NONE
4144 ) {
4145 ifbmp = ~excl_ifbmp;
4146 rtw_mi_status_by_ifbmp(dvobj, ifbmp, &mstate);
4147 rtw_mi_get_ch_setting_union_by_ifbmp(dvobj, ifbmp, &u_ch, &u_bw, &u_offset);
4148 } else {
4149 ifbmp = ~excl_ifbmp & ~BIT(adapter->iface_id);
4150 rtw_mi_status_by_ifbmp(dvobj, ifbmp, &mstate);
4151 rtw_mi_get_ch_setting_union_by_ifbmp(dvobj, ifbmp, &u_ch, &u_bw, &u_offset);
4152 if (u_ch != 0)
4153 sync_ch = _TRUE;
4154
4155 switch (mlme_act) {
4156 case MLME_STA_CONNECTING:
4157 MSTATE_STA_LG_NUM(&mstate)++;
4158 break;
4159 case MLME_STA_CONNECTED:
4160 MSTATE_STA_LD_NUM(&mstate)++;
4161 break;
4162 case MLME_STA_DISCONNECTED:
4163 break;
4164 #ifdef CONFIG_AP_MODE
4165 case MLME_AP_STARTED:
4166 MSTATE_AP_NUM(&mstate)++;
4167 break;
4168 case MLME_AP_STOPPED:
4169 break;
4170 #endif
4171 #ifdef CONFIG_RTW_MESH
4172 case MLME_MESH_STARTED:
4173 MSTATE_MESH_NUM(&mstate)++;
4174 break;
4175 case MLME_MESH_STOPPED:
4176 break;
4177 #endif
4178 default:
4179 rtw_warn_on(1);
4180 break;
4181 }
4182
4183 if (sync_ch == _TRUE) {
4184 if (!MLME_IS_OPCH_SW(adapter)) {
4185 if (!rtw_is_chbw_grouped(mlmeext->cur_channel, mlmeext->cur_bwmode, mlmeext->cur_ch_offset, u_ch, u_bw, u_offset)) {
4186 RTW_INFO(FUNC_ADPT_FMT" can't sync %u,%u,%u with %u,%u,%u\n", FUNC_ADPT_ARG(adapter)
4187 , mlmeext->cur_channel, mlmeext->cur_bwmode, mlmeext->cur_ch_offset, u_ch, u_bw, u_offset);
4188 goto apply;
4189 }
4190
4191 rtw_sync_chbw(&mlmeext->cur_channel, &mlmeext->cur_bwmode, &mlmeext->cur_ch_offset
4192 , &u_ch, &u_bw, &u_offset);
4193 }
4194 } else {
4195 u_ch = mlmeext->cur_channel;
4196 u_bw = mlmeext->cur_bwmode;
4197 u_offset = mlmeext->cur_ch_offset;
4198 }
4199 }
4200
4201 if (MSTATE_STA_LG_NUM(&mstate) > 0) {
4202 /* STA mode is linking */
4203 goto apply;
4204 }
4205
4206 if (MSTATE_STA_LD_NUM(&mstate) > 0) {
4207 if (rtw_chset_is_dfs_chbw(rfctl->channel_set, u_ch, u_bw, u_offset)) {
4208 /*
4209 * if operate as slave w/o radar detect,
4210 * rely on AP on which STA mode connects
4211 */
4212 if (IS_DFS_SLAVE_WITH_RD(rfctl) && !rtw_rfctl_dfs_domain_unknown(rfctl))
4213 needed = _TRUE;
4214 ld_sta_in_dfs = _TRUE;
4215 }
4216 goto apply;
4217 }
4218
4219 if (!MSTATE_AP_NUM(&mstate) && !MSTATE_MESH_NUM(&mstate)) {
4220 /* No working AP/Mesh mode */
4221 goto apply;
4222 }
4223
4224 if (rtw_chset_is_dfs_chbw(rfctl->channel_set, u_ch, u_bw, u_offset))
4225 needed = _TRUE;
4226
4227 apply:
4228
4229 RTW_INFO(FUNC_ADPT_FMT" needed:%d, mlme_act:%u, excl_ifbmp:0x%02x\n"
4230 , FUNC_ADPT_ARG(adapter), needed, mlme_act, excl_ifbmp);
4231 RTW_INFO(FUNC_ADPT_FMT" ld_sta_num:%u, lg_sta_num:%u, ap_num:%u, mesh_num:%u, %u,%u,%u\n"
4232 , FUNC_ADPT_ARG(adapter), MSTATE_STA_LD_NUM(&mstate), MSTATE_STA_LG_NUM(&mstate)
4233 , MSTATE_AP_NUM(&mstate), MSTATE_MESH_NUM(&mstate)
4234 , u_ch, u_bw, u_offset);
4235
4236 if (needed == _TRUE)
4237 rtw_dfs_rd_enable(rfctl, u_ch, u_bw, u_offset, ld_sta_in_dfs);
4238 else
4239 rtw_dfs_rd_disable(rfctl, u_ch, u_bw, u_offset, ld_sta_in_dfs);
4240 }
4241
rtw_dfs_rd_en_decision_cmd(_adapter * adapter)4242 u8 rtw_dfs_rd_en_decision_cmd(_adapter *adapter)
4243 {
4244 struct cmd_obj *cmdobj;
4245 struct drvextra_cmd_parm *parm;
4246 struct cmd_priv *cmdpriv = &adapter->cmdpriv;
4247 u8 res = _FAIL;
4248
4249 cmdobj = rtw_zmalloc(sizeof(struct cmd_obj));
4250 if (cmdobj == NULL)
4251 goto exit;
4252
4253 parm = rtw_zmalloc(sizeof(struct drvextra_cmd_parm));
4254 if (parm == NULL) {
4255 rtw_mfree(cmdobj, sizeof(struct cmd_obj));
4256 goto exit;
4257 }
4258
4259 parm->ec_id = DFS_RADAR_DETECT_EN_DEC_WK_CID;
4260 parm->type = 0;
4261 parm->size = 0;
4262 parm->pbuf = NULL;
4263
4264 init_h2fwcmd_w_parm_no_rsp(cmdobj, parm, CMD_SET_DRV_EXTRA);
4265 res = rtw_enqueue_cmd(cmdpriv, cmdobj);
4266
4267 exit:
4268 return res;
4269 }
4270 #endif /* CONFIG_DFS_MASTER */
4271
4272 #endif /* CONFIG_AP_MODE */
4273
4274 #ifdef CONFIG_BT_COEXIST
4275 struct btinfo {
4276 u8 cid;
4277 u8 len;
4278
4279 u8 bConnection:1;
4280 u8 bSCOeSCO:1;
4281 u8 bInQPage:1;
4282 u8 bACLBusy:1;
4283 u8 bSCOBusy:1;
4284 u8 bHID:1;
4285 u8 bA2DP:1;
4286 u8 bFTP:1;
4287
4288 u8 retry_cnt:4;
4289 u8 rsvd_34:1;
4290 u8 rsvd_35:1;
4291 u8 rsvd_36:1;
4292 u8 rsvd_37:1;
4293
4294 u8 rssi;
4295
4296 u8 rsvd_50:1;
4297 u8 rsvd_51:1;
4298 u8 rsvd_52:1;
4299 u8 rsvd_53:1;
4300 u8 rsvd_54:1;
4301 u8 rsvd_55:1;
4302 u8 eSCO_SCO:1;
4303 u8 Master_Slave:1;
4304
4305 u8 rsvd_6;
4306 u8 rsvd_7;
4307 };
4308
btinfo_evt_dump(void * sel,void * buf)4309 void btinfo_evt_dump(void *sel, void *buf)
4310 {
4311 struct btinfo *info = (struct btinfo *)buf;
4312
4313 RTW_PRINT_SEL(sel, "cid:0x%02x, len:%u\n", info->cid, info->len);
4314
4315 if (info->len > 2)
4316 RTW_PRINT_SEL(sel, "byte2:%s%s%s%s%s%s%s%s\n"
4317 , info->bConnection ? "bConnection " : ""
4318 , info->bSCOeSCO ? "bSCOeSCO " : ""
4319 , info->bInQPage ? "bInQPage " : ""
4320 , info->bACLBusy ? "bACLBusy " : ""
4321 , info->bSCOBusy ? "bSCOBusy " : ""
4322 , info->bHID ? "bHID " : ""
4323 , info->bA2DP ? "bA2DP " : ""
4324 , info->bFTP ? "bFTP" : ""
4325 );
4326
4327 if (info->len > 3)
4328 RTW_PRINT_SEL(sel, "retry_cnt:%u\n", info->retry_cnt);
4329
4330 if (info->len > 4)
4331 RTW_PRINT_SEL(sel, "rssi:%u\n", info->rssi);
4332
4333 if (info->len > 5)
4334 RTW_PRINT_SEL(sel, "byte5:%s%s\n"
4335 , info->eSCO_SCO ? "eSCO_SCO " : ""
4336 , info->Master_Slave ? "Master_Slave " : ""
4337 );
4338 }
4339
rtw_btinfo_hdl(_adapter * adapter,u8 * buf,u16 buf_len)4340 static void rtw_btinfo_hdl(_adapter *adapter, u8 *buf, u16 buf_len)
4341 {
4342 #define BTINFO_WIFI_FETCH 0x23
4343 #define BTINFO_BT_AUTO_RPT 0x27
4344 #ifdef CONFIG_BT_COEXIST_SOCKET_TRX
4345 struct btinfo_8761ATV *info = (struct btinfo_8761ATV *)buf;
4346 #else /* !CONFIG_BT_COEXIST_SOCKET_TRX */
4347 struct btinfo *info = (struct btinfo *)buf;
4348 #endif /* CONFIG_BT_COEXIST_SOCKET_TRX */
4349 u8 cmd_idx;
4350 u8 len;
4351
4352 cmd_idx = info->cid;
4353
4354 if (info->len > buf_len - 2) {
4355 rtw_warn_on(1);
4356 len = buf_len - 2;
4357 } else
4358 len = info->len;
4359
4360 /* #define DBG_PROC_SET_BTINFO_EVT */
4361 #ifdef DBG_PROC_SET_BTINFO_EVT
4362 #ifdef CONFIG_BT_COEXIST_SOCKET_TRX
4363 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"
4364 , __func__, buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7]);
4365 #else/* !CONFIG_BT_COEXIST_SOCKET_TRX */
4366 btinfo_evt_dump(RTW_DBGDUMP, info);
4367 #endif /* CONFIG_BT_COEXIST_SOCKET_TRX */
4368 #endif /* DBG_PROC_SET_BTINFO_EVT */
4369
4370 /* transform BT-FW btinfo to WiFI-FW C2H format and notify */
4371 if (cmd_idx == BTINFO_WIFI_FETCH)
4372 buf[1] = 0;
4373 else if (cmd_idx == BTINFO_BT_AUTO_RPT)
4374 buf[1] = 2;
4375 #ifdef CONFIG_BT_COEXIST_SOCKET_TRX
4376 else if (0x01 == cmd_idx || 0x02 == cmd_idx)
4377 buf[1] = buf[0];
4378 #endif /* CONFIG_BT_COEXIST_SOCKET_TRX */
4379 rtw_btcoex_BtInfoNotify(adapter , len + 1, &buf[1]);
4380 }
4381
rtw_btinfo_cmd(_adapter * adapter,u8 * buf,u16 len)4382 u8 rtw_btinfo_cmd(_adapter *adapter, u8 *buf, u16 len)
4383 {
4384 struct cmd_obj *ph2c;
4385 struct drvextra_cmd_parm *pdrvextra_cmd_parm;
4386 u8 *btinfo;
4387 struct cmd_priv *pcmdpriv = &adapter->cmdpriv;
4388 u8 res = _SUCCESS;
4389
4390 ph2c = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
4391 if (ph2c == NULL) {
4392 res = _FAIL;
4393 goto exit;
4394 }
4395
4396 pdrvextra_cmd_parm = (struct drvextra_cmd_parm *)rtw_zmalloc(sizeof(struct drvextra_cmd_parm));
4397 if (pdrvextra_cmd_parm == NULL) {
4398 rtw_mfree((u8 *)ph2c, sizeof(struct cmd_obj));
4399 res = _FAIL;
4400 goto exit;
4401 }
4402
4403 btinfo = rtw_zmalloc(len);
4404 if (btinfo == NULL) {
4405 rtw_mfree((u8 *)ph2c, sizeof(struct cmd_obj));
4406 rtw_mfree((u8 *)pdrvextra_cmd_parm, sizeof(struct drvextra_cmd_parm));
4407 res = _FAIL;
4408 goto exit;
4409 }
4410
4411 pdrvextra_cmd_parm->ec_id = BTINFO_WK_CID;
4412 pdrvextra_cmd_parm->type = 0;
4413 pdrvextra_cmd_parm->size = len;
4414 pdrvextra_cmd_parm->pbuf = btinfo;
4415
4416 _rtw_memcpy(btinfo, buf, len);
4417
4418 init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, CMD_SET_DRV_EXTRA);
4419
4420 res = rtw_enqueue_cmd(pcmdpriv, ph2c);
4421
4422 exit:
4423 return res;
4424 }
4425
rtw_btc_reduce_wl_txpwr_hdl(_adapter * adapter,u32 pwr_lvl)4426 static void rtw_btc_reduce_wl_txpwr_hdl(_adapter *adapter, u32 pwr_lvl)
4427 {
4428 rtw_btcoex_set_reduced_wl_pwr_lvl(adapter, pwr_lvl);
4429 rtw_btcoex_do_reduce_wl_pwr_lvl(adapter);
4430
4431 RTW_INFO(FUNC_ADPT_FMT ": BTC reduce WL TxPwr %d dB!\n",
4432 FUNC_ADPT_ARG(adapter), pwr_lvl);
4433 }
4434
rtw_btc_reduce_wl_txpwr_cmd(_adapter * adapter,u32 val)4435 u8 rtw_btc_reduce_wl_txpwr_cmd(_adapter *adapter, u32 val)
4436 {
4437 struct cmd_obj *pcmdobj;
4438 struct drvextra_cmd_parm *pdrvextra_cmd_parm;
4439 struct cmd_priv *pcmdpriv = &adapter->cmdpriv;
4440 u8 res = _SUCCESS;
4441
4442 pcmdobj = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
4443 if (pcmdobj == NULL) {
4444 res = _FAIL;
4445 goto exit;
4446 }
4447
4448 pdrvextra_cmd_parm = (struct drvextra_cmd_parm *)rtw_zmalloc(sizeof(struct drvextra_cmd_parm));
4449 if (pdrvextra_cmd_parm == NULL) {
4450 rtw_mfree((u8 *)pcmdobj, sizeof(struct cmd_obj));
4451 res = _FAIL;
4452 goto exit;
4453 }
4454
4455 pdrvextra_cmd_parm->ec_id = BTC_REDUCE_WL_TXPWR_CID;
4456 pdrvextra_cmd_parm->type = val;
4457 pdrvextra_cmd_parm->size = 0;
4458 pdrvextra_cmd_parm->pbuf = NULL;
4459
4460 init_h2fwcmd_w_parm_no_rsp(pcmdobj, pdrvextra_cmd_parm, CMD_SET_DRV_EXTRA);
4461
4462 res = rtw_enqueue_cmd(pcmdpriv, pcmdobj);
4463
4464 exit:
4465 return res;
4466 }
4467 #endif /* CONFIG_BT_COEXIST */
4468
rtw_test_h2c_cmd(_adapter * adapter,u8 * buf,u8 len)4469 u8 rtw_test_h2c_cmd(_adapter *adapter, u8 *buf, u8 len)
4470 {
4471 struct cmd_obj *pcmdobj;
4472 struct drvextra_cmd_parm *pdrvextra_cmd_parm;
4473 u8 *ph2c_content;
4474 struct cmd_priv *pcmdpriv = &adapter->cmdpriv;
4475 u8 res = _SUCCESS;
4476
4477 pcmdobj = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
4478 if (pcmdobj == NULL) {
4479 res = _FAIL;
4480 goto exit;
4481 }
4482
4483 pdrvextra_cmd_parm = (struct drvextra_cmd_parm *)rtw_zmalloc(sizeof(struct drvextra_cmd_parm));
4484 if (pdrvextra_cmd_parm == NULL) {
4485 rtw_mfree((u8 *)pcmdobj, sizeof(struct cmd_obj));
4486 res = _FAIL;
4487 goto exit;
4488 }
4489
4490 ph2c_content = rtw_zmalloc(len);
4491 if (ph2c_content == NULL) {
4492 rtw_mfree((u8 *)pcmdobj, sizeof(struct cmd_obj));
4493 rtw_mfree((u8 *)pdrvextra_cmd_parm, sizeof(struct drvextra_cmd_parm));
4494 res = _FAIL;
4495 goto exit;
4496 }
4497
4498 pdrvextra_cmd_parm->ec_id = TEST_H2C_CID;
4499 pdrvextra_cmd_parm->type = 0;
4500 pdrvextra_cmd_parm->size = len;
4501 pdrvextra_cmd_parm->pbuf = ph2c_content;
4502
4503 _rtw_memcpy(ph2c_content, buf, len);
4504
4505 init_h2fwcmd_w_parm_no_rsp(pcmdobj, pdrvextra_cmd_parm, CMD_SET_DRV_EXTRA);
4506
4507 res = rtw_enqueue_cmd(pcmdpriv, pcmdobj);
4508
4509 exit:
4510 return res;
4511 }
4512
4513 #ifdef CONFIG_MP_INCLUDED
rtw_mp_cmd_hdl(_adapter * padapter,u8 mp_cmd_id)4514 static s32 rtw_mp_cmd_hdl(_adapter *padapter, u8 mp_cmd_id)
4515 {
4516 HAL_DATA_TYPE *pHalData = GET_HAL_DATA(padapter);
4517 int ret = H2C_SUCCESS;
4518 uint status = _SUCCESS;
4519
4520 if (mp_cmd_id == MP_START) {
4521 if (padapter->registrypriv.mp_mode == 0) {
4522 rtw_intf_stop(padapter);
4523 rtw_hal_deinit(padapter);
4524 padapter->registrypriv.mp_mode = 1;
4525 #ifdef CONFIG_BT_COEXIST
4526 padapter->mppriv.CureFuseBTCoex = pHalData->EEPROMBluetoothCoexist;
4527 pHalData->EEPROMBluetoothCoexist = _FALSE;
4528 #endif
4529 #ifdef CONFIG_RF_POWER_TRIM
4530 if (!IS_HARDWARE_TYPE_8814A(padapter) && !IS_HARDWARE_TYPE_8822B(padapter) && !IS_HARDWARE_TYPE_8822C(padapter)) {
4531 padapter->registrypriv.RegPwrTrimEnable = 1;
4532 rtw_hal_read_chip_info(padapter);
4533 }
4534 #endif /*CONFIG_RF_POWER_TRIM*/
4535 rtw_reset_drv_sw(padapter);
4536 #ifdef CONFIG_NEW_NETDEV_HDL
4537 if (!rtw_is_hw_init_completed(padapter)) {
4538 status = rtw_hal_init(padapter);
4539 if (status == _FAIL) {
4540 ret = H2C_REJECTED;
4541 goto exit;
4542 }
4543 rtw_hal_iface_init(padapter);
4544 }
4545 #else
4546 status = rtw_hal_init(padapter);
4547 if (status == _FAIL) {
4548 ret = H2C_REJECTED;
4549 goto exit;
4550 }
4551 #endif /*CONFIG_NEW_NETDEV_HDL*/
4552 #ifndef RTW_HALMAC
4553 rtw_intf_start(padapter);
4554 #endif /* !RTW_HALMAC */
4555 #ifdef RTW_HALMAC /*for New IC*/
4556 MPT_InitializeAdapter(padapter, 1);
4557 #endif /* CONFIG_MP_INCLUDED */
4558 }
4559
4560 if (padapter->registrypriv.mp_mode == 0) {
4561 ret = H2C_REJECTED;
4562 goto exit;
4563 }
4564
4565 if (padapter->mppriv.mode == MP_OFF) {
4566 if (mp_start_test(padapter) == _FAIL) {
4567 ret = H2C_REJECTED;
4568 goto exit;
4569 }
4570 padapter->mppriv.mode = MP_ON;
4571 MPT_PwrCtlDM(padapter, 0);
4572 }
4573 padapter->mppriv.bmac_filter = _FALSE;
4574 #ifdef CONFIG_RTL8723B
4575 #ifdef CONFIG_USB_HCI
4576 rtw_write32(padapter, 0x765, 0x0000);
4577 rtw_write32(padapter, 0x948, 0x0280);
4578 #else
4579 rtw_write32(padapter, 0x765, 0x0000);
4580 rtw_write32(padapter, 0x948, 0x0000);
4581 #endif
4582 #ifdef CONFIG_FOR_RTL8723BS_VQ0
4583 rtw_write32(padapter, 0x765, 0x0000);
4584 rtw_write32(padapter, 0x948, 0x0280);
4585 #endif
4586 rtw_write8(padapter, 0x66, 0x27); /*Open BT uart Log*/
4587 rtw_write8(padapter, 0xc50, 0x20); /*for RX init Gain*/
4588 #endif
4589 odm_write_dig(&pHalData->odmpriv, 0x20);
4590
4591 } else if (mp_cmd_id == MP_STOP) {
4592 if (padapter->registrypriv.mp_mode == 1) {
4593 MPT_DeInitAdapter(padapter);
4594 rtw_intf_stop(padapter);
4595 rtw_hal_deinit(padapter);
4596 padapter->registrypriv.mp_mode = 0;
4597 #ifdef CONFIG_BT_COEXIST
4598 pHalData->EEPROMBluetoothCoexist = padapter->mppriv.CureFuseBTCoex;
4599 #endif
4600 rtw_reset_drv_sw(padapter);
4601 #ifdef CONFIG_NEW_NETDEV_HDL
4602 if (!rtw_is_hw_init_completed(padapter)) {
4603 status = rtw_hal_init(padapter);
4604 if (status == _FAIL) {
4605 ret = H2C_REJECTED;
4606 goto exit;
4607 }
4608 rtw_hal_iface_init(padapter);
4609 }
4610 #else
4611 status = rtw_hal_init(padapter);
4612 if (status == _FAIL) {
4613 ret = H2C_REJECTED;
4614 goto exit;
4615 }
4616 #endif /*CONFIG_NEW_NETDEV_HDL*/
4617 #ifndef RTW_HALMAC
4618 rtw_intf_start(padapter);
4619 #endif /* !RTW_HALMAC */
4620 }
4621
4622 if (padapter->mppriv.mode != MP_OFF) {
4623 mp_stop_test(padapter);
4624 padapter->mppriv.mode = MP_OFF;
4625 }
4626
4627 } else {
4628 RTW_INFO(FUNC_ADPT_FMT"invalid id:%d\n", FUNC_ADPT_ARG(padapter), mp_cmd_id);
4629 ret = H2C_PARAMETERS_ERROR;
4630 rtw_warn_on(1);
4631 }
4632
4633 exit:
4634 return ret;
4635 }
4636
rtw_mp_cmd(_adapter * adapter,u8 mp_cmd_id,u8 flags)4637 u8 rtw_mp_cmd(_adapter *adapter, u8 mp_cmd_id, u8 flags)
4638 {
4639 struct cmd_obj *cmdobj;
4640 struct drvextra_cmd_parm *parm;
4641 struct cmd_priv *pcmdpriv = &adapter->cmdpriv;
4642 struct submit_ctx sctx;
4643 u8 res = _SUCCESS;
4644
4645 parm = (struct drvextra_cmd_parm *)rtw_zmalloc(sizeof(struct drvextra_cmd_parm));
4646 if (parm == NULL) {
4647 res = _FAIL;
4648 goto exit;
4649 }
4650
4651 parm->ec_id = MP_CMD_WK_CID;
4652 parm->type = mp_cmd_id;
4653 parm->size = 0;
4654 parm->pbuf = NULL;
4655
4656 if (flags & RTW_CMDF_DIRECTLY) {
4657 /* no need to enqueue, do the cmd hdl directly and free cmd parameter */
4658 if (H2C_SUCCESS != rtw_mp_cmd_hdl(adapter, mp_cmd_id))
4659 res = _FAIL;
4660 rtw_mfree((u8 *)parm, sizeof(*parm));
4661 } else {
4662 /* need enqueue, prepare cmd_obj and enqueue */
4663 cmdobj = (struct cmd_obj *)rtw_zmalloc(sizeof(*cmdobj));
4664 if (cmdobj == NULL) {
4665 res = _FAIL;
4666 rtw_mfree((u8 *)parm, sizeof(*parm));
4667 goto exit;
4668 }
4669
4670 init_h2fwcmd_w_parm_no_rsp(cmdobj, parm, CMD_SET_DRV_EXTRA);
4671
4672 if (flags & RTW_CMDF_WAIT_ACK) {
4673 cmdobj->sctx = &sctx;
4674 rtw_sctx_init(&sctx, 10 * 1000);
4675 }
4676
4677 res = rtw_enqueue_cmd(pcmdpriv, cmdobj);
4678
4679 if (res == _SUCCESS && (flags & RTW_CMDF_WAIT_ACK)) {
4680 rtw_sctx_wait(&sctx, __func__);
4681 _enter_critical_mutex(&pcmdpriv->sctx_mutex, NULL);
4682 if (sctx.status == RTW_SCTX_SUBMITTED)
4683 cmdobj->sctx = NULL;
4684 _exit_critical_mutex(&pcmdpriv->sctx_mutex, NULL);
4685 if (sctx.status != RTW_SCTX_DONE_SUCCESS)
4686 res = _FAIL;
4687 }
4688 }
4689
4690 exit:
4691 return res;
4692 }
4693 #endif /*CONFIG_MP_INCLUDED*/
4694
4695 #ifdef CONFIG_RTW_CUSTOMER_STR
rtw_customer_str_cmd_hdl(_adapter * adapter,u8 write,const u8 * cstr)4696 static s32 rtw_customer_str_cmd_hdl(_adapter *adapter, u8 write, const u8 *cstr)
4697 {
4698 int ret = H2C_SUCCESS;
4699
4700 if (write)
4701 ret = rtw_hal_h2c_customer_str_write(adapter, cstr);
4702 else
4703 ret = rtw_hal_h2c_customer_str_req(adapter);
4704
4705 return ret == _SUCCESS ? H2C_SUCCESS : H2C_REJECTED;
4706 }
4707
rtw_customer_str_cmd(_adapter * adapter,u8 write,const u8 * cstr)4708 static u8 rtw_customer_str_cmd(_adapter *adapter, u8 write, const u8 *cstr)
4709 {
4710 struct cmd_obj *cmdobj;
4711 struct drvextra_cmd_parm *parm;
4712 u8 *str = NULL;
4713 struct cmd_priv *pcmdpriv = &adapter->cmdpriv;
4714 struct submit_ctx sctx;
4715 u8 res = _SUCCESS;
4716
4717 parm = (struct drvextra_cmd_parm *)rtw_zmalloc(sizeof(struct drvextra_cmd_parm));
4718 if (parm == NULL) {
4719 res = _FAIL;
4720 goto exit;
4721 }
4722
4723 if (write) {
4724 str = rtw_zmalloc(RTW_CUSTOMER_STR_LEN);
4725 if (str == NULL) {
4726 rtw_mfree((u8 *)parm, sizeof(struct drvextra_cmd_parm));
4727 res = _FAIL;
4728 goto exit;
4729 }
4730 }
4731
4732 parm->ec_id = CUSTOMER_STR_WK_CID;
4733 parm->type = write;
4734 parm->size = write ? RTW_CUSTOMER_STR_LEN : 0;
4735 parm->pbuf = write ? str : NULL;
4736
4737 if (write)
4738 _rtw_memcpy(str, cstr, RTW_CUSTOMER_STR_LEN);
4739
4740 /* need enqueue, prepare cmd_obj and enqueue */
4741 cmdobj = (struct cmd_obj *)rtw_zmalloc(sizeof(*cmdobj));
4742 if (cmdobj == NULL) {
4743 res = _FAIL;
4744 rtw_mfree((u8 *)parm, sizeof(*parm));
4745 if (write)
4746 rtw_mfree(str, RTW_CUSTOMER_STR_LEN);
4747 goto exit;
4748 }
4749
4750 init_h2fwcmd_w_parm_no_rsp(cmdobj, parm, CMD_SET_DRV_EXTRA);
4751
4752 cmdobj->sctx = &sctx;
4753 rtw_sctx_init(&sctx, 2 * 1000);
4754
4755 res = rtw_enqueue_cmd(pcmdpriv, cmdobj);
4756
4757 if (res == _SUCCESS) {
4758 rtw_sctx_wait(&sctx, __func__);
4759 _enter_critical_mutex(&pcmdpriv->sctx_mutex, NULL);
4760 if (sctx.status == RTW_SCTX_SUBMITTED)
4761 cmdobj->sctx = NULL;
4762 _exit_critical_mutex(&pcmdpriv->sctx_mutex, NULL);
4763 if (sctx.status != RTW_SCTX_DONE_SUCCESS)
4764 res = _FAIL;
4765 }
4766
4767 exit:
4768 return res;
4769 }
4770
rtw_customer_str_req_cmd(_adapter * adapter)4771 inline u8 rtw_customer_str_req_cmd(_adapter *adapter)
4772 {
4773 return rtw_customer_str_cmd(adapter, 0, NULL);
4774 }
4775
rtw_customer_str_write_cmd(_adapter * adapter,const u8 * cstr)4776 inline u8 rtw_customer_str_write_cmd(_adapter *adapter, const u8 *cstr)
4777 {
4778 return rtw_customer_str_cmd(adapter, 1, cstr);
4779 }
4780 #endif /* CONFIG_RTW_CUSTOMER_STR */
4781
rtw_c2h_wk_cmd(PADAPTER padapter,u8 * pbuf,u16 length,u8 type)4782 u8 rtw_c2h_wk_cmd(PADAPTER padapter, u8 *pbuf, u16 length, u8 type)
4783 {
4784 struct cmd_obj *ph2c;
4785 struct drvextra_cmd_parm *pdrvextra_cmd_parm;
4786 struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
4787 u8 *extra_cmd_buf;
4788 u8 res = _SUCCESS;
4789
4790 ph2c = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
4791 if (ph2c == NULL) {
4792 res = _FAIL;
4793 goto exit;
4794 }
4795
4796 pdrvextra_cmd_parm = (struct drvextra_cmd_parm *)rtw_zmalloc(sizeof(struct drvextra_cmd_parm));
4797 if (pdrvextra_cmd_parm == NULL) {
4798 rtw_mfree((u8 *)ph2c, sizeof(struct cmd_obj));
4799 res = _FAIL;
4800 goto exit;
4801 }
4802
4803 extra_cmd_buf = rtw_zmalloc(length);
4804 if (extra_cmd_buf == NULL) {
4805 rtw_mfree((u8 *)ph2c, sizeof(struct cmd_obj));
4806 rtw_mfree((u8 *)pdrvextra_cmd_parm, sizeof(struct drvextra_cmd_parm));
4807 res = _FAIL;
4808 goto exit;
4809 }
4810
4811 _rtw_memcpy(extra_cmd_buf, pbuf, length);
4812 pdrvextra_cmd_parm->ec_id = C2H_WK_CID;
4813 pdrvextra_cmd_parm->type = type;
4814 pdrvextra_cmd_parm->size = length;
4815 pdrvextra_cmd_parm->pbuf = extra_cmd_buf;
4816
4817 init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, CMD_SET_DRV_EXTRA);
4818
4819 res = rtw_enqueue_cmd(pcmdpriv, ph2c);
4820
4821 exit:
4822 return res;
4823 }
4824
4825 #ifdef CONFIG_FW_C2H_REG
rtw_c2h_reg_wk_cmd(_adapter * adapter,u8 * c2h_evt)4826 inline u8 rtw_c2h_reg_wk_cmd(_adapter *adapter, u8 *c2h_evt)
4827 {
4828 return rtw_c2h_wk_cmd(adapter, c2h_evt, c2h_evt ? C2H_REG_LEN : 0, C2H_TYPE_REG);
4829 }
4830 #endif
4831
4832 #ifdef CONFIG_FW_C2H_PKT
rtw_c2h_packet_wk_cmd(_adapter * adapter,u8 * c2h_evt,u16 length)4833 inline u8 rtw_c2h_packet_wk_cmd(_adapter *adapter, u8 *c2h_evt, u16 length)
4834 {
4835 return rtw_c2h_wk_cmd(adapter, c2h_evt, length, C2H_TYPE_PKT);
4836 }
4837 #endif
4838
_rtw_run_in_thread_cmd(_adapter * adapter,void (* func)(void *),void * context,s32 timeout_ms)4839 static u8 _rtw_run_in_thread_cmd(_adapter *adapter, void (*func)(void *), void *context, s32 timeout_ms)
4840 {
4841 struct cmd_priv *cmdpriv = &adapter->cmdpriv;
4842 struct cmd_obj *cmdobj;
4843 struct RunInThread_param *parm;
4844 struct submit_ctx sctx;
4845 s32 res = _SUCCESS;
4846
4847 cmdobj = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
4848 if (NULL == cmdobj) {
4849 res = _FAIL;
4850 goto exit;
4851 }
4852
4853 parm = (struct RunInThread_param *)rtw_zmalloc(sizeof(struct RunInThread_param));
4854 if (NULL == parm) {
4855 rtw_mfree((u8 *)cmdobj, sizeof(struct cmd_obj));
4856 res = _FAIL;
4857 goto exit;
4858 }
4859
4860 parm->func = func;
4861 parm->context = context;
4862 init_h2fwcmd_w_parm_no_rsp(cmdobj, parm, CMD_RUN_INTHREAD);
4863
4864 if (timeout_ms >= 0) {
4865 cmdobj->sctx = &sctx;
4866 rtw_sctx_init(&sctx, timeout_ms);
4867 }
4868
4869 res = rtw_enqueue_cmd(cmdpriv, cmdobj);
4870
4871 if (res == _SUCCESS && timeout_ms >= 0) {
4872 rtw_sctx_wait(&sctx, __func__);
4873 _enter_critical_mutex(&cmdpriv->sctx_mutex, NULL);
4874 if (sctx.status == RTW_SCTX_SUBMITTED)
4875 cmdobj->sctx = NULL;
4876 _exit_critical_mutex(&cmdpriv->sctx_mutex, NULL);
4877 if (sctx.status != RTW_SCTX_DONE_SUCCESS)
4878 res = _FAIL;
4879 }
4880
4881 exit:
4882 return res;
4883 }
4884
rtw_run_in_thread_cmd(_adapter * adapter,void (* func)(void *),void * context)4885 u8 rtw_run_in_thread_cmd(_adapter *adapter, void (*func)(void *), void *context)
4886 {
4887 return _rtw_run_in_thread_cmd(adapter, func, context, -1);
4888 }
4889
rtw_run_in_thread_cmd_wait(_adapter * adapter,void (* func)(void *),void * context,s32 timeout_ms)4890 u8 rtw_run_in_thread_cmd_wait(_adapter *adapter, void (*func)(void *), void *context, s32 timeout_ms)
4891 {
4892 return _rtw_run_in_thread_cmd(adapter, func, context, timeout_ms);
4893 }
4894
4895 #ifdef CONFIG_FW_C2H_REG
c2h_evt_hdl(_adapter * adapter,u8 * c2h_evt,c2h_id_filter filter)4896 s32 c2h_evt_hdl(_adapter *adapter, u8 *c2h_evt, c2h_id_filter filter)
4897 {
4898 s32 ret = _FAIL;
4899 u8 buf[C2H_REG_LEN] = {0};
4900 u8 id, seq, plen;
4901 u8 *payload;
4902
4903 if (!c2h_evt) {
4904 /* No c2h event in cmd_obj, read c2h event before handling*/
4905 if (rtw_hal_c2h_evt_read(adapter, buf) != _SUCCESS)
4906 goto exit;
4907 c2h_evt = buf;
4908 }
4909
4910 rtw_hal_c2h_reg_hdr_parse(adapter, c2h_evt, &id, &seq, &plen, &payload);
4911
4912 if (filter && filter(adapter, id, seq, plen, payload) == _FALSE)
4913 goto exit;
4914
4915 ret = rtw_hal_c2h_handler(adapter, id, seq, plen, payload);
4916
4917 exit:
4918 return ret;
4919 }
4920 #endif /* CONFIG_FW_C2H_REG */
4921
session_tracker_cmd(_adapter * adapter,u8 cmd,struct sta_info * sta,u8 * local_naddr,u8 * local_port,u8 * remote_naddr,u8 * remote_port)4922 u8 session_tracker_cmd(_adapter *adapter, u8 cmd, struct sta_info *sta, u8 *local_naddr, u8 *local_port, u8 *remote_naddr, u8 *remote_port)
4923 {
4924 struct cmd_priv *cmdpriv = &adapter->cmdpriv;
4925 struct cmd_obj *cmdobj;
4926 struct drvextra_cmd_parm *cmd_parm;
4927 struct st_cmd_parm *st_parm;
4928 u8 res = _SUCCESS;
4929
4930 cmdobj = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
4931 if (cmdobj == NULL) {
4932 res = _FAIL;
4933 goto exit;
4934 }
4935
4936 cmd_parm = (struct drvextra_cmd_parm *)rtw_zmalloc(sizeof(struct drvextra_cmd_parm));
4937 if (cmd_parm == NULL) {
4938 rtw_mfree((u8 *)cmdobj, sizeof(struct cmd_obj));
4939 res = _FAIL;
4940 goto exit;
4941 }
4942
4943 st_parm = (struct st_cmd_parm *)rtw_zmalloc(sizeof(struct st_cmd_parm));
4944 if (st_parm == NULL) {
4945 rtw_mfree((u8 *)cmdobj, sizeof(struct cmd_obj));
4946 rtw_mfree((u8 *)cmd_parm, sizeof(struct drvextra_cmd_parm));
4947 res = _FAIL;
4948 goto exit;
4949 }
4950
4951 st_parm->cmd = cmd;
4952 st_parm->sta = sta;
4953 if (cmd != ST_CMD_CHK) {
4954 _rtw_memcpy(&st_parm->local_naddr, local_naddr, 4);
4955 _rtw_memcpy(&st_parm->local_port, local_port, 2);
4956 _rtw_memcpy(&st_parm->remote_naddr, remote_naddr, 4);
4957 _rtw_memcpy(&st_parm->remote_port, remote_port, 2);
4958 }
4959
4960 cmd_parm->ec_id = SESSION_TRACKER_WK_CID;
4961 cmd_parm->type = 0;
4962 cmd_parm->size = sizeof(struct st_cmd_parm);
4963 cmd_parm->pbuf = (u8 *)st_parm;
4964 init_h2fwcmd_w_parm_no_rsp(cmdobj, cmd_parm, CMD_SET_DRV_EXTRA);
4965 cmdobj->no_io = 1;
4966
4967 res = rtw_enqueue_cmd(cmdpriv, cmdobj);
4968
4969 exit:
4970 return res;
4971 }
4972
session_tracker_chk_cmd(_adapter * adapter,struct sta_info * sta)4973 inline u8 session_tracker_chk_cmd(_adapter *adapter, struct sta_info *sta)
4974 {
4975 return session_tracker_cmd(adapter, ST_CMD_CHK, sta, NULL, NULL, NULL, NULL);
4976 }
4977
session_tracker_add_cmd(_adapter * adapter,struct sta_info * sta,u8 * local_naddr,u8 * local_port,u8 * remote_naddr,u8 * remote_port)4978 inline u8 session_tracker_add_cmd(_adapter *adapter, struct sta_info *sta, u8 *local_naddr, u8 *local_port, u8 *remote_naddr, u8 *remote_port)
4979 {
4980 return session_tracker_cmd(adapter, ST_CMD_ADD, sta, local_naddr, local_port, remote_naddr, remote_port);
4981 }
4982
session_tracker_del_cmd(_adapter * adapter,struct sta_info * sta,u8 * local_naddr,u8 * local_port,u8 * remote_naddr,u8 * remote_port)4983 inline u8 session_tracker_del_cmd(_adapter *adapter, struct sta_info *sta, u8 *local_naddr, u8 *local_port, u8 *remote_naddr, u8 *remote_port)
4984 {
4985 return session_tracker_cmd(adapter, ST_CMD_DEL, sta, local_naddr, local_port, remote_naddr, remote_port);
4986 }
4987
session_tracker_chk_for_sta(_adapter * adapter,struct sta_info * sta)4988 void session_tracker_chk_for_sta(_adapter *adapter, struct sta_info *sta)
4989 {
4990 struct st_ctl_t *st_ctl = &sta->st_ctl;
4991 int i;
4992 _irqL irqL;
4993 _list *plist, *phead, *pnext;
4994 _list dlist;
4995 struct session_tracker *st = NULL;
4996 u8 op_wfd_mode = MIRACAST_DISABLED;
4997
4998 if (DBG_SESSION_TRACKER)
4999 RTW_INFO(FUNC_ADPT_FMT" sta:%p\n", FUNC_ADPT_ARG(adapter), sta);
5000
5001 if (!(sta->state & WIFI_ASOC_STATE))
5002 goto exit;
5003
5004 for (i = 0; i < SESSION_TRACKER_REG_ID_NUM; i++) {
5005 if (st_ctl->reg[i].s_proto != 0)
5006 break;
5007 }
5008 if (i >= SESSION_TRACKER_REG_ID_NUM)
5009 goto chk_sta;
5010
5011 _rtw_init_listhead(&dlist);
5012
5013 _enter_critical_bh(&st_ctl->tracker_q.lock, &irqL);
5014
5015 phead = &st_ctl->tracker_q.queue;
5016 plist = get_next(phead);
5017 pnext = get_next(plist);
5018 while (rtw_end_of_queue_search(phead, plist) == _FALSE) {
5019 st = LIST_CONTAINOR(plist, struct session_tracker, list);
5020 plist = pnext;
5021 pnext = get_next(pnext);
5022
5023 if (st->status != ST_STATUS_ESTABLISH
5024 && rtw_get_passing_time_ms(st->set_time) > ST_EXPIRE_MS
5025 ) {
5026 rtw_list_delete(&st->list);
5027 rtw_list_insert_tail(&st->list, &dlist);
5028 }
5029
5030 /* TODO: check OS for status update */
5031 if (st->status == ST_STATUS_CHECK)
5032 st->status = ST_STATUS_ESTABLISH;
5033
5034 if (st->status != ST_STATUS_ESTABLISH)
5035 continue;
5036
5037 #ifdef CONFIG_WFD
5038 if (0)
5039 RTW_INFO(FUNC_ADPT_FMT" local:%u, remote:%u, rtsp:%u, %u, %u\n", FUNC_ADPT_ARG(adapter)
5040 , ntohs(st->local_port), ntohs(st->remote_port), adapter->wfd_info.rtsp_ctrlport, adapter->wfd_info.tdls_rtsp_ctrlport
5041 , adapter->wfd_info.peer_rtsp_ctrlport);
5042 if (ntohs(st->local_port) == adapter->wfd_info.rtsp_ctrlport)
5043 op_wfd_mode |= MIRACAST_SINK;
5044 if (ntohs(st->local_port) == adapter->wfd_info.tdls_rtsp_ctrlport)
5045 op_wfd_mode |= MIRACAST_SINK;
5046 if (ntohs(st->remote_port) == adapter->wfd_info.peer_rtsp_ctrlport)
5047 op_wfd_mode |= MIRACAST_SOURCE;
5048 #endif
5049 }
5050
5051 _exit_critical_bh(&st_ctl->tracker_q.lock, &irqL);
5052
5053 plist = get_next(&dlist);
5054 while (rtw_end_of_queue_search(&dlist, plist) == _FALSE) {
5055 st = LIST_CONTAINOR(plist, struct session_tracker, list);
5056 plist = get_next(plist);
5057 rtw_mfree((u8 *)st, sizeof(struct session_tracker));
5058 }
5059
5060 chk_sta:
5061 if (STA_OP_WFD_MODE(sta) != op_wfd_mode) {
5062 STA_SET_OP_WFD_MODE(sta, op_wfd_mode);
5063 rtw_sta_media_status_rpt_cmd(adapter, sta, 1);
5064 }
5065
5066 exit:
5067 return;
5068 }
5069
session_tracker_chk_for_adapter(_adapter * adapter)5070 void session_tracker_chk_for_adapter(_adapter *adapter)
5071 {
5072 struct sta_priv *stapriv = &adapter->stapriv;
5073 struct sta_info *sta;
5074 int i;
5075 _irqL irqL;
5076 _list *plist, *phead;
5077 u8 op_wfd_mode = MIRACAST_DISABLED;
5078
5079 _enter_critical_bh(&stapriv->sta_hash_lock, &irqL);
5080
5081 for (i = 0; i < NUM_STA; i++) {
5082 phead = &(stapriv->sta_hash[i]);
5083 plist = get_next(phead);
5084
5085 while ((rtw_end_of_queue_search(phead, plist)) == _FALSE) {
5086 sta = LIST_CONTAINOR(plist, struct sta_info, hash_list);
5087 plist = get_next(plist);
5088
5089 session_tracker_chk_for_sta(adapter, sta);
5090
5091 op_wfd_mode |= STA_OP_WFD_MODE(sta);
5092 }
5093 }
5094
5095 _exit_critical_bh(&stapriv->sta_hash_lock, &irqL);
5096
5097 #ifdef CONFIG_WFD
5098 adapter->wfd_info.op_wfd_mode = MIRACAST_MODE_REVERSE(op_wfd_mode);
5099 #endif
5100 }
5101
session_tracker_cmd_hdl(_adapter * adapter,struct st_cmd_parm * parm)5102 void session_tracker_cmd_hdl(_adapter *adapter, struct st_cmd_parm *parm)
5103 {
5104 u8 cmd = parm->cmd;
5105 struct sta_info *sta = parm->sta;
5106
5107 if (cmd == ST_CMD_CHK) {
5108 if (sta)
5109 session_tracker_chk_for_sta(adapter, sta);
5110 else
5111 session_tracker_chk_for_adapter(adapter);
5112
5113 goto exit;
5114
5115 } else if (cmd == ST_CMD_ADD || cmd == ST_CMD_DEL) {
5116 struct st_ctl_t *st_ctl;
5117 u32 local_naddr = parm->local_naddr;
5118 u16 local_port = parm->local_port;
5119 u32 remote_naddr = parm->remote_naddr;
5120 u16 remote_port = parm->remote_port;
5121 struct session_tracker *st = NULL;
5122 _irqL irqL;
5123 _list *plist, *phead;
5124 u8 free_st = 0;
5125 u8 alloc_st = 0;
5126
5127 if (DBG_SESSION_TRACKER)
5128 RTW_INFO(FUNC_ADPT_FMT" cmd:%u, sta:%p, local:"IP_FMT":"PORT_FMT", remote:"IP_FMT":"PORT_FMT"\n"
5129 , FUNC_ADPT_ARG(adapter), cmd, sta
5130 , IP_ARG(&local_naddr), PORT_ARG(&local_port)
5131 , IP_ARG(&remote_naddr), PORT_ARG(&remote_port)
5132 );
5133
5134 if (!(sta->state & WIFI_ASOC_STATE))
5135 goto exit;
5136
5137 st_ctl = &sta->st_ctl;
5138
5139 _enter_critical_bh(&st_ctl->tracker_q.lock, &irqL);
5140
5141 phead = &st_ctl->tracker_q.queue;
5142 plist = get_next(phead);
5143 while (rtw_end_of_queue_search(phead, plist) == _FALSE) {
5144 st = LIST_CONTAINOR(plist, struct session_tracker, list);
5145
5146 if (st->local_naddr == local_naddr
5147 && st->local_port == local_port
5148 && st->remote_naddr == remote_naddr
5149 && st->remote_port == remote_port)
5150 break;
5151
5152 plist = get_next(plist);
5153 }
5154
5155 if (rtw_end_of_queue_search(phead, plist) == _TRUE)
5156 st = NULL;
5157
5158 switch (cmd) {
5159 case ST_CMD_DEL:
5160 if (st) {
5161 rtw_list_delete(plist);
5162 free_st = 1;
5163 }
5164 goto unlock;
5165 case ST_CMD_ADD:
5166 if (!st)
5167 alloc_st = 1;
5168 }
5169
5170 unlock:
5171 _exit_critical_bh(&st_ctl->tracker_q.lock, &irqL);
5172
5173 if (free_st) {
5174 rtw_mfree((u8 *)st, sizeof(struct session_tracker));
5175 goto exit;
5176 }
5177
5178 if (alloc_st) {
5179 st = (struct session_tracker *)rtw_zmalloc(sizeof(struct session_tracker));
5180 if (!st)
5181 goto exit;
5182
5183 st->local_naddr = local_naddr;
5184 st->local_port = local_port;
5185 st->remote_naddr = remote_naddr;
5186 st->remote_port = remote_port;
5187 st->set_time = rtw_get_current_time();
5188 st->status = ST_STATUS_CHECK;
5189
5190 _enter_critical_bh(&st_ctl->tracker_q.lock, &irqL);
5191 rtw_list_insert_tail(&st->list, phead);
5192 _exit_critical_bh(&st_ctl->tracker_q.lock, &irqL);
5193 }
5194 }
5195
5196 exit:
5197 return;
5198 }
5199
5200 #if defined(CONFIG_RTW_MESH) && defined(RTW_PER_CMD_SUPPORT_FW)
rtw_req_per_cmd_hdl(_adapter * adapter)5201 static s32 rtw_req_per_cmd_hdl(_adapter *adapter)
5202 {
5203 struct dvobj_priv *dvobj = adapter_to_dvobj(adapter);
5204 struct macid_ctl_t *macid_ctl = dvobj_to_macidctl(dvobj);
5205 struct macid_bmp req_macid_bmp, *macid_bmp;
5206 u8 i, ret = _FAIL;
5207
5208 macid_bmp = &macid_ctl->if_g[adapter->iface_id];
5209 _rtw_memcpy(&req_macid_bmp, macid_bmp, sizeof(struct macid_bmp));
5210
5211 /* Clear none mesh's macid */
5212 for (i = 0; i < macid_ctl->num; i++) {
5213 u8 role;
5214 role = GET_H2CCMD_MSRRPT_PARM_ROLE(&macid_ctl->h2c_msr[i]);
5215 if (role != H2C_MSR_ROLE_MESH)
5216 rtw_macid_map_clr(&req_macid_bmp, i);
5217 }
5218
5219 /* group_macid: always be 0 in NIC, so only pass macid_bitmap.m0
5220 * rpt_type: 0 includes all info in 1, use 0 for now
5221 * macid_bitmap: pass m0 only for NIC
5222 */
5223 ret = rtw_hal_set_req_per_rpt_cmd(adapter, 0, 0, req_macid_bmp.m0);
5224
5225 return ret;
5226 }
5227
rtw_req_per_cmd(_adapter * adapter)5228 u8 rtw_req_per_cmd(_adapter *adapter)
5229 {
5230 struct cmd_obj *cmdobj;
5231 struct drvextra_cmd_parm *parm;
5232 struct cmd_priv *pcmdpriv = &adapter->cmdpriv;
5233 struct submit_ctx sctx;
5234 u8 res = _SUCCESS;
5235
5236 parm = (struct drvextra_cmd_parm *)rtw_zmalloc(sizeof(struct drvextra_cmd_parm));
5237 if (parm == NULL) {
5238 res = _FAIL;
5239 goto exit;
5240 }
5241
5242 parm->ec_id = REQ_PER_CMD_WK_CID;
5243 parm->type = 0;
5244 parm->size = 0;
5245 parm->pbuf = NULL;
5246
5247 cmdobj = (struct cmd_obj *)rtw_zmalloc(sizeof(*cmdobj));
5248 if (cmdobj == NULL) {
5249 res = _FAIL;
5250 rtw_mfree((u8 *)parm, sizeof(*parm));
5251 goto exit;
5252 }
5253
5254 init_h2fwcmd_w_parm_no_rsp(cmdobj, parm, CMD_SET_DRV_EXTRA);
5255
5256 res = rtw_enqueue_cmd(pcmdpriv, cmdobj);
5257
5258 exit:
5259 return res;
5260 }
5261 #endif
5262
5263
rtw_ac_parm_cmd_hdl(_adapter * padapter,u8 * _ac_parm_buf,int ac_type)5264 void rtw_ac_parm_cmd_hdl(_adapter *padapter, u8 *_ac_parm_buf, int ac_type)
5265 {
5266
5267 u32 ac_parm_buf;
5268
5269 _rtw_memcpy(&ac_parm_buf, _ac_parm_buf, sizeof(ac_parm_buf));
5270 switch (ac_type) {
5271 case XMIT_VO_QUEUE:
5272 RTW_INFO(FUNC_NDEV_FMT" AC_VO = 0x%08x\n", FUNC_ADPT_ARG(padapter), (unsigned int) ac_parm_buf);
5273 rtw_hal_set_hwreg(padapter, HW_VAR_AC_PARAM_VO, (u8 *)(&ac_parm_buf));
5274 break;
5275
5276 case XMIT_VI_QUEUE:
5277 RTW_INFO(FUNC_NDEV_FMT" AC_VI = 0x%08x\n", FUNC_ADPT_ARG(padapter), (unsigned int) ac_parm_buf);
5278 rtw_hal_set_hwreg(padapter, HW_VAR_AC_PARAM_VI, (u8 *)(&ac_parm_buf));
5279 break;
5280
5281 case XMIT_BE_QUEUE:
5282 RTW_INFO(FUNC_NDEV_FMT" AC_BE = 0x%08x\n", FUNC_ADPT_ARG(padapter), (unsigned int) ac_parm_buf);
5283 rtw_hal_set_hwreg(padapter, HW_VAR_AC_PARAM_BE, (u8 *)(&ac_parm_buf));
5284 break;
5285
5286 case XMIT_BK_QUEUE:
5287 RTW_INFO(FUNC_NDEV_FMT" AC_BK = 0x%08x\n", FUNC_ADPT_ARG(padapter), (unsigned int) ac_parm_buf);
5288 rtw_hal_set_hwreg(padapter, HW_VAR_AC_PARAM_BK, (u8 *)(&ac_parm_buf));
5289 break;
5290
5291 default:
5292 break;
5293 }
5294
5295 }
5296
5297
rtw_drvextra_cmd_hdl(_adapter * padapter,unsigned char * pbuf)5298 u8 rtw_drvextra_cmd_hdl(_adapter *padapter, unsigned char *pbuf)
5299 {
5300 int ret = H2C_SUCCESS;
5301 struct drvextra_cmd_parm *pdrvextra_cmd;
5302
5303 if (!pbuf)
5304 return H2C_PARAMETERS_ERROR;
5305
5306 pdrvextra_cmd = (struct drvextra_cmd_parm *)pbuf;
5307
5308 switch (pdrvextra_cmd->ec_id) {
5309 case STA_MSTATUS_RPT_WK_CID:
5310 rtw_sta_media_status_rpt_cmd_hdl(padapter, (struct sta_media_status_rpt_cmd_parm *)pdrvextra_cmd->pbuf);
5311 break;
5312
5313 case DYNAMIC_CHK_WK_CID:/*only primary padapter go to this cmd, but execute dynamic_chk_wk_hdl() for two interfaces */
5314 rtw_dynamic_chk_wk_hdl(padapter);
5315 break;
5316 case POWER_SAVING_CTRL_WK_CID:
5317 power_saving_wk_hdl(padapter);
5318 break;
5319 #ifdef CONFIG_LPS
5320 case LPS_CTRL_WK_CID:
5321 lps_ctrl_wk_hdl(padapter, (u8)pdrvextra_cmd->type, pdrvextra_cmd->pbuf);
5322 break;
5323 case DM_IN_LPS_WK_CID:
5324 rtw_dm_in_lps_hdl(padapter);
5325 break;
5326 case LPS_CHANGE_DTIM_CID:
5327 rtw_lps_change_dtim_hdl(padapter, (u8)pdrvextra_cmd->type);
5328 break;
5329 #endif
5330 #if (RATE_ADAPTIVE_SUPPORT == 1)
5331 case RTP_TIMER_CFG_WK_CID:
5332 rpt_timer_setting_wk_hdl(padapter, pdrvextra_cmd->type);
5333 break;
5334 #endif
5335 #ifdef CONFIG_ANTENNA_DIVERSITY
5336 case ANT_SELECT_WK_CID:
5337 antenna_select_wk_hdl(padapter, pdrvextra_cmd->type);
5338 break;
5339 #endif
5340 #ifdef CONFIG_P2P_PS
5341 case P2P_PS_WK_CID:
5342 p2p_ps_wk_hdl(padapter, pdrvextra_cmd->type);
5343 break;
5344 #endif
5345 #ifdef CONFIG_P2P
5346 case P2P_PROTO_WK_CID:
5347 /*
5348 * Commented by Albert 2011/07/01
5349 * I used the type_size as the type command
5350 */
5351 ret = p2p_protocol_wk_hdl(padapter, pdrvextra_cmd->type, pdrvextra_cmd->pbuf);
5352 break;
5353 #endif
5354 #ifdef CONFIG_AP_MODE
5355 case CHECK_HIQ_WK_CID:
5356 rtw_chk_hi_queue_hdl(padapter);
5357 break;
5358 #endif
5359 /* add for CONFIG_IEEE80211W, none 11w can use it */
5360 case RESET_SECURITYPRIV:
5361 reset_securitypriv_hdl(padapter);
5362 break;
5363 case FREE_ASSOC_RESOURCES:
5364 free_assoc_resources_hdl(padapter, (u8)pdrvextra_cmd->type);
5365 break;
5366 case C2H_WK_CID:
5367 switch (pdrvextra_cmd->type) {
5368 #ifdef CONFIG_FW_C2H_REG
5369 case C2H_TYPE_REG:
5370 c2h_evt_hdl(padapter, pdrvextra_cmd->pbuf, NULL);
5371 break;
5372 #endif
5373 #ifdef CONFIG_FW_C2H_PKT
5374 case C2H_TYPE_PKT:
5375 rtw_hal_c2h_pkt_hdl(padapter, pdrvextra_cmd->pbuf, pdrvextra_cmd->size);
5376 break;
5377 #endif
5378 default:
5379 RTW_ERR("unknown C2H type:%d\n", pdrvextra_cmd->type);
5380 rtw_warn_on(1);
5381 break;
5382 }
5383 break;
5384 #ifdef CONFIG_BEAMFORMING
5385 case BEAMFORMING_WK_CID:
5386 beamforming_wk_hdl(padapter, pdrvextra_cmd->type, pdrvextra_cmd->pbuf);
5387 break;
5388 #endif
5389 case DM_RA_MSK_WK_CID:
5390 rtw_dm_ra_mask_hdl(padapter, (struct sta_info *)pdrvextra_cmd->pbuf);
5391 break;
5392 #ifdef CONFIG_BT_COEXIST
5393 case BTINFO_WK_CID:
5394 rtw_btinfo_hdl(padapter, pdrvextra_cmd->pbuf, pdrvextra_cmd->size);
5395 break;
5396 case BTC_REDUCE_WL_TXPWR_CID:
5397 rtw_btc_reduce_wl_txpwr_hdl(padapter, pdrvextra_cmd->type);
5398 break;
5399 #endif
5400 #ifdef CONFIG_DFS_MASTER
5401 case DFS_RADAR_DETECT_WK_CID:
5402 rtw_dfs_rd_hdl(padapter);
5403 break;
5404 case DFS_RADAR_DETECT_EN_DEC_WK_CID:
5405 rtw_dfs_rd_en_decision(padapter, MLME_ACTION_NONE, 0);
5406 break;
5407 #endif
5408 case SESSION_TRACKER_WK_CID:
5409 session_tracker_cmd_hdl(padapter, (struct st_cmd_parm *)pdrvextra_cmd->pbuf);
5410 break;
5411 case EN_HW_UPDATE_TSF_WK_CID:
5412 rtw_hal_set_hwreg(padapter, HW_VAR_EN_HW_UPDATE_TSF, NULL);
5413 break;
5414 case PERIOD_TSF_UPDATE_END_WK_CID:
5415 rtw_hal_periodic_tsf_update_chk(padapter);
5416 break;
5417 case TEST_H2C_CID:
5418 rtw_hal_fill_h2c_cmd(padapter, pdrvextra_cmd->pbuf[0], pdrvextra_cmd->size - 1, &pdrvextra_cmd->pbuf[1]);
5419 break;
5420 case MP_CMD_WK_CID:
5421 #ifdef CONFIG_MP_INCLUDED
5422 ret = rtw_mp_cmd_hdl(padapter, pdrvextra_cmd->type);
5423 #endif
5424 break;
5425 #ifdef CONFIG_RTW_CUSTOMER_STR
5426 case CUSTOMER_STR_WK_CID:
5427 ret = rtw_customer_str_cmd_hdl(padapter, pdrvextra_cmd->type, pdrvextra_cmd->pbuf);
5428 break;
5429 #endif
5430
5431 #ifdef CONFIG_RTW_REPEATER_SON
5432 case RSON_SCAN_WK_CID:
5433 rtw_rson_scan_cmd_hdl(padapter, pdrvextra_cmd->type);
5434 break;
5435 #endif
5436
5437 #ifdef CONFIG_IOCTL_CFG80211
5438 case MGNT_TX_WK_CID:
5439 ret = rtw_mgnt_tx_handler(padapter, pdrvextra_cmd->pbuf);
5440 break;
5441 #endif /* CONFIG_IOCTL_CFG80211 */
5442
5443 #if (defined(CONFIG_P2P) && defined(CONFIG_CONCURRENT_MODE)) || defined(CONFIG_IOCTL_CFG80211)
5444 case ROCH_WK_CID:
5445 ret = rtw_roch_wk_hdl(padapter, pdrvextra_cmd->type, pdrvextra_cmd->pbuf);
5446 break;
5447 #endif /* (defined(CONFIG_P2P) && defined(CONFIG_CONCURRENT_MODE)) || defined(CONFIG_IOCTL_CFG80211) */
5448
5449 #ifdef CONFIG_MCC_MODE
5450 case MCC_CMD_WK_CID:
5451 ret = rtw_mcc_cmd_hdl(padapter, pdrvextra_cmd->type, pdrvextra_cmd->pbuf);
5452 break;
5453 #endif /* CONFIG_MCC_MODE */
5454 #if defined(CONFIG_RTW_MESH) && defined(RTW_PER_CMD_SUPPORT_FW)
5455 case REQ_PER_CMD_WK_CID:
5456 ret = rtw_req_per_cmd_hdl(padapter);
5457 break;
5458 #endif
5459 #ifdef CONFIG_SUPPORT_STATIC_SMPS
5460 case SSMPS_WK_CID :
5461 rtw_ssmps_wk_hdl(padapter, (struct ssmps_cmd_parm *)pdrvextra_cmd->pbuf);
5462 break;
5463 #endif
5464 #ifdef CONFIG_CTRL_TXSS_BY_TP
5465 case TXSS_WK_CID :
5466 rtw_ctrl_txss_wk_hdl(padapter, (struct txss_cmd_parm *)pdrvextra_cmd->pbuf);
5467 break;
5468 #endif
5469 case AC_PARM_CMD_WK_CID:
5470 rtw_ac_parm_cmd_hdl(padapter, pdrvextra_cmd->pbuf, pdrvextra_cmd->type);
5471 break;
5472 #ifdef CONFIG_AP_MODE
5473 case STOP_AP_WK_CID:
5474 stop_ap_hdl(padapter);
5475 break;
5476 #endif
5477 #ifdef CONFIG_RTW_TOKEN_BASED_XMIT
5478 case TBTX_CONTROL_TX_WK_CID:
5479 tx_control_hdl(padapter);
5480 break;
5481 #endif
5482 default:
5483 break;
5484 }
5485
5486 if (pdrvextra_cmd->pbuf && pdrvextra_cmd->size > 0)
5487 rtw_mfree(pdrvextra_cmd->pbuf, pdrvextra_cmd->size);
5488
5489 return ret;
5490 }
5491
rtw_survey_cmd_callback(_adapter * padapter,struct cmd_obj * pcmd)5492 void rtw_survey_cmd_callback(_adapter *padapter , struct cmd_obj *pcmd)
5493 {
5494 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
5495
5496
5497 if (pcmd->res == H2C_DROPPED) {
5498 /* TODO: cancel timer and do timeout handler directly... */
5499 /* need to make timeout handlerOS independent */
5500 mlme_set_scan_to_timer(pmlmepriv, 1);
5501 } else if (pcmd->res != H2C_SUCCESS) {
5502 mlme_set_scan_to_timer(pmlmepriv, 1);
5503 }
5504
5505 /* free cmd */
5506 rtw_free_cmd_obj(pcmd);
5507
5508 }
rtw_disassoc_cmd_callback(_adapter * padapter,struct cmd_obj * pcmd)5509 void rtw_disassoc_cmd_callback(_adapter *padapter, struct cmd_obj *pcmd)
5510 {
5511 _irqL irqL;
5512 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
5513
5514
5515 if (pcmd->res != H2C_SUCCESS) {
5516 _enter_critical_bh(&pmlmepriv->lock, &irqL);
5517 set_fwstate(pmlmepriv, WIFI_ASOC_STATE);
5518 _exit_critical_bh(&pmlmepriv->lock, &irqL);
5519 goto exit;
5520 }
5521 #ifdef CONFIG_BR_EXT
5522 else /* clear bridge database */
5523 nat25_db_cleanup(padapter);
5524 #endif /* CONFIG_BR_EXT */
5525
5526 /* free cmd */
5527 rtw_free_cmd_obj(pcmd);
5528
5529 exit:
5530 return;
5531 }
5532
rtw_joinbss_cmd_callback(_adapter * padapter,struct cmd_obj * pcmd)5533 void rtw_joinbss_cmd_callback(_adapter *padapter, struct cmd_obj *pcmd)
5534 {
5535 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
5536
5537
5538 if (pcmd->res == H2C_DROPPED) {
5539 /* TODO: cancel timer and do timeout handler directly... */
5540 /* need to make timeout handlerOS independent */
5541 _set_timer(&pmlmepriv->assoc_timer, 1);
5542 } else if (pcmd->res != H2C_SUCCESS)
5543 _set_timer(&pmlmepriv->assoc_timer, 1);
5544
5545 rtw_free_cmd_obj(pcmd);
5546
5547 }
5548
rtw_create_ibss_post_hdl(_adapter * padapter,int status)5549 void rtw_create_ibss_post_hdl(_adapter *padapter, int status)
5550 {
5551 _irqL irqL;
5552 struct wlan_network *pwlan = NULL;
5553 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
5554 WLAN_BSSID_EX *pdev_network = &padapter->registrypriv.dev_network;
5555 struct wlan_network *mlme_cur_network = &(pmlmepriv->cur_network);
5556
5557 if (status != H2C_SUCCESS)
5558 _set_timer(&pmlmepriv->assoc_timer, 1);
5559
5560 _cancel_timer_ex(&pmlmepriv->assoc_timer);
5561
5562 _enter_critical_bh(&pmlmepriv->lock, &irqL);
5563
5564 {
5565 _irqL irqL;
5566
5567 pwlan = _rtw_alloc_network(pmlmepriv);
5568 _enter_critical_bh(&(pmlmepriv->scanned_queue.lock), &irqL);
5569 if (pwlan == NULL) {
5570 pwlan = rtw_get_oldest_wlan_network(&pmlmepriv->scanned_queue);
5571 if (pwlan == NULL) {
5572 _exit_critical_bh(&(pmlmepriv->scanned_queue.lock), &irqL);
5573 goto createbss_cmd_fail;
5574 }
5575 pwlan->last_scanned = rtw_get_current_time();
5576 } else
5577 rtw_list_insert_tail(&(pwlan->list), &pmlmepriv->scanned_queue.queue);
5578
5579 pdev_network->Length = get_WLAN_BSSID_EX_sz(pdev_network);
5580 _rtw_memcpy(&(pwlan->network), pdev_network, pdev_network->Length);
5581 /* pwlan->fixed = _TRUE; */
5582
5583 /* copy pdev_network information to pmlmepriv->cur_network */
5584 _rtw_memcpy(&mlme_cur_network->network, pdev_network, (get_WLAN_BSSID_EX_sz(pdev_network)));
5585
5586 #if 0
5587 /* reset DSConfig */
5588 mlme_cur_network->network.Configuration.DSConfig = (u32)rtw_ch2freq(pdev_network->Configuration.DSConfig);
5589 #endif
5590
5591 _clr_fwstate_(pmlmepriv, WIFI_UNDER_LINKING);
5592 _exit_critical_bh(&(pmlmepriv->scanned_queue.lock), &irqL);
5593 /* we will set WIFI_ASOC_STATE when there is one more sat to join us (rtw_stassoc_event_callback) */
5594 }
5595
5596 createbss_cmd_fail:
5597 _exit_critical_bh(&pmlmepriv->lock, &irqL);
5598 return;
5599 }
5600
5601
5602
rtw_setstaKey_cmdrsp_callback(_adapter * padapter,struct cmd_obj * pcmd)5603 void rtw_setstaKey_cmdrsp_callback(_adapter *padapter , struct cmd_obj *pcmd)
5604 {
5605
5606 struct sta_priv *pstapriv = &padapter->stapriv;
5607 struct set_stakey_rsp *psetstakey_rsp = (struct set_stakey_rsp *)(pcmd->rsp);
5608 struct sta_info *psta = rtw_get_stainfo(pstapriv, psetstakey_rsp->addr);
5609
5610
5611 if (psta == NULL) {
5612 goto exit;
5613 }
5614
5615 /* psta->cmn.aid = psta->cmn.mac_id = psetstakey_rsp->keyid; */ /* CAM_ID(CAM_ENTRY) */
5616
5617 exit:
5618
5619 rtw_free_cmd_obj(pcmd);
5620
5621
5622 }
5623
rtw_getrttbl_cmd_cmdrsp_callback(_adapter * padapter,struct cmd_obj * pcmd)5624 void rtw_getrttbl_cmd_cmdrsp_callback(_adapter *padapter, struct cmd_obj *pcmd)
5625 {
5626
5627 rtw_free_cmd_obj(pcmd);
5628 #ifdef CONFIG_MP_INCLUDED
5629 if (padapter->registrypriv.mp_mode == 1)
5630 padapter->mppriv.workparam.bcompleted = _TRUE;
5631 #endif
5632
5633
5634 }
5635
set_txq_params_cmd(_adapter * adapter,u32 ac_parm,u8 ac_type)5636 u8 set_txq_params_cmd(_adapter *adapter, u32 ac_parm, u8 ac_type)
5637 {
5638 struct cmd_obj *cmdobj;
5639 struct drvextra_cmd_parm *pdrvextra_cmd_parm;
5640 struct cmd_priv *pcmdpriv = &adapter->cmdpriv;
5641 u8 *ac_parm_buf = NULL;
5642 u8 sz;
5643 u8 res = _SUCCESS;
5644
5645
5646 cmdobj = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
5647 if (cmdobj == NULL) {
5648 res = _FAIL;
5649 goto exit;
5650 }
5651
5652 pdrvextra_cmd_parm = (struct drvextra_cmd_parm *)rtw_zmalloc(sizeof(struct drvextra_cmd_parm));
5653 if (pdrvextra_cmd_parm == NULL) {
5654 rtw_mfree((u8 *)cmdobj, sizeof(struct cmd_obj));
5655 res = _FAIL;
5656 goto exit;
5657 }
5658
5659 sz = sizeof(ac_parm);
5660 ac_parm_buf = rtw_zmalloc(sz);
5661 if (ac_parm_buf == NULL) {
5662 rtw_mfree((u8 *)cmdobj, sizeof(struct cmd_obj));
5663 rtw_mfree((u8 *)pdrvextra_cmd_parm, sizeof(struct drvextra_cmd_parm));
5664 res = _FAIL;
5665 goto exit;
5666 }
5667
5668 pdrvextra_cmd_parm->ec_id = AC_PARM_CMD_WK_CID;
5669 pdrvextra_cmd_parm->type = ac_type;
5670 pdrvextra_cmd_parm->size = sz;
5671 pdrvextra_cmd_parm->pbuf = ac_parm_buf;
5672
5673 _rtw_memcpy(ac_parm_buf, &ac_parm, sz);
5674
5675 init_h2fwcmd_w_parm_no_rsp(cmdobj, pdrvextra_cmd_parm, CMD_SET_DRV_EXTRA);
5676 res = rtw_enqueue_cmd(pcmdpriv, cmdobj);
5677
5678 exit:
5679 return res;
5680 }
5681
5682 /* Driver writes beacon length to REG for FW adjusting beacon receive time */
5683 #ifdef CONFIG_WRITE_BCN_LEN_TO_FW
rtw_write_bcnlen_to_fw_cmd(_adapter * padapter,u16 bcn_len)5684 u8 rtw_write_bcnlen_to_fw_cmd(_adapter *padapter, u16 bcn_len)
5685 {
5686 struct cmd_obj *pcmd;
5687 struct write_bcnlen_param *parm;
5688 struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
5689 u8 res = _SUCCESS;
5690
5691 pcmd = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
5692 if (pcmd == NULL) {
5693 res = _FAIL;
5694 goto exit;
5695 }
5696
5697 parm = (struct write_bcnlen_param *)rtw_zmalloc(sizeof(struct write_bcnlen_param));
5698 if (parm == NULL) {
5699 rtw_mfree((unsigned char *)pcmd, sizeof(struct cmd_obj));
5700 res = _FAIL;
5701 goto exit;
5702 }
5703
5704 parm->bcn_len = bcn_len;
5705 init_h2fwcmd_w_parm_no_rsp(pcmd, parm, CMD_WRITE_BCN_LEN);
5706 res = rtw_enqueue_cmd(pcmdpriv, pcmd);
5707
5708 exit:
5709 return res;
5710 }
5711 #endif /* CONFIG_WRITE_BCN_LEN_TO_FW */
5712