1 /******************************************************************************
2 *
3 * Copyright(c) 2007 - 2021 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
19 #ifndef DBG_CMD_EXECUTE
20 #define DBG_CMD_EXECUTE 0
21 #endif
22
23 /*
24 Caller and the rtw_cmd_thread can protect cmd_q by spin_lock.
25 No irqsave is necessary.
26 */
rtw_init_cmd_priv(struct dvobj_priv * dvobj)27 u32 rtw_init_cmd_priv(struct dvobj_priv *dvobj)
28 {
29 u32 res = _SUCCESS;
30 struct cmd_priv *pcmdpriv = &dvobj->cmdpriv;
31
32 pcmdpriv->dvobj = dvobj;
33 #if 0 /*#ifdef CONFIG_CORE_CMD_THREAD*/
34 _rtw_init_sema(&(pcmdpriv->cmd_queue_sema), 0);
35 _rtw_init_sema(&(pcmdpriv->start_cmdthread_sema), 0);
36 _rtw_init_queue(&(pcmdpriv->cmd_queue));
37 #endif
38
39 /* allocate DMA-able/Non-Page memory for cmd_buf and rsp_buf */
40
41 pcmdpriv->cmd_seq = 1;
42
43 pcmdpriv->cmd_allocated_buf = rtw_zmalloc(MAX_CMDSZ + CMDBUFF_ALIGN_SZ);
44
45 if (pcmdpriv->cmd_allocated_buf == NULL) {
46 res = _FAIL;
47 goto exit;
48 }
49
50 pcmdpriv->cmd_buf = pcmdpriv->cmd_allocated_buf + CMDBUFF_ALIGN_SZ - ((SIZE_PTR)(pcmdpriv->cmd_allocated_buf) & (CMDBUFF_ALIGN_SZ - 1));
51
52 pcmdpriv->rsp_allocated_buf = rtw_zmalloc(MAX_RSPSZ + 4);
53
54 if (pcmdpriv->rsp_allocated_buf == NULL) {
55 res = _FAIL;
56 goto exit;
57 }
58
59 pcmdpriv->rsp_buf = pcmdpriv->rsp_allocated_buf + 4 - ((SIZE_PTR)(pcmdpriv->rsp_allocated_buf) & 3);
60
61 pcmdpriv->cmd_issued_cnt = 0;
62
63 _rtw_mutex_init(&pcmdpriv->sctx_mutex);
64
65 ATOMIC_SET(&pcmdpriv->event_seq, 0);
66 pcmdpriv->evt_done_cnt = 0;
67 exit:
68 return res;
69
70 }
71
rtw_free_cmd_priv(struct dvobj_priv * dvobj)72 void rtw_free_cmd_priv(struct dvobj_priv *dvobj)
73 {
74 struct cmd_priv *pcmdpriv = &dvobj->cmdpriv;
75
76 #if 0 /*#ifdef CONFIG_CORE_CMD_THREAD*/
77 _rtw_spinlock_free(&(pcmdpriv->cmd_queue.lock));
78 _rtw_free_sema(&(pcmdpriv->cmd_queue_sema));
79 _rtw_free_sema(&(pcmdpriv->start_cmdthread_sema));
80 #endif
81 if (pcmdpriv->cmd_allocated_buf)
82 rtw_mfree(pcmdpriv->cmd_allocated_buf, MAX_CMDSZ + CMDBUFF_ALIGN_SZ);
83
84 if (pcmdpriv->rsp_allocated_buf)
85 rtw_mfree(pcmdpriv->rsp_allocated_buf, MAX_RSPSZ + 4);
86
87 _rtw_mutex_free(&pcmdpriv->sctx_mutex);
88 }
89
rtw_cmd_filter(struct cmd_priv * pcmdpriv,struct cmd_obj * cmd_obj)90 static int rtw_cmd_filter(struct cmd_priv *pcmdpriv, struct cmd_obj *cmd_obj)
91 {
92 u8 bAllow = _FALSE; /* set to _TRUE to allow enqueuing cmd when hw_init_completed is _FALSE */
93 struct dvobj_priv *dvobj = pcmdpriv->dvobj;
94
95
96 if (cmd_obj->cmdcode == CMD_SET_CHANPLAN)
97 bAllow = _TRUE;
98
99 if (cmd_obj->no_io)
100 bAllow = _TRUE;
101
102 return _SUCCESS;
103 }
104
105 /*
106 Calling Context:
107
108 rtw_enqueue_cmd can only be called between kernel thread,
109 since only spin_lock is used.
110
111 ISR/Call-Back functions can't call this sub-function.
112
113 */
114 #ifdef DBG_CMD_QUEUE
115 extern u8 dump_cmd_id;
116 #endif
117
118 #if 0 /*#ifdef CONFIG_CORE_CMD_THREAD*/
119 static sint _rtw_enqueue_cmd(_queue *queue, struct cmd_obj *obj, bool to_head)
120 {
121 unsigned long sp_flags;
122
123 if (obj == NULL)
124 goto exit;
125
126 /* _rtw_spinlock_bh(&queue->lock); */
127 _rtw_spinlock_irq(&queue->lock, &sp_flags);
128
129 if (to_head)
130 rtw_list_insert_head(&obj->list, &queue->queue);
131 else
132 rtw_list_insert_tail(&obj->list, &queue->queue);
133
134 #ifdef DBG_CMD_QUEUE
135 if (dump_cmd_id) {
136 RTW_INFO("%s===> cmdcode:0x%02x\n", __FUNCTION__, obj->cmdcode);
137 if (obj->cmdcode == CMD_SET_MLME_EVT) {
138 if (obj->parmbuf) {
139 struct rtw_evt_header *evt_hdr = (struct rtw_evt_header *)(obj->parmbuf);
140 RTW_INFO("evt_hdr->id:%d\n", evt_hdr->id);
141 }
142 }
143 if (obj->cmdcode == CMD_SET_DRV_EXTRA) {
144 if (obj->parmbuf) {
145 struct drvextra_cmd_parm *pdrvextra_cmd_parm = (struct drvextra_cmd_parm *)(obj->parmbuf);
146 RTW_INFO("pdrvextra_cmd_parm->ec_id:0x%02x\n", pdrvextra_cmd_parm->ec_id);
147 }
148 }
149 }
150
151 if (queue->queue.prev->next != &queue->queue) {
152 RTW_INFO("[%d] head %p, tail %p, tail->prev->next %p[tail], tail->next %p[head]\n", __LINE__,
153 &queue->queue, queue->queue.prev, queue->queue.prev->prev->next, queue->queue.prev->next);
154
155 RTW_INFO("==========%s============\n", __FUNCTION__);
156 RTW_INFO("head:%p,obj_addr:%p\n", &queue->queue, obj);
157 RTW_INFO("padapter: %p\n", obj->padapter);
158 RTW_INFO("cmdcode: 0x%02x\n", obj->cmdcode);
159 RTW_INFO("res: %d\n", obj->res);
160 RTW_INFO("parmbuf: %p\n", obj->parmbuf);
161 RTW_INFO("cmdsz: %d\n", obj->cmdsz);
162 RTW_INFO("rsp: %p\n", obj->rsp);
163 RTW_INFO("rspsz: %d\n", obj->rspsz);
164 RTW_INFO("sctx: %p\n", obj->sctx);
165 RTW_INFO("list->next: %p\n", obj->list.next);
166 RTW_INFO("list->prev: %p\n", obj->list.prev);
167 }
168 #endif /* DBG_CMD_QUEUE */
169
170 /* _rtw_spinunlock_bh(&queue->lock); */
171 _rtw_spinunlock_irq(&queue->lock, &sp_flags);
172
173 exit:
174
175
176 return _SUCCESS;
177 }
178 #else
_rtw_enqueue_cmd(struct cmd_obj * obj,bool to_head)179 static sint _rtw_enqueue_cmd(struct cmd_obj *obj, bool to_head)
180 {
181 u32 res;
182
183 res = rtw_enqueue_phl_cmd(obj);
184
185 #ifdef DBG_CMD_QUEUE
186 if (dump_cmd_id) {
187 RTW_INFO("%s===> cmdcode:0x%02x\n", __FUNCTION__, obj->cmdcode);
188 if (obj->cmdcode == CMD_SET_MLME_EVT) {
189 if (obj->parmbuf) {
190 struct rtw_evt_header *evt_hdr = (struct rtw_evt_header *)(obj->parmbuf);
191 RTW_INFO("evt_hdr->id:%d\n", evt_hdr->id);
192 }
193 }
194 if (obj->cmdcode == CMD_SET_DRV_EXTRA) {
195 if (obj->parmbuf) {
196 struct drvextra_cmd_parm *pdrvextra_cmd_parm = (struct drvextra_cmd_parm *)(obj->parmbuf);
197 RTW_INFO("pdrvextra_cmd_parm->ec_id:0x%02x\n", pdrvextra_cmd_parm->ec_id);
198 }
199 }
200 }
201 #endif /* DBG_CMD_QUEUE */
202 return res;
203 }
204 #endif
205
rtw_enqueue_cmd(struct cmd_priv * pcmdpriv,struct cmd_obj * cmd_obj)206 u32 rtw_enqueue_cmd(struct cmd_priv *pcmdpriv, struct cmd_obj *cmd_obj)
207 {
208 int res = _FAIL;
209
210 if (cmd_obj == NULL)
211 goto exit;
212
213 res = rtw_cmd_filter(pcmdpriv, cmd_obj);
214 if ((_FAIL == res) || (cmd_obj->cmdsz > MAX_CMDSZ)) {
215 if (cmd_obj->cmdsz > MAX_CMDSZ) {
216 RTW_INFO("%s failed due to obj->cmdsz(%d) > MAX_CMDSZ(%d)\n", __func__, cmd_obj->cmdsz, MAX_CMDSZ);
217 rtw_warn_on(1);
218 }
219
220 if (cmd_obj->cmdcode == CMD_SET_DRV_EXTRA) {
221 struct drvextra_cmd_parm *extra_parm = (struct drvextra_cmd_parm *)cmd_obj->parmbuf;
222
223 if (extra_parm->pbuf && extra_parm->size > 0)
224 rtw_mfree(extra_parm->pbuf, extra_parm->size);
225 }
226 rtw_free_cmd_obj(cmd_obj);
227 goto exit;
228 }
229
230
231 res = _rtw_enqueue_cmd(cmd_obj, 0);
232 #if 0 /*#ifdef CONFIG_CORE_CMD_THREAD*/
233 if (res == _SUCCESS)
234 _rtw_up_sema(&pcmdpriv->cmd_queue_sema);
235 #endif
236
237 exit:
238 return res;
239 }
240
241 #if 0 /*#ifdef CONFIG_CORE_CMD_THREAD*/
242 struct cmd_obj *_rtw_dequeue_cmd(_queue *queue)
243 {
244 struct cmd_obj *obj;
245 unsigned long sp_flags;
246
247 /* _rtw_spinlock_bh(&(queue->lock)); */
248 _rtw_spinlock_irq(&queue->lock, &sp_flags);
249
250 #ifdef DBG_CMD_QUEUE
251 if (queue->queue.prev->next != &queue->queue) {
252 RTW_INFO("[%d] head %p, tail %p, tail->prev->next %p[tail], tail->next %p[head]\n", __LINE__,
253 &queue->queue, queue->queue.prev, queue->queue.prev->prev->next, queue->queue.prev->next);
254 }
255 #endif /* DBG_CMD_QUEUE */
256
257
258 if (rtw_is_list_empty(&(queue->queue)))
259 obj = NULL;
260 else {
261 obj = LIST_CONTAINOR(get_next(&(queue->queue)), struct cmd_obj, list);
262
263 #ifdef DBG_CMD_QUEUE
264 if (queue->queue.prev->next != &queue->queue) {
265 RTW_INFO("==========%s============\n", __FUNCTION__);
266 RTW_INFO("head:%p,obj_addr:%p\n", &queue->queue, obj);
267 RTW_INFO("padapter: %p\n", obj->padapter);
268 RTW_INFO("cmdcode: 0x%02x\n", obj->cmdcode);
269 RTW_INFO("res: %d\n", obj->res);
270 RTW_INFO("parmbuf: %p\n", obj->parmbuf);
271 RTW_INFO("cmdsz: %d\n", obj->cmdsz);
272 RTW_INFO("rsp: %p\n", obj->rsp);
273 RTW_INFO("rspsz: %d\n", obj->rspsz);
274 RTW_INFO("sctx: %p\n", obj->sctx);
275 RTW_INFO("list->next: %p\n", obj->list.next);
276 RTW_INFO("list->prev: %p\n", obj->list.prev);
277 }
278
279 if (dump_cmd_id) {
280 RTW_INFO("%s===> cmdcode:0x%02x\n", __FUNCTION__, obj->cmdcode);
281 if (obj->cmdcode == CMD_SET_DRV_EXTRA) {
282 if (obj->parmbuf) {
283 struct drvextra_cmd_parm *pdrvextra_cmd_parm = (struct drvextra_cmd_parm *)(obj->parmbuf);
284 printk("pdrvextra_cmd_parm->ec_id:0x%02x\n", pdrvextra_cmd_parm->ec_id);
285 }
286 }
287
288 }
289 #endif /* DBG_CMD_QUEUE */
290
291 rtw_list_delete(&obj->list);
292 }
293
294 /* _rtw_spinunlock_bh(&(queue->lock)); */
295 _rtw_spinunlock_irq(&queue->lock, &sp_flags);
296
297
298 return obj;
299 }
300
301 struct cmd_obj *rtw_dequeue_cmd(struct cmd_priv *pcmdpriv)
302 {
303 struct cmd_obj *cmd_obj;
304
305 cmd_obj = _rtw_dequeue_cmd(&pcmdpriv->cmd_queue);
306
307 return cmd_obj;
308 }
309 #endif
rtw_free_cmd_obj(struct cmd_obj * pcmd)310 void rtw_free_cmd_obj(struct cmd_obj *pcmd)
311 {
312 if (pcmd->parmbuf != NULL) {
313 /* free parmbuf in cmd_obj */
314 rtw_mfree((unsigned char *)pcmd->parmbuf, pcmd->cmdsz);
315 }
316 if (pcmd->rsp != NULL) {
317 if (pcmd->rspsz != 0) {
318 /* free rsp in cmd_obj */
319 rtw_mfree((unsigned char *)pcmd->rsp, pcmd->rspsz);
320 }
321 }
322
323 /* free cmd_obj */
324 rtw_mfree((unsigned char *)pcmd, sizeof(struct cmd_obj));
325 }
rtw_run_cmd(_adapter * padapter,struct cmd_obj * pcmd,bool discard)326 void rtw_run_cmd(_adapter *padapter, struct cmd_obj *pcmd, bool discard)
327 {
328 u8 ret;
329 u8 *pcmdbuf;
330 systime cmd_start_time;
331 u32 cmd_process_time;
332 u8(*cmd_hdl)(_adapter *padapter, u8 *pbuf);
333 void (*pcmd_callback)(_adapter *dev, struct cmd_obj *pcmd);
334 struct cmd_priv *pcmdpriv = &(adapter_to_dvobj(padapter)->cmdpriv);
335 struct drvextra_cmd_parm *extra_parm = NULL;
336
337 cmd_start_time = rtw_get_current_time();
338 pcmdpriv->cmd_issued_cnt++;
339
340 if (discard)
341 goto post_process;
342
343 if (pcmd->cmdsz > MAX_CMDSZ) {
344 RTW_ERR("%s cmdsz:%d > MAX_CMDSZ:%d\n", __func__, pcmd->cmdsz, MAX_CMDSZ);
345 pcmd->res = H2C_PARAMETERS_ERROR;
346 goto post_process;
347 }
348
349 if (pcmd->cmdcode >= (sizeof(wlancmds) / sizeof(struct rtw_cmd))) {
350 RTW_ERR("%s undefined cmdcode:%d\n", __func__, pcmd->cmdcode);
351 pcmd->res = H2C_PARAMETERS_ERROR;
352 goto post_process;
353 }
354
355 cmd_hdl = wlancmds[pcmd->cmdcode].cmd_hdl;
356 if (!cmd_hdl) {
357 RTW_ERR("%s no cmd_hdl for cmdcode:%d\n", __func__, pcmd->cmdcode);
358 pcmd->res = H2C_PARAMETERS_ERROR;
359 goto post_process;
360 }
361
362 if (DBG_CMD_EXECUTE)
363 RTW_INFO(ADPT_FMT" "CMD_FMT" %sexecute\n", ADPT_ARG(pcmd->padapter), CMD_ARG(pcmd)
364 , pcmd->res == H2C_ENQ_HEAD ? "ENQ_HEAD " : (pcmd->res == H2C_ENQ_HEAD_FAIL ? "ENQ_HEAD_FAIL " : ""));
365
366 pcmdbuf = pcmdpriv->cmd_buf;
367 _rtw_memcpy(pcmdbuf, pcmd->parmbuf, pcmd->cmdsz);
368 ret = cmd_hdl(pcmd->padapter, pcmdbuf);
369 pcmd->res = ret;
370
371 pcmdpriv->cmd_seq++;
372
373 post_process:
374
375 _rtw_mutex_lock_interruptible(&pcmdpriv->sctx_mutex);
376 if (pcmd->sctx) {
377 if (0)
378 RTW_PRINT(FUNC_ADPT_FMT" pcmd->sctx\n", FUNC_ADPT_ARG(pcmd->padapter));
379 if (pcmd->res == H2C_SUCCESS)
380 rtw_sctx_done(&pcmd->sctx);
381 else
382 rtw_sctx_done_err(&pcmd->sctx, RTW_SCTX_DONE_CMD_ERROR);
383 }
384 _rtw_mutex_unlock(&pcmdpriv->sctx_mutex);
385
386 cmd_process_time = rtw_get_passing_time_ms(cmd_start_time);
387 if (cmd_process_time > 1000) {
388 RTW_INFO(ADPT_FMT" "CMD_FMT" process_time=%d\n", ADPT_ARG(pcmd->padapter), CMD_ARG(pcmd), cmd_process_time);
389 if (0)
390 rtw_warn_on(1);
391 }
392
393 /* call callback function for post-processed */
394 if (pcmd->cmdcode >= (sizeof(wlancmds) / sizeof(struct rtw_cmd)))
395 pcmd_callback = wlancmds[pcmd->cmdcode].callback;
396 else
397 pcmd_callback = NULL;
398
399 if (pcmd_callback == NULL) {
400 rtw_free_cmd_obj(pcmd);
401 } else {
402 /* todo: !!! fill rsp_buf to pcmd->rsp if (pcmd->rsp!=NULL) */
403 pcmd_callback(pcmd->padapter, pcmd);/* need conider that free cmd_obj in rtw_cmd_callback */
404 }
405 }
406 #if 0 /*#ifdef CONFIG_CORE_CMD_THREAD*/
407 void rtw_stop_cmd_thread(_adapter *adapter)
408 {
409 if (adapter->cmdThread) {
410 _rtw_up_sema(&adapter->cmdpriv.cmd_queue_sema);
411 rtw_thread_stop(adapter->cmdThread);
412 adapter->cmdThread = NULL;
413 }
414 }
415
416 thread_return rtw_cmd_thread(thread_context context)
417 {
418 u8 ret;
419 struct cmd_obj *pcmd;
420 u8 *pcmdbuf, *prspbuf;
421 systime cmd_start_time;
422 u32 cmd_process_time;
423 u8(*cmd_hdl)(_adapter *padapter, u8 *pbuf);
424 void (*pcmd_callback)(_adapter *dev, struct cmd_obj *pcmd);
425 _adapter *padapter = (_adapter *)context;
426 struct cmd_priv *pcmdpriv = &(padapter->cmdpriv);
427 struct drvextra_cmd_parm *extra_parm = NULL;
428 unsigned long sp_flags;
429
430 rtw_thread_enter("RTW_CMD_THREAD");
431
432 pcmdbuf = pcmdpriv->cmd_buf;
433 prspbuf = pcmdpriv->rsp_buf;
434 ATOMIC_SET(&(pcmdpriv->cmdthd_running), _TRUE);
435 _rtw_up_sema(&pcmdpriv->start_cmdthread_sema);
436
437
438 while (1) {
439 if (_rtw_down_sema(&pcmdpriv->cmd_queue_sema) == _FAIL) {
440 RTW_PRINT(FUNC_ADPT_FMT" _rtw_down_sema(&pcmdpriv->cmd_queue_sema) return _FAIL, break\n", FUNC_ADPT_ARG(padapter));
441 break;
442 }
443
444 if (RTW_CANNOT_RUN(adapter_to_dvobj(padapter))) {
445 RTW_DBG(FUNC_ADPT_FMT "- bDriverStopped(%s) bSurpriseRemoved(%s)\n",
446 FUNC_ADPT_ARG(padapter),
447 dev_is_drv_stopped(adapter_to_dvobj(padapter)) ? "True" : "False",
448 dev_is_surprise_removed(adapter_to_dvobj(padapter)) ? "True" : "False");
449 break;
450 }
451
452 _rtw_spinlock_irq(&pcmdpriv->cmd_queue.lock, &sp_flags);
453 if (rtw_is_list_empty(&(pcmdpriv->cmd_queue.queue))) {
454 /* RTW_INFO("%s: cmd queue is empty!\n", __func__); */
455 _rtw_spinunlock_irq(&pcmdpriv->cmd_queue.lock, &sp_flags);
456 continue;
457 }
458 _rtw_spinunlock_irq(&pcmdpriv->cmd_queue.lock, &sp_flags);
459
460 _next:
461 if (RTW_CANNOT_RUN(adapter_to_dvobj(padapter))) {
462 RTW_PRINT("%s: DriverStopped(%s) SurpriseRemoved(%s) break at line %d\n",
463 __func__
464 , dev_is_drv_stopped(adapter_to_dvobj(padapter)) ? "True" : "False"
465 , dev_is_surprise_removed(adapter_to_dvobj(padapter)) ? "True" : "False"
466 , __LINE__);
467 break;
468 }
469
470 pcmd = rtw_dequeue_cmd(pcmdpriv);
471 if (!pcmd) {
472 #ifdef CONFIG_LPS_LCLK
473 rtw_unregister_cmd_alive(padapter);
474 #endif
475 continue;
476 }
477
478 cmd_start_time = rtw_get_current_time();
479 pcmdpriv->cmd_issued_cnt++;
480
481 if (pcmd->cmdsz > MAX_CMDSZ) {
482 RTW_ERR("%s cmdsz:%d > MAX_CMDSZ:%d\n", __func__, pcmd->cmdsz, MAX_CMDSZ);
483 pcmd->res = H2C_PARAMETERS_ERROR;
484 goto post_process;
485 }
486
487 if (pcmd->cmdcode >= (sizeof(wlancmds) / sizeof(struct rtw_cmd))) {
488 RTW_ERR("%s undefined cmdcode:%d\n", __func__, pcmd->cmdcode);
489 pcmd->res = H2C_PARAMETERS_ERROR;
490 goto post_process;
491 }
492
493 cmd_hdl = wlancmds[pcmd->cmdcode].cmd_hdl;
494 if (!cmd_hdl) {
495 RTW_ERR("%s no cmd_hdl for cmdcode:%d\n", __func__, pcmd->cmdcode);
496 pcmd->res = H2C_PARAMETERS_ERROR;
497 goto post_process;
498 }
499
500 if (_FAIL == rtw_cmd_filter(pcmdpriv, pcmd)) {
501 pcmd->res = H2C_DROPPED;
502 if (pcmd->cmdcode == CMD_SET_DRV_EXTRA) {
503 extra_parm = (struct drvextra_cmd_parm *)pcmd->parmbuf;
504 if (extra_parm && extra_parm->pbuf && extra_parm->size > 0)
505 rtw_mfree(extra_parm->pbuf, extra_parm->size);
506 }
507 #if CONFIG_DFS
508 else if (pcmd->cmdcode == CMD_SET_CHANSWITCH)
509 adapter_to_rfctl(padapter)->csa_chandef.chan = 0;
510 #endif
511 goto post_process;
512 }
513
514 #ifdef CONFIG_LPS_LCLK
515 if (pcmd->no_io)
516 rtw_unregister_cmd_alive(padapter);
517 else {
518 if (rtw_register_cmd_alive(padapter) != _SUCCESS) {
519 if (DBG_CMD_EXECUTE)
520 RTW_PRINT("%s: wait to leave LPS_LCLK\n", __func__);
521
522 pcmd->res = H2C_ENQ_HEAD;
523 ret = _rtw_enqueue_cmd(&pcmdpriv->cmd_queue, pcmd, 1);
524 if (ret == _SUCCESS) {
525 if (DBG_CMD_EXECUTE)
526 RTW_INFO(ADPT_FMT" "CMD_FMT" ENQ_HEAD\n", ADPT_ARG(pcmd->padapter), CMD_ARG(pcmd));
527 continue;
528 }
529
530 RTW_INFO(ADPT_FMT" "CMD_FMT" ENQ_HEAD_FAIL\n", ADPT_ARG(pcmd->padapter), CMD_ARG(pcmd));
531 pcmd->res = H2C_ENQ_HEAD_FAIL;
532 rtw_warn_on(1);
533 }
534 }
535 #endif /* CONFIG_LPS_LCLK */
536
537 if (DBG_CMD_EXECUTE)
538 RTW_INFO(ADPT_FMT" "CMD_FMT" %sexecute\n", ADPT_ARG(pcmd->padapter), CMD_ARG(pcmd)
539 , pcmd->res == H2C_ENQ_HEAD ? "ENQ_HEAD " : (pcmd->res == H2C_ENQ_HEAD_FAIL ? "ENQ_HEAD_FAIL " : ""));
540
541 _rtw_memcpy(pcmdbuf, pcmd->parmbuf, pcmd->cmdsz);
542 ret = cmd_hdl(pcmd->padapter, pcmdbuf);
543 pcmd->res = ret;
544
545 pcmdpriv->cmd_seq++;
546
547 post_process:
548
549 _rtw_mutex_lock_interruptible(&(pcmd->padapter->cmdpriv.sctx_mutex));
550 if (pcmd->sctx) {
551 if (0)
552 RTW_PRINT(FUNC_ADPT_FMT" pcmd->sctx\n", FUNC_ADPT_ARG(pcmd->padapter));
553 if (pcmd->res == H2C_SUCCESS)
554 rtw_sctx_done(&pcmd->sctx);
555 else
556 rtw_sctx_done_err(&pcmd->sctx, RTW_SCTX_DONE_CMD_ERROR);
557 }
558 _rtw_mutex_unlock(&(pcmd->padapter->cmdpriv.sctx_mutex));
559
560 cmd_process_time = rtw_get_passing_time_ms(cmd_start_time);
561 if (cmd_process_time > 1000) {
562 RTW_INFO(ADPT_FMT" "CMD_FMT" process_time=%d\n", ADPT_ARG(pcmd->padapter), CMD_ARG(pcmd), cmd_process_time);
563 if (0)
564 rtw_warn_on(1);
565 }
566
567 /* call callback function for post-processed */
568 if (pcmd->cmdcode >= (sizeof(wlancmds) / sizeof(struct rtw_cmd)))
569 pcmd_callback = wlancmds[pcmd->cmdcode].callback;
570 else
571 pcmd_callback = NULL;
572
573 if (pcmd_callback == NULL) {
574 rtw_free_cmd_obj(pcmd);
575 } else {
576 /* todo: !!! fill rsp_buf to pcmd->rsp if (pcmd->rsp!=NULL) */
577 pcmd_callback(pcmd->padapter, pcmd);/* need conider that free cmd_obj in rtw_cmd_callback */
578 }
579
580 flush_signals_thread();
581
582 goto _next;
583
584 }
585
586 #ifdef CONFIG_LPS_LCLK
587 rtw_unregister_cmd_alive(padapter);
588 #endif
589
590 /* to avoid enqueue cmd after free all cmd_obj */
591 ATOMIC_SET(&(pcmdpriv->cmdthd_running), _FALSE);
592
593 /* free all cmd_obj resources */
594 do {
595 pcmd = rtw_dequeue_cmd(pcmdpriv);
596 if (pcmd == NULL)
597 break;
598
599 if (0)
600 RTW_INFO("%s: leaving... drop "CMD_FMT"\n", __func__, CMD_ARG(pcmd));
601
602 if (pcmd->cmdcode == CMD_SET_DRV_EXTRA) {
603 extra_parm = (struct drvextra_cmd_parm *)pcmd->parmbuf;
604 if (extra_parm->pbuf && extra_parm->size > 0)
605 rtw_mfree(extra_parm->pbuf, extra_parm->size);
606 }
607 #if CONFIG_DFS
608 else if (pcmd->cmdcode == CMD_SET_CHANSWITCH)
609 adapter_to_rfctl(padapter)->csa_chandef.chan = 0;
610 #endif
611
612 _rtw_mutex_lock_interruptible(&(pcmd->padapter->cmdpriv.sctx_mutex));
613 if (pcmd->sctx) {
614 if (0)
615 RTW_PRINT(FUNC_ADPT_FMT" pcmd->sctx\n", FUNC_ADPT_ARG(pcmd->padapter));
616 rtw_sctx_done_err(&pcmd->sctx, RTW_SCTX_DONE_CMD_DROP);
617 }
618 _rtw_mutex_unlock(&(pcmd->padapter->cmdpriv.sctx_mutex));
619
620 rtw_free_cmd_obj(pcmd);
621 } while (1);
622
623 RTW_INFO(FUNC_ADPT_FMT " Exit\n", FUNC_ADPT_ARG(padapter));
624
625 rtw_thread_wait_stop();
626
627 return 0;
628 }
629 #endif
630
rtw_readtssi_cmdrsp_callback(_adapter * padapter,struct cmd_obj * pcmd)631 void rtw_readtssi_cmdrsp_callback(_adapter *padapter, struct cmd_obj *pcmd)
632 {
633
634 rtw_mfree((unsigned char *) pcmd->parmbuf, pcmd->cmdsz);
635 rtw_mfree((unsigned char *) pcmd, sizeof(struct cmd_obj));
636
637 #ifdef CONFIG_MP_INCLUDED
638 if (padapter->registrypriv.mp_mode == 1)
639 padapter->mppriv.workparam.bcompleted = _TRUE;
640 #endif
641
642 }
643
rtw_createbss_cmd(_adapter * adapter,int flags,bool adhoc,u8 ifbmp,u8 excl_ifbmp,s16 req_ch,s8 req_bw,s8 req_offset)644 static u8 rtw_createbss_cmd(_adapter *adapter, int flags, bool adhoc
645 , u8 ifbmp, u8 excl_ifbmp, s16 req_ch, s8 req_bw, s8 req_offset)
646 {
647 struct cmd_obj *cmdobj;
648 struct createbss_parm *parm;
649 struct cmd_priv *pcmdpriv = &adapter_to_dvobj(adapter)->cmdpriv;
650 struct submit_ctx sctx;
651 u8 res = _SUCCESS;
652
653 if (req_ch > 0 && req_bw >= 0 && req_offset >= 0) {
654 if (!rtw_chset_is_chbw_valid(adapter_to_chset(adapter), req_ch, req_bw, req_offset, 0, 0)) {
655 res = _FAIL;
656 goto exit;
657 }
658 }
659
660 /* prepare cmd parameter */
661 parm = (struct createbss_parm *)rtw_zmalloc(sizeof(*parm));
662 if (parm == NULL) {
663 res = _FAIL;
664 goto exit;
665 }
666
667 if (adhoc) {
668 /* for now, adhoc doesn't support ch,bw,offset request */
669 parm->adhoc = 1;
670 } else {
671 parm->adhoc = 0;
672 parm->ifbmp = ifbmp;
673 parm->excl_ifbmp = excl_ifbmp;
674 parm->req_ch = req_ch;
675 parm->req_bw = req_bw;
676 parm->req_offset = req_offset;
677 parm->ifbmp_ch_changed = 0;
678 parm->ch_to_set = 0;
679 parm->bw_to_set = 0;
680 parm->offset_to_set = 0;
681 parm->do_rfk = _FALSE;
682 }
683
684 if (flags & RTW_CMDF_DIRECTLY) {
685 /* no need to enqueue, do the cmd hdl directly and free cmd parameter */
686 if (H2C_SUCCESS != createbss_hdl(adapter, (u8 *)parm))
687 res = _FAIL;
688 rtw_mfree((u8 *)parm, sizeof(*parm));
689 } else {
690 /* need enqueue, prepare cmd_obj and enqueue */
691 cmdobj = (struct cmd_obj *)rtw_zmalloc(sizeof(*cmdobj));
692 if (cmdobj == NULL) {
693 res = _FAIL;
694 rtw_mfree((u8 *)parm, sizeof(*parm));
695 goto exit;
696 }
697 cmdobj->padapter = adapter;
698
699 init_h2fwcmd_w_parm_no_rsp(cmdobj, parm, CMD_CREATE_BSS);
700
701 if (flags & RTW_CMDF_WAIT_ACK) {
702 cmdobj->sctx = &sctx;
703 rtw_sctx_init(&sctx, 5000);
704 }
705
706 res = rtw_enqueue_cmd(pcmdpriv, cmdobj);
707
708 if (res == _SUCCESS && (flags & RTW_CMDF_WAIT_ACK)) {
709 res = rtw_sctx_wait(&sctx, __func__);
710 _rtw_mutex_lock_interruptible(&pcmdpriv->sctx_mutex);
711 if (sctx.status == RTW_SCTX_SUBMITTED)
712 cmdobj->sctx = NULL;
713 _rtw_mutex_unlock(&pcmdpriv->sctx_mutex);
714 }
715 }
716
717 exit:
718 return res;
719 }
720
rtw_create_ibss_cmd(_adapter * adapter,int flags)721 inline u8 rtw_create_ibss_cmd(_adapter *adapter, int flags)
722 {
723 return rtw_createbss_cmd(adapter, flags
724 , 1
725 , 0, 0
726 , 0, REQ_BW_NONE, REQ_OFFSET_NONE /* for now, adhoc doesn't support ch,bw,offset request */
727 );
728 }
729
rtw_startbss_cmd(_adapter * adapter,int flags)730 inline u8 rtw_startbss_cmd(_adapter *adapter, int flags)
731 {
732 return rtw_createbss_cmd(adapter, flags
733 , 0
734 , BIT(adapter->iface_id), 0
735 , 0, REQ_BW_NONE, REQ_OFFSET_NONE /* excute entire AP setup cmd */
736 );
737 }
738
rtw_change_bss_chbw_cmd(_adapter * adapter,int flags,u8 ifbmp,u8 excl_ifbmp,s16 req_ch,s8 req_bw,s8 req_offset)739 inline u8 rtw_change_bss_chbw_cmd(_adapter *adapter, int flags
740 , u8 ifbmp, u8 excl_ifbmp, s16 req_ch, s8 req_bw, s8 req_offset)
741 {
742 return rtw_createbss_cmd(adapter, flags
743 , 0
744 , ifbmp, excl_ifbmp
745 , req_ch, req_bw, req_offset
746 );
747 }
748
749 #ifdef CONFIG_80211D
750 /* Return corresponding country_chplan setting */
rtw_joinbss_check_country_ie(_adapter * adapter,const WLAN_BSSID_EX * network,struct country_chplan * ent,WLAN_BSSID_EX * out_network)751 static bool rtw_joinbss_check_country_ie(_adapter *adapter, const WLAN_BSSID_EX *network, struct country_chplan *ent, WLAN_BSSID_EX *out_network)
752 {
753 struct rf_ctl_t *rfctl = adapter_to_rfctl(adapter);
754 bool ret = 0;
755
756 if (rfctl->regd_src == REGD_SRC_RTK_PRIV
757 && !rtw_rfctl_is_disable_sw_channel_plan(rfctl_to_dvobj(rfctl))
758 ) {
759 struct mlme_priv *mlme = &adapter->mlmepriv;
760 const u8 *country_ie = NULL;
761 sint country_ie_len = 0;
762
763 if (rtw_iface_accept_country_ie(adapter)) {
764 country_ie = rtw_get_ie(BSS_EX_TLV_IES(network)
765 , WLAN_EID_COUNTRY, &country_ie_len, BSS_EX_TLV_IES_LEN(network));
766 if (country_ie) {
767 if (country_ie_len < 6) {
768 country_ie = NULL;
769 country_ie_len = 0;
770 } else
771 country_ie_len += 2;
772 }
773 }
774
775 if (country_ie) {
776 enum country_ie_slave_status status;
777
778 rtw_buf_update(&mlme->recv_country_ie, &mlme->recv_country_ie_len, country_ie, country_ie_len);
779
780 status = rtw_get_chplan_from_recv_country_ie(adapter
781 , network->Configuration.DSConfig > 14 ? BAND_ON_5G : BAND_ON_24G
782 , network->Configuration.DSConfig, country_ie, ent, NULL, __func__);
783 if (status != COUNTRY_IE_SLAVE_NOCOUNTRY)
784 ret = 1;
785
786 if (out_network) {
787 _rtw_memcpy(BSS_EX_IES(out_network) + BSS_EX_IES_LEN(out_network)
788 , country_ie, country_ie_len);
789 BSS_EX_IES_LEN(out_network) += country_ie_len;
790 }
791 } else
792 rtw_buf_free(&mlme->recv_country_ie, &mlme->recv_country_ie_len);
793 }
794
795 return ret;
796 }
797 #endif /* CONFIG_80211D */
798
rtw_joinbss_cmd(_adapter * padapter,struct wlan_network * pnetwork)799 u8 rtw_joinbss_cmd(_adapter *padapter, struct wlan_network *pnetwork)
800 {
801 u8 *auth, res = _SUCCESS;
802 uint t_len = 0;
803 WLAN_BSSID_EX *psecnetwork;
804 struct cmd_obj *pcmd;
805 struct cmd_priv *pcmdpriv = &adapter_to_dvobj(padapter)->cmdpriv;
806 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
807 struct qos_priv *pqospriv = &pmlmepriv->qospriv;
808 struct security_priv *psecuritypriv = &padapter->securitypriv;
809 struct registry_priv *pregistrypriv = &padapter->registrypriv;
810 #ifdef CONFIG_80211D
811 struct country_chplan country_ent;
812 #endif
813 struct country_chplan *req_chplan = NULL;
814 #ifdef CONFIG_80211N_HT
815 struct ht_priv *phtpriv = &pmlmepriv->htpriv;
816 #endif /* CONFIG_80211N_HT */
817 #ifdef CONFIG_80211AC_VHT
818 struct vht_priv *pvhtpriv = &pmlmepriv->vhtpriv;
819 #endif /* CONFIG_80211AC_VHT */
820 #ifdef CONFIG_80211AX_HE
821 struct he_priv *phepriv = &pmlmepriv->hepriv;
822 #endif /* CONFIG_80211AX_HE */
823 NDIS_802_11_NETWORK_INFRASTRUCTURE ndis_network_mode = pnetwork->network.InfrastructureMode;
824 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
825 struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
826 struct rf_ctl_t *rfctl = adapter_to_rfctl(padapter);
827 u32 tmp_len;
828 u8 *ptmp = NULL;
829
830 rtw_led_control(padapter, LED_CTL_START_TO_LINK);
831
832 pcmd = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
833 if (pcmd == NULL) {
834 res = _FAIL;
835 goto exit;
836 }
837 pcmd->padapter = padapter;
838
839 /* for IEs is fix buf size */
840 t_len = sizeof(WLAN_BSSID_EX);
841
842
843 /* for hidden ap to set fw_state here */
844 if (!MLME_IS_STA(padapter) || !MLME_IS_ADHOC(padapter)) {
845 switch (ndis_network_mode) {
846 case Ndis802_11IBSS:
847 set_fwstate(pmlmepriv, WIFI_ADHOC_STATE);
848 break;
849
850 case Ndis802_11Infrastructure:
851 set_fwstate(pmlmepriv, WIFI_STATION_STATE);
852 break;
853
854 default:
855 rtw_warn_on(1);
856 break;
857 }
858 }
859
860 pmlmeinfo->assoc_AP_vendor = check_assoc_AP(pnetwork->network.IEs, pnetwork->network.IELength);
861
862 #ifdef CONFIG_80211AC_VHT
863 /* save AP beamform_cap info for BCM IOT issue */
864 if (pmlmeinfo->assoc_AP_vendor == HT_IOT_PEER_BROADCOM)
865 get_vht_bf_cap(pnetwork->network.IEs,
866 pnetwork->network.IELength,
867 &pvhtpriv->ap_bf_cap);
868 #endif
869 /*
870 Modified by Arvin 2015/05/13
871 Solution for allocating a new WLAN_BSSID_EX to avoid race condition issue between disconnect and joinbss
872 */
873 psecnetwork = (WLAN_BSSID_EX *)rtw_zmalloc(sizeof(WLAN_BSSID_EX));
874 if (psecnetwork == NULL) {
875 if (pcmd != NULL)
876 rtw_mfree((unsigned char *)pcmd, sizeof(struct cmd_obj));
877
878 res = _FAIL;
879
880
881 goto exit;
882 }
883
884 _rtw_memset(psecnetwork, 0, t_len);
885
886 _rtw_memcpy(psecnetwork, &pnetwork->network, get_WLAN_BSSID_EX_sz(&pnetwork->network));
887
888 auth = &psecuritypriv->authenticator_ie[0];
889 psecuritypriv->authenticator_ie[0] = (unsigned char)psecnetwork->IELength;
890
891 if ((psecnetwork->IELength - 12) < (256 - 1))
892 _rtw_memcpy(&psecuritypriv->authenticator_ie[1], &psecnetwork->IEs[12], psecnetwork->IELength - 12);
893 else
894 _rtw_memcpy(&psecuritypriv->authenticator_ie[1], &psecnetwork->IEs[12], (256 - 1));
895
896 psecnetwork->IELength = 0;
897 /* Added by Albert 2009/02/18 */
898 /* If the the driver wants to use the bssid to create the connection. */
899 /* If not, we have to copy the connecting AP's MAC address to it so that */
900 /* the driver just has the bssid information for PMKIDList searching. */
901
902 if (pmlmepriv->assoc_by_bssid == _FALSE)
903 _rtw_memcpy(&pmlmepriv->assoc_bssid[0], &pnetwork->network.MacAddress[0], ETH_ALEN);
904
905 /* copy fixed ie */
906 _rtw_memcpy(psecnetwork->IEs, pnetwork->network.IEs, 12);
907 psecnetwork->IELength = 12;
908
909 psecnetwork->IELength += rtw_restruct_sec_ie(padapter, psecnetwork->IEs + psecnetwork->IELength);
910
911
912 pqospriv->qos_option = 0;
913
914 if (pregistrypriv->wmm_enable) {
915 #ifdef CONFIG_WMMPS_STA
916 rtw_uapsd_use_default_setting(padapter);
917 #endif /* CONFIG_WMMPS_STA */
918 tmp_len = rtw_restruct_wmm_ie(padapter, &pnetwork->network.IEs[0], &psecnetwork->IEs[0], pnetwork->network.IELength, psecnetwork->IELength);
919
920 if (psecnetwork->IELength != tmp_len) {
921 psecnetwork->IELength = tmp_len;
922 pqospriv->qos_option = 1; /* There is WMM IE in this corresp. beacon */
923 } else {
924 pqospriv->qos_option = 0;/* There is no WMM IE in this corresp. beacon */
925 RTW_INFO("%s follow wifi logo,no WMM IE will be legacy mode \n", __func__);
926 }
927 }
928
929 #ifdef RTW_WKARD_UPDATE_PHL_ROLE_CAP
930 rtw_update_phl_cap_by_rgstry(padapter);
931 #endif
932
933 #ifdef CONFIG_80211D
934 if (rtw_joinbss_check_country_ie(padapter, &pnetwork->network, &country_ent, psecnetwork))
935 req_chplan = &country_ent;
936 #endif
937
938 #ifdef CONFIG_80211N_HT
939 phtpriv->ht_option = _FALSE;
940 if (pregistrypriv->ht_enable && is_supported_ht(pregistrypriv->wireless_mode)) {
941 ptmp = rtw_get_ie(&pnetwork->network.IEs[12], _HT_CAPABILITY_IE_, &tmp_len, pnetwork->network.IELength - 12);
942 if (ptmp && tmp_len > 0 && (pqospriv->qos_option == 1)) {
943 /* Added by Albert 2010/06/23 */
944 /* For the WEP mode, we will use the bg mode to do the connection to avoid some IOT issue. */
945 /* Especially for Realtek 8192u SoftAP. */
946 if ((padapter->securitypriv.dot11PrivacyAlgrthm != _WEP40_) &&
947 (padapter->securitypriv.dot11PrivacyAlgrthm != _WEP104_) &&
948 (padapter->securitypriv.dot11PrivacyAlgrthm != _TKIP_)) {
949 rtw_ht_use_default_setting(padapter);
950
951 /* rtw_restructure_ht_ie */
952 rtw_restructure_ht_ie(padapter, &pnetwork->network.IEs[12], &psecnetwork->IEs[0],
953 pnetwork->network.IELength - 12, &psecnetwork->IELength,
954 pnetwork->network.Configuration.DSConfig, req_chplan);
955 }
956 }
957 }
958
959 #ifdef CONFIG_80211AC_VHT
960 pvhtpriv->vht_option = _FALSE;
961 if (phtpriv->ht_option
962 && REGSTY_IS_11AC_ENABLE(pregistrypriv)
963 && is_supported_vht(pregistrypriv->wireless_mode)
964 && (pqospriv->qos_option == 1)
965 && ((req_chplan && COUNTRY_CHPLAN_EN_11AC(req_chplan))
966 || (!req_chplan && RFCTL_REG_EN_11AC(rfctl)))
967 ) {
968 u8 vht_enable = 0;
969
970 if (pnetwork->network.Configuration.DSConfig > 14)
971 vht_enable = 1;
972 else if ((REGSTY_IS_11AC_24G_ENABLE(pregistrypriv)) && (padapter->registrypriv.wifi_spec == 0))
973 vht_enable = 1;
974
975 if (vht_enable == 1)
976 rtw_restructure_vht_ie(padapter, &pnetwork->network.IEs[0], &psecnetwork->IEs[0],
977 pnetwork->network.IELength, &psecnetwork->IELength, req_chplan);
978 }
979 #endif /* CONFIG_80211AC_VHT */
980
981 #ifdef CONFIG_80211AX_HE
982 phepriv->he_option = _FALSE;
983 if (((phtpriv->ht_option && pnetwork->network.Configuration.DSConfig <= 14)
984 #ifdef CONFIG_80211AC_VHT
985 || (pvhtpriv->vht_option && pnetwork->network.Configuration.DSConfig > 14)
986 #endif
987 )
988 && REGSTY_IS_11AX_ENABLE(pregistrypriv)
989 && is_supported_he(pregistrypriv->wireless_mode)
990 && (pqospriv->qos_option == 1)
991 && ((req_chplan && COUNTRY_CHPLAN_EN_11AX(req_chplan))
992 || (!req_chplan && RFCTL_REG_EN_11AX(rfctl)))
993 ) {
994 rtw_restructure_he_ie(padapter, &pnetwork->network.IEs[0], &psecnetwork->IEs[0],
995 pnetwork->network.IELength, &psecnetwork->IELength, req_chplan);
996 }
997 #endif /* CONFIG_80211AX_HE */
998
999 #endif /* CONFIG_80211N_HT */
1000
1001 rtw_append_extended_cap(padapter, &psecnetwork->IEs[0], &psecnetwork->IELength);
1002
1003 #ifdef CONFIG_RTW_80211R
1004 rtw_ft_validate_akm_type(padapter, pnetwork);
1005 #endif
1006
1007 #if 0
1008 psecuritypriv->supplicant_ie[0] = (u8)psecnetwork->IELength;
1009
1010 if (psecnetwork->IELength < (256 - 1))
1011 _rtw_memcpy(&psecuritypriv->supplicant_ie[1], &psecnetwork->IEs[0], psecnetwork->IELength);
1012 else
1013 _rtw_memcpy(&psecuritypriv->supplicant_ie[1], &psecnetwork->IEs[0], (256 - 1));
1014 #endif
1015
1016 pcmd->cmdsz = sizeof(WLAN_BSSID_EX);
1017
1018 _rtw_init_listhead(&pcmd->list);
1019 pcmd->cmdcode = CMD_JOINBSS; /*_JoinBss_CMD_;*/
1020 pcmd->parmbuf = (unsigned char *)psecnetwork;
1021 pcmd->rsp = NULL;
1022 pcmd->rspsz = 0;
1023
1024 res = rtw_enqueue_cmd(pcmdpriv, pcmd);
1025
1026 exit:
1027
1028
1029 return res;
1030 }
1031
1032 #ifdef CONFIG_STA_CMD_DISPR
1033 /* for sta_mode only */
sta_disassoc_cmd(struct _ADAPTER * a,u32 deauth_timeout_ms,int flags)1034 static u8 sta_disassoc_cmd(struct _ADAPTER *a, u32 deauth_timeout_ms, int flags)
1035 {
1036 struct cmd_priv *cmdpriv = &adapter_to_dvobj(a)->cmdpriv;
1037 struct cmd_obj *cmd = NULL;
1038 struct disconnect_parm *param = NULL;
1039 struct submit_ctx sctx;
1040 enum rtw_phl_status status;
1041 int ret;
1042 u8 res = _FAIL;
1043
1044
1045 if (!MLME_IS_ASOC(a))
1046 return _SUCCESS;
1047
1048 param = (struct disconnect_parm *)rtw_zmalloc(sizeof(*param));
1049 if (!param) {
1050 RTW_ERR(FUNC_ADPT_FMT ": alloc param FAIL!", FUNC_ADPT_ARG(a));
1051 goto exit;
1052 }
1053 cmd = (struct cmd_obj *)rtw_zmalloc(sizeof(*cmd));
1054 if (!cmd) {
1055 RTW_ERR(FUNC_ADPT_FMT ": alloc cmd FAIL!", FUNC_ADPT_ARG(a));
1056 rtw_mfree((u8 *)param, sizeof(*param));
1057 goto exit;
1058 }
1059
1060 param->deauth_timeout_ms = deauth_timeout_ms;
1061 init_h2fwcmd_w_parm_no_rsp(cmd, param, CMD_DISCONNECT);
1062 cmd->padapter = a;
1063 if (flags & RTW_CMDF_WAIT_ACK) {
1064 cmd->sctx = &sctx;
1065 rtw_sctx_init(&sctx, 2000);
1066 }
1067
1068 status = rtw_disconnect_cmd(a, cmd);
1069 if (status != RTW_PHL_STATUS_SUCCESS) {
1070 /* param & cmd would be freed in rtw_enqueue_cmd() */
1071 RTW_ERR(FUNC_ADPT_FMT ": send disconnect cmd FAIL!(0x%x)\n",
1072 FUNC_ADPT_ARG(a), status);
1073 goto exit;
1074 }
1075 res = _SUCCESS;
1076
1077 if (flags & RTW_CMDF_WAIT_ACK) {
1078 ret = rtw_sctx_wait(&sctx, __func__);
1079 if (ret == _FAIL)
1080 res = _FAIL;
1081 _rtw_spinlock(&a->disconnect_lock);
1082 if (a->discon_cmd) {
1083 a->discon_cmd->sctx = NULL;
1084 /*
1085 * a->discon_param would be
1086 * freed by disconnect cmd dispatcher.
1087 */
1088 }
1089 _rtw_spinunlock(&a->disconnect_lock);
1090 }
1091
1092 exit:
1093 return res;
1094 }
1095 #endif /* CONFIG_STA_CMD_DISPR */
1096
rtw_disassoc_cmd(_adapter * padapter,u32 deauth_timeout_ms,int flags)1097 u8 rtw_disassoc_cmd(_adapter *padapter, u32 deauth_timeout_ms, int flags) /* for sta_mode */
1098 {
1099 struct cmd_obj *cmdobj = NULL;
1100 struct disconnect_parm *param = NULL;
1101 struct cmd_priv *cmdpriv = &adapter_to_dvobj(padapter)->cmdpriv;
1102
1103 struct submit_ctx sctx;
1104 u8 res = _SUCCESS;
1105
1106
1107 #ifdef CONFIG_STA_CMD_DISPR
1108 if (MLME_IS_STA(padapter))
1109 return sta_disassoc_cmd(padapter, deauth_timeout_ms, flags);
1110 #endif /* CONFIG_STA_CMD_DISPR */
1111
1112 /* prepare cmd parameter */
1113 param = (struct disconnect_parm *)rtw_zmalloc(sizeof(*param));
1114 if (param == NULL) {
1115 res = _FAIL;
1116 goto exit;
1117 }
1118 param->deauth_timeout_ms = deauth_timeout_ms;
1119
1120 if (flags & RTW_CMDF_DIRECTLY) {
1121 /* no need to enqueue, do the cmd hdl directly and free cmd parameter */
1122 if (disconnect_hdl(padapter, (u8 *)param) != H2C_SUCCESS)
1123 res = _FAIL;
1124 rtw_mfree((u8 *)param, sizeof(*param));
1125
1126 } else {
1127 cmdobj = (struct cmd_obj *)rtw_zmalloc(sizeof(*cmdobj));
1128 if (cmdobj == NULL) {
1129 res = _FAIL;
1130 rtw_mfree((u8 *)param, sizeof(*param));
1131 goto exit;
1132 }
1133 cmdobj->padapter = padapter;
1134 init_h2fwcmd_w_parm_no_rsp(cmdobj, param, CMD_DISCONNECT);
1135 if (flags & RTW_CMDF_WAIT_ACK) {
1136 cmdobj->sctx = &sctx;
1137 rtw_sctx_init(&sctx, 2000);
1138 }
1139 res = rtw_enqueue_cmd(cmdpriv, cmdobj);
1140 if (res == _FAIL) {
1141 RTW_ERR(FUNC_ADPT_FMT ": enqueue disconnect cmd FAIL!\n",
1142 FUNC_ADPT_ARG(padapter));
1143 goto exit;
1144 }
1145 if (flags & RTW_CMDF_WAIT_ACK) {
1146 rtw_sctx_wait(&sctx, __func__);
1147 _rtw_mutex_lock_interruptible(&cmdpriv->sctx_mutex);
1148 if (sctx.status == RTW_SCTX_SUBMITTED)
1149 cmdobj->sctx = NULL;
1150 _rtw_mutex_unlock(&cmdpriv->sctx_mutex);
1151 }
1152 }
1153
1154 exit:
1155 return res;
1156 }
1157
1158
rtw_stop_ap_cmd(_adapter * adapter,u8 flags)1159 u8 rtw_stop_ap_cmd(_adapter *adapter, u8 flags)
1160 {
1161 #ifdef CONFIG_AP_MODE
1162 struct cmd_obj *cmdobj;
1163 struct drvextra_cmd_parm *parm;
1164 struct cmd_priv *pcmdpriv = &adapter_to_dvobj(adapter)->cmdpriv;
1165 struct submit_ctx sctx;
1166 u8 res = _SUCCESS;
1167
1168 if (flags & RTW_CMDF_DIRECTLY) {
1169 /* no need to enqueue, do the cmd hdl directly and free cmd parameter */
1170 if (H2C_SUCCESS != stop_ap_hdl(adapter))
1171 res = _FAIL;
1172 } else {
1173 parm = (struct drvextra_cmd_parm *)rtw_zmalloc(sizeof(struct drvextra_cmd_parm));
1174 if (parm == NULL) {
1175 res = _FAIL;
1176 goto exit;
1177 }
1178
1179 parm->ec_id = STOP_AP_WK_CID;
1180 parm->type = 0;
1181 parm->size = 0;
1182 parm->pbuf = NULL;
1183
1184 /* need enqueue, prepare cmd_obj and enqueue */
1185 cmdobj = (struct cmd_obj *)rtw_zmalloc(sizeof(*cmdobj));
1186 if (cmdobj == NULL) {
1187 res = _FAIL;
1188 goto exit;
1189 }
1190 cmdobj->padapter = adapter;
1191
1192 init_h2fwcmd_w_parm_no_rsp(cmdobj, parm, CMD_SET_DRV_EXTRA);
1193
1194 if (flags & RTW_CMDF_WAIT_ACK) {
1195 cmdobj->sctx = &sctx;
1196 rtw_sctx_init(&sctx, 2000);
1197 }
1198
1199 res = rtw_enqueue_cmd(pcmdpriv, cmdobj);
1200
1201 if (res == _SUCCESS && (flags & RTW_CMDF_WAIT_ACK)) {
1202 rtw_sctx_wait(&sctx, __func__);
1203 _rtw_mutex_lock_interruptible(&pcmdpriv->sctx_mutex);
1204 if (sctx.status == RTW_SCTX_SUBMITTED)
1205 cmdobj->sctx = NULL;
1206 _rtw_mutex_unlock(&pcmdpriv->sctx_mutex);
1207 }
1208 }
1209
1210 exit:
1211 return res;
1212 #endif
1213 }
1214
1215 #ifdef CONFIG_RTW_TOKEN_BASED_XMIT
rtw_tx_control_cmd(_adapter * adapter)1216 u8 rtw_tx_control_cmd(_adapter *adapter)
1217 {
1218 struct cmd_obj *cmd;
1219 struct drvextra_cmd_parm *pdrvextra_cmd_parm;
1220 struct cmd_priv *pcmdpriv = &adapter_to_dvobj(adapter)->cmdpriv;
1221
1222 u8 res = _SUCCESS;
1223
1224 cmd = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
1225 if (cmd == NULL){
1226 res = _FAIL;
1227 goto exit;
1228 }
1229 cmd->padapter = adapter;
1230
1231 pdrvextra_cmd_parm = (struct drvextra_cmd_parm *)rtw_zmalloc(sizeof(struct drvextra_cmd_parm));
1232 if (pdrvextra_cmd_parm == NULL) {
1233 rtw_mfree((unsigned char *)cmd, sizeof(struct cmd_obj));
1234 res = _FAIL;
1235 goto exit;
1236 }
1237
1238 pdrvextra_cmd_parm->ec_id = TBTX_CONTROL_TX_WK_CID;
1239 pdrvextra_cmd_parm->type = 0;
1240 pdrvextra_cmd_parm->size = 0;
1241 pdrvextra_cmd_parm->pbuf = NULL;
1242 init_h2fwcmd_w_parm_no_rsp(cmd, pdrvextra_cmd_parm, CMD_SET_DRV_EXTRA);
1243
1244 res = rtw_enqueue_cmd(pcmdpriv, cmd);
1245
1246 exit:
1247 return res;
1248 }
1249 #endif
1250
rtw_setopmode_cmd(_adapter * adapter,NDIS_802_11_NETWORK_INFRASTRUCTURE networktype,u8 flags)1251 u8 rtw_setopmode_cmd(_adapter *adapter, NDIS_802_11_NETWORK_INFRASTRUCTURE networktype, u8 flags)
1252 {
1253 struct cmd_obj *cmdobj;
1254 struct setopmode_parm *parm;
1255 struct cmd_priv *pcmdpriv = &adapter_to_dvobj(adapter)->cmdpriv;
1256 struct submit_ctx sctx;
1257 u8 res = _SUCCESS;
1258
1259 /* prepare cmd parameter */
1260 parm = (struct setopmode_parm *)rtw_zmalloc(sizeof(*parm));
1261 if (parm == NULL) {
1262 res = _FAIL;
1263 goto exit;
1264 }
1265 parm->mode = (u8)networktype;
1266
1267 if (flags & RTW_CMDF_DIRECTLY) {
1268 /* no need to enqueue, do the cmd hdl directly and free cmd parameter */
1269 if (H2C_SUCCESS != setopmode_hdl(adapter, (u8 *)parm))
1270 res = _FAIL;
1271 rtw_mfree((u8 *)parm, sizeof(*parm));
1272 } else {
1273 /* need enqueue, prepare cmd_obj and enqueue */
1274 cmdobj = (struct cmd_obj *)rtw_zmalloc(sizeof(*cmdobj));
1275 if (cmdobj == NULL) {
1276 res = _FAIL;
1277 rtw_mfree((u8 *)parm, sizeof(*parm));
1278 goto exit;
1279 }
1280 cmdobj->padapter = adapter;
1281
1282 init_h2fwcmd_w_parm_no_rsp(cmdobj, parm, CMD_SET_OPMODE);
1283
1284 if (flags & RTW_CMDF_WAIT_ACK) {
1285 cmdobj->sctx = &sctx;
1286 rtw_sctx_init(&sctx, 2000);
1287 }
1288
1289 res = rtw_enqueue_cmd(pcmdpriv, cmdobj);
1290
1291 if (res == _SUCCESS && (flags & RTW_CMDF_WAIT_ACK)) {
1292 rtw_sctx_wait(&sctx, __func__);
1293 _rtw_mutex_lock_interruptible(&pcmdpriv->sctx_mutex);
1294 if (sctx.status == RTW_SCTX_SUBMITTED)
1295 cmdobj->sctx = NULL;
1296 _rtw_mutex_unlock(&pcmdpriv->sctx_mutex);
1297 }
1298 }
1299
1300 exit:
1301 return res;
1302 }
1303
1304 #ifdef CONFIG_CMD_DISP
rtw_setstakey_cmd(_adapter * padapter,struct sta_info * sta,u8 key_type,bool enqueue)1305 u8 rtw_setstakey_cmd(_adapter *padapter, struct sta_info *sta, u8 key_type, bool enqueue)
1306 {
1307 struct set_stakey_parm setstakey_para;
1308
1309 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1310 struct security_priv *psecuritypriv = &padapter->securitypriv;
1311 u8 key_len =16;
1312 u8 res = _SUCCESS;
1313
1314 _rtw_memset(&setstakey_para, 0, sizeof(struct set_stakey_parm));
1315 _rtw_memcpy(setstakey_para.addr, sta->phl_sta->mac_addr, ETH_ALEN);
1316
1317 if (MLME_IS_STA(padapter))
1318 setstakey_para.algorithm = (unsigned char) psecuritypriv->dot11PrivacyAlgrthm;
1319 else
1320 GET_ENCRY_ALGO(psecuritypriv, sta, setstakey_para.algorithm, _FALSE);
1321
1322 if ((setstakey_para.algorithm == _GCMP_256_) || (setstakey_para.algorithm == _CCMP_256_))
1323 key_len = 32;
1324
1325 if (key_type == GROUP_KEY) {
1326 _rtw_memcpy(&setstakey_para.key, &psecuritypriv->dot118021XGrpKey[psecuritypriv->dot118021XGrpKeyid].skey, key_len);
1327 setstakey_para.gk = 1;
1328 } else if (key_type == UNICAST_KEY)
1329 _rtw_memcpy(&setstakey_para.key, &sta->dot118021x_UncstKey, key_len);
1330 #ifdef CONFIG_TDLS
1331 else if (key_type == TDLS_KEY) {
1332 _rtw_memcpy(&setstakey_para.key, sta->tpk.tk, key_len);
1333 setstakey_para.algorithm = (u8)sta->dot118021XPrivacy;
1334 }
1335 #endif /* CONFIG_TDLS */
1336
1337 /* jeff: set this becasue at least sw key is ready */
1338 padapter->securitypriv.busetkipkey = _TRUE;
1339
1340 if (enqueue) {
1341 set_stakey_hdl(padapter, &setstakey_para, PHL_CMD_NO_WAIT, 0);
1342 } else {
1343 set_stakey_hdl(padapter, &setstakey_para, PHL_CMD_DIRECTLY, 0);
1344 }
1345 exit:
1346 return res;
1347 }
1348
rtw_clearstakey_cmd(_adapter * padapter,struct sta_info * sta,u8 enqueue)1349 u8 rtw_clearstakey_cmd(_adapter *padapter, struct sta_info *sta, u8 enqueue)
1350 {
1351 struct cmd_obj *cmd;
1352 struct set_stakey_parm *psetstakey_para;
1353 struct cmd_priv *pcmdpriv = &adapter_to_dvobj(padapter)->cmdpriv;
1354 struct set_stakey_rsp *psetstakey_rsp = NULL;
1355 s16 cam_id = 0;
1356 u8 res = _SUCCESS;
1357
1358 if (!sta) {
1359 RTW_ERR("%s sta == NULL\n", __func__);
1360 goto exit;
1361 }
1362
1363 if (!enqueue)
1364 rtw_hw_del_all_key(padapter, sta, PHL_CMD_DIRECTLY, 0);
1365 else
1366 rtw_hw_del_all_key(padapter, sta, PHL_CMD_NO_WAIT, 0);
1367
1368 exit:
1369
1370
1371 return res;
1372 }
1373 #else /* CONFIG_FSM */
rtw_setstakey_cmd(_adapter * padapter,struct sta_info * sta,u8 key_type,bool enqueue)1374 u8 rtw_setstakey_cmd(_adapter *padapter, struct sta_info *sta, u8 key_type, bool enqueue)
1375 {
1376 struct cmd_obj *pcmd;
1377 struct set_stakey_parm *psetstakey_para;
1378 struct cmd_priv *pcmdpriv = &adapter_to_dvobj(padapter)->cmdpriv;
1379 struct set_stakey_rsp *psetstakey_rsp = NULL;
1380
1381 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1382 struct security_priv *psecuritypriv = &padapter->securitypriv;
1383 u8 key_len =16;
1384 u8 res = _SUCCESS;
1385
1386
1387 psetstakey_para = (struct set_stakey_parm *)rtw_zmalloc(sizeof(struct set_stakey_parm));
1388 if (psetstakey_para == NULL) {
1389 res = _FAIL;
1390 goto exit;
1391 }
1392
1393 _rtw_memcpy(psetstakey_para->addr, sta->phl_sta->mac_addr, ETH_ALEN);
1394
1395 if (MLME_IS_STA(padapter))
1396 psetstakey_para->algorithm = (unsigned char) psecuritypriv->dot11PrivacyAlgrthm;
1397 else
1398 GET_ENCRY_ALGO(psecuritypriv, sta, psetstakey_para->algorithm, _FALSE);
1399
1400 if ((psetstakey_para->algorithm == _GCMP_256_) || (psetstakey_para->algorithm == _CCMP_256_))
1401 key_len = 32;
1402
1403 if (key_type == GROUP_KEY) {
1404 _rtw_memcpy(&psetstakey_para->key, &psecuritypriv->dot118021XGrpKey[psecuritypriv->dot118021XGrpKeyid].skey, key_len);
1405 psetstakey_para->gk = 1;
1406 } else if (key_type == UNICAST_KEY)
1407 _rtw_memcpy(&psetstakey_para->key, &sta->dot118021x_UncstKey, key_len);
1408 #ifdef CONFIG_TDLS
1409 else if (key_type == TDLS_KEY) {
1410 _rtw_memcpy(&psetstakey_para->key, sta->tpk.tk, key_len);
1411 psetstakey_para->algorithm = (u8)sta->dot118021XPrivacy;
1412 }
1413 #endif /* CONFIG_TDLS */
1414
1415 /* jeff: set this becasue at least sw key is ready */
1416 padapter->securitypriv.busetkipkey = _TRUE;
1417
1418 if (enqueue) {
1419 pcmd = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
1420 if (pcmd == NULL) {
1421 rtw_mfree((u8 *) psetstakey_para, sizeof(struct set_stakey_parm));
1422 res = _FAIL;
1423 goto exit;
1424 }
1425 pcmd->padapter = padapter;
1426
1427 psetstakey_rsp = (struct set_stakey_rsp *)rtw_zmalloc(sizeof(struct set_stakey_rsp));
1428 if (psetstakey_rsp == NULL) {
1429 rtw_mfree((u8 *) pcmd, sizeof(struct cmd_obj));
1430 rtw_mfree((u8 *) psetstakey_para, sizeof(struct set_stakey_parm));
1431 res = _FAIL;
1432 goto exit;
1433 }
1434
1435 init_h2fwcmd_w_parm_no_rsp(pcmd, psetstakey_para, CMD_SET_STAKEY);
1436 pcmd->rsp = (u8 *) psetstakey_rsp;
1437 pcmd->rspsz = sizeof(struct set_stakey_rsp);
1438 res = rtw_enqueue_cmd(pcmdpriv, pcmd);
1439 } else {
1440 set_stakey_hdl(padapter, (u8 *)psetstakey_para);
1441 rtw_mfree((u8 *) psetstakey_para, sizeof(struct set_stakey_parm));
1442 }
1443 exit:
1444 return res;
1445 }
1446
rtw_clearstakey_cmd(_adapter * padapter,struct sta_info * sta,u8 enqueue)1447 u8 rtw_clearstakey_cmd(_adapter *padapter, struct sta_info *sta, u8 enqueue)
1448 {
1449 struct cmd_obj *cmd;
1450 struct set_stakey_parm *psetstakey_para;
1451 struct cmd_priv *pcmdpriv = &adapter_to_dvobj(padapter)->cmdpriv;
1452 struct set_stakey_rsp *psetstakey_rsp = NULL;
1453 s16 cam_id = 0;
1454 u8 res = _SUCCESS;
1455
1456 if (!sta) {
1457 RTW_ERR("%s sta == NULL\n", __func__);
1458 goto exit;
1459 }
1460
1461 if (!enqueue) {
1462 rtw_hw_del_all_key(padapter, sta, PHL_CMD_DIRECTLY, 0);
1463 } else {
1464 cmd = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
1465 if (cmd == NULL) {
1466 res = _FAIL;
1467 goto exit;
1468 }
1469
1470 psetstakey_para = (struct set_stakey_parm *)rtw_zmalloc(sizeof(struct set_stakey_parm));
1471 if (psetstakey_para == NULL) {
1472 rtw_mfree((u8 *)cmd, sizeof(struct cmd_obj));
1473 res = _FAIL;
1474 goto exit;
1475 }
1476 cmd->padapter = padapter;
1477
1478 psetstakey_rsp = (struct set_stakey_rsp *)rtw_zmalloc(sizeof(struct set_stakey_rsp));
1479 if (psetstakey_rsp == NULL) {
1480 rtw_mfree((u8 *)cmd, sizeof(struct cmd_obj));
1481 rtw_mfree((u8 *)psetstakey_para, sizeof(struct set_stakey_parm));
1482 res = _FAIL;
1483 goto exit;
1484 }
1485
1486 init_h2fwcmd_w_parm_no_rsp(cmd, psetstakey_para, CMD_SET_STAKEY);
1487 cmd->rsp = (u8 *) psetstakey_rsp;
1488 cmd->rspsz = sizeof(struct set_stakey_rsp);
1489
1490 _rtw_memcpy(psetstakey_para->addr, sta->phl_sta->mac_addr, ETH_ALEN);
1491
1492 psetstakey_para->algorithm = _NO_PRIVACY_;
1493
1494 res = rtw_enqueue_cmd(pcmdpriv, cmd);
1495
1496 }
1497
1498 exit:
1499
1500
1501 return res;
1502 }
1503 #endif
1504
rtw_addbareq_cmd(_adapter * padapter,u8 tid,u8 * addr)1505 u8 rtw_addbareq_cmd(_adapter *padapter, u8 tid, u8 *addr)
1506 {
1507 struct cmd_priv *pcmdpriv = &adapter_to_dvobj(padapter)->cmdpriv;
1508 struct cmd_obj *cmd;
1509 struct addBaReq_parm *paddbareq_parm;
1510
1511 u8 res = _SUCCESS;
1512
1513
1514 cmd = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
1515 if (cmd == NULL) {
1516 res = _FAIL;
1517 goto exit;
1518 }
1519 cmd->padapter = padapter;
1520
1521 paddbareq_parm = (struct addBaReq_parm *)rtw_zmalloc(sizeof(struct addBaReq_parm));
1522 if (paddbareq_parm == NULL) {
1523 rtw_mfree((unsigned char *)cmd, sizeof(struct cmd_obj));
1524 res = _FAIL;
1525 goto exit;
1526 }
1527
1528 paddbareq_parm->tid = tid;
1529 _rtw_memcpy(paddbareq_parm->addr, addr, ETH_ALEN);
1530
1531 init_h2fwcmd_w_parm_no_rsp(cmd, paddbareq_parm, CMD_ADD_BAREQ);
1532
1533 /* RTW_INFO("rtw_addbareq_cmd, tid=%d\n", tid); */
1534
1535 /* rtw_enqueue_cmd(pcmdpriv, ph2c); */
1536 res = rtw_enqueue_cmd(pcmdpriv, cmd);
1537
1538 exit:
1539 return res;
1540 }
1541
rtw_addbarsp_cmd(_adapter * padapter,u8 * addr,u16 tid,struct ADDBA_request * paddba_req,u8 status,u8 size,u16 start_seq)1542 u8 rtw_addbarsp_cmd(_adapter *padapter, u8 *addr, u16 tid,
1543 struct ADDBA_request *paddba_req, u8 status,
1544 u8 size, u16 start_seq)
1545 {
1546 struct cmd_priv *pcmdpriv = &adapter_to_dvobj(padapter)->cmdpriv;
1547 struct cmd_obj *cmd;
1548 struct addBaRsp_parm *paddBaRsp_parm;
1549 u8 res = _SUCCESS;
1550
1551
1552 cmd = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
1553 if (cmd == NULL) {
1554 res = _FAIL;
1555 goto exit;
1556 }
1557 cmd->padapter = padapter;
1558
1559 paddBaRsp_parm = (struct addBaRsp_parm *)rtw_zmalloc(sizeof(struct addBaRsp_parm));
1560
1561 if (paddBaRsp_parm == NULL) {
1562 rtw_mfree((unsigned char *)cmd, sizeof(struct cmd_obj));
1563 res = _FAIL;
1564 goto exit;
1565 }
1566
1567 _rtw_memcpy(paddBaRsp_parm->addr, addr, ETH_ALEN);
1568 _rtw_memcpy(&(paddBaRsp_parm->preq), paddba_req, sizeof(struct ADDBA_request));
1569 paddBaRsp_parm->tid = tid;
1570 paddBaRsp_parm->status = status;
1571 paddBaRsp_parm->size = size;
1572 paddBaRsp_parm->start_seq = start_seq;
1573
1574 init_h2fwcmd_w_parm_no_rsp(cmd, paddBaRsp_parm, CMD_ADD_BARSP);
1575
1576 res = rtw_enqueue_cmd(pcmdpriv, cmd);
1577
1578 exit:
1579
1580
1581 return res;
1582 }
1583
rtw_delba_cmd(struct _ADAPTER * a,u8 * addr,u16 tid)1584 u8 rtw_delba_cmd(struct _ADAPTER *a, u8 *addr, u16 tid)
1585 {
1586 struct cmd_priv *cmdpriv = &adapter_to_dvobj(a)->cmdpriv;
1587 struct cmd_obj *cmd = NULL;
1588 struct addBaReq_parm *parm = NULL;
1589
1590
1591 cmd = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
1592 if (!cmd)
1593 return _FAIL;
1594 cmd->padapter = a;
1595
1596 parm = (struct addBaReq_parm *)rtw_zmalloc(sizeof(struct addBaReq_parm));
1597 if (!parm) {
1598 rtw_mfree(cmd, sizeof(struct cmd_obj));
1599 return _FAIL;
1600 }
1601
1602 parm->tid = tid;
1603 _rtw_memcpy(parm->addr, addr, ETH_ALEN);
1604 init_h2fwcmd_w_parm_no_rsp(cmd, parm, CMD_DELBA);
1605
1606 return rtw_enqueue_cmd(cmdpriv, cmd);
1607 }
1608
1609 /* add for CONFIG_IEEE80211W, none 11w can use it */
rtw_reset_securitypriv_cmd(_adapter * padapter)1610 u8 rtw_reset_securitypriv_cmd(_adapter *padapter)
1611 {
1612 struct cmd_obj *cmd;
1613 struct drvextra_cmd_parm *pdrvextra_cmd_parm;
1614 struct cmd_priv *pcmdpriv = &adapter_to_dvobj(padapter)->cmdpriv;
1615 u8 res = _SUCCESS;
1616
1617
1618 cmd = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
1619 if (cmd == NULL) {
1620 res = _FAIL;
1621 goto exit;
1622 }
1623 cmd->padapter = padapter;
1624
1625 pdrvextra_cmd_parm = (struct drvextra_cmd_parm *)rtw_zmalloc(sizeof(struct drvextra_cmd_parm));
1626 if (pdrvextra_cmd_parm == NULL) {
1627 rtw_mfree((unsigned char *)cmd, sizeof(struct cmd_obj));
1628 res = _FAIL;
1629 goto exit;
1630 }
1631
1632 pdrvextra_cmd_parm->ec_id = RESET_SECURITYPRIV;
1633 pdrvextra_cmd_parm->type = 0;
1634 pdrvextra_cmd_parm->size = 0;
1635 pdrvextra_cmd_parm->pbuf = NULL;
1636
1637 init_h2fwcmd_w_parm_no_rsp(cmd, pdrvextra_cmd_parm, CMD_SET_DRV_EXTRA);
1638
1639
1640 /* rtw_enqueue_cmd(pcmdpriv, ph2c); */
1641 res = rtw_enqueue_cmd(pcmdpriv, cmd);
1642
1643 exit:
1644 return res;
1645
1646 }
1647
free_assoc_resources_hdl(_adapter * padapter,u8 lock_scanned_queue)1648 void free_assoc_resources_hdl(_adapter *padapter, u8 lock_scanned_queue)
1649 {
1650 rtw_free_assoc_resources(padapter, lock_scanned_queue);
1651 }
1652
rtw_free_assoc_resources_cmd(_adapter * padapter,u8 lock_scanned_queue,int flags)1653 u8 rtw_free_assoc_resources_cmd(_adapter *padapter, u8 lock_scanned_queue, int flags)
1654 {
1655 struct cmd_obj *cmd;
1656 struct drvextra_cmd_parm *pdrvextra_cmd_parm;
1657 struct cmd_priv *pcmdpriv = &adapter_to_dvobj(padapter)->cmdpriv;
1658 struct submit_ctx sctx;
1659 u8 res = _SUCCESS;
1660
1661 if (flags & RTW_CMDF_DIRECTLY) {
1662 free_assoc_resources_hdl(padapter, lock_scanned_queue);
1663 }
1664 else {
1665 cmd = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
1666 if (cmd == NULL) {
1667 res = _FAIL;
1668 goto exit;
1669 }
1670 cmd->padapter = padapter;
1671
1672 pdrvextra_cmd_parm = (struct drvextra_cmd_parm *)rtw_zmalloc(sizeof(struct drvextra_cmd_parm));
1673 if (pdrvextra_cmd_parm == NULL) {
1674 rtw_mfree((unsigned char *)cmd, sizeof(struct cmd_obj));
1675 res = _FAIL;
1676 goto exit;
1677 }
1678
1679 pdrvextra_cmd_parm->ec_id = FREE_ASSOC_RESOURCES;
1680 pdrvextra_cmd_parm->type = lock_scanned_queue;
1681 pdrvextra_cmd_parm->size = 0;
1682 pdrvextra_cmd_parm->pbuf = NULL;
1683
1684 init_h2fwcmd_w_parm_no_rsp(cmd, pdrvextra_cmd_parm, CMD_SET_DRV_EXTRA);
1685 if (flags & RTW_CMDF_WAIT_ACK) {
1686 cmd->sctx = &sctx;
1687 rtw_sctx_init(&sctx, 2000);
1688 }
1689
1690 res = rtw_enqueue_cmd(pcmdpriv, cmd);
1691
1692 if (res == _SUCCESS && (flags & RTW_CMDF_WAIT_ACK)) {
1693 rtw_sctx_wait(&sctx, __func__);
1694 _rtw_mutex_lock_interruptible(&pcmdpriv->sctx_mutex);
1695 if (sctx.status == RTW_SCTX_SUBMITTED)
1696 cmd->sctx = NULL;
1697 _rtw_mutex_unlock(&pcmdpriv->sctx_mutex);
1698 }
1699 }
1700 exit:
1701 return res;
1702
1703 }
1704 #if 0 /*#ifdef CONFIG_CORE_DM_CHK_TIMER*/
1705 u8 rtw_dynamic_chk_wk_cmd(_adapter *padapter)
1706 {
1707 struct cmd_obj *cmd;
1708 struct drvextra_cmd_parm *pdrvextra_cmd_parm;
1709 struct cmd_priv *pcmdpriv = &adapter_to_dvobj(padapter)->cmdpriv;
1710 u8 res = _SUCCESS;
1711
1712
1713 /* only primary padapter does this cmd */
1714
1715 cmd = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
1716 if (cmd == NULL) {
1717 res = _FAIL;
1718 goto exit;
1719 }
1720 cmd->padapter = padapter;
1721
1722 pdrvextra_cmd_parm = (struct drvextra_cmd_parm *)rtw_zmalloc(sizeof(struct drvextra_cmd_parm));
1723 if (pdrvextra_cmd_parm == NULL) {
1724 rtw_mfree((unsigned char *)cmd, sizeof(struct cmd_obj));
1725 res = _FAIL;
1726 goto exit;
1727 }
1728
1729 pdrvextra_cmd_parm->ec_id = DYNAMIC_CHK_WK_CID;
1730 pdrvextra_cmd_parm->type = 0;
1731 pdrvextra_cmd_parm->size = 0;
1732 pdrvextra_cmd_parm->pbuf = NULL;
1733 init_h2fwcmd_w_parm_no_rsp(cmd, pdrvextra_cmd_parm, CMD_SET_DRV_EXTRA);
1734
1735
1736 /* rtw_enqueue_cmd(pcmdpriv, ph2c); */
1737 res = rtw_enqueue_cmd(pcmdpriv, cmd);
1738
1739 exit:
1740 return res;
1741 }
1742 #endif
rtw_set_chbw_cmd(_adapter * padapter,u8 ch,u8 bw,u8 ch_offset,u8 flags)1743 u8 rtw_set_chbw_cmd(_adapter *padapter, u8 ch, u8 bw, u8 ch_offset, u8 flags)
1744 {
1745 struct cmd_obj *pcmdobj;
1746 struct set_ch_parm *set_ch_parm;
1747 struct cmd_priv *pcmdpriv = &adapter_to_dvobj(padapter)->cmdpriv;
1748 struct submit_ctx sctx;
1749 u8 res = _SUCCESS;
1750
1751
1752 RTW_INFO(FUNC_NDEV_FMT" ch:%u, bw:%u, ch_offset:%u\n",
1753 FUNC_NDEV_ARG(padapter->pnetdev), ch, bw, ch_offset);
1754
1755 /* check input parameter */
1756
1757 /* prepare cmd parameter */
1758 set_ch_parm = (struct set_ch_parm *)rtw_zmalloc(sizeof(*set_ch_parm));
1759 if (set_ch_parm == NULL) {
1760 res = _FAIL;
1761 goto exit;
1762 }
1763 set_ch_parm->ch = ch;
1764 set_ch_parm->bw = bw;
1765 set_ch_parm->ch_offset = ch_offset;
1766 set_ch_parm->do_rfk = _FALSE;/*TODO - Need check if do_rfk*/
1767
1768 if (flags & RTW_CMDF_DIRECTLY) {
1769 /* no need to enqueue, do the cmd hdl directly and free cmd parameter */
1770 if (H2C_SUCCESS != rtw_set_chbw_hdl(padapter, (u8 *)set_ch_parm))
1771 res = _FAIL;
1772
1773 rtw_mfree((u8 *)set_ch_parm, sizeof(*set_ch_parm));
1774 } else {
1775 /* need enqueue, prepare cmd_obj and enqueue */
1776 pcmdobj = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
1777 if (pcmdobj == NULL) {
1778 rtw_mfree((u8 *)set_ch_parm, sizeof(*set_ch_parm));
1779 res = _FAIL;
1780 goto exit;
1781 }
1782 pcmdobj->padapter = padapter;
1783
1784 init_h2fwcmd_w_parm_no_rsp(pcmdobj, set_ch_parm, CMD_SET_CHANNEL);
1785
1786 if (flags & RTW_CMDF_WAIT_ACK) {
1787 pcmdobj->sctx = &sctx;
1788 rtw_sctx_init(&sctx, 10 * 1000);
1789 }
1790
1791 res = rtw_enqueue_cmd(pcmdpriv, pcmdobj);
1792
1793 if (res == _SUCCESS && (flags & RTW_CMDF_WAIT_ACK)) {
1794 rtw_sctx_wait(&sctx, __func__);
1795 _rtw_mutex_lock_interruptible(&pcmdpriv->sctx_mutex);
1796 if (sctx.status == RTW_SCTX_SUBMITTED)
1797 pcmdobj->sctx = NULL;
1798 _rtw_mutex_unlock(&pcmdpriv->sctx_mutex);
1799 }
1800 }
1801
1802 /* do something based on res... */
1803 exit:
1804 RTW_INFO(FUNC_NDEV_FMT" res:%u\n", FUNC_NDEV_ARG(padapter->pnetdev), res);
1805 return res;
1806 }
1807
_rtw_set_chplan_cmd(_adapter * adapter,int flags,u8 chplan,u8 chplan_6g,const struct country_chplan * country_ent,enum regd_src_t regd_src,enum rtw_regd_inr inr,const struct country_ie_slave_record * cisr)1808 static u8 _rtw_set_chplan_cmd(_adapter *adapter, int flags
1809 , u8 chplan, u8 chplan_6g, const struct country_chplan *country_ent
1810 , enum regd_src_t regd_src, enum rtw_regd_inr inr
1811 , const struct country_ie_slave_record *cisr)
1812 {
1813 struct cmd_obj *cmdobj;
1814 struct SetChannelPlan_param *parm;
1815 struct cmd_priv *pcmdpriv = &adapter_to_dvobj(adapter)->cmdpriv;
1816 struct submit_ctx sctx;
1817 #ifdef PLATFORM_LINUX
1818 bool rtnl_lock_needed = rtw_rtnl_lock_needed(adapter_to_dvobj(adapter));
1819 #endif
1820 u8 res = _SUCCESS;
1821
1822 /* check if allow software config */
1823 if (rtw_rfctl_is_disable_sw_channel_plan(adapter_to_dvobj(adapter)) == _TRUE) {
1824 res = _FAIL;
1825 goto exit;
1826 }
1827
1828 if (country_ent) {
1829 /* if country_entry is provided, replace chplan */
1830 chplan = country_ent->chplan;
1831 #if CONFIG_IEEE80211_BAND_6GHZ
1832 chplan_6g = country_ent->chplan_6g;
1833 #endif
1834 }
1835
1836 /* prepare cmd parameter */
1837 parm = (struct SetChannelPlan_param *)rtw_zmalloc(sizeof(*parm));
1838 if (parm == NULL) {
1839 res = _FAIL;
1840 goto exit;
1841 }
1842 parm->regd_src = regd_src;
1843 parm->inr = inr;
1844 if (country_ent) {
1845 _rtw_memcpy(&parm->country_ent, country_ent, sizeof(parm->country_ent));
1846 parm->has_country = 1;
1847 }
1848 parm->channel_plan = chplan;
1849 #if CONFIG_IEEE80211_BAND_6GHZ
1850 parm->channel_plan_6g = chplan_6g;
1851 #endif
1852 #ifdef CONFIG_80211D
1853 if (cisr) {
1854 _rtw_memcpy(&parm->cisr, cisr, sizeof(*cisr));
1855 parm->has_cisr = 1;
1856 }
1857 #endif
1858 #ifdef PLATFORM_LINUX
1859 if (flags & (RTW_CMDF_DIRECTLY | RTW_CMDF_WAIT_ACK))
1860 parm->rtnl_lock_needed = rtnl_lock_needed; /* synchronous call, follow caller's */
1861 else
1862 parm->rtnl_lock_needed = 1; /* asynchronous call, always needed */
1863 #endif
1864
1865 if (flags & RTW_CMDF_DIRECTLY) {
1866 /* no need to enqueue, do the cmd hdl directly and free cmd parameter */
1867 if (H2C_SUCCESS != rtw_set_chplan_hdl(adapter, (u8 *)parm))
1868 res = _FAIL;
1869 rtw_mfree((u8 *)parm, sizeof(*parm));
1870 } else {
1871 /* need enqueue, prepare cmd_obj and enqueue */
1872 cmdobj = (struct cmd_obj *)rtw_zmalloc(sizeof(*cmdobj));
1873 if (cmdobj == NULL) {
1874 res = _FAIL;
1875 rtw_mfree((u8 *)parm, sizeof(*parm));
1876 goto exit;
1877 }
1878 cmdobj->padapter = adapter;
1879
1880 init_h2fwcmd_w_parm_no_rsp(cmdobj, parm, CMD_SET_CHANPLAN);
1881
1882 if (flags & RTW_CMDF_WAIT_ACK) {
1883 cmdobj->sctx = &sctx;
1884 rtw_sctx_init(&sctx, 2000);
1885 }
1886
1887 res = rtw_enqueue_cmd(pcmdpriv, cmdobj);
1888
1889 if (res == _SUCCESS && (flags & RTW_CMDF_WAIT_ACK)) {
1890 rtw_sctx_wait(&sctx, __func__);
1891 _rtw_mutex_lock_interruptible(&pcmdpriv->sctx_mutex);
1892 if (sctx.status == RTW_SCTX_SUBMITTED)
1893 cmdobj->sctx = NULL;
1894 _rtw_mutex_unlock(&pcmdpriv->sctx_mutex);
1895 if (sctx.status != RTW_SCTX_DONE_SUCCESS)
1896 res = _FAIL;
1897 }
1898
1899 /* allow set channel plan when cmd_thread is not running */
1900 if (res != _SUCCESS && (flags & RTW_CMDF_WAIT_ACK)) {
1901 parm = (struct SetChannelPlan_param *)rtw_zmalloc(sizeof(*parm));
1902 if (parm == NULL) {
1903 res = _FAIL;
1904 goto exit;
1905 }
1906 parm->regd_src = regd_src;
1907 parm->inr = inr;
1908 if (country_ent) {
1909 _rtw_memcpy(&parm->country_ent, country_ent, sizeof(parm->country_ent));
1910 parm->has_country = 1;
1911 }
1912 parm->channel_plan = chplan;
1913 #if CONFIG_IEEE80211_BAND_6GHZ
1914 parm->channel_plan_6g = chplan_6g;
1915 #endif
1916 #ifdef CONFIG_80211D
1917 if (cisr) {
1918 _rtw_memcpy(&parm->cisr, cisr, sizeof(*cisr));
1919 parm->has_cisr = 1;
1920 }
1921 #endif
1922 #ifdef PLATFORM_LINUX
1923 parm->rtnl_lock_needed = rtnl_lock_needed; /* synchronous call, follow caller's */
1924 #endif
1925
1926 if (H2C_SUCCESS != rtw_set_chplan_hdl(adapter, (u8 *)parm))
1927 res = _FAIL;
1928 else
1929 res = _SUCCESS;
1930 rtw_mfree((u8 *)parm, sizeof(*parm));
1931 }
1932 }
1933
1934 exit:
1935 return res;
1936 }
1937
rtw_set_chplan_cmd(_adapter * adapter,int flags,u8 chplan,u8 chplan_6g,enum rtw_regd_inr inr)1938 inline u8 rtw_set_chplan_cmd(_adapter *adapter, int flags, u8 chplan, u8 chplan_6g, enum rtw_regd_inr inr)
1939 {
1940 return _rtw_set_chplan_cmd(adapter, flags, chplan, chplan_6g, NULL, REGD_SRC_RTK_PRIV, inr, NULL);
1941 }
1942
rtw_set_country_cmd(_adapter * adapter,int flags,const char * country_code,enum rtw_regd_inr inr)1943 inline u8 rtw_set_country_cmd(_adapter *adapter, int flags, const char *country_code, enum rtw_regd_inr inr)
1944 {
1945 struct country_chplan ent;
1946
1947 if (IS_ALPHA2_WORLDWIDE(country_code)) {
1948 rtw_get_chplan_worldwide(&ent);
1949 goto cmd;
1950 }
1951
1952 if (is_alpha(country_code[0]) == _FALSE
1953 || is_alpha(country_code[1]) == _FALSE
1954 ) {
1955 RTW_PRINT("%s input country_code is not alpha2\n", __func__);
1956 return _FAIL;
1957 }
1958
1959 if (!rtw_get_chplan_from_country(country_code, &ent)) {
1960 RTW_PRINT("%s unsupported country_code:\"%c%c\"\n", __func__, country_code[0], country_code[1]);
1961 return _FAIL;
1962 }
1963
1964 cmd:
1965 RTW_PRINT("%s country_code:\"%c%c\"\n", __func__, country_code[0], country_code[1]);
1966
1967 return _rtw_set_chplan_cmd(adapter, flags, RTW_CHPLAN_UNSPECIFIED, RTW_CHPLAN_6G_UNSPECIFIED, &ent, REGD_SRC_RTK_PRIV, inr, NULL);
1968 }
1969
1970 #ifdef CONFIG_REGD_SRC_FROM_OS
rtw_sync_os_regd_cmd(_adapter * adapter,int flags,const char * country_code,u8 dfs_region,enum rtw_regd_inr inr)1971 inline u8 rtw_sync_os_regd_cmd(_adapter *adapter, int flags, const char *country_code, u8 dfs_region, enum rtw_regd_inr inr)
1972 {
1973 struct country_chplan ent;
1974 struct country_chplan rtk_ent;
1975 bool rtk_ent_exist;
1976
1977 rtk_ent_exist = rtw_get_chplan_from_country(country_code, &rtk_ent);
1978
1979 _rtw_memcpy(ent.alpha2, country_code, 2);
1980
1981 /*
1982 * Regulation follows OS, the internal txpwr limit selection is searched by alpha2
1983 * "00" => WW, others use string mapping
1984 * When no matching txpwr limit selection is found, use
1985 * 1. txpwr lmit selection associated with alpha2 inside driver regulation database
1986 * 2. WW when driver has no support of this alpha2
1987 */
1988
1989 ent.chplan = rtk_ent_exist ? rtk_ent.chplan : RTW_CHPLAN_UNSPECIFIED;
1990 #if CONFIG_IEEE80211_BAND_6GHZ
1991 ent.chplan_6g = rtk_ent_exist ? rtk_ent.chplan_6g : RTW_CHPLAN_6G_UNSPECIFIED;
1992 #endif
1993 ent.edcca_mode_2g_override = rtk_ent_exist ? rtk_ent.edcca_mode_2g_override : RTW_EDCCA_DEF;
1994 #if CONFIG_IEEE80211_BAND_5GHZ
1995 ent.edcca_mode_5g_override = rtk_ent_exist ? rtk_ent.edcca_mode_5g_override : RTW_EDCCA_DEF;
1996 #endif
1997 #if CONFIG_IEEE80211_BAND_6GHZ
1998 ent.edcca_mode_6g_override = rtk_ent_exist ? rtk_ent.edcca_mode_6g_override : RTW_EDCCA_DEF;
1999 #endif
2000 ent.txpwr_lmt_override = rtk_ent_exist ? rtk_ent.txpwr_lmt_override : TXPWR_LMT_DEF;
2001 #if defined(CONFIG_80211AC_VHT) || defined(CONFIG_80211AX_HE)
2002 ent.proto_en = CHPLAN_PROTO_EN_ALL;
2003 #endif
2004
2005 /* TODO: dfs_region */
2006
2007 return _rtw_set_chplan_cmd(adapter, flags, RTW_CHPLAN_UNSPECIFIED, RTW_CHPLAN_6G_UNSPECIFIED, &ent, REGD_SRC_OS, inr, NULL);
2008 }
2009 #endif /* CONFIG_REGD_SRC_FROM_OS */
2010
rtw_get_chplan_cmd(_adapter * adapter,int flags,struct get_chplan_resp ** chplan)2011 u8 rtw_get_chplan_cmd(_adapter *adapter, int flags, struct get_chplan_resp **chplan)
2012 {
2013 struct cmd_obj *cmdobj;
2014 struct get_channel_plan_param *parm;
2015 struct cmd_priv *pcmdpriv = &adapter_to_dvobj(adapter)->cmdpriv;
2016 struct submit_ctx sctx;
2017 u8 res = _FAIL;
2018
2019 if (!(flags & (RTW_CMDF_DIRECTLY | RTW_CMDF_WAIT_ACK)))
2020 goto exit;
2021
2022 /* prepare cmd parameter */
2023 parm = rtw_zmalloc(sizeof(*parm));
2024 if (parm == NULL)
2025 goto exit;
2026 parm->chplan = chplan;
2027
2028 if (flags & RTW_CMDF_DIRECTLY) {
2029 /* no need to enqueue, do the cmd hdl directly and free cmd parameter */
2030 if (H2C_SUCCESS == rtw_get_chplan_hdl(adapter, (u8 *)parm))
2031 res = _SUCCESS;
2032 rtw_mfree((u8 *)parm, sizeof(*parm));
2033 } else {
2034 /* need enqueue, prepare cmd_obj and enqueue */
2035 cmdobj = (struct cmd_obj *)rtw_zmalloc(sizeof(*cmdobj));
2036 if (cmdobj == NULL) {
2037 rtw_mfree((u8 *)parm, sizeof(*parm));
2038 goto exit;
2039 }
2040 cmdobj->padapter = adapter;
2041
2042 init_h2fwcmd_w_parm_no_rsp(cmdobj, parm, CMD_GET_CHANPLAN);
2043
2044 if (flags & RTW_CMDF_WAIT_ACK) {
2045 cmdobj->sctx = &sctx;
2046 rtw_sctx_init(&sctx, 2000);
2047 }
2048
2049 res = rtw_enqueue_cmd(pcmdpriv, cmdobj);
2050
2051 if (res == _SUCCESS && (flags & RTW_CMDF_WAIT_ACK)) {
2052 rtw_sctx_wait(&sctx, __func__);
2053 _rtw_mutex_lock_interruptible(&pcmdpriv->sctx_mutex);
2054 if (sctx.status == RTW_SCTX_SUBMITTED)
2055 cmdobj->sctx = NULL;
2056 _rtw_mutex_unlock(&pcmdpriv->sctx_mutex);
2057 if (sctx.status != RTW_SCTX_DONE_SUCCESS)
2058 res = _FAIL;
2059 }
2060
2061 /* allow get channel plan when cmd_thread is not running */
2062 if (res != _SUCCESS && (flags & RTW_CMDF_WAIT_ACK)) {
2063 parm = rtw_zmalloc(sizeof(*parm));
2064 if (parm == NULL)
2065 goto exit;
2066 parm->chplan = chplan;
2067
2068 if (H2C_SUCCESS == rtw_get_chplan_hdl(adapter, (u8 *)parm))
2069 res = _SUCCESS;
2070
2071 rtw_mfree((u8 *)parm, sizeof(*parm));
2072 }
2073 }
2074
2075 exit:
2076 return res;
2077 }
2078
2079 #ifdef CONFIG_80211D
rtw_apply_recv_country_ie_cmd(_adapter * adapter,int flags,enum band_type band,u8 opch,const u8 * country_ie)2080 inline u8 rtw_apply_recv_country_ie_cmd(_adapter *adapter, int flags, enum band_type band,u8 opch, const u8 *country_ie)
2081 {
2082 struct country_chplan ent;
2083 struct country_ie_slave_record cisr;
2084
2085 rtw_get_chplan_from_recv_country_ie(adapter, band, opch, country_ie, &ent, &cisr, NULL);
2086
2087 return _rtw_set_chplan_cmd(adapter, flags, RTW_CHPLAN_UNSPECIFIED, RTW_CHPLAN_6G_UNSPECIFIED
2088 , NULL, REGD_SRC_RTK_PRIV, RTW_REGD_SET_BY_COUNTRY_IE, &cisr);
2089 }
2090 #endif /* CONFIG_80211D */
2091
2092 #ifdef CONFIG_RTW_LED_HANDLED_BY_CMD_THREAD
rtw_led_blink_cmd(_adapter * padapter,void * pLed)2093 u8 rtw_led_blink_cmd(_adapter *padapter, void *pLed)
2094 {
2095 struct cmd_obj *pcmdobj;
2096 struct LedBlink_param *ledBlink_param;
2097 struct cmd_priv *pcmdpriv = &adapter_to_dvobj(padapter)->cmdpriv;
2098 u8 res = _SUCCESS;
2099
2100 pcmdobj = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
2101 if (pcmdobj == NULL) {
2102 res = _FAIL;
2103 goto exit;
2104 }
2105 pcmdobj->padapter = padapter;
2106
2107 ledBlink_param = (struct LedBlink_param *)rtw_zmalloc(sizeof(struct LedBlink_param));
2108 if (ledBlink_param == NULL) {
2109 rtw_mfree((u8 *)pcmdobj, sizeof(struct cmd_obj));
2110 res = _FAIL;
2111 goto exit;
2112 }
2113
2114 ledBlink_param->pLed = pLed;
2115
2116 init_h2fwcmd_w_parm_no_rsp(pcmdobj, ledBlink_param, CMD_LEDBLINK);
2117 res = rtw_enqueue_cmd(pcmdpriv, pcmdobj);
2118
2119 exit:
2120 return res;
2121 }
2122 #endif /*CONFIG_RTW_LED_HANDLED_BY_CMD_THREAD*/
2123
rtw_set_csa_cmd(_adapter * adapter)2124 u8 rtw_set_csa_cmd(_adapter *adapter)
2125 {
2126 struct cmd_obj *cmdobj;
2127 struct cmd_priv *cmdpriv = &adapter_to_dvobj(adapter)->cmdpriv;
2128 u8 res = _SUCCESS;
2129
2130 cmdobj = rtw_zmalloc(sizeof(struct cmd_obj));
2131 if (cmdobj == NULL) {
2132 res = _FAIL;
2133 goto exit;
2134 }
2135 cmdobj->padapter = adapter;
2136
2137 init_h2fwcmd_w_parm_no_parm_rsp(cmdobj, CMD_SET_CHANSWITCH);
2138 res = rtw_enqueue_cmd(cmdpriv, cmdobj);
2139
2140 exit:
2141 return res;
2142 }
2143
rtw_tdls_cmd(_adapter * padapter,u8 * addr,u8 option)2144 u8 rtw_tdls_cmd(_adapter *padapter, u8 *addr, u8 option)
2145 {
2146 u8 res = _SUCCESS;
2147 #ifdef CONFIG_TDLS
2148 struct cmd_obj *pcmdobj;
2149 struct TDLSoption_param *TDLSoption;
2150 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
2151 struct cmd_priv *pcmdpriv = &adapter_to_dvobj(padapter)->cmdpriv;
2152
2153 pcmdobj = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
2154 if (pcmdobj == NULL) {
2155 res = _FAIL;
2156 goto exit;
2157 }
2158 pcmdobj->padapter = padapter;
2159
2160 TDLSoption = (struct TDLSoption_param *)rtw_zmalloc(sizeof(struct TDLSoption_param));
2161 if (TDLSoption == NULL) {
2162 rtw_mfree((u8 *)pcmdobj, sizeof(struct cmd_obj));
2163 res = _FAIL;
2164 goto exit;
2165 }
2166
2167 _rtw_spinlock(&(padapter->tdlsinfo.cmd_lock));
2168 if (addr != NULL)
2169 _rtw_memcpy(TDLSoption->addr, addr, 6);
2170 TDLSoption->option = option;
2171 _rtw_spinunlock(&(padapter->tdlsinfo.cmd_lock));
2172 init_h2fwcmd_w_parm_no_rsp(pcmdobj, TDLSoption, CMD_TDLS);
2173 res = rtw_enqueue_cmd(pcmdpriv, pcmdobj);
2174
2175 exit:
2176 #endif /* CONFIG_TDLS */
2177
2178 return res;
2179 }
2180
rtw_ssmps_wk_hdl(_adapter * adapter,struct ssmps_cmd_parm * ssmp_param)2181 u8 rtw_ssmps_wk_hdl(_adapter *adapter, struct ssmps_cmd_parm *ssmp_param)
2182 {
2183 u8 res = _SUCCESS;
2184 struct sta_info *sta = ssmp_param->sta;
2185 u8 smps = ssmp_param->smps;
2186
2187 if (sta == NULL)
2188 return _FALSE;
2189
2190 if (smps)
2191 rtw_ssmps_enter(adapter, sta);
2192 else
2193 rtw_ssmps_leave(adapter, sta);
2194 return res;
2195 }
2196
rtw_ssmps_wk_cmd(_adapter * adapter,struct sta_info * sta,u8 smps,u8 enqueue)2197 u8 rtw_ssmps_wk_cmd(_adapter *adapter, struct sta_info *sta, u8 smps, u8 enqueue)
2198 {
2199 struct cmd_obj *cmdobj;
2200 struct drvextra_cmd_parm *cmd_parm;
2201 struct ssmps_cmd_parm *ssmp_param;
2202 struct cmd_priv *pcmdpriv = &adapter_to_dvobj(adapter)->cmdpriv;
2203 u8 res = _SUCCESS;
2204
2205 if (enqueue) {
2206 cmdobj = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
2207 if (cmdobj == NULL) {
2208 res = _FAIL;
2209 goto exit;
2210 }
2211 cmdobj->padapter = adapter;
2212
2213 cmd_parm = (struct drvextra_cmd_parm *)rtw_zmalloc(sizeof(struct drvextra_cmd_parm));
2214 if (cmd_parm == NULL) {
2215 rtw_mfree((unsigned char *)cmdobj, sizeof(struct cmd_obj));
2216 res = _FAIL;
2217 goto exit;
2218 }
2219
2220 ssmp_param = (struct ssmps_cmd_parm *)rtw_zmalloc(sizeof(struct ssmps_cmd_parm));
2221 if (ssmp_param == NULL) {
2222 rtw_mfree((u8 *)cmdobj, sizeof(struct cmd_obj));
2223 rtw_mfree((u8 *)cmd_parm, sizeof(struct drvextra_cmd_parm));
2224 res = _FAIL;
2225 goto exit;
2226 }
2227
2228 ssmp_param->smps = smps;
2229 ssmp_param->sta = sta;
2230
2231 cmd_parm->ec_id = SSMPS_WK_CID;
2232 cmd_parm->type = 0;
2233 cmd_parm->size = sizeof(struct ssmps_cmd_parm);
2234 cmd_parm->pbuf = (u8 *)ssmp_param;
2235
2236 init_h2fwcmd_w_parm_no_rsp(cmdobj, cmd_parm, CMD_SET_DRV_EXTRA);
2237
2238 res = rtw_enqueue_cmd(pcmdpriv, cmdobj);
2239 } else {
2240 struct ssmps_cmd_parm tmp_ssmp_param;
2241
2242 tmp_ssmp_param.smps = smps;
2243 tmp_ssmp_param.sta = sta;
2244 rtw_ssmps_wk_hdl(adapter, &tmp_ssmp_param);
2245 }
2246
2247 exit:
2248 return res;
2249 }
2250
2251 #ifdef CONFIG_SUPPORT_STATIC_SMPS
_ssmps_chk_by_tp(_adapter * adapter,u8 from_timer)2252 u8 _ssmps_chk_by_tp(_adapter *adapter, u8 from_timer)
2253 {
2254 u8 enter_smps = _FALSE;
2255 struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
2256 struct mlme_ext_priv *pmlmeext = &(adapter->mlmeextpriv);
2257 struct sta_priv *pstapriv = &adapter->stapriv;
2258 struct sta_info *psta;
2259 u32 tx_tp_mbits, rx_tp_mbits;
2260
2261 if (!MLME_IS_STA(adapter) ||
2262 !rtw_hw_is_mimo_support(adapter) ||
2263 !pmlmeext->ssmps_en ||
2264 (pmlmeext->chandef.chan > 14)
2265 )
2266 return enter_smps;
2267
2268 psta = rtw_get_stainfo(pstapriv, get_bssid(pmlmepriv));
2269 if (psta == NULL) {
2270 RTW_ERR(ADPT_FMT" sta == NULL\n", ADPT_ARG(adapter));
2271 rtw_warn_on(1);
2272 return enter_smps;
2273 }
2274 /*TODO*/
2275 if (psta->phl_sta->asoc_cap.nss_tx == 1)
2276 return enter_smps;
2277
2278 tx_tp_mbits = psta->sta_stats.tx_tp_kbits >> 10;
2279 rx_tp_mbits = psta->sta_stats.rx_tp_kbits >> 10;
2280
2281 #ifdef DBG_STATIC_SMPS
2282 if (pmlmeext->ssmps_test) {
2283 enter_smps = (pmlmeext->ssmps_test_en == 1) ? _TRUE : _FALSE;
2284 }
2285 else
2286 #endif
2287 {
2288 if ((tx_tp_mbits <= pmlmeext->ssmps_tx_tp_th) &&
2289 (rx_tp_mbits <= pmlmeext->ssmps_rx_tp_th))
2290 enter_smps = _TRUE;
2291 else
2292 enter_smps = _FALSE;
2293 }
2294
2295 if (1) {
2296 RTW_INFO(FUNC_ADPT_FMT" tx_tp:%d [%d], rx_tp:%d [%d] , SSMPS enter :%s\n",
2297 FUNC_ADPT_ARG(adapter),
2298 tx_tp_mbits, pmlmeext->ssmps_tx_tp_th,
2299 rx_tp_mbits, pmlmeext->ssmps_rx_tp_th,
2300 (enter_smps == _TRUE) ? "True" : "False");
2301 #ifdef DBG_STATIC_SMPS
2302 RTW_INFO(FUNC_ADPT_FMT" test:%d test_en:%d\n",
2303 FUNC_ADPT_ARG(adapter),
2304 pmlmeext->ssmps_test,
2305 pmlmeext->ssmps_test_en);
2306 #endif
2307 }
2308
2309 if (enter_smps) {
2310 if (!from_timer && psta->phl_sta->sm_ps != SM_PS_STATIC)
2311 rtw_ssmps_enter(adapter, psta);
2312 } else {
2313 if (!from_timer && psta->phl_sta->sm_ps != SM_PS_DISABLE)
2314 rtw_ssmps_leave(adapter, psta);
2315 else {
2316 u8 ps_change = _FALSE;
2317
2318 if (enter_smps && psta->phl_sta->sm_ps != SM_PS_STATIC)
2319 ps_change = _TRUE;
2320 else if (!enter_smps && psta->phl_sta->sm_ps != SM_PS_DISABLE)
2321 ps_change = _TRUE;
2322
2323 if (ps_change)
2324 rtw_ssmps_wk_cmd(adapter, psta, enter_smps, 1);
2325 }
2326 }
2327
2328 return enter_smps;
2329 }
2330 #endif /*CONFIG_SUPPORT_STATIC_SMPS*/
2331
2332 #ifdef CONFIG_CTRL_TXSS_BY_TP
rtw_ctrl_txss_update(_adapter * adapter,struct sta_info * sta)2333 void rtw_ctrl_txss_update(_adapter *adapter, struct sta_info *sta)
2334 {
2335 struct mlme_ext_priv *pmlmeext = &(adapter->mlmeextpriv);
2336
2337 pmlmeext->txss_bk = sta->phl_sta->asoc_cap.nss_rx;
2338 }
2339
rtw_ctrl_txss(_adapter * adapter,struct sta_info * sta,bool tx_1ss)2340 u8 rtw_ctrl_txss(_adapter *adapter, struct sta_info *sta, bool tx_1ss)
2341 {
2342 struct mlme_ext_priv *pmlmeext = &(adapter->mlmeextpriv);
2343 struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(adapter);
2344 u8 lps_changed = _FALSE;
2345 u8 rst = _SUCCESS;
2346
2347 if (pmlmeext->txss_1ss == tx_1ss)
2348 return _FALSE;
2349 /*
2350 if (pwrpriv->bLeisurePs && pwrpriv->pwr_mode != PM_PS_MODE_ACTIVE) {
2351 lps_changed = _TRUE;
2352 LPS_Leave(adapter, "LPS_CTRL_TXSS");
2353 }
2354 */
2355
2356 RTW_INFO(ADPT_FMT" STA [" MAC_FMT "] set tx to %d ss\n",
2357 ADPT_ARG(adapter), MAC_ARG(sta->phl_sta->mac_addr),
2358 (tx_1ss) ? 1 : rtw_get_sta_tx_nss(adapter, sta));
2359
2360 /*update ra*/
2361 if (tx_1ss)
2362 sta->phl_sta->asoc_cap.nss_rx = 1;
2363 else
2364 sta->phl_sta->asoc_cap.nss_rx = pmlmeext->txss_bk;
2365 rtw_phl_cmd_change_stainfo(adapter_to_dvobj(adapter)->phl,
2366 sta->phl_sta,
2367 STA_CHG_RAMASK,
2368 NULL,
2369 0,
2370 PHL_CMD_DIRECTLY,
2371 0);
2372
2373 /*configure trx mode*/
2374 /*rtw_phydm_trx_cfg(adapter, tx_1ss);*/
2375 pmlmeext->txss_1ss = tx_1ss;
2376 /*
2377 if (lps_changed)
2378 LPS_Enter(adapter, "LPS_CTRL_TXSS");
2379 */
2380
2381 return rst;
2382 }
2383
rtw_ctrl_txss_wk_hdl(_adapter * adapter,struct txss_cmd_parm * txss_param)2384 u8 rtw_ctrl_txss_wk_hdl(_adapter *adapter, struct txss_cmd_parm *txss_param)
2385 {
2386 if (!txss_param->sta)
2387 return _FALSE;
2388
2389 return rtw_ctrl_txss(adapter, txss_param->sta, txss_param->tx_1ss);
2390 }
2391
rtw_ctrl_txss_wk_cmd(_adapter * adapter,struct sta_info * sta,bool tx_1ss,u8 flag)2392 u8 rtw_ctrl_txss_wk_cmd(_adapter *adapter, struct sta_info *sta, bool tx_1ss, u8 flag)
2393 {
2394 struct cmd_obj *cmdobj;
2395 struct drvextra_cmd_parm *cmd_parm;
2396 struct txss_cmd_parm *txss_param;
2397 struct cmd_priv *pcmdpriv = &adapter_to_dvobj(adapter)->cmdpriv;
2398 struct submit_ctx sctx;
2399 u8 res = _SUCCESS;
2400
2401 txss_param = (struct txss_cmd_parm *)rtw_zmalloc(sizeof(struct txss_cmd_parm));
2402 if (txss_param == NULL) {
2403 res = _FAIL;
2404 goto exit;
2405 }
2406
2407 txss_param->tx_1ss = tx_1ss;
2408 txss_param->sta = sta;
2409
2410 if (flag & RTW_CMDF_DIRECTLY) {
2411 res = rtw_ctrl_txss_wk_hdl(adapter, txss_param);
2412 rtw_mfree((u8 *)txss_param, sizeof(*txss_param));
2413 } else {
2414 cmdobj = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
2415 if (cmdobj == NULL) {
2416 res = _FAIL;
2417 goto exit;
2418 }
2419 cmdobj->padapter = adapter;
2420
2421 cmd_parm = (struct drvextra_cmd_parm *)rtw_zmalloc(sizeof(struct drvextra_cmd_parm));
2422 if (cmd_parm == NULL) {
2423 rtw_mfree((u8 *)cmdobj, sizeof(struct cmd_obj));
2424 res = _FAIL;
2425 goto exit;
2426 }
2427
2428 cmd_parm->ec_id = TXSS_WK_CID;
2429 cmd_parm->type = 0;
2430 cmd_parm->size = sizeof(struct txss_cmd_parm);
2431 cmd_parm->pbuf = (u8 *)txss_param;
2432
2433 init_h2fwcmd_w_parm_no_rsp(cmdobj, cmd_parm, CMD_SET_DRV_EXTRA);
2434
2435 if (flag & RTW_CMDF_WAIT_ACK) {
2436 cmdobj->sctx = &sctx;
2437 rtw_sctx_init(&sctx, 10 * 1000);
2438 }
2439
2440 res = rtw_enqueue_cmd(pcmdpriv, cmdobj);
2441 if (res == _SUCCESS && (flag & RTW_CMDF_WAIT_ACK)) {
2442 rtw_sctx_wait(&sctx, __func__);
2443 _rtw_mutex_lock_interruptible(&pcmdpriv->sctx_mutex);
2444 if (sctx.status == RTW_SCTX_SUBMITTED)
2445 cmdobj->sctx = NULL;
2446 _rtw_mutex_unlock(&pcmdpriv->sctx_mutex);
2447 if (sctx.status != RTW_SCTX_DONE_SUCCESS)
2448 res = _FAIL;
2449 }
2450 }
2451
2452 exit:
2453 return res;
2454 }
2455
rtw_ctrl_tx_ss_by_tp(_adapter * adapter,u8 from_timer)2456 void rtw_ctrl_tx_ss_by_tp(_adapter *adapter, u8 from_timer)
2457 {
2458 bool tx_1ss = _FALSE; /*change tx from 2ss to 1ss*/
2459 struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
2460 struct mlme_ext_priv *pmlmeext = &(adapter->mlmeextpriv);
2461 struct sta_priv *pstapriv = &adapter->stapriv;
2462 struct sta_info *psta;
2463 u32 tx_tp_mbits;
2464
2465 if (!MLME_IS_STA(adapter) ||
2466 !rtw_hw_is_mimo_support(adapter) ||
2467 !pmlmeext->txss_ctrl_en
2468 )
2469 return;
2470
2471 psta = rtw_get_stainfo(pstapriv, get_bssid(pmlmepriv));
2472 if (psta == NULL) {
2473 RTW_ERR(ADPT_FMT" sta == NULL\n", ADPT_ARG(adapter));
2474 rtw_warn_on(1);
2475 return;
2476 }
2477
2478 tx_tp_mbits = psta->sta_stats.tx_tp_kbits >> 10;
2479 if (tx_tp_mbits >= pmlmeext->txss_tp_th) {
2480 tx_1ss = _FALSE;
2481 } else {
2482 if (pmlmeext->txss_tp_chk_cnt && --pmlmeext->txss_tp_chk_cnt)
2483 tx_1ss = _FALSE;
2484 else
2485 tx_1ss = _TRUE;
2486 }
2487
2488 if (1) {
2489 RTW_INFO(FUNC_ADPT_FMT" tx_tp:%d [%d] tx_1ss(%d):%s\n",
2490 FUNC_ADPT_ARG(adapter),
2491 tx_tp_mbits, pmlmeext->txss_tp_th,
2492 pmlmeext->txss_tp_chk_cnt,
2493 (tx_1ss == _TRUE) ? "True" : "False");
2494 }
2495
2496 if (pmlmeext->txss_1ss != tx_1ss) {
2497 if (from_timer)
2498 rtw_ctrl_txss_wk_cmd(adapter, psta, tx_1ss, 0);
2499 else
2500 rtw_ctrl_txss(adapter, psta, tx_1ss);
2501 }
2502 }
2503 #ifdef DBG_CTRL_TXSS
dbg_ctrl_txss(_adapter * adapter,bool tx_1ss)2504 void dbg_ctrl_txss(_adapter *adapter, bool tx_1ss)
2505 {
2506 struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
2507 struct mlme_ext_priv *pmlmeext = &(adapter->mlmeextpriv);
2508 struct sta_priv *pstapriv = &adapter->stapriv;
2509 struct sta_info *psta;
2510
2511 if (!MLME_IS_STA(adapter) ||
2512 !rtw_hw_is_mimo_support(adapter)
2513 )
2514 return;
2515
2516 psta = rtw_get_stainfo(pstapriv, get_bssid(pmlmepriv));
2517 if (psta == NULL) {
2518 RTW_ERR(ADPT_FMT" sta == NULL\n", ADPT_ARG(adapter));
2519 rtw_warn_on(1);
2520 return;
2521 }
2522
2523 rtw_ctrl_txss(adapter, psta, tx_1ss);
2524 }
2525 #endif
2526 #endif /*CONFIG_CTRL_TXSS_BY_TP*/
2527
2528 #ifdef CONFIG_LPS
2529 #ifdef CONFIG_LPS_CHK_BY_TP
2530 #ifdef LPS_BCN_CNT_MONITOR
_bcn_cnt_expected(struct sta_info * psta)2531 static u8 _bcn_cnt_expected(struct sta_info *psta)
2532 {
2533 _adapter *adapter = psta->padapter;
2534 struct mlme_ext_priv *pmlmeext = &adapter->mlmeextpriv;
2535 struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
2536 u8 dtim = rtw_get_bcn_dtim_period(adapter);
2537 u8 bcn_cnt = 0;
2538
2539 if ((pmlmeinfo->bcn_interval !=0) && (dtim != 0))
2540 bcn_cnt = 2000 / pmlmeinfo->bcn_interval / dtim * 4 / 5; /*2s*/
2541 if (0)
2542 RTW_INFO("%s bcn_cnt:%d\n", __func__, bcn_cnt);
2543
2544 if (bcn_cnt == 0) {
2545 RTW_ERR(FUNC_ADPT_FMT" bcn_cnt == 0\n", FUNC_ADPT_ARG(adapter));
2546 rtw_warn_on(1);
2547 }
2548
2549 return bcn_cnt;
2550 }
2551 #endif
_lps_chk_by_tp(_adapter * adapter,u8 from_timer)2552 u8 _lps_chk_by_tp(_adapter *adapter, u8 from_timer)
2553 {
2554 u8 enter_ps = _FALSE;
2555 struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
2556 struct sta_priv *pstapriv = &adapter->stapriv;
2557 struct sta_info *psta;
2558 struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(adapter);
2559 u32 tx_tp_mbits, rx_tp_mbits, bi_tp_mbits;
2560 u8 rx_bcn_cnt;
2561
2562 psta = rtw_get_stainfo(pstapriv, get_bssid(pmlmepriv));
2563 if (psta == NULL) {
2564 RTW_ERR(ADPT_FMT" sta == NULL\n", ADPT_ARG(adapter));
2565 rtw_warn_on(1);
2566 return enter_ps;
2567 }
2568
2569 rx_bcn_cnt = rtw_get_bcn_cnt(psta->padapter);
2570 psta->sta_stats.acc_tx_bytes = psta->sta_stats.tx_bytes;
2571 psta->sta_stats.acc_rx_bytes = psta->sta_stats.rx_bytes;
2572
2573 #if 1
2574 tx_tp_mbits = psta->sta_stats.tx_tp_kbits >> 10;
2575 rx_tp_mbits = psta->sta_stats.rx_tp_kbits >> 10;
2576 bi_tp_mbits = tx_tp_mbits + rx_tp_mbits;
2577 #else
2578 tx_tp_mbits = psta->sta_stats.smooth_tx_tp_kbits >> 10;
2579 rx_tp_mbits = psta->sta_stats.smooth_rx_tp_kbits >> 10;
2580 bi_tp_mbits = tx_tp_mbits + rx_tp_mbits;
2581 #endif
2582
2583 if ((bi_tp_mbits >= pwrpriv->lps_bi_tp_th) ||
2584 (tx_tp_mbits >= pwrpriv->lps_tx_tp_th) ||
2585 (rx_tp_mbits >= pwrpriv->lps_rx_tp_th)) {
2586 enter_ps = _FALSE;
2587 pwrpriv->lps_chk_cnt = pwrpriv->lps_chk_cnt_th;
2588 }
2589 else {
2590 #ifdef LPS_BCN_CNT_MONITOR
2591 u8 bcn_cnt = _bcn_cnt_expected(psta);
2592
2593 if (bcn_cnt && (rx_bcn_cnt < bcn_cnt)) {
2594 pwrpriv->lps_chk_cnt = 2;
2595 RTW_ERR(FUNC_ADPT_FMT" BCN_CNT:%d(%d) invalid\n",
2596 FUNC_ADPT_ARG(adapter), rx_bcn_cnt, bcn_cnt);
2597 }
2598 #endif
2599
2600 if (pwrpriv->lps_chk_cnt && --pwrpriv->lps_chk_cnt)
2601 enter_ps = _FALSE;
2602 else
2603 enter_ps = _TRUE;
2604 }
2605
2606 if (1) {
2607 RTW_INFO(FUNC_ADPT_FMT" tx_tp:%d [%d], rx_tp:%d [%d], bi_tp:%d [%d], enter_ps(%d):%s\n",
2608 FUNC_ADPT_ARG(adapter),
2609 tx_tp_mbits, pwrpriv->lps_tx_tp_th,
2610 rx_tp_mbits, pwrpriv->lps_rx_tp_th,
2611 bi_tp_mbits, pwrpriv->lps_bi_tp_th,
2612 pwrpriv->lps_chk_cnt,
2613 (enter_ps == _TRUE) ? "True" : "False");
2614 RTW_INFO(FUNC_ADPT_FMT" tx_pkt_cnt :%d [%d], rx_pkt_cnt :%d [%d]\n",
2615 FUNC_ADPT_ARG(adapter),
2616 pmlmepriv->LinkDetectInfo.NumTxOkInPeriod,
2617 pwrpriv->lps_tx_pkts,
2618 pmlmepriv->LinkDetectInfo.NumRxUnicastOkInPeriod,
2619 pwrpriv->lps_rx_pkts);
2620 if (!adapter->bsta_tp_dump)
2621 RTW_INFO(FUNC_ADPT_FMT" bcn_cnt:%d (per-%d second)\n",
2622 FUNC_ADPT_ARG(adapter),
2623 rx_bcn_cnt,
2624 2);
2625 }
2626
2627 if (enter_ps) {
2628 if (!from_timer)
2629 LPS_Enter(adapter, "TRAFFIC_IDLE");
2630 } else {
2631 if (!from_timer)
2632 LPS_Leave(adapter, "TRAFFIC_BUSY");
2633 else {
2634 #ifdef CONFIG_CONCURRENT_MODE
2635 #ifndef CONFIG_FW_MULTI_PORT_SUPPORT
2636 if (adapter->hw_port == HW_PORT0)
2637 #endif
2638 #endif
2639 rtw_lps_ctrl_wk_cmd(adapter, LPS_CTRL_TRAFFIC_BUSY, 0);
2640 }
2641 }
2642
2643 return enter_ps;
2644 }
2645 #endif
2646
_lps_chk_by_pkt_cnts(_adapter * padapter,u8 from_timer,u8 bBusyTraffic)2647 static u8 _lps_chk_by_pkt_cnts(_adapter *padapter, u8 from_timer, u8 bBusyTraffic)
2648 {
2649 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
2650 u8 bEnterPS = _FALSE;
2651
2652 /* check traffic for powersaving. */
2653 if (((pmlmepriv->LinkDetectInfo.NumRxUnicastOkInPeriod + pmlmepriv->LinkDetectInfo.NumTxOkInPeriod) > 8) ||
2654 #ifdef CONFIG_LPS_SLOW_TRANSITION
2655 (pmlmepriv->LinkDetectInfo.NumRxUnicastOkInPeriod > 2)
2656 #else /* CONFIG_LPS_SLOW_TRANSITION */
2657 (pmlmepriv->LinkDetectInfo.NumRxUnicastOkInPeriod > 4)
2658 #endif /* CONFIG_LPS_SLOW_TRANSITION */
2659 ) {
2660 #ifdef DBG_RX_COUNTER_DUMP
2661 if (padapter->dump_rx_cnt_mode & DUMP_DRV_TRX_COUNTER_DATA)
2662 RTW_INFO("(-)Tx = %d, Rx = %d\n", pmlmepriv->LinkDetectInfo.NumTxOkInPeriod, pmlmepriv->LinkDetectInfo.NumRxUnicastOkInPeriod);
2663 #endif
2664
2665 bEnterPS = _FALSE;
2666 #ifdef CONFIG_LPS_SLOW_TRANSITION
2667 if (bBusyTraffic == _TRUE) {
2668 if (pmlmepriv->LinkDetectInfo.TrafficTransitionCount <= 4)
2669 pmlmepriv->LinkDetectInfo.TrafficTransitionCount = 4;
2670
2671 pmlmepriv->LinkDetectInfo.TrafficTransitionCount++;
2672
2673 /* RTW_INFO("Set TrafficTransitionCount to %d\n", pmlmepriv->LinkDetectInfo.TrafficTransitionCount); */
2674
2675 if (pmlmepriv->LinkDetectInfo.TrafficTransitionCount > 30/*TrafficTransitionLevel*/)
2676 pmlmepriv->LinkDetectInfo.TrafficTransitionCount = 30;
2677 }
2678 #endif /* CONFIG_LPS_SLOW_TRANSITION */
2679 } else {
2680 #ifdef DBG_RX_COUNTER_DUMP
2681 if (padapter->dump_rx_cnt_mode & DUMP_DRV_TRX_COUNTER_DATA)
2682 RTW_INFO("(+)Tx = %d, Rx = %d\n", pmlmepriv->LinkDetectInfo.NumTxOkInPeriod, pmlmepriv->LinkDetectInfo.NumRxUnicastOkInPeriod);
2683 #endif
2684
2685 #ifdef CONFIG_LPS_SLOW_TRANSITION
2686 if (pmlmepriv->LinkDetectInfo.TrafficTransitionCount >= 2)
2687 pmlmepriv->LinkDetectInfo.TrafficTransitionCount -= 2;
2688 else
2689 pmlmepriv->LinkDetectInfo.TrafficTransitionCount = 0;
2690
2691 if (pmlmepriv->LinkDetectInfo.TrafficTransitionCount == 0)
2692 bEnterPS = _TRUE;
2693 #else /* CONFIG_LPS_SLOW_TRANSITION */
2694 bEnterPS = _TRUE;
2695 #endif /* CONFIG_LPS_SLOW_TRANSITION */
2696 }
2697
2698 #ifdef CONFIG_DYNAMIC_DTIM
2699 if (pmlmepriv->LinkDetectInfo.LowPowerTransitionCount == 8)
2700 bEnterPS = _FALSE;
2701
2702 RTW_INFO("LowPowerTransitionCount=%d\n", pmlmepriv->LinkDetectInfo.LowPowerTransitionCount);
2703 #endif /* CONFIG_DYNAMIC_DTIM */
2704
2705 /* LeisurePS only work in infra mode. */
2706 if (bEnterPS) {
2707 if (!from_timer) {
2708 #ifdef CONFIG_DYNAMIC_DTIM
2709 if (pmlmepriv->LinkDetectInfo.LowPowerTransitionCount < 8)
2710 adapter_to_pwrctl(padapter)->dtim = 1;
2711 else
2712 adapter_to_pwrctl(padapter)->dtim = 3;
2713 #endif /* CONFIG_DYNAMIC_DTIM */
2714 LPS_Enter(padapter, "TRAFFIC_IDLE");
2715 } else {
2716 /* do this at caller */
2717 /* rtw_lps_ctrl_wk_cmd(adapter, LPS_CTRL_ENTER, 0); */
2718 /* rtw_hal_dm_watchdog_in_lps(padapter); */
2719 }
2720
2721 #ifdef CONFIG_DYNAMIC_DTIM
2722 if (adapter_to_pwrctl(padapter)->bFwCurrentInPSMode == _TRUE)
2723 pmlmepriv->LinkDetectInfo.LowPowerTransitionCount++;
2724 #endif /* CONFIG_DYNAMIC_DTIM */
2725 } else {
2726 #ifdef CONFIG_DYNAMIC_DTIM
2727 if (pmlmepriv->LinkDetectInfo.LowPowerTransitionCount != 8)
2728 pmlmepriv->LinkDetectInfo.LowPowerTransitionCount = 0;
2729 else
2730 pmlmepriv->LinkDetectInfo.LowPowerTransitionCount++;
2731 #endif /* CONFIG_DYNAMIC_DTIM */
2732
2733 if (!from_timer)
2734 LPS_Leave(padapter, "TRAFFIC_BUSY");
2735 else {
2736 #ifdef CONFIG_CONCURRENT_MODE
2737 #ifndef CONFIG_FW_MULTI_PORT_SUPPORT
2738 if (padapter->hw_port == HW_PORT0)
2739 #endif
2740 #endif
2741 rtw_lps_ctrl_wk_cmd(padapter, LPS_CTRL_TRAFFIC_BUSY, 0);
2742 }
2743 }
2744
2745 return bEnterPS;
2746 }
2747 #endif /* CONFIG_LPS */
2748
2749 /* from_timer == 1 means driver is in LPS */
traffic_status_watchdog(_adapter * padapter,u8 from_timer)2750 u8 traffic_status_watchdog(_adapter *padapter, u8 from_timer)
2751 {
2752 u8 bEnterPS = _FALSE;
2753 u16 BusyThresholdHigh;
2754 u16 BusyThresholdLow;
2755 u16 BusyThreshold;
2756 u8 bBusyTraffic = _FALSE, bTxBusyTraffic = _FALSE, bRxBusyTraffic = _FALSE;
2757 u8 bHigherBusyTraffic = _FALSE, bHigherBusyRxTraffic = _FALSE, bHigherBusyTxTraffic = _FALSE;
2758
2759 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
2760 #ifdef CONFIG_TDLS
2761 struct tdls_info *ptdlsinfo = &(padapter->tdlsinfo);
2762 struct tdls_txmgmt txmgmt;
2763 u8 baddr[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
2764 #endif /* CONFIG_TDLS */
2765 #ifdef CONFIG_TRAFFIC_PROTECT
2766 RT_LINK_DETECT_T *link_detect = &pmlmepriv->LinkDetectInfo;
2767 #endif
2768
2769 #ifdef CONFIG_BTC
2770 if (padapter->registrypriv.wifi_spec != 1) {
2771 BusyThresholdHigh = 25;
2772 BusyThresholdLow = 10;
2773 } else
2774 #endif /* CONFIG_BTC */
2775 {
2776 BusyThresholdHigh = 100;
2777 BusyThresholdLow = 75;
2778 }
2779 BusyThreshold = BusyThresholdHigh;
2780
2781
2782 /* */
2783 /* Determine if our traffic is busy now */
2784 /* */
2785 if ((check_fwstate(pmlmepriv, WIFI_ASOC_STATE) == _TRUE)
2786 /*&& !MgntInitAdapterInProgress(pMgntInfo)*/) {
2787 /* if we raise bBusyTraffic in last watchdog, using lower threshold. */
2788 if (pmlmepriv->LinkDetectInfo.bBusyTraffic)
2789 BusyThreshold = BusyThresholdLow;
2790
2791 if (pmlmepriv->LinkDetectInfo.NumRxOkInPeriod > BusyThreshold ||
2792 pmlmepriv->LinkDetectInfo.NumTxOkInPeriod > BusyThreshold) {
2793 bBusyTraffic = _TRUE;
2794
2795 if (pmlmepriv->LinkDetectInfo.NumRxOkInPeriod > pmlmepriv->LinkDetectInfo.NumTxOkInPeriod)
2796 bRxBusyTraffic = _TRUE;
2797 else
2798 bTxBusyTraffic = _TRUE;
2799 }
2800
2801 /* Higher Tx/Rx data. */
2802 if (pmlmepriv->LinkDetectInfo.NumRxOkInPeriod > 4000 ||
2803 pmlmepriv->LinkDetectInfo.NumTxOkInPeriod > 4000) {
2804 bHigherBusyTraffic = _TRUE;
2805
2806 if (pmlmepriv->LinkDetectInfo.NumRxOkInPeriod > pmlmepriv->LinkDetectInfo.NumTxOkInPeriod)
2807 bHigherBusyRxTraffic = _TRUE;
2808 else
2809 bHigherBusyTxTraffic = _TRUE;
2810 }
2811
2812 #ifdef CONFIG_TRAFFIC_PROTECT
2813 #define TX_ACTIVE_TH 10
2814 #define RX_ACTIVE_TH 20
2815 #define TRAFFIC_PROTECT_PERIOD_MS 4500
2816
2817 if (link_detect->NumTxOkInPeriod > TX_ACTIVE_TH
2818 || link_detect->NumRxUnicastOkInPeriod > RX_ACTIVE_TH) {
2819
2820 RTW_INFO(FUNC_ADPT_FMT" acqiure wake_lock for %u ms(tx:%d,rx_unicast:%d)\n",
2821 FUNC_ADPT_ARG(padapter),
2822 TRAFFIC_PROTECT_PERIOD_MS,
2823 link_detect->NumTxOkInPeriod,
2824 link_detect->NumRxUnicastOkInPeriod);
2825
2826 rtw_lock_traffic_suspend_timeout(TRAFFIC_PROTECT_PERIOD_MS);
2827 }
2828 #endif
2829
2830 #ifdef CONFIG_TDLS
2831 #ifdef CONFIG_TDLS_AUTOSETUP
2832 /* TDLS_WATCHDOG_PERIOD * 2sec, periodically send */
2833 if (rtw_hw_chk_wl_func(adapter_to_dvobj(padapter), WL_FUNC_TDLS) == _TRUE) {
2834 if ((ptdlsinfo->watchdog_count % TDLS_WATCHDOG_PERIOD) == 0) {
2835 _rtw_memcpy(txmgmt.peer, baddr, ETH_ALEN);
2836 issue_tdls_dis_req(padapter, &txmgmt);
2837 }
2838 ptdlsinfo->watchdog_count++;
2839 }
2840 #endif /* CONFIG_TDLS_AUTOSETUP */
2841 #endif /* CONFIG_TDLS */
2842
2843 #ifdef CONFIG_SUPPORT_STATIC_SMPS
2844 _ssmps_chk_by_tp(padapter, from_timer);
2845 #endif
2846 #ifdef CONFIG_CTRL_TXSS_BY_TP
2847 rtw_ctrl_tx_ss_by_tp(padapter, from_timer);
2848 #endif
2849
2850 #ifdef CONFIG_LPS
2851 if (adapter_to_pwrctl(padapter)->bLeisurePs && MLME_IS_STA(padapter)) {
2852 #ifdef CONFIG_LPS_CHK_BY_TP
2853 if (adapter_to_pwrctl(padapter)->lps_chk_by_tp)
2854 bEnterPS = _lps_chk_by_tp(padapter, from_timer);
2855 else
2856 #endif /*CONFIG_LPS_CHK_BY_TP*/
2857 bEnterPS = _lps_chk_by_pkt_cnts(padapter, from_timer, bBusyTraffic);
2858 }
2859 #endif /* CONFIG_LPS */
2860
2861 } else {
2862 #ifdef CONFIG_LPS
2863 if (!from_timer && rtw_mi_get_assoc_if_num(padapter) == 0)
2864 LPS_Leave(padapter, "NON_LINKED");
2865 #endif
2866 }
2867
2868 session_tracker_chk_cmd(padapter, NULL);
2869
2870 #ifdef CONFIG_BEAMFORMING
2871 #ifdef RTW_WKARD_TX_DISABLE_BFEE
2872 /*For each padapter*/
2873 rtw_core_bf_watchdog(padapter);
2874 #endif
2875 #endif
2876
2877 pmlmepriv->LinkDetectInfo.NumRxOkInPeriod = 0;
2878 pmlmepriv->LinkDetectInfo.NumTxOkInPeriod = 0;
2879 pmlmepriv->LinkDetectInfo.NumRxUnicastOkInPeriod = 0;
2880 pmlmepriv->LinkDetectInfo.bBusyTraffic = bBusyTraffic;
2881 pmlmepriv->LinkDetectInfo.bTxBusyTraffic = bTxBusyTraffic;
2882 pmlmepriv->LinkDetectInfo.bRxBusyTraffic = bRxBusyTraffic;
2883 pmlmepriv->LinkDetectInfo.bHigherBusyTraffic = bHigherBusyTraffic;
2884 pmlmepriv->LinkDetectInfo.bHigherBusyRxTraffic = bHigherBusyRxTraffic;
2885 pmlmepriv->LinkDetectInfo.bHigherBusyTxTraffic = bHigherBusyTxTraffic;
2886
2887 return bEnterPS;
2888
2889 }
2890
2891
2892 /* for 11n Logo 4.2.31/4.2.32 */
dynamic_update_bcn_check(_adapter * padapter)2893 static void dynamic_update_bcn_check(_adapter *padapter)
2894 {
2895 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
2896 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
2897
2898 if (!padapter->registrypriv.wifi_spec)
2899 return;
2900
2901 if (!padapter->registrypriv.ht_enable || !is_supported_ht(padapter->registrypriv.wireless_mode))
2902 return;
2903
2904 if (!MLME_IS_AP(padapter))
2905 return;
2906
2907 if (pmlmeext->bstart_bss) {
2908 /* In 10 * 2 = 20s, there are no legacy AP, update HT info */
2909 static u8 count = 1;
2910
2911 if (count % 10 == 0) {
2912 count = 1;
2913 #ifdef CONFIG_80211N_HT
2914 if (_FALSE == ATOMIC_READ(&pmlmepriv->olbc)
2915 && _FALSE == ATOMIC_READ(&pmlmepriv->olbc_ht)) {
2916
2917 if (rtw_ht_operation_update(padapter) > 0) {
2918 rtw_update_beacon(padapter, _HT_CAPABILITY_IE_, NULL, _FALSE, 0);
2919 rtw_update_beacon(padapter, _HT_ADD_INFO_IE_, NULL, _TRUE, 0);
2920 }
2921 }
2922 #endif /* CONFIG_80211N_HT */
2923 }
2924
2925 #ifdef CONFIG_80211N_HT
2926 /* In 2s, there are any legacy AP, update HT info, and then reset count */
2927
2928 if (_FALSE != ATOMIC_READ(&pmlmepriv->olbc)
2929 && _FALSE != ATOMIC_READ(&pmlmepriv->olbc_ht)) {
2930
2931 if (rtw_ht_operation_update(padapter) > 0) {
2932 rtw_update_beacon(padapter, _HT_CAPABILITY_IE_, NULL, _FALSE, 0);
2933 rtw_update_beacon(padapter, _HT_ADD_INFO_IE_, NULL, _TRUE, 0);
2934
2935 }
2936 ATOMIC_SET(&pmlmepriv->olbc, _FALSE);
2937 ATOMIC_SET(&pmlmepriv->olbc_ht, _FALSE);
2938 count = 0;
2939 }
2940 #endif /* CONFIG_80211N_HT */
2941 count ++;
2942 }
2943 }
2944
2945 struct turbo_edca_setting{
2946 u32 edca_ul; /* uplink, tx */
2947 u32 edca_dl; /* downlink, rx */
2948 };
2949
2950 #define TURBO_EDCA_ENT(UL, DL) {UL, DL}
2951
2952 #define TURBO_EDCA_MODE_NUM 8
2953 static struct turbo_edca_setting ctrl_turbo_edca[TURBO_EDCA_MODE_NUM] = {
2954 /* { UL, DL } */
2955 TURBO_EDCA_ENT(0x5e431c, 0x431c), /* mode 0 */
2956
2957 TURBO_EDCA_ENT(0x431c, 0x431c), /* mode 1 */
2958
2959 TURBO_EDCA_ENT(0x5e431c, 0x5e431c), /* mode 2 */
2960
2961 TURBO_EDCA_ENT(0x5ea42b, 0x5ea42b), /* mode 3 */
2962
2963 TURBO_EDCA_ENT(0x5ea42b, 0x431c), /* mode 4 */
2964
2965 TURBO_EDCA_ENT(0x6ea42b, 0x6ea42b), /* mode 5 */
2966
2967 TURBO_EDCA_ENT(0xa42b, 0xa42b), /* mode 6 */
2968
2969 TURBO_EDCA_ENT(0x5e431c, 0xa42b), /* mode 7 */
2970 };
2971
rtw_turbo_edca(_adapter * padapter)2972 void rtw_turbo_edca(_adapter *padapter)
2973 {
2974 struct registry_priv *pregpriv = &padapter->registrypriv;
2975 struct dvobj_priv *dvobj = adapter_to_dvobj(padapter);
2976 struct rtw_phl_com_t *phl_com = GET_PHL_COM(dvobj);
2977 u32 edca_be_ul = padapter->last_edca;
2978 u32 edca_be_dl = padapter->last_edca;
2979 u32 ac_parm = padapter->last_edca;
2980 u8 ac;
2981 u8 is_linked = _FALSE;
2982
2983 if (padapter->dis_turboedca == DIS_TURBO)
2984 return;
2985
2986 if (rtw_mi_check_status(padapter, MI_ASSOC))
2987 is_linked = _TRUE;
2988
2989 if (is_linked != _TRUE)
2990 return;
2991
2992 if (pregpriv->wifi_spec == 1)
2993 return;
2994
2995 /* keep this condition at last check */
2996 if (padapter->dis_turboedca == DIS_TURBO_USE_MANUAL) {
2997 if (padapter->edca_param_mode < TURBO_EDCA_MODE_NUM) {
2998
2999 struct turbo_edca_setting param;
3000
3001 param = ctrl_turbo_edca[padapter->edca_param_mode];
3002 edca_be_ul = param.edca_ul;
3003 edca_be_dl = param.edca_dl;
3004 } else {
3005 edca_be_ul = padapter->edca_param_mode;
3006 edca_be_dl = padapter->edca_param_mode;
3007 }
3008 }
3009
3010 if (phl_com->phl_stats.tx_traffic.lvl == RTW_TFC_HIGH)
3011 ac_parm = edca_be_ul;
3012 else if (phl_com->phl_stats.tx_traffic.lvl != RTW_TFC_HIGH)
3013 ac_parm = edca_be_dl;
3014 else
3015 return;
3016
3017 if (padapter->last_edca != ac_parm) {
3018 ac = 0;
3019 /*RTW_INFO("%s, edca(0x%08x), lvl(%d), sts(%d)\n", __func__, ac_parm,
3020 phl_com->phl_stats.tx_traffic.lvl, phl_com->phl_stats.tx_traffic.sts);*/
3021 rtw_hw_set_edca(padapter, ac, ac_parm);
3022 padapter->last_edca = ac_parm;
3023 }
3024 }
3025
rtw_get_turbo_edca(_adapter * padapter,u8 aifs,u8 ecwmin,u8 ecwmax,u8 txop)3026 u32 rtw_get_turbo_edca(_adapter *padapter, u8 aifs, u8 ecwmin, u8 ecwmax, u8 txop)
3027 {
3028 struct registry_priv *pregpriv = &padapter->registrypriv;
3029 u32 ret = 0;
3030 u8 decide_txop = txop;
3031 u8 default_txop = 0x5e;
3032 u32 ac_parm = padapter->last_edca;
3033 u8 ac = 0;/*BE*/
3034
3035 if (padapter->dis_turboedca == DIS_TURBO)
3036 return ret;
3037
3038 if (pregpriv->wifi_spec == 1)
3039 return ret;
3040
3041 if (default_txop > txop)
3042 decide_txop = default_txop;
3043 else
3044 decide_txop = txop;
3045
3046 ac_parm = aifs | (ecwmin << 8) | (ecwmax << 12) | (decide_txop << 16);
3047
3048 return ac_parm;
3049
3050 }
3051
rtw_iface_dynamic_chk_wk_hdl(_adapter * padapter)3052 void rtw_iface_dynamic_chk_wk_hdl(_adapter *padapter)
3053 {
3054 #ifdef CONFIG_ACTIVE_KEEP_ALIVE_CHECK
3055 #ifdef CONFIG_AP_MODE
3056 if (MLME_IS_AP(padapter) || MLME_IS_MESH(padapter)) {
3057 expire_timeout_chk(padapter);
3058 #ifdef CONFIG_RTW_MESH
3059 if (MLME_IS_MESH(padapter) && MLME_IS_ASOC(padapter))
3060 rtw_mesh_peer_status_chk(padapter);
3061 #endif
3062 }
3063 #endif
3064 #endif /* CONFIG_ACTIVE_KEEP_ALIVE_CHECK */
3065 dynamic_update_bcn_check(padapter);
3066
3067 linked_status_chk(padapter, 0);
3068 traffic_status_watchdog(padapter, 0);
3069 rtw_turbo_edca(padapter);
3070
3071 /* for debug purpose */
3072 _linked_info_dump(padapter);
3073
3074 #ifdef CONFIG_RTW_CFGVENDOR_RSSIMONITOR
3075 rtw_cfgvendor_rssi_monitor_evt(padapter);
3076 #endif
3077
3078
3079 }
3080
rtw_dynamic_chk_wk_hdl(_adapter * padapter)3081 void rtw_dynamic_chk_wk_hdl(_adapter *padapter)
3082 {
3083 rtw_mi_dynamic_chk_wk_hdl(padapter);
3084
3085 #ifdef DBG_CONFIG_ERROR_DETECT
3086 rtw_hal_sreset_xmit_status_check(padapter);
3087 rtw_hal_sreset_linked_status_check(padapter);
3088 #endif
3089
3090 /* if(check_fwstate(pmlmepriv, WIFI_UNDER_LINKING|WIFI_UNDER_SURVEY)==_FALSE) */
3091 {
3092 #ifdef DBG_RX_COUNTER_DUMP
3093 rtw_dump_rx_counters(padapter);
3094 #endif
3095 }
3096
3097 #ifdef CONFIG_RTW_MULTI_AP
3098 rtw_ch_util_rpt(padapter);
3099 #endif
3100
3101 #ifdef CONFIG_DFS_MASTER
3102 rtw_chset_chk_non_ocp_finish(adapter_to_rfctl(padapter));
3103 #endif
3104
3105 #ifdef CONFIG_IPS_CHECK_IN_WD
3106 /* always call rtw_ps_processor() at last one. */
3107 rtw_ps_processor(padapter);
3108 #endif
3109 }
3110
rtw_dynamic_chk_wk_sw_hdl(_adapter * padapter)3111 void rtw_dynamic_chk_wk_sw_hdl(_adapter *padapter)
3112 {
3113 #ifdef CONFIG_RTW_MULTI_AP
3114 rtw_ch_util_rpt(padapter);
3115 #endif
3116
3117 rtw_update_phl_edcca_mode(padapter);
3118
3119 #ifdef CONFIG_DFS_MASTER
3120 rtw_chset_chk_non_ocp_finish(adapter_to_rfctl(padapter));
3121 #endif
3122 }
3123
rtw_dynamic_chk_wk_hw_hdl(_adapter * padapter)3124 void rtw_dynamic_chk_wk_hw_hdl(_adapter *padapter)
3125 {
3126 rtw_mi_dynamic_chk_wk_hdl(padapter);
3127
3128 #ifdef DBG_CONFIG_ERROR_DETECT
3129 rtw_hal_sreset_xmit_status_check(padapter);
3130 rtw_hal_sreset_linked_status_check(padapter);
3131 #endif
3132
3133 /* if(check_fwstate(pmlmepriv, WIFI_UNDER_LINKING|WIFI_UNDER_SURVEY)==_FALSE) */
3134 {
3135 #ifdef DBG_RX_COUNTER_DUMP
3136 rtw_dump_rx_counters(padapter);
3137 #endif
3138 }
3139
3140 #ifdef CONFIG_IPS_CHECK_IN_WD
3141 /* always call rtw_ps_processor() at last one. */
3142 rtw_ps_processor(padapter);
3143 #endif
3144
3145 #ifdef RTW_DETECT_HANG
3146 rtw_is_hang_check(padapter);
3147 #endif
3148 }
3149
3150
3151 #ifdef CONFIG_LPS
3152 struct lps_ctrl_wk_parm {
3153 s8 lps_level;
3154 #ifdef CONFIG_LPS_1T1R
3155 s8 lps_1t1r;
3156 #endif
3157 };
3158
lps_ctrl_wk_hdl(_adapter * padapter,u8 lps_ctrl_type,u8 * buf)3159 void lps_ctrl_wk_hdl(_adapter *padapter, u8 lps_ctrl_type, u8 *buf)
3160 {
3161 struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(padapter);
3162 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
3163 struct lps_ctrl_wk_parm *parm = (struct lps_ctrl_wk_parm *)buf;
3164 u8 mstatus;
3165
3166 if ((check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) == _TRUE)
3167 || (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE) == _TRUE))
3168 return;
3169
3170 switch (lps_ctrl_type) {
3171 case LPS_CTRL_SCAN:
3172 /* RTW_INFO("LPS_CTRL_SCAN\n"); */
3173 if (check_fwstate(pmlmepriv, WIFI_ASOC_STATE) == _TRUE) {
3174 /* connect */
3175 LPS_Leave(padapter, "LPS_CTRL_SCAN");
3176 }
3177 break;
3178 case LPS_CTRL_JOINBSS:
3179 /* RTW_INFO("LPS_CTRL_JOINBSS\n"); */
3180 LPS_Leave(padapter, "LPS_CTRL_JOINBSS");
3181 break;
3182 case LPS_CTRL_CONNECT:
3183 /* RTW_INFO("LPS_CTRL_CONNECT\n"); */
3184 mstatus = 1;/* connect */
3185 /* Reset LPS Setting */
3186 pwrpriv->LpsIdleCount = 0;
3187 rtw_hal_set_hwreg(padapter, HW_VAR_H2C_FW_JOINBSSRPT, (u8 *)(&mstatus));
3188 break;
3189 case LPS_CTRL_DISCONNECT:
3190 /* RTW_INFO("LPS_CTRL_DISCONNECT\n"); */
3191 mstatus = 0;/* disconnect */
3192 LPS_Leave(padapter, "LPS_CTRL_DISCONNECT");
3193 rtw_hal_set_hwreg(padapter, HW_VAR_H2C_FW_JOINBSSRPT, (u8 *)(&mstatus));
3194 break;
3195 case LPS_CTRL_SPECIAL_PACKET:
3196 /* RTW_INFO("LPS_CTRL_SPECIAL_PACKET\n"); */
3197 rtw_set_lps_deny(padapter, LPS_DELAY_MS);
3198 LPS_Leave(padapter, "LPS_CTRL_SPECIAL_PACKET");
3199 break;
3200 case LPS_CTRL_LEAVE:
3201 LPS_Leave(padapter, "LPS_CTRL_LEAVE");
3202 break;
3203 case LPS_CTRL_LEAVE_SET_OPTION:
3204 LPS_Leave(padapter, "LPS_CTRL_LEAVE_SET_OPTION");
3205 if (parm) {
3206 if (parm->lps_level >= 0)
3207 pwrpriv->lps_level = parm->lps_level;
3208 #ifdef CONFIG_LPS_1T1R
3209 if (parm->lps_1t1r >= 0)
3210 pwrpriv->lps_1t1r = parm->lps_1t1r;
3211 #endif
3212 }
3213 break;
3214 case LPS_CTRL_LEAVE_CFG80211_PWRMGMT:
3215 LPS_Leave(padapter, "CFG80211_PWRMGMT");
3216 break;
3217 case LPS_CTRL_TRAFFIC_BUSY:
3218 LPS_Leave(padapter, "LPS_CTRL_TRAFFIC_BUSY");
3219 break;
3220 case LPS_CTRL_TX_TRAFFIC_LEAVE:
3221 LPS_Leave(padapter, "LPS_CTRL_TX_TRAFFIC_LEAVE");
3222 break;
3223 case LPS_CTRL_RX_TRAFFIC_LEAVE:
3224 LPS_Leave(padapter, "LPS_CTRL_RX_TRAFFIC_LEAVE");
3225 break;
3226 case LPS_CTRL_ENTER:
3227 LPS_Enter(padapter, "TRAFFIC_IDLE_1");
3228 break;
3229 default:
3230 break;
3231 }
3232
3233 }
3234
_rtw_lps_ctrl_wk_cmd(_adapter * adapter,u8 lps_ctrl_type,s8 lps_level,s8 lps_1t1r,u8 flags)3235 static u8 _rtw_lps_ctrl_wk_cmd(_adapter *adapter, u8 lps_ctrl_type, s8 lps_level, s8 lps_1t1r, u8 flags)
3236 {
3237 struct cmd_obj *cmdobj;
3238 struct drvextra_cmd_parm *parm;
3239 struct lps_ctrl_wk_parm *wk_parm = NULL;
3240 struct cmd_priv *pcmdpriv = &adapter_to_dvobj(adapter)->cmdpriv;
3241 struct submit_ctx sctx;
3242 u8 res = _SUCCESS;
3243
3244 if (lps_ctrl_type == LPS_CTRL_LEAVE_SET_OPTION) {
3245 wk_parm = rtw_zmalloc(sizeof(*wk_parm));
3246 if (wk_parm == NULL) {
3247 res = _FAIL;
3248 goto exit;
3249 }
3250 wk_parm->lps_level = lps_level;
3251 #ifdef CONFIG_LPS_1T1R
3252 wk_parm->lps_1t1r = lps_1t1r;
3253 #endif
3254 }
3255
3256 if (flags & RTW_CMDF_DIRECTLY) {
3257 /* no need to enqueue, do the cmd hdl directly */
3258 lps_ctrl_wk_hdl(adapter, lps_ctrl_type, (u8 *)wk_parm);
3259 if (wk_parm)
3260 rtw_mfree(wk_parm, sizeof(*wk_parm));
3261 } else {
3262 /* need enqueue, prepare cmd_obj and enqueue */
3263 parm = rtw_zmalloc(sizeof(*parm));
3264 if (parm == NULL) {
3265 if (wk_parm)
3266 rtw_mfree(wk_parm, sizeof(*wk_parm));
3267 res = _FAIL;
3268 goto exit;
3269 }
3270
3271 parm->ec_id = LPS_CTRL_WK_CID;
3272 parm->type = lps_ctrl_type;
3273 parm->size = wk_parm ? sizeof(*wk_parm) : 0;
3274 parm->pbuf = (u8 *)wk_parm;
3275
3276 cmdobj = rtw_zmalloc(sizeof(*cmdobj));
3277 if (cmdobj == NULL) {
3278 rtw_mfree(parm, sizeof(*parm));
3279 if (wk_parm)
3280 rtw_mfree(wk_parm, sizeof(*wk_parm));
3281 res = _FAIL;
3282 goto exit;
3283 }
3284 cmdobj->padapter = adapter;
3285
3286 init_h2fwcmd_w_parm_no_rsp(cmdobj, parm, CMD_SET_DRV_EXTRA);
3287
3288 if (flags & RTW_CMDF_WAIT_ACK) {
3289 cmdobj->sctx = &sctx;
3290 rtw_sctx_init(&sctx, 2000);
3291 }
3292
3293 res = rtw_enqueue_cmd(pcmdpriv, cmdobj);
3294
3295 if (res == _SUCCESS && (flags & RTW_CMDF_WAIT_ACK)) {
3296 rtw_sctx_wait(&sctx, __func__);
3297 _rtw_mutex_lock_interruptible(&pcmdpriv->sctx_mutex);
3298 if (sctx.status == RTW_SCTX_SUBMITTED)
3299 cmdobj->sctx = NULL;
3300 _rtw_mutex_unlock(&pcmdpriv->sctx_mutex);
3301 if (sctx.status != RTW_SCTX_DONE_SUCCESS)
3302 res = _FAIL;
3303 }
3304 }
3305
3306 exit:
3307 return res;
3308 }
3309
rtw_lps_ctrl_wk_cmd(_adapter * adapter,u8 lps_ctrl_type,u8 flags)3310 u8 rtw_lps_ctrl_wk_cmd(_adapter *adapter, u8 lps_ctrl_type, u8 flags)
3311 {
3312 return _rtw_lps_ctrl_wk_cmd(adapter, lps_ctrl_type, -1, -1, flags);
3313 }
3314
rtw_lps_ctrl_leave_set_level_cmd(_adapter * adapter,u8 lps_level,u8 flags)3315 u8 rtw_lps_ctrl_leave_set_level_cmd(_adapter *adapter, u8 lps_level, u8 flags)
3316 {
3317 return _rtw_lps_ctrl_wk_cmd(adapter, LPS_CTRL_LEAVE_SET_OPTION, lps_level, -1, flags);
3318 }
3319
3320 #ifdef CONFIG_LPS_1T1R
rtw_lps_ctrl_leave_set_1t1r_cmd(_adapter * adapter,u8 lps_1t1r,u8 flags)3321 u8 rtw_lps_ctrl_leave_set_1t1r_cmd(_adapter *adapter, u8 lps_1t1r, u8 flags)
3322 {
3323 return _rtw_lps_ctrl_wk_cmd(adapter, LPS_CTRL_LEAVE_SET_OPTION, -1, lps_1t1r, flags);
3324 }
3325 #endif
3326
rtw_dm_in_lps_hdl(_adapter * padapter)3327 void rtw_dm_in_lps_hdl(_adapter *padapter)
3328 {
3329 rtw_hal_set_hwreg(padapter, HW_VAR_DM_IN_LPS_LCLK, NULL);
3330 }
3331
rtw_dm_in_lps_wk_cmd(_adapter * padapter)3332 u8 rtw_dm_in_lps_wk_cmd(_adapter *padapter)
3333 {
3334 struct cmd_obj *cmd;
3335 struct drvextra_cmd_parm *pdrvextra_cmd_parm;
3336 struct cmd_priv *pcmdpriv = &adapter_to_dvobj(padapter)->cmdpriv;
3337 u8 res = _SUCCESS;
3338
3339
3340 cmd = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
3341 if (cmd == NULL) {
3342 res = _FAIL;
3343 goto exit;
3344 }
3345 cmd->padapter = padapter;
3346
3347 pdrvextra_cmd_parm = (struct drvextra_cmd_parm *)rtw_zmalloc(sizeof(struct drvextra_cmd_parm));
3348 if (pdrvextra_cmd_parm == NULL) {
3349 rtw_mfree((unsigned char *)cmd, sizeof(struct cmd_obj));
3350 res = _FAIL;
3351 goto exit;
3352 }
3353
3354 pdrvextra_cmd_parm->ec_id = DM_IN_LPS_WK_CID;
3355 pdrvextra_cmd_parm->type = 0;
3356 pdrvextra_cmd_parm->size = 0;
3357 pdrvextra_cmd_parm->pbuf = NULL;
3358
3359 init_h2fwcmd_w_parm_no_rsp(cmd, pdrvextra_cmd_parm, CMD_SET_DRV_EXTRA);
3360
3361 res = rtw_enqueue_cmd(pcmdpriv, cmd);
3362
3363 exit:
3364 return res;
3365 }
3366
rtw_lps_change_dtim_hdl(_adapter * padapter,u8 dtim)3367 void rtw_lps_change_dtim_hdl(_adapter *padapter, u8 dtim)
3368 {
3369 struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(padapter);
3370
3371 if (dtim <= 0 || dtim > 16)
3372 return;
3373
3374 #ifdef CONFIG_LPS_LCLK
3375 _enter_pwrlock(&pwrpriv->lock);
3376 #endif
3377
3378 if (pwrpriv->dtim != dtim) {
3379 RTW_INFO("change DTIM from %d to %d, bFwCurrentInPSMode=%d, ps_mode=%d\n", pwrpriv->dtim, dtim,
3380 pwrpriv->bFwCurrentInPSMode, pwrpriv->pwr_mode);
3381
3382 pwrpriv->dtim = dtim;
3383 }
3384
3385 if ((pwrpriv->bFwCurrentInPSMode == _TRUE) && (pwrpriv->pwr_mode > PM_PS_MODE_ACTIVE)) {
3386 u8 ps_mode = pwrpriv->pwr_mode;
3387
3388 /* RTW_INFO("change DTIM from %d to %d, ps_mode=%d\n", pwrpriv->dtim, dtim, ps_mode); */
3389
3390 rtw_hal_set_hwreg(padapter, HW_VAR_H2C_FW_PWRMODE, (u8 *)(&ps_mode));
3391 }
3392
3393 #ifdef CONFIG_LPS_LCLK
3394 _exit_pwrlock(&pwrpriv->lock);
3395 #endif
3396
3397 }
3398
3399 #endif
3400
rtw_lps_change_dtim_cmd(_adapter * padapter,u8 dtim)3401 u8 rtw_lps_change_dtim_cmd(_adapter *padapter, u8 dtim)
3402 {
3403 struct cmd_obj *cmd;
3404 struct drvextra_cmd_parm *pdrvextra_cmd_parm;
3405 struct cmd_priv *pcmdpriv = &adapter_to_dvobj(padapter)->cmdpriv;
3406 u8 res = _SUCCESS;
3407 /*
3408 #ifdef CONFIG_CONCURRENT_MODE
3409 if (padapter->hw_port != HW_PORT0)
3410 return res;
3411 #endif
3412 */
3413 {
3414 cmd = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
3415 if (cmd == NULL) {
3416 res = _FAIL;
3417 goto exit;
3418 }
3419 cmd->padapter = padapter;
3420
3421 pdrvextra_cmd_parm = (struct drvextra_cmd_parm *)rtw_zmalloc(sizeof(struct drvextra_cmd_parm));
3422 if (pdrvextra_cmd_parm == NULL) {
3423 rtw_mfree((unsigned char *)cmd, sizeof(struct cmd_obj));
3424 res = _FAIL;
3425 goto exit;
3426 }
3427
3428 pdrvextra_cmd_parm->ec_id = LPS_CHANGE_DTIM_CID;
3429 pdrvextra_cmd_parm->type = dtim;
3430 pdrvextra_cmd_parm->size = 0;
3431 pdrvextra_cmd_parm->pbuf = NULL;
3432
3433 init_h2fwcmd_w_parm_no_rsp(cmd, pdrvextra_cmd_parm, CMD_SET_DRV_EXTRA);
3434
3435 res = rtw_enqueue_cmd(pcmdpriv, cmd);
3436 }
3437 exit:
3438 return res;
3439 }
3440
3441
3442 #ifdef CONFIG_POWER_SAVING
power_saving_wk_hdl(_adapter * padapter)3443 void power_saving_wk_hdl(_adapter *padapter)
3444 {
3445 rtw_ps_processor(padapter);
3446 }
3447 #endif
3448 /* add for CONFIG_IEEE80211W, none 11w can use it */
reset_securitypriv_hdl(_adapter * padapter)3449 void reset_securitypriv_hdl(_adapter *padapter)
3450 {
3451 rtw_reset_securitypriv(padapter);
3452 }
3453
3454 #ifdef CONFIG_IOCTL_CFG80211
3455 #if 0 /*!CONFIG_PHL_ARCH*/
3456 static u8 _p2p_roch_cmd(_adapter *adapter
3457 , u64 cookie, struct wireless_dev *wdev
3458 , struct ieee80211_channel *ch, enum nl80211_channel_type ch_type
3459 , unsigned int duration
3460 , u8 flags
3461 )
3462 {
3463 struct cmd_obj *cmdobj;
3464 struct drvextra_cmd_parm *parm;
3465 struct p2p_roch_parm *roch_parm;
3466 struct cmd_priv *pcmdpriv = &adapter_to_dvobj(adapter)->cmdpriv;
3467 struct submit_ctx sctx;
3468 u8 cancel = duration ? 0 : 1;
3469 u8 res = _SUCCESS;
3470
3471 roch_parm = (struct p2p_roch_parm *)rtw_zmalloc(sizeof(struct p2p_roch_parm));
3472 if (roch_parm == NULL) {
3473 res = _FAIL;
3474 goto exit;
3475 }
3476
3477 roch_parm->cookie = cookie;
3478 roch_parm->wdev = wdev;
3479 if (!cancel) {
3480 _rtw_memcpy(&roch_parm->ch, ch, sizeof(struct ieee80211_channel));
3481 roch_parm->ch_type = ch_type;
3482 roch_parm->duration = duration;
3483 }
3484
3485 if (flags & RTW_CMDF_DIRECTLY) {
3486 /* no need to enqueue, do the cmd hdl directly and free cmd parameter */
3487 if (H2C_SUCCESS != p2p_protocol_wk_hdl(adapter, cancel ? P2P_CANCEL_RO_CH_WK : P2P_RO_CH_WK, (u8 *)roch_parm))
3488 res = _FAIL;
3489 rtw_mfree((u8 *)roch_parm, sizeof(*roch_parm));
3490 } else {
3491 /* need enqueue, prepare cmd_obj and enqueue */
3492 parm = (struct drvextra_cmd_parm *)rtw_zmalloc(sizeof(struct drvextra_cmd_parm));
3493 if (parm == NULL) {
3494 rtw_mfree((u8 *)roch_parm, sizeof(*roch_parm));
3495 res = _FAIL;
3496 goto exit;
3497 }
3498
3499 parm->ec_id = P2P_PROTO_WK_CID;
3500 parm->type = cancel ? P2P_CANCEL_RO_CH_WK : P2P_RO_CH_WK;
3501 parm->size = sizeof(*roch_parm);
3502 parm->pbuf = (u8 *)roch_parm;
3503
3504 cmdobj = (struct cmd_obj *)rtw_zmalloc(sizeof(*cmdobj));
3505 if (cmdobj == NULL) {
3506 res = _FAIL;
3507 rtw_mfree((u8 *)roch_parm, sizeof(*roch_parm));
3508 rtw_mfree((u8 *)parm, sizeof(*parm));
3509 goto exit;
3510 }
3511 cmdobj->padapter = adapter;
3512
3513 init_h2fwcmd_w_parm_no_rsp(cmdobj, parm, CMD_SET_DRV_EXTRA);
3514
3515 if (flags & RTW_CMDF_WAIT_ACK) {
3516 cmdobj->sctx = &sctx;
3517 rtw_sctx_init(&sctx, 10 * 1000);
3518 }
3519
3520 res = rtw_enqueue_cmd(pcmdpriv, cmdobj);
3521
3522 if (res == _SUCCESS && (flags & RTW_CMDF_WAIT_ACK)) {
3523 rtw_sctx_wait(&sctx, __func__);
3524 _rtw_mutex_lock_interruptible(&pcmdpriv->sctx_mutex);
3525 if (sctx.status == RTW_SCTX_SUBMITTED)
3526 cmdobj->sctx = NULL;
3527 _rtw_mutex_unlock(&pcmdpriv->sctx_mutex);
3528 if (sctx.status != RTW_SCTX_DONE_SUCCESS)
3529 res = _FAIL;
3530 }
3531 }
3532
3533 exit:
3534 return res;
3535 }
3536 #endif /*!CONFIG_PHL_ARCH*/
3537
rtw_mgnt_tx_cmd(_adapter * adapter,u8 tx_ch,u8 no_cck,const u8 * buf,size_t len,int wait_ack,u8 flags)3538 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)
3539 {
3540 struct cmd_obj *cmdobj;
3541 struct drvextra_cmd_parm *parm;
3542 struct mgnt_tx_parm *mgnt_parm;
3543 struct cmd_priv *pcmdpriv = &adapter_to_dvobj(adapter)->cmdpriv;
3544 struct submit_ctx sctx;
3545 u8 res = _SUCCESS;
3546
3547 mgnt_parm = (struct mgnt_tx_parm *)rtw_zmalloc(sizeof(struct mgnt_tx_parm));
3548 if (mgnt_parm == NULL) {
3549 res = _FAIL;
3550 goto exit;
3551 }
3552
3553 mgnt_parm->tx_ch = tx_ch;
3554 mgnt_parm->no_cck = no_cck;
3555 mgnt_parm->buf = buf;
3556 mgnt_parm->len = len;
3557 mgnt_parm->wait_ack = wait_ack;
3558
3559 if (flags & RTW_CMDF_DIRECTLY) {
3560 /* no need to enqueue, do the cmd hdl directly and free cmd parameter */
3561 if (H2C_SUCCESS != rtw_mgnt_tx_handler(adapter, (u8 *)mgnt_parm))
3562 res = _FAIL;
3563 rtw_mfree((u8 *)mgnt_parm, sizeof(*mgnt_parm));
3564 } else {
3565 /* need enqueue, prepare cmd_obj and enqueue */
3566 parm = (struct drvextra_cmd_parm *)rtw_zmalloc(sizeof(struct drvextra_cmd_parm));
3567 if (parm == NULL) {
3568 rtw_mfree((u8 *)mgnt_parm, sizeof(*mgnt_parm));
3569 res = _FAIL;
3570 goto exit;
3571 }
3572
3573 parm->ec_id = MGNT_TX_WK_CID;
3574 parm->type = 0;
3575 parm->size = sizeof(*mgnt_parm);
3576 parm->pbuf = (u8 *)mgnt_parm;
3577
3578 cmdobj = (struct cmd_obj *)rtw_zmalloc(sizeof(*cmdobj));
3579 if (cmdobj == NULL) {
3580 res = _FAIL;
3581 rtw_mfree((u8 *)mgnt_parm, sizeof(*mgnt_parm));
3582 rtw_mfree((u8 *)parm, sizeof(*parm));
3583 goto exit;
3584 }
3585 cmdobj->padapter = adapter;
3586
3587 init_h2fwcmd_w_parm_no_rsp(cmdobj, parm, CMD_SET_DRV_EXTRA);
3588
3589 if (flags & RTW_CMDF_WAIT_ACK) {
3590 cmdobj->sctx = &sctx;
3591 rtw_sctx_init(&sctx, 10 * 1000);
3592 }
3593
3594 res = rtw_enqueue_cmd(pcmdpriv, cmdobj);
3595
3596 if (res == _SUCCESS && (flags & RTW_CMDF_WAIT_ACK)) {
3597 rtw_sctx_wait(&sctx, __func__);
3598 _rtw_mutex_lock_interruptible(&pcmdpriv->sctx_mutex);
3599 if (sctx.status == RTW_SCTX_SUBMITTED)
3600 cmdobj->sctx = NULL;
3601 _rtw_mutex_unlock(&pcmdpriv->sctx_mutex);
3602 if (sctx.status != RTW_SCTX_DONE_SUCCESS)
3603 res = _FAIL;
3604 }
3605 }
3606
3607 exit:
3608 return res;
3609 }
3610 #endif
3611
3612 #ifdef CONFIG_POWER_SAVING
rtw_ps_cmd(_adapter * padapter)3613 u8 rtw_ps_cmd(_adapter *padapter)
3614 {
3615 struct cmd_obj *ppscmd;
3616 struct drvextra_cmd_parm *pdrvextra_cmd_parm;
3617 struct cmd_priv *pcmdpriv = &adapter_to_dvobj(padapter)->cmdpriv;
3618
3619 u8 res = _SUCCESS;
3620
3621 #ifdef CONFIG_CONCURRENT_MODE
3622 if (!is_primary_adapter(padapter))
3623 goto exit;
3624 #endif
3625
3626 ppscmd = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
3627 if (ppscmd == NULL) {
3628 res = _FAIL;
3629 goto exit;
3630 }
3631 ppscmd->padapter = padapter;
3632
3633 pdrvextra_cmd_parm = (struct drvextra_cmd_parm *)rtw_zmalloc(sizeof(struct drvextra_cmd_parm));
3634 if (pdrvextra_cmd_parm == NULL) {
3635 rtw_mfree((unsigned char *)ppscmd, sizeof(struct cmd_obj));
3636 res = _FAIL;
3637 goto exit;
3638 }
3639
3640 pdrvextra_cmd_parm->ec_id = POWER_SAVING_CTRL_WK_CID;
3641 pdrvextra_cmd_parm->type = 0;
3642 pdrvextra_cmd_parm->size = 0;
3643 pdrvextra_cmd_parm->pbuf = NULL;
3644 init_h2fwcmd_w_parm_no_rsp(ppscmd, pdrvextra_cmd_parm, CMD_SET_DRV_EXTRA);
3645
3646 res = rtw_enqueue_cmd(pcmdpriv, ppscmd);
3647 exit:
3648 return res;
3649 }
3650 #endif /*CONFIG_POWER_SAVING*/
3651
3652 #if CONFIG_DFS
rtw_dfs_ch_switch_hdl(_adapter * adapter)3653 void rtw_dfs_ch_switch_hdl(_adapter *adapter)
3654 {
3655 struct dvobj_priv *dvobj = adapter_to_dvobj(adapter);
3656 struct rf_ctl_t *rfctl = dvobj_to_rfctl(dvobj);
3657 struct mlme_ext_priv *pmlmeext = &adapter->mlmeextpriv;
3658 u8 ifbmp_m = rtw_mi_get_ap_mesh_ifbmp(adapter);
3659 u8 ifbmp_s = rtw_mi_get_ld_sta_ifbmp(adapter);
3660 s16 req_ch;
3661 u8 req_bw = CHANNEL_WIDTH_20, req_offset = CHAN_OFFSET_NO_EXT, csa_timer = _FALSE;
3662 u8 need_discon = _FALSE;
3663
3664 rtw_hal_macid_sleep_all_used(adapter);
3665
3666 if (rtw_chset_search_ch(rfctl->channel_set, rfctl->csa_chandef.chan) >= 0
3667 && !rtw_chset_is_ch_non_ocp(rfctl->channel_set, rfctl->csa_chandef.chan)
3668 ) {
3669 /* CSA channel available and valid */
3670 req_ch = rfctl->csa_chandef.chan;
3671 RTW_INFO("CSA : %s valid CSA ch%u\n", __func__, rfctl->csa_chandef.chan);
3672 csa_timer = _TRUE;
3673 } else if (ifbmp_m) {
3674 /* no available or valid CSA channel, having AP/MESH ifaces */
3675 req_ch = REQ_CH_NONE;
3676 need_discon = _TRUE;
3677 RTW_INFO("CSA : %s ch sel by AP/MESH ifaces\n", __func__);
3678 } else {
3679 /* no available or valid CSA channel and no AP/MESH ifaces */
3680 if (!is_supported_24g(dvobj_to_regsty(dvobj)->band_type)
3681 #ifdef CONFIG_DFS_MASTER
3682 || rfctl->radar_detected
3683 #endif
3684 )
3685 req_ch = 36;
3686 else
3687 req_ch = 1;
3688 need_discon = _TRUE;
3689 RTW_INFO("CSA : %s switch to ch%d\n", __func__, req_ch);
3690 }
3691
3692 if (!need_discon) {
3693 if (rfctl->csa_ch_width == 1) {
3694 req_bw = CHANNEL_WIDTH_80;
3695 req_offset = rfctl->csa_chandef.offset;
3696 } else if (rfctl->csa_ch_width == 0 && rfctl->csa_chandef.offset != CHAN_OFFSET_NO_EXT) {
3697 req_bw = CHANNEL_WIDTH_40;
3698 req_offset = rfctl->csa_chandef.offset;
3699 } else {
3700 req_bw = CHANNEL_WIDTH_20;
3701 req_offset = CHAN_OFFSET_NO_EXT;
3702 }
3703
3704 /* get correct offset and check ch/bw/offset is valid or not */
3705 if (!rtw_get_offset_by_chbw(req_ch, req_bw, &req_offset)) {
3706 req_bw = CHANNEL_WIDTH_20;
3707 req_offset = CHAN_OFFSET_NO_EXT;
3708 }
3709 }
3710
3711 RTW_INFO("CSA : req_ch=%d, req_bw=%d, req_offset=%d, ifbmp_m=0x%02x, ifbmp_s=0x%02x\n"
3712 , req_ch, req_bw, req_offset, ifbmp_m, ifbmp_s);
3713
3714 /* check all STA ifaces status */
3715 if (ifbmp_s) {
3716 _adapter *iface;
3717 int i;
3718
3719 for (i = 0; i < dvobj->iface_nums; i++) {
3720 iface = dvobj->padapters[i];
3721 if (!iface || !(ifbmp_s & BIT(iface->iface_id)))
3722 continue;
3723
3724 if (need_discon) {
3725 set_fwstate(&iface->mlmepriv, WIFI_OP_CH_SWITCHING);
3726 issue_deauth(iface, get_bssid(&iface->mlmepriv), WLAN_REASON_DEAUTH_LEAVING);
3727 } else {
3728 /* update STA mode ch/bw/offset */
3729 iface->mlmeextpriv.chandef.chan= req_ch;
3730 iface->mlmeextpriv.chandef.bw = req_bw;
3731 iface->mlmeextpriv.chandef.offset = req_offset;
3732 /* updaet STA mode DSConfig , ap mode will update in rtw_change_bss_chbw_cmd */
3733 iface->mlmepriv.cur_network.network.Configuration.DSConfig = req_ch;
3734 set_fwstate(&iface->mlmepriv, WIFI_CSA_UPDATE_BEACON);
3735
3736 #ifdef CONFIG_80211D
3737 if (iface->mlmepriv.recv_country_ie) {
3738 if (rtw_apply_recv_country_ie_cmd(iface, RTW_CMDF_DIRECTLY
3739 , req_ch > 14 ? BAND_ON_5G : BAND_ON_24G, req_ch
3740 , iface->mlmepriv.recv_country_ie) != _SUCCESS
3741 )
3742 RTW_WARN(FUNC_ADPT_FMT" rtw_apply_recv_country_ie_cmd() fail\n", FUNC_ADPT_ARG(iface));
3743 }
3744 #endif
3745 }
3746 }
3747 }
3748
3749 if (csa_timer) {
3750 RTW_INFO("pmlmeext->csa_timer 70 seconds\n");
3751 /* wait 70 seconds for receiving beacons */
3752 _set_timer(&pmlmeext->csa_timer, CAC_TIME_MS + 10000);
3753 }
3754
3755 #ifdef CONFIG_AP_MODE
3756 if (ifbmp_m) {
3757 u8 execlude = 0;
3758
3759 if (need_discon)
3760 execlude = ifbmp_s;
3761 /* trigger channel selection with consideraton of asoc STA ifaces */
3762 rtw_change_bss_chbw_cmd(dvobj_get_primary_adapter(dvobj), RTW_CMDF_DIRECTLY
3763 , ifbmp_m, execlude, req_ch, REQ_BW_ORI, REQ_OFFSET_NONE);
3764 } else
3765 #endif
3766 {
3767 /* no AP/MESH iface, switch DFS status and channel directly */
3768 rtw_warn_on(req_ch <= 0);
3769 #ifdef CONFIG_DFS_MASTER
3770 if (need_discon)
3771 rtw_dfs_rd_en_decision(adapter, MLME_OPCH_SWITCH, ifbmp_s);
3772 else
3773 rtw_dfs_rd_en_decision(adapter, MLME_OPCH_SWITCH, 0);
3774 #endif
3775
3776 set_channel_bwmode(adapter, req_ch, req_offset, req_bw, _TRUE);
3777 /* update union ch/bw/offset for STA only */
3778 rtw_mi_update_union_chan_inf(adapter, req_ch, req_offset, req_bw);
3779 rtw_rfctl_update_op_mode(rfctl, 0, 0);
3780 }
3781
3782 /* make asoc STA ifaces disconnect */
3783 if (ifbmp_s && need_discon) {
3784 _adapter *iface;
3785 struct mlme_ext_priv *pmlmeext;
3786 struct mlme_ext_info *pmlmeinfo;
3787 int i;
3788
3789 for (i = 0; i < dvobj->iface_nums; i++) {
3790 iface = dvobj->padapters[i];
3791 if (!iface || !(ifbmp_s & BIT(iface->iface_id)))
3792 continue;
3793 rtw_disassoc_cmd(iface, 0, RTW_CMDF_DIRECTLY);
3794 rtw_indicate_disconnect(iface, 0, _FALSE);
3795 #ifndef CONFIG_STA_CMD_DISPR
3796 rtw_free_assoc_resources(iface, _TRUE);
3797 #endif
3798 rtw_free_network_queue(iface, _TRUE);
3799
3800 pmlmeext = &iface->mlmeextpriv;
3801 pmlmeinfo = &pmlmeext->mlmext_info;
3802 pmlmeinfo->disconnect_occurred_time = rtw_systime_to_ms(rtw_get_current_time());
3803
3804 if (rtw_chset_is_dfs_chbw(rfctl->channel_set, req_ch, req_bw, req_offset)) {
3805 RTW_INFO("Switched to DFS band (ch %d, bw %d, offset %d) again!!\n",
3806 req_ch, req_bw, req_offset);
3807 pmlmeinfo->disconnect_code = DISCONNECTION_BY_DRIVER_DUE_TO_RECEIVE_CSA_DFS;
3808 } else {
3809 pmlmeinfo->disconnect_code = DISCONNECTION_BY_DRIVER_DUE_TO_RECEIVE_CSA_NON_DFS;
3810 }
3811
3812 pmlmeinfo->wifi_reason_code = WLAN_REASON_DEAUTH_LEAVING;
3813 }
3814 }
3815
3816 reset_csa_param(rfctl);
3817
3818 rtw_hal_macid_wakeup_all_used(adapter);
3819 rtw_mi_os_xmit_schedule(adapter);
3820 }
3821 #endif /* CONFIG_DFS */
3822
3823 #ifdef CONFIG_AP_MODE
3824
rtw_chk_hi_queue_hdl(_adapter * padapter)3825 static void rtw_chk_hi_queue_hdl(_adapter *padapter)
3826 {
3827 struct sta_info *psta_bmc;
3828 struct sta_priv *pstapriv = &padapter->stapriv;
3829 systime start = rtw_get_current_time();
3830 u8 empty = _FALSE;
3831
3832 psta_bmc = rtw_get_bcmc_stainfo(padapter);
3833 if (!psta_bmc)
3834 return;
3835
3836 rtw_hal_get_hwreg(padapter, HW_VAR_CHK_HI_QUEUE_EMPTY, &empty);
3837
3838 while (_FALSE == empty && rtw_get_passing_time_ms(start) < rtw_get_wait_hiq_empty_ms()) {
3839 rtw_msleep_os(100);
3840 rtw_hal_get_hwreg(padapter, HW_VAR_CHK_HI_QUEUE_EMPTY, &empty);
3841 }
3842
3843 if (psta_bmc->sleepq_len == 0) {
3844 if (empty == _SUCCESS) {
3845 bool update_tim = _FALSE;
3846
3847 if (rtw_tim_map_is_set(padapter, pstapriv->tim_bitmap, 0))
3848 update_tim = _TRUE;
3849
3850 rtw_tim_map_clear(padapter, pstapriv->tim_bitmap, 0);
3851 rtw_tim_map_clear(padapter, pstapriv->sta_dz_bitmap, 0);
3852
3853 if (update_tim == _TRUE)
3854 _update_beacon(padapter, _TIM_IE_, NULL, _TRUE, 0,"bmc sleepq and HIQ empty");
3855 } else /* re check again */
3856 rtw_chk_hi_queue_cmd(padapter);
3857
3858 }
3859
3860 }
3861
rtw_chk_hi_queue_cmd(_adapter * padapter)3862 u8 rtw_chk_hi_queue_cmd(_adapter *padapter)
3863 {
3864 struct cmd_obj *cmd;
3865 struct drvextra_cmd_parm *pdrvextra_cmd_parm;
3866 struct cmd_priv *pcmdpriv = &adapter_to_dvobj(padapter)->cmdpriv;
3867 u8 res = _SUCCESS;
3868
3869 cmd = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
3870 if (cmd == NULL) {
3871 res = _FAIL;
3872 goto exit;
3873 }
3874 cmd->padapter = padapter;
3875
3876 pdrvextra_cmd_parm = (struct drvextra_cmd_parm *)rtw_zmalloc(sizeof(struct drvextra_cmd_parm));
3877 if (pdrvextra_cmd_parm == NULL) {
3878 rtw_mfree((unsigned char *)cmd, sizeof(struct cmd_obj));
3879 res = _FAIL;
3880 goto exit;
3881 }
3882
3883 pdrvextra_cmd_parm->ec_id = CHECK_HIQ_WK_CID;
3884 pdrvextra_cmd_parm->type = 0;
3885 pdrvextra_cmd_parm->size = 0;
3886 pdrvextra_cmd_parm->pbuf = NULL;
3887
3888 init_h2fwcmd_w_parm_no_rsp(cmd, pdrvextra_cmd_parm, CMD_SET_DRV_EXTRA);
3889
3890 res = rtw_enqueue_cmd(pcmdpriv, cmd);
3891
3892 exit:
3893 return res;
3894
3895 }
3896
3897 #ifdef CONFIG_DFS_MASTER
rtw_dfs_rd_hdl(_adapter * adapter)3898 u8 rtw_dfs_rd_hdl(_adapter *adapter)
3899 {
3900 struct dvobj_priv *dvobj = adapter_to_dvobj(adapter);
3901 struct rf_ctl_t *rfctl = adapter_to_rfctl(adapter);
3902 u8 open_chan;
3903 u8 cch;
3904
3905 if (!rfctl->radar_detect_enabled)
3906 goto exit;
3907
3908 cch = rtw_get_center_ch(rfctl->radar_detect_ch, rfctl->radar_detect_bw, rfctl->radar_detect_offset);
3909
3910 open_chan = rtw_get_oper_ch(adapter);
3911 if (open_chan != rfctl->radar_detect_ch
3912 || rtw_get_passing_time_ms(rtw_get_on_oper_ch_time(adapter)) < 300
3913 ) {
3914 /* offchannel, bypass radar detect */
3915 goto cac_status_chk;
3916 }
3917
3918 if (IS_CH_WAITING(rfctl) && !IS_UNDER_CAC(rfctl)) {
3919 /* non_ocp, bypass radar detect */
3920 goto cac_status_chk;
3921 }
3922
3923 if (!rfctl->dbg_dfs_fake_radar_detect_cnt
3924 && rtw_odm_radar_detect(adapter) != _TRUE)
3925 goto cac_status_chk;
3926
3927 if (!rfctl->dbg_dfs_fake_radar_detect_cnt
3928 && rfctl->dbg_dfs_radar_detect_trigger_non
3929 ) {
3930 /* radar detect debug mode, trigger no mlme flow */
3931 RTW_INFO("%s radar detected on test mode, trigger no mlme flow\n", __func__);
3932 goto cac_status_chk;
3933 }
3934
3935 if (rfctl->dbg_dfs_fake_radar_detect_cnt != 0) {
3936 RTW_INFO("%s fake radar detected, cnt:%d\n", __func__
3937 , rfctl->dbg_dfs_fake_radar_detect_cnt);
3938 rfctl->dbg_dfs_fake_radar_detect_cnt--;
3939 } else
3940 RTW_INFO("%s radar detected\n", __func__);
3941
3942 rfctl->radar_detected = 1;
3943
3944 rtw_chset_update_non_ocp(rfctl->channel_set
3945 , rfctl->radar_detect_ch, rfctl->radar_detect_bw, rfctl->radar_detect_offset);
3946
3947 if (IS_UNDER_CAC(rfctl))
3948 rtw_nlrtw_cac_abort_event(adapter, cch, rfctl->radar_detect_bw);
3949 rtw_nlrtw_radar_detect_event(adapter, cch, rfctl->radar_detect_bw);
3950
3951 rtw_dfs_ch_switch_hdl(adapter);
3952
3953 if (rfctl->radar_detect_enabled)
3954 goto set_timer;
3955 goto exit;
3956
3957 cac_status_chk:
3958
3959 if (!IS_CAC_STOPPED(rfctl)
3960 && ((IS_UNDER_CAC(rfctl) && rfctl->cac_force_stop)
3961 || !IS_CH_WAITING(rfctl)
3962 )
3963 ) {
3964 u8 pause = 0x00;
3965
3966 rtw_hal_set_hwreg(adapter, HW_VAR_TXPAUSE, &pause);
3967 rfctl->cac_start_time = rfctl->cac_end_time = RTW_CAC_STOPPED;
3968 rtw_nlrtw_cac_finish_event(adapter, cch, rfctl->radar_detect_bw);
3969
3970 if (rtw_mi_check_fwstate(adapter, WIFI_UNDER_LINKING|WIFI_UNDER_SURVEY) == _FALSE) {
3971 u8 do_rfk = _TRUE;
3972 u8 u_ch, u_bw, u_offset;
3973
3974 if (rtw_mi_get_ch_setting_union(adapter, &u_ch, &u_bw, &u_offset))
3975 set_channel_bwmode(adapter, u_ch, u_offset, u_bw, do_rfk);
3976 else
3977 rtw_warn_on(1);
3978
3979 rtw_hal_set_hwreg(adapter, HW_VAR_RESUME_BCN, NULL);
3980 rtw_mi_tx_beacon_hdl(adapter);
3981 }
3982 }
3983
3984 set_timer:
3985 _set_timer(&rfctl->radar_detect_timer
3986 , rtw_odm_radar_detect_polling_int_ms(dvobj));
3987
3988 exit:
3989 return H2C_SUCCESS;
3990 }
3991
rtw_dfs_rd_cmd(_adapter * adapter,bool enqueue)3992 u8 rtw_dfs_rd_cmd(_adapter *adapter, bool enqueue)
3993 {
3994 struct cmd_obj *cmdobj;
3995 struct drvextra_cmd_parm *parm;
3996 struct cmd_priv *cmdpriv = &adapter_to_dvobj(adapter)->cmdpriv;
3997 u8 res = _FAIL;
3998
3999 if (enqueue) {
4000 cmdobj = rtw_zmalloc(sizeof(struct cmd_obj));
4001 if (cmdobj == NULL)
4002 goto exit;
4003 cmdobj->padapter = adapter;
4004
4005 parm = rtw_zmalloc(sizeof(struct drvextra_cmd_parm));
4006 if (parm == NULL) {
4007 rtw_mfree(cmdobj, sizeof(struct cmd_obj));
4008 goto exit;
4009 }
4010
4011 parm->ec_id = DFS_RADAR_DETECT_WK_CID;
4012 parm->type = 0;
4013 parm->size = 0;
4014 parm->pbuf = NULL;
4015
4016 init_h2fwcmd_w_parm_no_rsp(cmdobj, parm, CMD_SET_DRV_EXTRA);
4017 res = rtw_enqueue_cmd(cmdpriv, cmdobj);
4018 } else {
4019 rtw_dfs_rd_hdl(adapter);
4020 res = _SUCCESS;
4021 }
4022
4023 exit:
4024 return res;
4025 }
4026
rtw_dfs_rd_timer_hdl(void * ctx)4027 void rtw_dfs_rd_timer_hdl(void *ctx)
4028 {
4029 struct rf_ctl_t *rfctl = (struct rf_ctl_t *)ctx;
4030 struct dvobj_priv *dvobj = rfctl_to_dvobj(rfctl);
4031
4032 rtw_dfs_rd_cmd(dvobj_get_primary_adapter(dvobj), _TRUE);
4033 }
4034
rtw_dfs_rd_enable(struct rf_ctl_t * rfctl,u8 ch,u8 bw,u8 offset,bool bypass_cac)4035 static void rtw_dfs_rd_enable(struct rf_ctl_t *rfctl, u8 ch, u8 bw, u8 offset, bool bypass_cac)
4036 {
4037 struct dvobj_priv *dvobj = rfctl_to_dvobj(rfctl);
4038 _adapter *adapter = dvobj_get_primary_adapter(dvobj);
4039
4040 RTW_INFO("%s on %u,%u,%u\n", __func__, ch, bw, offset);
4041
4042 if (bypass_cac)
4043 rfctl->cac_start_time = rfctl->cac_end_time = RTW_CAC_STOPPED;
4044 else if (rtw_is_cac_reset_needed(rfctl, ch, bw, offset) == _TRUE)
4045 rtw_reset_cac(rfctl, ch, bw, offset);
4046
4047 rfctl->radar_detect_by_others = _FALSE;
4048 rfctl->radar_detect_ch = ch;
4049 rfctl->radar_detect_bw = bw;
4050 rfctl->radar_detect_offset = offset;
4051
4052 rfctl->radar_detected = 0;
4053
4054 if (IS_CH_WAITING(rfctl))
4055 rtw_hal_set_hwreg(adapter, HW_VAR_STOP_BCN, NULL);
4056
4057 if (!rfctl->radar_detect_enabled) {
4058 RTW_INFO("%s set radar_detect_enabled\n", __func__);
4059 rfctl->radar_detect_enabled = 1;
4060 #ifdef CONFIG_LPS
4061 LPS_Leave(adapter, "RADAR_DETECT_EN");
4062 #endif
4063 _set_timer(&rfctl->radar_detect_timer
4064 , rtw_odm_radar_detect_polling_int_ms(dvobj));
4065
4066 if (rtw_rfctl_overlap_radar_detect_ch(rfctl)) {
4067 if (IS_CH_WAITING(rfctl)) {
4068 u8 pause = 0xFF;
4069
4070 rtw_hal_set_hwreg(adapter, HW_VAR_TXPAUSE, &pause);
4071 }
4072 rtw_odm_radar_detect_enable(adapter);
4073 }
4074 }
4075 }
4076
rtw_dfs_rd_disable(struct rf_ctl_t * rfctl,u8 ch,u8 bw,u8 offset,bool by_others)4077 static void rtw_dfs_rd_disable(struct rf_ctl_t *rfctl, u8 ch, u8 bw, u8 offset, bool by_others)
4078 {
4079 _adapter *adapter = dvobj_get_primary_adapter(rfctl_to_dvobj(rfctl));
4080
4081 rfctl->radar_detect_by_others = by_others;
4082
4083 if (rfctl->radar_detect_enabled) {
4084 bool overlap_radar_detect_ch = rtw_rfctl_overlap_radar_detect_ch(rfctl);
4085
4086 RTW_INFO("%s clear radar_detect_enabled\n", __func__);
4087
4088 rfctl->radar_detect_enabled = 0;
4089 rfctl->radar_detected = 0;
4090 rfctl->radar_detect_ch = 0;
4091 rfctl->radar_detect_bw = 0;
4092 rfctl->radar_detect_offset = 0;
4093 rfctl->cac_start_time = rfctl->cac_end_time = RTW_CAC_STOPPED;
4094 _cancel_timer_ex(&rfctl->radar_detect_timer);
4095
4096 if (rtw_mi_check_fwstate(adapter, WIFI_UNDER_LINKING|WIFI_UNDER_SURVEY) == _FALSE) {
4097 rtw_hal_set_hwreg(adapter, HW_VAR_RESUME_BCN, NULL);
4098 rtw_mi_tx_beacon_hdl(adapter);
4099 }
4100
4101 if (overlap_radar_detect_ch) {
4102 u8 pause = 0x00;
4103
4104 rtw_hal_set_hwreg(adapter, HW_VAR_TXPAUSE, &pause);
4105 rtw_odm_radar_detect_disable(adapter);
4106 }
4107 }
4108
4109 if (by_others) {
4110 rfctl->radar_detect_ch = ch;
4111 rfctl->radar_detect_bw = bw;
4112 rfctl->radar_detect_offset = offset;
4113 }
4114 }
4115
rtw_dfs_rd_en_decision(_adapter * adapter,u8 mlme_act,u8 excl_ifbmp)4116 void rtw_dfs_rd_en_decision(_adapter *adapter, u8 mlme_act, u8 excl_ifbmp)
4117 {
4118 struct dvobj_priv *dvobj = adapter_to_dvobj(adapter);
4119 struct rf_ctl_t *rfctl = adapter_to_rfctl(adapter);
4120 struct mlme_ext_priv *mlmeext = &adapter->mlmeextpriv;
4121 struct mi_state mstate;
4122 u8 ifbmp;
4123 u8 u_ch, u_bw, u_offset;
4124 bool ld_sta_in_dfs = _FALSE;
4125 bool sync_ch = _FALSE; /* _FALSE: asign channel directly */
4126 bool needed = _FALSE;
4127
4128 if (mlme_act == MLME_OPCH_SWITCH
4129 || mlme_act == MLME_ACTION_NONE
4130 ) {
4131 ifbmp = ~excl_ifbmp;
4132 rtw_mi_status_by_ifbmp(dvobj, ifbmp, &mstate);
4133 rtw_mi_get_ch_setting_union_by_ifbmp(dvobj, ifbmp, &u_ch, &u_bw, &u_offset);
4134 } else {
4135 ifbmp = ~excl_ifbmp & ~BIT(adapter->iface_id);
4136 rtw_mi_status_by_ifbmp(dvobj, ifbmp, &mstate);
4137 rtw_mi_get_ch_setting_union_by_ifbmp(dvobj, ifbmp, &u_ch, &u_bw, &u_offset);
4138 if (u_ch != 0)
4139 sync_ch = _TRUE;
4140
4141 switch (mlme_act) {
4142 case MLME_STA_CONNECTING:
4143 MSTATE_STA_LG_NUM(&mstate)++;
4144 break;
4145 case MLME_STA_CONNECTED:
4146 MSTATE_STA_LD_NUM(&mstate)++;
4147 break;
4148 case MLME_STA_DISCONNECTED:
4149 break;
4150 #ifdef CONFIG_AP_MODE
4151 case MLME_AP_STARTED:
4152 MSTATE_AP_NUM(&mstate)++;
4153 break;
4154 case MLME_AP_STOPPED:
4155 break;
4156 #endif
4157 #ifdef CONFIG_RTW_MESH
4158 case MLME_MESH_STARTED:
4159 MSTATE_MESH_NUM(&mstate)++;
4160 break;
4161 case MLME_MESH_STOPPED:
4162 break;
4163 #endif
4164 default:
4165 rtw_warn_on(1);
4166 break;
4167 }
4168
4169 if (sync_ch == _TRUE) {
4170 if (!MLME_IS_OPCH_SW(adapter)) {
4171 if (!rtw_is_chbw_grouped(mlmeext->chandef.chan, mlmeext->chandef.bw, mlmeext->chandef.offset, u_ch, u_bw, u_offset)) {
4172 RTW_INFO(FUNC_ADPT_FMT" can't sync %u,%u,%u with %u,%u,%u\n", FUNC_ADPT_ARG(adapter)
4173 , mlmeext->chandef.chan, mlmeext->chandef.bw, mlmeext->chandef.offset, u_ch, u_bw, u_offset);
4174 goto apply;
4175 }
4176
4177 rtw_sync_chbw(&mlmeext->chandef.chan, (u8 *)(&mlmeext->chandef.bw), (u8 *)(&mlmeext->chandef.offset)
4178 , &u_ch, &u_bw, &u_offset);
4179 }
4180 } else {
4181 u_ch = mlmeext->chandef.chan;
4182 u_bw = mlmeext->chandef.bw;
4183 u_offset = mlmeext->chandef.offset;
4184 }
4185 }
4186
4187 if (MSTATE_STA_LG_NUM(&mstate) > 0) {
4188 /* STA mode is linking */
4189 goto apply;
4190 }
4191
4192 if (MSTATE_STA_LD_NUM(&mstate) > 0) {
4193 if (rtw_chset_is_dfs_chbw(rfctl->channel_set, u_ch, u_bw, u_offset)) {
4194 /*
4195 * if operate as slave w/o radar detect,
4196 * rely on AP on which STA mode connects
4197 */
4198 if (IS_DFS_SLAVE_WITH_RD(rfctl) && !rtw_rfctl_dfs_domain_unknown(rfctl))
4199 needed = _TRUE;
4200 ld_sta_in_dfs = _TRUE;
4201 }
4202 goto apply;
4203 }
4204
4205 if (!MSTATE_AP_NUM(&mstate) && !MSTATE_MESH_NUM(&mstate)) {
4206 /* No working AP/Mesh mode */
4207 goto apply;
4208 }
4209
4210 if (rtw_chset_is_dfs_chbw(rfctl->channel_set, u_ch, u_bw, u_offset))
4211 needed = _TRUE;
4212
4213 apply:
4214
4215 RTW_INFO(FUNC_ADPT_FMT" needed:%d, mlme_act:%u, excl_ifbmp:0x%02x\n"
4216 , FUNC_ADPT_ARG(adapter), needed, mlme_act, excl_ifbmp);
4217 RTW_INFO(FUNC_ADPT_FMT" ld_sta_num:%u, lg_sta_num:%u, ap_num:%u, mesh_num:%u, %u,%u,%u\n"
4218 , FUNC_ADPT_ARG(adapter), MSTATE_STA_LD_NUM(&mstate), MSTATE_STA_LG_NUM(&mstate)
4219 , MSTATE_AP_NUM(&mstate), MSTATE_MESH_NUM(&mstate)
4220 , u_ch, u_bw, u_offset);
4221
4222 if (needed == _TRUE)
4223 rtw_dfs_rd_enable(rfctl, u_ch, u_bw, u_offset, ld_sta_in_dfs);
4224 else
4225 rtw_dfs_rd_disable(rfctl, u_ch, u_bw, u_offset, ld_sta_in_dfs);
4226 }
4227
rtw_dfs_rd_en_decision_cmd(_adapter * adapter)4228 u8 rtw_dfs_rd_en_decision_cmd(_adapter *adapter)
4229 {
4230 struct cmd_obj *cmdobj;
4231 struct drvextra_cmd_parm *parm;
4232 struct cmd_priv *cmdpriv = &adapter_to_dvobj(adapter)->cmdpriv;
4233 u8 res = _FAIL;
4234
4235 cmdobj = rtw_zmalloc(sizeof(struct cmd_obj));
4236 if (cmdobj == NULL)
4237 goto exit;
4238
4239 cmdobj->padapter = adapter;
4240
4241 parm = rtw_zmalloc(sizeof(struct drvextra_cmd_parm));
4242 if (parm == NULL) {
4243 rtw_mfree(cmdobj, sizeof(struct cmd_obj));
4244 goto exit;
4245 }
4246
4247 parm->ec_id = DFS_RADAR_DETECT_EN_DEC_WK_CID;
4248 parm->type = 0;
4249 parm->size = 0;
4250 parm->pbuf = NULL;
4251
4252 init_h2fwcmd_w_parm_no_rsp(cmdobj, parm, CMD_SET_DRV_EXTRA);
4253 res = rtw_enqueue_cmd(cmdpriv, cmdobj);
4254
4255 exit:
4256 return res;
4257 }
4258 #endif /* CONFIG_DFS_MASTER */
4259
4260 #endif /* CONFIG_AP_MODE */
4261
4262 #if 0 /*def RTW_PHL_DBG_CMD*/
4263
4264 u8 sample_txwd[] =
4265 {
4266 /*dword 00*/ 0x80, 0x00, 0x40, 0x00,
4267 /*dword 01*/ 0x00, 0x00, 0x00, 0x00,
4268 /*dword 02*/ 0xF2, 0x05, 0x00, 0x00,
4269 /*dword 03*/ 0x3E, 0x11, 0x00, 0x00,
4270 /*dword 04*/ 0x00, 0x00, 0x00, 0x00,
4271 /*dword 05*/ 0x00, 0x00, 0x00, 0x00,
4272 /*dword 06*/ 0x00, 0x07, 0x9B, 0x63,
4273 /*dword 07*/ 0x3F, 0x00, 0x00, 0x00,
4274 /*dword 08*/ 0x00, 0x00, 0x00, 0x00,
4275 /*dword 09*/ 0x00, 0x00, 0x00, 0x00,
4276 /*dword 10*/ 0x0C, 0x00, 0x00, 0x00,
4277 /*dword 11*/ 0x00, 0x00, 0x00, 0x00,
4278 };
4279
4280 #define WD_SPEC(_name, _idx_dw, _bit_start, _bit_end) { \
4281 .name = (_name), \
4282 .idx_dw = (_idx_dw), \
4283 .bit_start = (_bit_start), \
4284 .bit_end = (_bit_end) \
4285 }
4286
4287 struct parse_wd {
4288 char name[32];
4289 u8 idx_dw;
4290 u8 bit_start;
4291 u8 bit_end;
4292 };
4293
4294 #define MAX_PHL_CMD_LEN 200
4295 #define MAX_PHL_CMD_NUM 10
4296 #define MAX_PHL_CMD_STR_LEN 200
4297
4298 char *get_next_para_str(char *para)
4299 {
4300 return (para+MAX_PHL_CMD_STR_LEN);
4301 }
4302
4303 static struct parse_wd parse_txwd_8852ae_full[] = {
4304 WD_SPEC("EN_HWSEQ_MODE" , 0, 0, 1),
4305 WD_SPEC("HW_SSN_SEL" , 0, 2, 3),
4306 WD_SPEC("SMH_EN" , 0, 4, 4),
4307 WD_SPEC("HWAMSDU" , 0, 5, 5),
4308 WD_SPEC("HW_AES_IV" , 0, 6, 6),
4309 WD_SPEC("WD page" , 0, 7, 7),
4310 WD_SPEC("CHK_EN" , 0, 8, 8),
4311 WD_SPEC("WP_INT" , 0, 9, 9),
4312 WD_SPEC("STF mode" , 0, 10, 10),
4313 WD_SPEC("HEADERwLLC_LEN" , 0, 11, 15),
4314 WD_SPEC("CHANNEL_DMA" , 0, 16, 19),
4315 WD_SPEC("FW_download" , 0, 20, 20),
4316 WD_SPEC("PKT_OFFSET" , 0, 21, 21),
4317 WD_SPEC("WDINFO_EN" , 0, 22, 22),
4318 WD_SPEC("MOREDATA" , 0, 23, 23),
4319 WD_SPEC("WP_OFFSET" , 0, 24, 31),
4320
4321 WD_SPEC("SHCUT_CAMID" , 1, 0, 7),
4322 WD_SPEC("DMA_TXAGG_NUM" , 1, 8, 15),
4323 WD_SPEC("PLD(Packet ID)" , 1, 16, 31),
4324
4325 WD_SPEC("TXPKTSIZE" , 2, 0, 13),
4326 WD_SPEC("RU_TC" , 2, 14, 16),
4327 WD_SPEC("QSEL" , 2, 17, 22),
4328 WD_SPEC("TID_indicate" , 2, 23, 23),
4329 WD_SPEC("MACID" , 2, 24, 30),
4330 WD_SPEC("RSVD" , 2, 31, 31),
4331
4332 WD_SPEC("Wifi_SEQ" , 3, 0, 11),
4333 WD_SPEC("AGG_EN" , 3, 12, 12),
4334 WD_SPEC("BK" , 3, 13, 13),
4335 WD_SPEC("RTS_TC" , 3, 14, 19),
4336 WD_SPEC("DATA_TC" , 3, 20, 25),
4337 WD_SPEC("MU_2nd_TC" , 3, 26, 28),
4338 WD_SPEC("MU_TC" , 3, 29, 31),
4339
4340 WD_SPEC("TIMESTAMP" , 4, 0, 15),
4341 WD_SPEC("AES_IV_L" , 4, 16, 31),
4342
4343 WD_SPEC("AES_IV_H" , 5, 0, 31),
4344
4345 WD_SPEC("MBSSID" , 6, 0, 3),
4346 WD_SPEC("Multiport_ID" , 6, 4, 6),
4347 WD_SPEC("RSVD" , 6, 7, 7),
4348 WD_SPEC("DATA_BW_ER" , 6, 8, 8),
4349 WD_SPEC("DISRTSFB" , 6, 9, 9),
4350 WD_SPEC("DISDATAFB" , 6, 10, 10),
4351 WD_SPEC("DATA_LDPC" , 6, 11, 11),
4352 WD_SPEC("DATA_STBC" , 6, 12, 13),
4353 WD_SPEC("DATA_DCM" , 6, 14, 14),
4354 WD_SPEC("DATA_ER" , 6, 15, 15),
4355 WD_SPEC("DataRate" , 6, 16, 24),
4356 WD_SPEC("GI_LTF" , 6, 25, 27),
4357 WD_SPEC("DATA_BW" , 6, 28, 29),
4358 WD_SPEC("USERATE_SEL" , 6, 30, 30),
4359 WD_SPEC("ACK_CH_INFO" , 6, 31, 31),
4360
4361 WD_SPEC("MAX_AGG_NUM" , 7, 0, 7),
4362 WD_SPEC("BCN_SRCH_SEQ" , 7, 8, 9),
4363 WD_SPEC("NAVUSEHDR" , 7, 10, 10),
4364 WD_SPEC("BMC" , 7, 11, 11),
4365 WD_SPEC("A_CTRL_BQR" , 7, 12, 12),
4366 WD_SPEC("A_CTRL_UPH" , 7, 13, 13),
4367 WD_SPEC("A_CTRL_BSR" , 7, 14, 14),
4368 WD_SPEC("A_CTRL_CAS" , 7, 15, 15),
4369 WD_SPEC("DATA_RTY_LOWEST_RATE" , 7, 16, 24),
4370 WD_SPEC("DATA_TXCNT_LMT" , 7, 25, 30),
4371 WD_SPEC("DATA_TXCNT_LMT_SEL" , 7, 31, 31),
4372
4373 WD_SPEC("SEC_CAM_IDX" , 8, 0, 7),
4374 WD_SPEC("SEC_HW_ENC" , 8, 8, 8),
4375 WD_SPEC("SECTYPE" , 8, 9, 12),
4376 WD_SPEC("lifetime_sel" , 8, 13, 15),
4377 WD_SPEC("RSVD" , 8, 16, 16),
4378 WD_SPEC("FORCE_TXOP" , 8, 17, 17),
4379 WD_SPEC("AMPDU_DENSITY" , 8, 18, 20),
4380 WD_SPEC("LSIG_TXOP_EN" , 8, 21, 21),
4381 WD_SPEC("TXPWR_OFSET_TYPE" , 8, 22, 24),
4382 WD_SPEC("RSVD" , 8, 25, 25),
4383 WD_SPEC("obw_cts2self_dup_type" , 8, 26, 29),
4384 WD_SPEC("RSVD" , 8, 30, 31),
4385
4386 WD_SPEC("Signaling_TA_PKT_EN" , 9, 0, 0),
4387 WD_SPEC("NDPA" , 9, 1, 2),
4388 WD_SPEC("SND_PKT_SEL" , 9, 3, 5),
4389 WD_SPEC("SIFS_Tx" , 9, 6, 6),
4390 WD_SPEC("HT_DATA_SND" , 9, 7, 7),
4391 WD_SPEC("RSVD" , 9, 8, 8),
4392 WD_SPEC("RTT_EN" , 9, 9, 9),
4393 WD_SPEC("SPE_RPT" , 9, 10, 10),
4394 WD_SPEC("BT_NULL" , 9, 11, 11),
4395 WD_SPEC("TRI_FRAME" , 9, 12, 12),
4396 WD_SPEC("NULL_1" , 9, 13, 13),
4397 WD_SPEC("NULL_0" , 9, 14, 14),
4398 WD_SPEC("RAW" , 9, 15, 15),
4399 WD_SPEC("Group_bit" , 9, 16, 23),
4400 WD_SPEC("RSVD" , 9, 24, 25),
4401 WD_SPEC("BCNPKT_TSF_CTRL" , 9, 26, 26),
4402 WD_SPEC("Signaling_TA_PKT_SC" , 9, 27, 30),
4403 WD_SPEC("FORCE_BSS_CLR" , 9, 31, 31),
4404
4405 WD_SPEC("SW_DEFINE" , 10, 0, 3),
4406 WD_SPEC("RSVD" , 10, 4, 26),
4407 WD_SPEC("RTS_EN" , 10, 27, 27),
4408 WD_SPEC("CTS2SELF" , 10, 28, 28),
4409 WD_SPEC("CCA_RTS" , 10, 29, 30),
4410 WD_SPEC("HW_RTS_EN" , 10, 31, 31),
4411
4412 WD_SPEC("RSVD" , 11, 0, 3),
4413 WD_SPEC("NDPA_duration" , 11, 4, 26),
4414 };
4415
4416 static struct parse_wd parse_rxwd_8852ae[] = {
4417 WD_SPEC("PKT_LEN" , 0, 0, 13),
4418 WD_SPEC("SHIFT" , 0, 14, 15),
4419 WD_SPEC("WL_HD_IV_LEN" , 0, 16, 21),
4420 WD_SPEC("BB_SEL" , 0, 22, 22),
4421 WD_SPEC("MAC_INFO_VLD" , 0, 23, 23),
4422 WD_SPEC("RPKT_TYPE" , 0, 24, 27),
4423 WD_SPEC("DRV_INFO_SIZE" , 0, 28, 30),
4424 WD_SPEC("LONG_RXD" , 0, 31, 31),
4425
4426 WD_SPEC("PPDU_TYPE" , 1, 0, 3),
4427 WD_SPEC("PPDU_CNT" , 1, 4, 6),
4428 WD_SPEC("SR_EN" , 1, 7, 7),
4429 WD_SPEC("USER_ID" , 1, 8, 15),
4430 WD_SPEC("RX_DATARATE" , 1, 16, 24),
4431 WD_SPEC("RX_GI_LTF" , 1, 25, 27),
4432 WD_SPEC("NON_SRG_PPDU" , 1, 28, 28),
4433 WD_SPEC("INTER_PPDU" , 1, 29, 29),
4434 WD_SPEC("BW" , 1, 30, 31),
4435
4436 WD_SPEC("FREERUN_CNT" , 2, 0, 31),
4437
4438 WD_SPEC("A1_MATCH" , 3, 1, 1),
4439 WD_SPEC("SW_DEC" , 3, 2, 2),
4440 WD_SPEC("HW_DEC" , 3, 3, 3),
4441 WD_SPEC("AMPDU" , 3, 4, 4),
4442 WD_SPEC("AMPDU_END_PKT" , 3, 5, 5),
4443 WD_SPEC("AMSDU" , 3, 6, 6),
4444 WD_SPEC("AMSDU_CUT" , 3, 7, 7),
4445 WD_SPEC("LAST_MSDU" , 3, 8, 8),
4446 WD_SPEC("BYPASS" , 3, 9, 9),
4447 WD_SPEC("CRC32" , 3, 10, 10),
4448 WD_SPEC("MAGIC_WAKE" , 3, 11, 11),
4449 WD_SPEC("UNICAST_WAKE" , 3, 12, 12),
4450 WD_SPEC("PATTERN_WAKE" , 3, 13, 13),
4451 WD_SPEC("GET_CH_INFO" , 3, 14, 14),
4452 WD_SPEC("RX_STATISTICS" , 3, 15, 15),
4453 WD_SPEC("PATTERN_IDX" , 3, 16, 20),
4454 WD_SPEC("TARGET_IDC" , 3, 21, 23),
4455 WD_SPEC("CHKSUM_OFFLOAD_EN" , 3, 24, 24),
4456 WD_SPEC("WITH_LLC" , 3, 25, 25),
4457 WD_SPEC("RSVD" , 3, 26, 31),
4458
4459 WD_SPEC("TYPE" , 4, 0, 1),
4460 WD_SPEC("MC" , 4, 2, 2),
4461 WD_SPEC("BC" , 4, 3, 3),
4462 WD_SPEC("MD" , 4, 4, 4),
4463 WD_SPEC("MF" , 4, 5, 5),
4464 WD_SPEC("PWR" , 4, 6, 6),
4465 WD_SPEC("QOS" , 4, 7, 7),
4466 WD_SPEC("TID" , 4, 8, 11),
4467 WD_SPEC("EOSP" , 4, 12, 12),
4468 WD_SPEC("HTC" , 4, 13, 13),
4469 WD_SPEC("QNULL" , 4, 14, 14),
4470 WD_SPEC("RSVD" , 4, 15, 15),
4471 WD_SPEC("SEQ" , 4, 16, 27),
4472 WD_SPEC("FRAG" , 4, 28, 31),
4473
4474 WD_SPEC("SEC_CAM_IDX" , 5, 0, 7),
4475 WD_SPEC("ADDR_CAM" , 5, 8, 15),
4476 WD_SPEC("MAC_ID" , 5, 16, 23),
4477 WD_SPEC("RX_PL_ID" , 5, 24, 27),
4478 WD_SPEC("ADDR_CAM_VLD" , 5, 28, 28),
4479 WD_SPEC("ADDR_FWD_EN" , 5, 29, 29),
4480 WD_SPEC("RX_PL_MATCH" , 5, 30, 30),
4481 WD_SPEC("RSVD" , 5, 31, 31),
4482 };
4483
4484
4485 enum WD_TYPE {
4486 TXWD_INFO = 0,
4487 TXWD_INFO_BODY,
4488 RXWD,
4489
4490 };
4491
4492 u32 get_txdesc_element_val(u32 val_dw, u8 bit_start, u8 bit_end)
4493 {
4494 u32 mask = 0;
4495 u32 i = 0;
4496
4497 if(bit_start>31
4498 || bit_end>31
4499 || (bit_start>bit_end)){
4500 printk("[%s] error %d %d\n", __FUNCTION__, bit_start, bit_end);
4501 return 0;
4502 }
4503
4504 for(i = bit_start; i<=bit_end; i++){
4505 mask |= (1<<i);
4506 }
4507
4508 return ((val_dw & mask)>>bit_start);
4509 }
4510
4511
4512 void parse_wd_8852ae(_adapter *adapter, u32 type, u32 idx_wd, u8 *wd)
4513 {
4514 u32 i, val = 0;
4515 u32 cur_dw = 0xFF;
4516 u32 idx, val_dw = 0;
4517 u32 array_size = 0;
4518 struct parse_wd *parser = NULL;
4519
4520 if(wd==NULL)
4521 return;
4522
4523 if(type == TXWD_INFO_BODY){
4524 parser = parse_txwd_8852ae_full;
4525 array_size = ARRAY_SIZE(parse_txwd_8852ae_full);
4526 }
4527 else if(type == RXWD){
4528 parser = parse_rxwd_8852ae;
4529 array_size = ARRAY_SIZE(parse_rxwd_8852ae);
4530 }
4531
4532 for(i = 0; i<array_size; i++){
4533 if(cur_dw != parser[i].idx_dw){
4534 cur_dw = parser[i].idx_dw;
4535 idx = (parser[i].idx_dw*4);
4536 val_dw = wd[idx] + (wd[idx+1]<<8) + (wd[idx+2]<<16) + (wd[idx+3]<<24);
4537 printk(">>>> WD[%03d].dw%02d = 0x%08x \n", idx_wd, cur_dw, val_dw);
4538 }
4539
4540 val = get_txdesc_element_val(val_dw,
4541 parser[i].bit_start, parser[i].bit_end);
4542
4543 printk("%s[%d:%d] = (0x%x)\n",
4544 parser[i].name,
4545 parser[i].bit_end, parser[i].bit_start, val);
4546 }
4547 printk("\n");
4548
4549 }
4550
4551
4552 void compare_wd_8852ae(_adapter *adapter, u32 type, u8 *wd1, u8 *wd2)
4553 {
4554 u32 i, val1, val2 = 0;
4555 u32 cur_dw = 0xFF;
4556 u32 idx, val_dw1, val_dw2 = 0;
4557 u32 array_size = 0;
4558 struct parse_wd *parser = NULL;
4559
4560 if((wd1==NULL) ||(wd2==NULL))
4561 return;
4562
4563 if(type == TXWD_INFO_BODY){
4564 parser = parse_txwd_8852ae_full;
4565 array_size = ARRAY_SIZE(parse_txwd_8852ae_full);
4566 }
4567
4568 for(i = 0; i<array_size; i++){
4569 if(cur_dw != parser[i].idx_dw){
4570 cur_dw = parser[i].idx_dw;
4571 idx = (parser[i].idx_dw*4);
4572 val_dw1 = wd1[idx] + (wd1[idx+1]<<8) + (wd1[idx+2]<<16) + (wd1[idx+3]<<24);
4573 val_dw2 = wd2[idx] + (wd2[idx+1]<<8) + (wd2[idx+2]<<16) + (wd2[idx+3]<<24);
4574 }
4575
4576 val1 = get_txdesc_element_val(val_dw1,
4577 parser[i].bit_start, parser[i].bit_end);
4578 val2 = get_txdesc_element_val(val_dw2,
4579 parser[i].bit_start, parser[i].bit_end);
4580
4581 if(val1 != val2){
4582 printk("Diff dw%02d: %s[%d:%d] = (0x%x) vs (0x%x)\n", cur_dw,
4583 parser[i].name,
4584 parser[i].bit_end, parser[i].bit_start, val1, val2);
4585 }
4586 }
4587 printk("\n");
4588
4589 }
4590
4591 void core_dump_map_tx(_adapter *adapter)
4592 {
4593 struct core_logs *log = &adapter->core_logs;
4594 u32 idx = 0;
4595
4596 printk("drvTx MAP");
4597 for(idx=0; idx<CORE_LOG_NUM; idx++){
4598 struct core_record *record = &log->drvTx[idx];
4599 if(idx >= log->txCnt_all)
4600 break;
4601 printk("[drvTx %03d]\n", idx);
4602 printk("type=%d totalSz=%d virtAddr=%p\n", record->type, record->totalSz, record->virtAddr[0]);
4603 }
4604
4605 printk("========= \n\n");
4606 printk("phlTx MAP");
4607 for(idx=0; idx<CORE_LOG_NUM; idx++){
4608 struct core_record *record = &log->phlTx[idx];
4609 u32 idx1 = 0;
4610 if(idx >= log->txCnt_phl)
4611 break;
4612 printk("[phlTx %03d]\n", idx);
4613 printk("type=%d totalSz=%d fragNum=%d\n", record->type, record->totalSz, record->fragNum);
4614 for(idx1=0; idx1<record->fragNum; idx1++){
4615 printk("frag#%d: len=%d virtaddr=%p \n", idx1,
4616 record->fragLen[idx1], record->virtAddr[idx1]);
4617 printk("frag#%d: phyAddrH=%d phyAddrL=%p \n", idx1,
4618 record->phyAddrH[idx1], record->phyAddrL[idx1]);
4619 }
4620 }
4621
4622 printk("========= \n\n");
4623 printk("TxRcycle MAP");
4624 for(idx=0; idx<CORE_LOG_NUM; idx++){
4625 struct core_record *record = &log->txRcycle[idx];
4626 u32 idx1 = 0;
4627 if(idx >= log->txCnt_recycle)
4628 break;
4629 printk("[TxRcycle %03d]\n", idx);
4630 printk("type=%d totalSz=%d fragNum=%d\n", record->type, record->totalSz, record->fragNum);
4631 for(idx1=0; idx1<record->fragNum; idx1++){
4632 printk("frag#%d: len=%d virtaddr=%p \n", idx1,
4633 record->fragLen[idx1], record->virtAddr[idx1]);
4634 printk("frag#%d: phyAddrH=%d phyAddrL=%p \n", idx1,
4635 record->phyAddrH[idx1], record->phyAddrL[idx1]);
4636 }
4637 }
4638 }
4639
4640 void core_dump_map_rx(_adapter *adapter)
4641 {
4642 struct core_logs *log = &adapter->core_logs;
4643 u32 idx = 0;
4644
4645 printk("drvRx MAP");
4646 for(idx=0; idx<CORE_LOG_NUM; idx++){
4647 struct core_record *record = &log->drvRx[idx];
4648 if(idx >= log->rxCnt_all)
4649 break;
4650 printk("[drvRx %03d]\n", idx);
4651 printk("type=%d totalSz=%d virtAddr=%p\n", record->type, record->totalSz, record->virtAddr[0]);
4652 printk("wl_seq=%d wl_type=0x%x wl_subtype=0x%x\n", record->wl_seq, record->wl_type, record->wl_subtype);
4653 }
4654
4655 printk("========= \n\n");
4656 printk("phlRx MAP");
4657 for(idx=0; idx<CORE_LOG_NUM; idx++){
4658 struct core_record *record = &log->phlRx[idx];
4659 if(idx >= log->rxCnt_phl)
4660 break;
4661 printk("[phlRx %03d]\n", idx);
4662 printk("type=%d totalSz=%d virtAddr=%p\n", record->type, record->totalSz, record->virtAddr[0]);
4663 }
4664
4665 printk("========= \n\n");
4666 printk("rxRcycle MAP");
4667 for(idx=0; idx<CORE_LOG_NUM; idx++){
4668 struct core_record *record = &log->rxRcycle[idx];
4669 if(idx >= log->rxCnt_recycle)
4670 break;
4671 printk("[rxRcycle %03d]\n", idx);
4672 printk("type=%d totalSz=%d virtAddr=%p\n", record->type, record->totalSz, record->virtAddr[0]);
4673 }
4674
4675 }
4676
4677
4678 void core_dump_record(_adapter *adapter, u8 dump_type)
4679 {
4680 struct core_logs *log = &adapter->core_logs;
4681 u32 idx = 0;
4682
4683 printk("txCnt_all: %d (%d) \n", log->txCnt_all, log->txCnt_all%CORE_LOG_NUM);
4684 printk("txCnt_data: %d \n", log->txCnt_data);
4685 printk("txCnt_mgmt: %d \n", log->txCnt_mgmt);
4686 printk("txCnt_phl: %d (%d), Sz=%d \n", log->txCnt_phl, log->txCnt_phl%CORE_LOG_NUM, log->txSize_phl);
4687 printk("txCnt_recycle: %d (%d), Sz=%d \n", log->txCnt_recycle, log->txCnt_recycle%CORE_LOG_NUM, log->txSize_recycle);
4688
4689 printk("rxCnt_all: %d (%d) \n", log->rxCnt_all, log->rxCnt_all%CORE_LOG_NUM);
4690 printk("rxCnt_data: %d (retry=%d)\n", log->rxCnt_data, log->rxCnt_data_retry);
4691 printk("rxCnt_mgmt: %d \n", log->rxCnt_mgmt);
4692 printk("rxCnt_phl: %d (%d), Sz=%d \n", log->rxCnt_phl, log->rxCnt_phl%CORE_LOG_NUM, log->rxSize_phl);
4693 printk("rxCnt_recycle: %d (%d), Sz=%d\n", log->rxCnt_recycle, log->rxCnt_recycle%CORE_LOG_NUM, log->rxSize_recycle);
4694 #ifdef CONFIG_RTW_CORE_RXSC
4695 printk("enable_rxsc: %d \n", adapter->enable_rxsc);
4696 printk("rxCnt_data: orig=%d shortcut=%d(ratio=%d)\n",
4697 log->rxCnt_data_orig, log->rxCnt_data_shortcut,
4698 log->rxCnt_data_shortcut*100/(log->rxCnt_data_orig+log->rxCnt_data_shortcut));
4699 printk("rxCnt_coreInd: %d \n", log->rxCnt_coreInd);
4700 #endif
4701
4702 if(dump_type == REC_DUMP_TX){
4703 core_dump_map_tx(adapter);
4704 }
4705 else if(dump_type == REC_DUMP_RX){
4706 core_dump_map_rx(adapter);
4707 }
4708 else if(dump_type == REC_DUMP_ALL){
4709 core_dump_map_tx(adapter);
4710 core_dump_map_rx(adapter);
4711 }
4712 }
4713
4714 void core_add_record(_adapter *adapter, u8 type, void *p)
4715 {
4716 struct core_logs *log = &adapter->core_logs;
4717
4718 if(!adapter->record_enable)
4719 return;
4720
4721 if(type == REC_TX_DATA){
4722 u32 idx = log->txCnt_all%CORE_LOG_NUM;
4723 struct core_record *record = &(log->drvTx[idx]);
4724 struct sk_buff *skb = p;
4725
4726 log->txCnt_data++;
4727 record->type = type;
4728 record->totalSz = skb->len;
4729 record->virtAddr[0] = skb->data;
4730 }
4731
4732 if(type == REC_TX_MGMT){
4733 u32 idx = log->txCnt_all%CORE_LOG_NUM;
4734 struct core_record *record = &(log->drvTx[idx]);
4735 struct xmit_frame *pxframe = p;
4736
4737 log->txCnt_mgmt++;
4738 record->type = type;
4739 record->totalSz = pxframe->attrib.pktlen;
4740 record->virtAddr[0] = pxframe->buf_addr;
4741 }
4742
4743 if(type == REC_TX_PHL || type == REC_TX_PHL_RCC){
4744 u32 idx = 0;
4745 struct core_record *record = NULL;
4746 struct rtw_xmit_req *txreq = p;
4747
4748 if(type == REC_TX_PHL){
4749 idx = log->txCnt_phl%CORE_LOG_NUM;
4750 record = &(log->phlTx[idx]);
4751 log->txCnt_phl++;
4752 }
4753
4754 if(type == REC_TX_PHL_RCC){
4755 idx = log->txCnt_recycle%CORE_LOG_NUM;
4756 record = &(log->txRcycle[idx]);
4757 log->txCnt_recycle++;
4758 }
4759
4760 record->type = type;
4761 record->totalSz = 0;
4762 record->fragNum = txreq->pkt_cnt;
4763
4764 {
4765 struct rtw_pkt_buf_list *pkt_list =(struct rtw_pkt_buf_list *)txreq->pkt_list;
4766 u32 idx1 = 0;
4767 for(idx1=0; idx1<txreq->pkt_cnt; idx1++){
4768 if(idx1 >= MAX_FRAG){
4769 printk("!! WARN[%s][%d] type=%d frag>= %d \n",
4770 __FUNCTION__, __LINE__, type, MAX_FRAG);
4771 break;
4772 }
4773 record->totalSz += pkt_list->length;
4774 record->fragLen[idx1] = pkt_list->length;
4775 record->virtAddr[idx1] = pkt_list->vir_addr;
4776 record->phyAddrL[idx1] = pkt_list->phy_addr_l;
4777 record->phyAddrH[idx1] = pkt_list->phy_addr_h;
4778 pkt_list++;
4779 }
4780 }
4781
4782 if(type == REC_TX_PHL)
4783 log->txSize_phl += record->totalSz;
4784 else if(type == REC_TX_PHL_RCC)
4785 log->txSize_recycle += record->totalSz;
4786
4787 }
4788
4789 if(type == REC_RX_PHL || type == REC_RX_PHL_RCC){
4790 u32 idx = 0;
4791 struct core_record *record = NULL;
4792 struct rtw_recv_pkt *rx_req = p;
4793 struct rtw_pkt_buf_list *pkt = rx_req->pkt_list;
4794
4795 if(type == REC_RX_PHL){
4796 idx = log->rxCnt_phl%CORE_LOG_NUM;
4797 record = &(log->phlRx[idx]);
4798 log->rxCnt_phl++;
4799 }
4800
4801 if(type == REC_RX_PHL_RCC){
4802 idx = log->rxCnt_recycle%CORE_LOG_NUM;
4803 record = &(log->rxRcycle[idx]);
4804 log->rxCnt_recycle++;
4805 }
4806
4807 record->type = type;
4808 record->totalSz = pkt->length;
4809 record->virtAddr[0] = pkt->vir_addr;
4810
4811 if(type == REC_RX_PHL)
4812 log->rxSize_phl += record->totalSz;
4813 else if(type == REC_RX_PHL_RCC)
4814 log->rxSize_recycle += record->totalSz;
4815 }
4816
4817 if(type == REC_RX_DATA || type == REC_RX_MGMT){
4818 u32 idx = log->rxCnt_all%CORE_LOG_NUM;
4819 struct core_record *record = &(log->drvRx[idx]);
4820 union recv_frame *prframe = p;
4821 struct rx_pkt_attrib *pattrib = &prframe->u.hdr.attrib;
4822
4823 if(type == REC_RX_DATA){
4824 log->rxCnt_data++;
4825 }
4826
4827 if(type == REC_RX_MGMT){
4828 log->rxCnt_mgmt++;
4829 }
4830
4831 record->type = type;
4832 record->totalSz = prframe->u.hdr.len;
4833 record->virtAddr[0] = prframe->u.hdr.rx_data;
4834
4835 record->wl_seq = pattrib->seq_num;
4836 record->wl_type = pattrib->wl_type;
4837 record->wl_subtype = pattrib->wl_subtype;
4838
4839 }
4840
4841 if(type == REC_RX_DATA_RETRY){
4842 log->rxCnt_data_retry++;
4843 }
4844
4845 log->txCnt_all = log->txCnt_mgmt + log->txCnt_data;
4846 log->rxCnt_all = log->rxCnt_mgmt + log->rxCnt_data;
4847 }
4848
4849
4850 void phl_dump_map_tx(_adapter *adapter)
4851 {
4852 struct phl_logs *log = &adapter->phl_logs;
4853 u32 idx = 0;
4854
4855 printk("txBd MAP");
4856 for(idx=0; idx<CORE_LOG_NUM; idx++){
4857 struct record_txbd *record = &log->txBd[idx];
4858 if(idx >= log->txCnt_bd)
4859 break;
4860 printk("[txBd %03d]\n", idx);
4861 {
4862 u8 *tmp=record->bd_buf;
4863 u32 len = record->bd_len;
4864 u32 idx1 = 0;
4865 if(tmp == NULL)
4866 break;
4867 for(idx1=0; idx1<len; idx1++){
4868 if(idx1%8==0) {
4869 printk("[%03d] %02x %02x %02x %02x %02x %02x %02x %02x \n",
4870 idx1, tmp[idx1], tmp[idx1+1], tmp[idx1+2], tmp[idx1+3],
4871 tmp[idx1+4], tmp[idx1+5], tmp[idx1+6], tmp[idx1+7]);
4872 }
4873 }
4874 printk("\n");
4875 }
4876 }
4877
4878 printk("========= \n\n");
4879 printk("txWd MAP");
4880 for(idx=0; idx<CORE_LOG_NUM; idx++){
4881 struct record_txwd *record = &log->txWd[idx];
4882 if(idx >= log->txCnt_wd)
4883 break;
4884 printk("[txWd %03d]\n", idx);
4885 {
4886 u8 *tmp=record->wd_buf;
4887 u32 len = record->wd_len;
4888 u32 idx1 = 0;
4889 if(tmp == NULL)
4890 break;
4891 for(idx1=0; idx1<len; idx1++){
4892 if(idx1%8==0) {
4893 printk("[%03d] %02x %02x %02x %02x %02x %02x %02x %02x \n",
4894 idx1, tmp[idx1], tmp[idx1+1], tmp[idx1+2], tmp[idx1+3],
4895 tmp[idx1+4], tmp[idx1+5], tmp[idx1+6], tmp[idx1+7]);
4896 }
4897 }
4898 printk("\n");
4899 }
4900 parse_wd_8852ae(adapter, TXWD_INFO_BODY, idx, record->wd_buf);
4901 //compare_wd_8852ae(adapter, TXWD_INFO_BODY, record->wd_buf, sample_txwd);
4902 }
4903
4904 printk("========= \n\n");
4905 printk("wpRecycle MAP");
4906 for(idx=0; idx<CORE_LOG_NUM; idx++){
4907 struct record_wp_rcc *record = &log->wpRecycle[idx];
4908 if(idx >= log->txCnt_recycle)
4909 break;
4910 printk("[txRecycle %03d]\n", idx);
4911 printk("wp_seq=%d \n", record->wp_seq);
4912 }
4913 }
4914
4915 void phl_dump_map_rx(_adapter *adapter)
4916 {
4917 struct phl_logs *log = &adapter->phl_logs;
4918 u32 idx = 0;
4919
4920 printk("rxPciMap MAP");
4921 for(idx=0; idx<CORE_LOG_NUM; idx++){
4922 struct record_pci *record = &log->rxPciMap[idx];
4923 if(idx >= log->rxCnt_map)
4924 break;
4925 printk("[rxPciMap %03d]\n", idx);
4926 printk("phyAddrL=%p len=%d\n", record->phyAddrL, record->map_len);
4927 }
4928
4929
4930 printk("========= \n\n");
4931 printk("rxPciUnmap MAP");
4932 for(idx=0; idx<CORE_LOG_NUM; idx++){
4933 struct record_pci *record = &log->rxPciUnmap[idx];
4934 if(idx >= log->rxCnt_unmap)
4935 break;
4936 printk("[rxPciUnmap %03d]\n", idx);
4937 printk("phyAddrL=%p len=%d\n", record->phyAddrL, record->map_len);
4938 }
4939
4940 printk("========= \n\n");
4941 printk("rxWd MAP");
4942 for(idx=0; idx<CORE_LOG_NUM; idx++){
4943 struct record_rxwd *record = &log->rxWd[idx];
4944 if(idx >= log->rxCnt_wd)
4945 break;
4946 printk("[rxWd %03d]\n", idx);
4947 {
4948 u8 *tmp = record->wd_buf;
4949 u32 len = record->wd_len;
4950 u32 idx1 = 0;
4951 if(tmp == NULL)
4952 break;
4953 for(idx1=0; idx1<len; idx1++){
4954 if(idx1%8==0) {
4955 printk("[%03d] %02x %02x %02x %02x %02x %02x %02x %02x \n",
4956 idx1, tmp[idx1], tmp[idx1+1], tmp[idx1+2], tmp[idx1+3],
4957 tmp[idx1+4], tmp[idx1+5], tmp[idx1+6], tmp[idx1+7]);
4958 }
4959 }
4960 printk("\n");
4961 }
4962 parse_wd_8852ae(adapter, RXWD, idx, record->wd_buf);
4963 }
4964
4965 printk("========= \n\n");
4966 printk("rxAmpdu MAP");
4967 for(idx=0; idx<CORE_LOG_NUM; idx++){
4968 if(idx >= log->rxCnt_ampdu)
4969 break;
4970 printk("[rxAmpdu %03d] = %d\n", idx, log->rxAmpdu[idx]);
4971 }
4972
4973 }
4974
4975 void phl_dump_record(_adapter *adapter, u8 dump_type)
4976 {
4977 struct phl_logs *log = &adapter->phl_logs;
4978 u32 idx = 0;
4979
4980 printk("txBd: %d (%d) \n", log->txCnt_bd, log->txCnt_bd%CORE_LOG_NUM);
4981 printk("txWd: %d (%d) \n", log->txCnt_wd, log->txCnt_wd%CORE_LOG_NUM);
4982 printk("wpCnt_recycle: %d (%d) \n", log->txCnt_recycle, log->txCnt_recycle%CORE_LOG_NUM);
4983
4984 printk("rxMap: %d (%d), Sz=%d \n", log->rxCnt_map, log->rxCnt_map%CORE_LOG_NUM, log->rxSize_map);
4985 printk("rxUnmap: %d (%d), Sz=%d \n", log->rxCnt_unmap, log->txCnt_wd%CORE_LOG_NUM, log->rxSize_map);
4986 printk("rxWd: %d (%d) \n", log->rxCnt_wd, log->rxCnt_wd%CORE_LOG_NUM);
4987 printk("rxCnt_ampdu: %d (%d) \n", log->rxCnt_ampdu, log->rxCnt_ampdu%CORE_LOG_NUM);
4988
4989 if(dump_type == REC_DUMP_TX)
4990 phl_dump_map_tx(adapter);
4991 else if(dump_type == REC_DUMP_RX)
4992 phl_dump_map_rx(adapter);
4993 else if(dump_type == REC_DUMP_ALL){
4994 phl_dump_map_tx(adapter);
4995 phl_dump_map_rx(adapter);
4996 }
4997 }
4998
4999 u32 tmp_rx_last_ppdu = 0;
5000
5001 void phl_add_record(void *d, u8 type, void *p, u32 num)
5002 {
5003 struct dvobj_priv *pobj = (struct dvobj_priv *)d;
5004 _adapter *adapter = dvobj_get_primary_adapter(pobj);
5005 struct phl_logs *log = &adapter->phl_logs;
5006
5007 if(!adapter->record_enable)
5008 return;
5009
5010 if(type == REC_TXWD){
5011 u32 idx = log->txCnt_wd%CORE_LOG_NUM;
5012 struct record_txwd *record = &(log->txWd[idx]);
5013
5014 log->txCnt_wd++;
5015 record->wd_len = num;
5016 memset((u8 *)record->wd_buf, 0, MAX_TXWD_SIZE);
5017 memcpy((u8 *)record->wd_buf, p, num);
5018 }
5019
5020 if(type == REC_TXBD){
5021 u32 idx = log->txCnt_bd%CORE_LOG_NUM;
5022 struct record_txbd *record = &(log->txBd[idx]);
5023
5024 log->txCnt_bd++;
5025 record->bd_len = num;
5026 memset((u8 *)record->bd_buf, 0, MAX_TXBD_SIZE);
5027 memcpy((u8 *)record->bd_buf, p, num);
5028 }
5029
5030 if(type == REC_WP_RCC){
5031 u32 idx = log->txCnt_recycle%CORE_LOG_NUM;
5032 struct record_wp_rcc *record = &(log->wpRecycle[idx]);
5033
5034 log->txCnt_recycle++;
5035 record->wp_seq = num;
5036 }
5037
5038 if(type == REC_RX_MAP || type == REC_RX_UNMAP){
5039 struct record_pci *record = NULL;
5040 if(type == REC_RX_MAP) {
5041 u32 idx = log->rxCnt_map%CORE_LOG_NUM;
5042 record = &(log->rxPciMap[idx]);
5043 log->rxCnt_map++;
5044 log->rxSize_map+=num;
5045 }
5046 else if(type == REC_RX_UNMAP) {
5047 u32 idx = log->rxCnt_unmap%CORE_LOG_NUM;
5048 record = &(log->rxPciUnmap[idx]);
5049 log->rxCnt_unmap++;
5050 log->rxSize_map+=num;
5051 }
5052 record->phyAddrL = p;
5053 record->map_len = num;
5054 }
5055
5056 if(type == REC_RXWD){
5057 u32 idx = log->rxCnt_wd%CORE_LOG_NUM;
5058 struct record_rxwd *record = &(log->rxWd[idx]);
5059
5060 log->rxCnt_wd++;
5061 record->wd_len = num;
5062 memset((u8 *)record->wd_buf, 0, MAX_RXWD_SIZE);
5063 memcpy((u8 *)record->wd_buf, p, num);
5064 }
5065
5066 if(type == REC_RX_AMPDU){
5067 u32 idx = 0;
5068
5069 if(log->rxCnt_ampdu == 0 && (log->rxAmpdu[0] == 0))
5070 tmp_rx_last_ppdu = num;
5071
5072 if(tmp_rx_last_ppdu != num){
5073 tmp_rx_last_ppdu = num;
5074
5075 log->rxCnt_ampdu ++;
5076 idx = log->rxCnt_ampdu%CORE_LOG_NUM;
5077 log->rxAmpdu[idx] = 1;
5078 }
5079 else{
5080 idx = log->rxCnt_ampdu%CORE_LOG_NUM;
5081 log->rxAmpdu[idx]++;
5082 }
5083 }
5084
5085 }
5086
5087 void core_cmd_record_trx(_adapter *adapter, void *cmd_para, u32 para_num)
5088 {
5089 u32 idx = 0;
5090 char *para = (char *)cmd_para;
5091
5092 if(para_num<=0)
5093 return;
5094
5095 if(!strcmp(para, "start")){
5096 u8 *log = NULL;
5097 log = (u8*)&adapter->core_logs;
5098 memset(log, 0, sizeof(struct core_logs));
5099 log = (u8*)&adapter->phl_logs;
5100 memset(log, 0, sizeof(struct phl_logs));
5101 adapter->record_enable = 1;
5102 }else if(!strcmp(para, "stop")){
5103 adapter->record_enable = 0;
5104 }else if(!strcmp(para, "dump")){
5105 u32 dump_type = 0;
5106 para=get_next_para_str(para);
5107 sscanf(para, "%d", &dump_type);
5108 phl_dump_record(adapter, (u8)dump_type);
5109 }
5110 }
5111
5112 void reset_txforce_para(_adapter *adapter)
5113 {
5114 adapter->txForce_rate = INV_TXFORCE_VAL;
5115 adapter->txForce_agg = INV_TXFORCE_VAL;
5116 adapter->txForce_aggnum = INV_TXFORCE_VAL;
5117 adapter->txForce_gi = INV_TXFORCE_VAL;
5118 }
5119
5120 void core_cmd_txforce(_adapter *adapter, void *cmd_para, u32 para_num)
5121 {
5122 u32 idx = 0;
5123 char *para = (char *)cmd_para;
5124
5125 if(para_num<=0)
5126 return;
5127
5128 if(!strcmp(para, "start")){
5129 adapter->txForce_enable = 1;
5130 reset_txforce_para(adapter);
5131 }else if(!strcmp(para, "stop")){
5132 adapter->txForce_enable = 0;
5133 reset_txforce_para(adapter);
5134 }else if(!strcmp(para, "rate")){
5135 u32 rate = 0;
5136 para=get_next_para_str(para);
5137 sscanf(para, "%x", &rate);
5138 adapter->txForce_rate = rate;
5139 }else if(!strcmp(para, "agg")){
5140 u32 agg = 0;
5141 para=get_next_para_str(para);
5142 sscanf(para, "%x", &agg);
5143 adapter->txForce_agg = agg;
5144 }else if(!strcmp(para, "aggnum")){
5145 u32 aggnum = 0;
5146 para=get_next_para_str(para);
5147 sscanf(para, "%d", &aggnum);
5148 adapter->txForce_aggnum = aggnum;
5149 }else if(!strcmp(para, "gi")){
5150 u32 gi = 0;
5151 para=get_next_para_str(para);
5152 sscanf(para, "%d", &gi);
5153 adapter->txForce_gi = gi;
5154 }else if(!strcmp(para, "macid")){
5155
5156 }else if(!strcmp(para, "retry")){
5157
5158 }
5159 }
5160
5161 #ifdef CONFIG_RTW_CORE_RXSC
5162 void core_cmd_rxsc(_adapter *adapter, void *cmd_para, u32 para_num)
5163 {
5164 u32 idx = 0;
5165 char *para = (char *)cmd_para;
5166
5167 printk("core_cmd_rxsc \n");
5168
5169 if(para_num<=0)
5170 return;
5171
5172 if(!strcmp(para, "enable")){
5173 printk("enable");
5174 adapter->enable_rxsc = 1;
5175 }else if(!strcmp(para, "disable")){
5176 printk("disable");
5177 adapter->enable_rxsc = 0;
5178 }else if(!strcmp(para, "dump")){
5179 struct core_logs *log = &adapter->core_logs;
5180 printk("dump");
5181 printk("enable_rxsc: %d \n", adapter->enable_rxsc);
5182 printk("rxCnt_data: orig=%d shortcut=%d(ratio=%d)\n",
5183 log->rxCnt_data_orig, log->rxCnt_data_shortcut,
5184 log->rxCnt_data_shortcut*100/(log->rxCnt_data_orig+log->rxCnt_data_shortcut));
5185 }
5186
5187 }
5188 #endif
5189
5190 void core_sniffer_rx(_adapter *adapter, u8 *pkt, u32 pktlen)
5191 {
5192 struct sk_buff* pskb = NULL;
5193
5194 if(!adapter->sniffer_enable)
5195 return;
5196
5197 if(pkt==NULL)
5198 return;
5199
5200 pskb = dev_alloc_skb(pktlen+200);
5201
5202 if(pskb == NULL){
5203 return;
5204 }
5205
5206 _rtw_memcpy(pskb->data, pkt, pktlen);
5207 pskb->len = pktlen;
5208
5209 skb_reset_mac_header(pskb);
5210 pskb->dev = adapter->pnetdev;
5211 pskb->dev->type = ARPHRD_IEEE80211;
5212 pskb->ip_summed = CHECKSUM_UNNECESSARY;
5213 pskb->pkt_type = PACKET_OTHERHOST;
5214 pskb->protocol = htons(ETH_P_802_2);
5215 netif_receive_skb(pskb);
5216
5217 return;
5218 }
5219
5220 void core_cmd_sniffer(_adapter *adapter, void *cmd_para, u32 para_num)
5221 {
5222 u32 idx=0;
5223 char *para = (char *)cmd_para;
5224
5225 if(para_num<=0)
5226 return;
5227
5228 if(!strcmp(para, "start")){
5229 adapter->sniffer_enable = 1;
5230 }else if(!strcmp(para, "stop")){
5231 adapter->sniffer_enable = 0;
5232 }
5233 }
5234
5235
5236 #define LEN_TEST_BUF 2000
5237 u8 test_buf[LEN_TEST_BUF];
5238
5239 #ifdef CONFIG_PCI_HCI
5240 #include <rtw_trx_pci.h>
5241 #endif
5242
5243 #include "../phl/phl_headers.h"
5244 #include "../phl/phl_api.h"
5245 #include "../phl/hal_g6/hal_api_mac.h"
5246 #include "../phl/hal_g6/mac/mac_reg.h"
5247
5248
5249 #define SHOW_REG32(adapter, reg) \
5250 do { \
5251 printk("\t%04X = %08X\n", \
5252 (reg), rtw_phl_read32(adapter->dvobj->phl, reg)); \
5253 } while (0)
5254
5255 #define SHOW_REG32_MSG(adapter, reg, msg) \
5256 do { \
5257 printk("\t%04X = %08X - %s\n", \
5258 (reg), rtw_phl_read32(adapter->dvobj->phl, reg), msg); \
5259 } while (0)
5260
5261 #define SHOW_REG16(adapter, reg) \
5262 do { \
5263 printk("\t%04X = %04X\n", \
5264 (reg), rtw_phl_read16(adapter->dvobj->phl, reg)); \
5265 } while (0)
5266
5267 #define SHOW_REG16_MSG(adapter, reg, msg) \
5268 do { \
5269 printk("\t%04X = %04X - %s\n", \
5270 (reg), rtw_phl_read16(adapter->dvobj->phl, reg), msg); \
5271 } while (0)
5272
5273
5274 static inline void _show_RX_counter(_adapter *adapter)
5275 {
5276 /* Show RX PPDU counters */
5277 int i;
5278 u32 reg32 = rtw_phl_read32(adapter->dvobj->phl, R_AX_RX_DBG_CNT_SEL);
5279 static const char *cnt_name[] = {"Invalid packet",
5280 "RE-CCA",
5281 "RX FIFO overflow",
5282 "RX packet full drop",
5283 "RX packet dma OK",
5284 "UD 0",
5285 "UD 1",
5286 "UD 2",
5287 "UD 3",
5288 "continuous FCS error",
5289 "RX packet filter drop",
5290 "CSI packet DMA OK",
5291 "CSI packet DMA drop",
5292 "RX MAC stop"
5293 };
5294
5295 printk("CMAC0 RX PPDU Counters @%04X:\n", R_AX_RX_DBG_CNT_SEL);
5296 reg32 &= ~(B_AX_RX_CNT_IDX_MSK << B_AX_RX_CNT_IDX_SH);
5297 for (i = 30; i < 44; i++) {
5298 rtw_phl_write32(adapter->dvobj->phl, R_AX_RX_DBG_CNT_SEL,
5299 reg32 | (i << B_AX_RX_CNT_IDX_SH));
5300 printk(" %02X: %d - %s\n", i,
5301 (
5302 ( rtw_phl_read32(adapter->dvobj->phl, R_AX_RX_DBG_CNT_SEL)
5303 >> B_AX_RX_DBG_CNT_SH)
5304 & B_AX_RX_DBG_CNT_MSK),
5305 cnt_name[i - 30]);
5306 }
5307
5308 reg32 = rtw_phl_read32(adapter->dvobj->phl, R_AX_RX_DBG_CNT_SEL_C1);
5309 printk("CMAC1 RX PPDU Counters @%04X:\n", R_AX_RX_DBG_CNT_SEL_C1);
5310 reg32 &= ~(B_AX_RX_CNT_IDX_MSK << B_AX_RX_CNT_IDX_SH);
5311 for (i = 30; i < 44; i++) {
5312 rtw_phl_write32(adapter->dvobj->phl, R_AX_RX_DBG_CNT_SEL_C1,
5313 reg32 | (i << B_AX_RX_CNT_IDX_SH));
5314 printk(" %02X: %d - %s\n", i,
5315 (
5316 ( rtw_phl_read32(adapter->dvobj->phl, R_AX_RX_DBG_CNT_SEL_C1)
5317 >> B_AX_RX_DBG_CNT_SH)
5318 & B_AX_RX_DBG_CNT_MSK),
5319 cnt_name[i - 30]);
5320 }
5321 } /* _show_RX_counter */
5322
5323 void _show_TX_dbg_status(_adapter *adapter)
5324 {
5325 u32 reg32 = rtw_phl_read32(adapter->dvobj->phl, 0x9F1C);
5326 printk("TX Debug: 0x%08X\n", reg32);
5327 }
5328
5329 void _show_BCN_dbg_status(_adapter *adapter)
5330 {
5331 SHOW_REG32_MSG(adapter, R_AX_PORT_CFG_P0, "PORT_CFG_P0");
5332 SHOW_REG32_MSG(adapter, R_AX_TBTT_PROHIB_P0, "TBTT_PROHIB_P0");
5333 SHOW_REG32_MSG(adapter, R_AX_EN_HGQ_NOLIMIT, "EN_HGQ_NOLIMIT");
5334 SHOW_REG32_MSG(adapter, R_AX_TBTT_AGG_P0, "TBTT_AGG_P0");
5335
5336 SHOW_REG32_MSG(adapter, R_AX_PORT_CFG_P0_C1, "PORT_CFG_P0_C1");
5337 SHOW_REG32_MSG(adapter, R_AX_TBTT_PROHIB_P0_C1, "TBTT_PROHIB_P0_C1");
5338 SHOW_REG32_MSG(adapter, R_AX_EN_HGQ_NOLIMIT_C1, "EN_HGQ_NOLIMIT_C1");
5339 SHOW_REG32_MSG(adapter, R_AX_TBTT_AGG_P0_C1, "TBTT_AGG_P0_C1");
5340
5341 SHOW_REG32_MSG(adapter, R_AX_WCPU_FW_CTRL, "R_AX_WCPU_FW_CTRL");
5342 }
5343
5344
5345 void core_cmd_dump_debug(_adapter *adapter, void *cmd_para, u32 para_num)
5346 {
5347 printk("TX path registers: \n");
5348
5349 SHOW_REG32_MSG(adapter, R_AX_RXQ_RXBD_IDX, "RX_BD_IDX");
5350 SHOW_REG32_MSG(adapter, R_AX_RPQ_RXBD_IDX, "RP_BD_IDX");
5351 SHOW_REG32_MSG(adapter, R_AX_ACH0_TXBD_IDX, "ACH0 IDX");
5352 SHOW_REG32_MSG(adapter, R_AX_ACH1_TXBD_IDX, "ACH1 IDX");
5353 SHOW_REG32_MSG(adapter, R_AX_ACH2_TXBD_IDX, "ACH2 IDX");
5354 SHOW_REG32_MSG(adapter, R_AX_ACH3_TXBD_IDX, "ACH3 IDX");
5355 SHOW_REG32_MSG(adapter, R_AX_ACH4_TXBD_IDX, "ACH4 IDX");
5356 SHOW_REG32_MSG(adapter, R_AX_ACH5_TXBD_IDX, "ACH5 IDX");
5357 SHOW_REG32_MSG(adapter, R_AX_ACH6_TXBD_IDX, "ACH6 IDX");
5358 SHOW_REG32_MSG(adapter, R_AX_ACH7_TXBD_IDX, "ACH7 IDX");
5359 SHOW_REG32_MSG(adapter, R_AX_CH8_TXBD_IDX, "CH8 IDX");
5360 SHOW_REG32_MSG(adapter, R_AX_CH9_TXBD_IDX, "CH9 IDX");
5361 SHOW_REG32_MSG(adapter, R_AX_CH10_TXBD_IDX, "CH10 IDX");
5362 SHOW_REG32_MSG(adapter, R_AX_CH11_TXBD_IDX, "CH11 IDX");
5363 SHOW_REG32_MSG(adapter, R_AX_CH12_TXBD_IDX, "CH12 IDX");
5364 #ifdef R_AX_PCIE_DBG_CTRL
5365 SHOW_REG32_MSG(adapter, R_AX_PCIE_DBG_CTRL, "DBG_CTRL");
5366 #else
5367 SHOW_REG32_MSG(adapter, 0x11C0, "DBG_CTRL");
5368 #endif
5369 SHOW_REG32_MSG(adapter, R_AX_DBG_ERR_FLAG, "DBG_ERR");
5370 SHOW_REG32_MSG(adapter, R_AX_PCIE_HIMR00, "IMR0");
5371 SHOW_REG32_MSG(adapter, R_AX_PCIE_HISR00, "ISR0");
5372 SHOW_REG32_MSG(adapter, R_AX_PCIE_HIMR10, "IMR1");
5373 SHOW_REG32_MSG(adapter, R_AX_PCIE_HISR10, "IMR1");
5374 SHOW_REG16_MSG(adapter, R_AX_ACH0_BDRAM_RWPTR, "CH0");
5375 SHOW_REG16_MSG(adapter, R_AX_ACH1_BDRAM_RWPTR, "CH1");
5376 SHOW_REG16_MSG(adapter, R_AX_ACH2_BDRAM_RWPTR, "CH2");
5377 SHOW_REG16_MSG(adapter, R_AX_ACH3_BDRAM_RWPTR, "CH3");
5378 SHOW_REG16_MSG(adapter, R_AX_ACH4_BDRAM_RWPTR, "CH4");
5379 SHOW_REG16_MSG(adapter, R_AX_ACH5_BDRAM_RWPTR, "CH5");
5380 SHOW_REG16_MSG(adapter, R_AX_ACH6_BDRAM_RWPTR, "CH6");
5381 SHOW_REG16_MSG(adapter, R_AX_ACH7_BDRAM_RWPTR, "CH7");
5382 SHOW_REG16_MSG(adapter, R_AX_CH8_BDRAM_RWPTR, "CH8");
5383 SHOW_REG16_MSG(adapter, R_AX_CH9_BDRAM_RWPTR, "CH9");
5384 SHOW_REG16_MSG(adapter, R_AX_CH10_BDRAM_RWPTR, "CH10");
5385 SHOW_REG16_MSG(adapter, R_AX_CH11_BDRAM_RWPTR, "CH11");
5386 SHOW_REG16_MSG(adapter, R_AX_CH12_BDRAM_RWPTR, "CH12");
5387 SHOW_REG32_MSG(adapter, R_AX_PCIE_DMA_STOP1, "DMA_STOP1");
5388 SHOW_REG32_MSG(adapter, R_AX_PCIE_DMA_BUSY1, "DMA_BUSY1");
5389 SHOW_REG32_MSG(adapter, R_AX_PCIE_DMA_STOP2, "DMA_STOP2");
5390 SHOW_REG32_MSG(adapter, R_AX_PCIE_DMA_BUSY2, "DMA_BUSY2");
5391 SHOW_REG32(adapter, 0x8840);
5392 SHOW_REG32(adapter, 0x8844);
5393 SHOW_REG32(adapter, 0x8854);
5394 SHOW_REG16(adapter, 0xCA22);
5395 SHOW_REG32(adapter, 0x8AA8);
5396
5397 /* Show TX PPDU counters */
5398 do {
5399 int i;
5400 u32 reg32 = rtw_phl_read32(adapter->dvobj->phl, R_AX_TX_PPDU_CNT);
5401
5402 printk("CMAC0 TX PPDU Counters @%04X:\n", R_AX_TX_PPDU_CNT);
5403
5404 reg32 &= ~(B_AX_PPDU_CNT_IDX_MSK << B_AX_PPDU_CNT_IDX_SH);
5405 for (i = 0; i < 11; i++) {
5406 rtw_phl_write32(adapter->dvobj->phl, R_AX_TX_PPDU_CNT,
5407 reg32 | (i << B_AX_PPDU_CNT_IDX_SH));
5408 printk(" %02X: %d\n", i,
5409 (
5410 ( rtw_phl_read32(adapter->dvobj->phl, R_AX_TX_PPDU_CNT)
5411 >> B_AX_TX_PPDU_CNT_SH)
5412 & B_AX_TX_PPDU_CNT_MSK));
5413 }
5414
5415 reg32 = rtw_phl_read32(adapter->dvobj->phl, R_AX_TX_PPDU_CNT_C1);
5416
5417 printk("CMAC1 TX PPDU Counters @%04X:\n", R_AX_TX_PPDU_CNT_C1);
5418
5419 reg32 &= ~(B_AX_PPDU_CNT_IDX_MSK << B_AX_PPDU_CNT_IDX_SH);
5420 for (i = 0; i < 11; i++) {
5421 rtw_phl_write32(adapter->dvobj->phl, R_AX_TX_PPDU_CNT_C1,
5422 reg32 | (i << B_AX_PPDU_CNT_IDX_SH));
5423 printk(" %02X: %d\n", i,
5424 (
5425 ( rtw_phl_read32(adapter->dvobj->phl, R_AX_TX_PPDU_CNT_C1)
5426 >> B_AX_TX_PPDU_CNT_SH)
5427 & B_AX_TX_PPDU_CNT_MSK));
5428 }
5429 } while (0);
5430
5431 /* Show RX PPDU counters */
5432 _show_RX_counter(adapter);
5433
5434 _show_TX_dbg_status(adapter);
5435
5436 _show_BCN_dbg_status(adapter);
5437
5438 }
5439
5440 void core_cmd_dump_reg(_adapter *adapter, void *cmd_para, u32 para_num)
5441 {
5442 u32 *para = (u32 *)cmd_para;
5443 void *phl = adapter->dvobj->phl;
5444 u32 reg_start, reg_end;
5445 u32 idx = 0;
5446
5447 reg_start = para[0];
5448 reg_end = reg_start + para[1];
5449
5450 while(1) {
5451 if((reg_start>=reg_end) || (reg_start >= 0xffff))
5452 break;
5453
5454 printk("[%04x] %08x %08x %08x %08x \n",
5455 reg_start,
5456 rtw_phl_read32(phl, reg_start), rtw_phl_read32(phl, reg_start+4),
5457 rtw_phl_read32(phl, reg_start+8), rtw_phl_read32(phl, reg_start+12));
5458
5459 reg_start+=16;
5460 }
5461 }
5462
5463 enum _CORE_CMD_PARA_TYPE {
5464 CMD_PARA_DEC = 0,
5465 CMD_PARA_HEX,
5466 CMD_PARA_STR,
5467 };
5468
5469 struct test_cmd_list {
5470 const char *name;
5471 void (*fun)(_adapter *, void *, u32);
5472 enum _CORE_CMD_PARA_TYPE para_type;
5473 };
5474
5475 void test_dump_dec(_adapter *adapter, void *cmd_para, u32 para_num)
5476 {
5477 u32 idx = 0;
5478 u32 *para = (u32 *)cmd_para;
5479 DBGP("para_num=%d\n", para_num);
5480
5481 for(idx=0; idx<para_num; idx++)
5482 DBGP("para[%d]=%d\n", para_num, para[idx]);
5483 }
5484
5485 void test_dump_hex(_adapter *adapter, void *cmd_para, u32 para_num)
5486 {
5487 u32 idx = 0;
5488 u32 *para = (u32 *)cmd_para;
5489 DBGP("para_num=%d\n", para_num);
5490
5491 for(idx=0; idx<para_num; idx++)
5492 DBGP("para[%d]=0x%x\n", para_num, para[idx]);
5493 }
5494
5495 void test_dump_str(_adapter *adapter, void *cmd_para, u32 para_num)
5496 {
5497 u32 idx = 0;
5498 char *para = (char *)cmd_para;
5499 DBGP("para_num=%d\n", para_num);
5500
5501 for(idx=0; idx<para_num; idx++, para+=MAX_PHL_CMD_STR_LEN)
5502 DBGP("para[%d]=%s\n", para_num, para);
5503 }
5504
5505 void get_all_cmd_para_value(_adapter *adapter, char *buf, u32 len, u32 *para, u8 type, u32 *num)
5506 {
5507 u8 *tmp = NULL;
5508
5509 if(!buf || !len)
5510 return;
5511
5512 DBGP("type=%d buf=%s para=%p num=%d\n", type, buf, para, *num);
5513
5514 if(len > 0){
5515 tmp = strsep(&buf, ",");
5516
5517 if(tmp){
5518 if(type == CMD_PARA_HEX)
5519 sscanf(tmp, "%x", para);
5520 else if(type == CMD_PARA_DEC)
5521 sscanf(tmp, "%d", para);
5522 para += 1;
5523 *num = *num+1;
5524 }
5525 else
5526 return;
5527
5528 if(buf && (len>strlen(tmp)))
5529 get_all_cmd_para_value(adapter, buf, strlen(buf), para, type, num);
5530 else
5531 return;
5532 }
5533 }
5534
5535 void get_all_cmd_para_str(_adapter *adapter, char *buf, u32 len, char *para, u8 type, u32* num)
5536 {
5537 u8 *tmp = NULL;
5538
5539 if(!buf || !len)
5540 return;
5541
5542 DBGP("type=%d buf=%s para=%p num=%d\n", type, buf, para, *num);
5543
5544 if(len > 0){
5545 tmp = strsep(&buf, ",");
5546
5547 if(tmp){
5548 strcpy(para, tmp);
5549 para += MAX_PHL_CMD_STR_LEN;
5550 *num = *num+1;
5551 }
5552 else
5553 return;
5554
5555 if(buf && (len>strlen(tmp)))
5556 get_all_cmd_para_str(adapter, buf, strlen(buf), para, type, num);
5557 else
5558 return;
5559 }
5560 }
5561
5562 struct test_cmd_list core_test_cmd_list[] = {
5563 {"dec", test_dump_dec, CMD_PARA_DEC},
5564 {"hex", test_dump_hex, CMD_PARA_HEX},
5565 {"str", test_dump_str, CMD_PARA_STR},
5566 {"dump_reg", core_cmd_dump_reg, CMD_PARA_HEX},
5567 {"dump_debug", core_cmd_dump_debug, CMD_PARA_DEC},
5568 {"record", core_cmd_record_trx, CMD_PARA_STR},
5569 {"txforce", core_cmd_txforce, CMD_PARA_STR},
5570 {"sniffer", core_cmd_sniffer, CMD_PARA_STR},
5571 #ifdef CONFIG_RTW_CORE_RXSC
5572 {"rxsc", core_cmd_rxsc, CMD_PARA_STR},
5573 #endif
5574 };
5575
5576 void core_cmd_phl_handler(_adapter *adapter, char *extra)
5577 {
5578 u32 para[MAX_PHL_CMD_NUM]={0};
5579 char para_str[MAX_PHL_CMD_NUM][MAX_PHL_CMD_STR_LEN]={0};
5580 char *cmd_name, *cmd_para = NULL;
5581 struct test_cmd_list *cmd = &core_test_cmd_list;
5582 u32 array_size = ARRAY_SIZE(core_test_cmd_list);
5583 u32 i = 0;
5584
5585 cmd_name = strsep(&extra, ",");
5586
5587 if(!cmd_name){
5588 for(i = 0; i<array_size; i++, cmd++)
5589 printk(" - %s\n", cmd->name);
5590 return;
5591 }
5592
5593 for(i = 0; i<array_size; i++, cmd++){
5594 if(!strcmp(cmd->name, cmd_name)){
5595 void *cmd_para = NULL;
5596 u32 cmd_para_num = 0;
5597 if(cmd->para_type == CMD_PARA_DEC || cmd->para_type == CMD_PARA_HEX){
5598 cmd_para = para;
5599 if(extra)
5600 get_all_cmd_para_value(adapter, extra, strlen(extra), para, cmd->para_type, &cmd_para_num);
5601 }
5602 else{
5603 cmd_para = para_str;
5604 if(extra)
5605 get_all_cmd_para_str(adapter, extra, strlen(extra), para_str, cmd->para_type, &cmd_para_num);
5606 }
5607
5608 cmd->fun(adapter, cmd_para, cmd_para_num);
5609 break;
5610 }
5611 }
5612
5613 }
5614
5615 #endif
5616
rtw_test_h2c_cmd(_adapter * adapter,u8 * buf,u8 len)5617 u8 rtw_test_h2c_cmd(_adapter *adapter, u8 *buf, u8 len)
5618 {
5619 struct cmd_obj *pcmdobj;
5620 struct drvextra_cmd_parm *pdrvextra_cmd_parm;
5621 u8 *ph2c_content;
5622 struct cmd_priv *pcmdpriv = &adapter_to_dvobj(adapter)->cmdpriv;
5623 u8 res = _SUCCESS;
5624
5625 pcmdobj = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
5626 if (pcmdobj == NULL) {
5627 res = _FAIL;
5628 goto exit;
5629 }
5630 pcmdobj->padapter = adapter;
5631
5632 pdrvextra_cmd_parm = (struct drvextra_cmd_parm *)rtw_zmalloc(sizeof(struct drvextra_cmd_parm));
5633 if (pdrvextra_cmd_parm == NULL) {
5634 rtw_mfree((u8 *)pcmdobj, sizeof(struct cmd_obj));
5635 res = _FAIL;
5636 goto exit;
5637 }
5638
5639 ph2c_content = rtw_zmalloc(len);
5640 if (ph2c_content == NULL) {
5641 rtw_mfree((u8 *)pcmdobj, sizeof(struct cmd_obj));
5642 rtw_mfree((u8 *)pdrvextra_cmd_parm, sizeof(struct drvextra_cmd_parm));
5643 res = _FAIL;
5644 goto exit;
5645 }
5646
5647 pdrvextra_cmd_parm->ec_id = TEST_H2C_CID;
5648 pdrvextra_cmd_parm->type = 0;
5649 pdrvextra_cmd_parm->size = len;
5650 pdrvextra_cmd_parm->pbuf = ph2c_content;
5651
5652 _rtw_memcpy(ph2c_content, buf, len);
5653
5654 init_h2fwcmd_w_parm_no_rsp(pcmdobj, pdrvextra_cmd_parm, CMD_SET_DRV_EXTRA);
5655
5656 res = rtw_enqueue_cmd(pcmdpriv, pcmdobj);
5657
5658 exit:
5659 return res;
5660 }
5661
5662 #ifdef CONFIG_MP_INCLUDED
rtw_mp_cmd_hdl(_adapter * padapter,u8 mp_cmd_id)5663 static s32 rtw_mp_cmd_hdl(_adapter *padapter, u8 mp_cmd_id)
5664 {
5665 struct dvobj_priv *dvobj = adapter_to_dvobj(padapter);
5666 int ret = H2C_SUCCESS;
5667 uint status = _FALSE;
5668 struct mp_priv *pmppriv = &padapter->mppriv;
5669 struct rtw_test_module_info test_module_info;
5670 struct rtw_mp_test_rpt my_mp_test_rpt;
5671
5672 if (mp_cmd_id == MP_START) {
5673 if (padapter->registrypriv.mp_mode == 0) {
5674
5675 test_module_info.tm_mode = RTW_DRV_MODE_MP;
5676 test_module_info.tm_type = RTW_TEST_SUB_MODULE_MP;
5677 pmppriv->keep_ips_status = dvobj->phl_com->dev_sw_cap.ps_cap.ips_en;
5678 pmppriv->keep_lps_status = dvobj->phl_com->dev_sw_cap.ps_cap.lps_en;
5679 dvobj->phl_com->dev_sw_cap.ps_cap.ips_en = PS_OP_MODE_DISABLED;
5680 dvobj->phl_com->dev_sw_cap.ps_cap.lps_en = PS_OP_MODE_DISABLED;
5681
5682 rtw_phl_test_submodule_init(dvobj->phl_com, &test_module_info);
5683 #ifdef CONFIG_BTC
5684 if (dvobj->phl_com->dev_cap.btc_mode == BTC_MODE_NORMAL ||\
5685 dvobj->phl_com->dev_cap.btc_mode == BTC_MODE_BT) {
5686
5687 pmppriv->mp_keep_btc_mode = dvobj->phl_com->dev_cap.btc_mode;
5688 rtw_mp_phl_config_arg(padapter, RTW_MP_CONFIG_CMD_SWITCH_BT_PATH);
5689 RTW_INFO("config BTC to WL Only\n");
5690 }
5691 #endif
5692 rtw_mp_phl_config_arg(padapter, RTW_MP_CONFIG_CMD_SET_PHY_INDEX);
5693 status = rtw_mp_phl_config_arg(padapter, RTW_MP_CONFIG_CMD_START_DUT);
5694
5695 if (status == _TRUE) {
5696 padapter->registrypriv.mp_mode = 1;
5697 MPT_InitializeAdapter(padapter, 1);
5698 }
5699 }
5700
5701 if (padapter->registrypriv.mp_mode == 0) {
5702 ret = H2C_REJECTED;
5703 goto exit;
5704 }
5705
5706 if (padapter->mppriv.mode == MP_OFF) {
5707 if (mp_start_test(padapter) == _FAIL) {
5708 ret = H2C_REJECTED;
5709 goto exit;
5710 }
5711 padapter->mppriv.mode = MP_ON;
5712 }
5713 padapter->mppriv.bmac_filter = _FALSE;
5714
5715 } else if (mp_cmd_id == MP_STOP) {
5716 if (padapter->registrypriv.mp_mode == 1) {
5717
5718 status = rtw_mp_phl_config_arg(padapter, RTW_MP_CONFIG_CMD_STOP_DUT);
5719 RTW_INFO("RTW_MP_CONFIG_CMD_STOP_DUT %s\n", status == _TRUE ? "ok" : "fail");
5720 rtw_phl_test_get_rpt(dvobj->phl_com, (u8*)&my_mp_test_rpt, sizeof(my_mp_test_rpt));
5721
5722 if (my_mp_test_rpt.status == _TRUE)
5723 RTW_INFO("TM Sub finished OK!!!\n");
5724 #ifdef CONFIG_BTC
5725 if (pmppriv->mp_keep_btc_mode != BTC_MODE_MAX) {
5726 pmppriv->btc_path = pmppriv->mp_keep_btc_mode;
5727 rtw_mp_phl_config_arg(padapter, RTW_MP_CONFIG_CMD_SWITCH_BT_PATH);
5728 }
5729 #endif
5730 test_module_info.tm_mode = RTW_DRV_MODE_NORMAL;
5731 test_module_info.tm_type = RTW_TEST_SUB_MODULE_MP;
5732 dvobj->phl_com->dev_sw_cap.ps_cap.ips_en = pmppriv->keep_ips_status;
5733 dvobj->phl_com->dev_sw_cap.ps_cap.lps_en = pmppriv->keep_lps_status;
5734
5735 rtw_phl_test_submodule_deinit(dvobj->phl_com, &test_module_info);
5736
5737 MPT_DeInitAdapter(padapter);
5738 padapter->registrypriv.mp_mode = 0;
5739 }
5740
5741 if (padapter->mppriv.mode != MP_OFF) {
5742 mp_stop_test(padapter);
5743 padapter->mppriv.mode = MP_OFF;
5744 }
5745
5746 } else {
5747 RTW_INFO(FUNC_ADPT_FMT"invalid id:%d\n", FUNC_ADPT_ARG(padapter), mp_cmd_id);
5748 ret = H2C_PARAMETERS_ERROR;
5749 rtw_warn_on(1);
5750 }
5751
5752 exit:
5753 return ret;
5754 }
5755
rtw_mp_cmd(_adapter * adapter,u8 mp_cmd_id,u8 flags)5756 u8 rtw_mp_cmd(_adapter *adapter, u8 mp_cmd_id, u8 flags)
5757 {
5758 struct cmd_obj *cmdobj;
5759 struct drvextra_cmd_parm *parm;
5760 struct cmd_priv *pcmdpriv = &adapter_to_dvobj(adapter)->cmdpriv;
5761 struct submit_ctx sctx;
5762 u8 res = _SUCCESS;
5763
5764 parm = (struct drvextra_cmd_parm *)rtw_zmalloc(sizeof(struct drvextra_cmd_parm));
5765 if (parm == NULL) {
5766 res = _FAIL;
5767 goto exit;
5768 }
5769
5770 parm->ec_id = MP_CMD_WK_CID;
5771 parm->type = mp_cmd_id;
5772 parm->size = 0;
5773 parm->pbuf = NULL;
5774
5775 if (flags & RTW_CMDF_DIRECTLY) {
5776 /* no need to enqueue, do the cmd hdl directly and free cmd parameter */
5777 if (H2C_SUCCESS != rtw_mp_cmd_hdl(adapter, mp_cmd_id))
5778 res = _FAIL;
5779 rtw_mfree((u8 *)parm, sizeof(*parm));
5780 } else {
5781 /* need enqueue, prepare cmd_obj and enqueue */
5782 cmdobj = (struct cmd_obj *)rtw_zmalloc(sizeof(*cmdobj));
5783 if (cmdobj == NULL) {
5784 res = _FAIL;
5785 rtw_mfree((u8 *)parm, sizeof(*parm));
5786 goto exit;
5787 }
5788 cmdobj->padapter = adapter;
5789
5790 init_h2fwcmd_w_parm_no_rsp(cmdobj, parm, CMD_SET_DRV_EXTRA);
5791
5792 if (flags & RTW_CMDF_WAIT_ACK) {
5793 cmdobj->sctx = &sctx;
5794 rtw_sctx_init(&sctx, 10 * 1000);
5795 }
5796
5797 res = rtw_enqueue_cmd(pcmdpriv, cmdobj);
5798
5799 if (res == _SUCCESS && (flags & RTW_CMDF_WAIT_ACK)) {
5800 rtw_sctx_wait(&sctx, __func__);
5801 _rtw_mutex_lock_interruptible(&pcmdpriv->sctx_mutex);
5802 if (sctx.status == RTW_SCTX_SUBMITTED)
5803 cmdobj->sctx = NULL;
5804 _rtw_mutex_unlock(&pcmdpriv->sctx_mutex);
5805 if (sctx.status != RTW_SCTX_DONE_SUCCESS)
5806 res = _FAIL;
5807 }
5808 }
5809
5810 exit:
5811 return res;
5812 }
5813 #endif /*CONFIG_MP_INCLUDED*/
5814
5815 #ifdef CONFIG_RTW_CUSTOMER_STR
rtw_customer_str_cmd_hdl(_adapter * adapter,u8 write,const u8 * cstr)5816 static s32 rtw_customer_str_cmd_hdl(_adapter *adapter, u8 write, const u8 *cstr)
5817 {
5818 int ret = H2C_SUCCESS;
5819
5820 if (write)
5821 ret = rtw_hal_h2c_customer_str_write(adapter, cstr);
5822 else
5823 ret = rtw_hal_h2c_customer_str_req(adapter);
5824
5825 return ret == _SUCCESS ? H2C_SUCCESS : H2C_REJECTED;
5826 }
5827
rtw_customer_str_cmd(_adapter * adapter,u8 write,const u8 * cstr)5828 static u8 rtw_customer_str_cmd(_adapter *adapter, u8 write, const u8 *cstr)
5829 {
5830 struct cmd_obj *cmdobj;
5831 struct drvextra_cmd_parm *parm;
5832 u8 *str = NULL;
5833 struct cmd_priv *pcmdpriv = &adapter_to_dvobj(adapter)->cmdpriv;
5834 struct submit_ctx sctx;
5835 u8 res = _SUCCESS;
5836
5837 parm = (struct drvextra_cmd_parm *)rtw_zmalloc(sizeof(struct drvextra_cmd_parm));
5838 if (parm == NULL) {
5839 res = _FAIL;
5840 goto exit;
5841 }
5842
5843 if (write) {
5844 str = rtw_zmalloc(RTW_CUSTOMER_STR_LEN);
5845 if (str == NULL) {
5846 rtw_mfree((u8 *)parm, sizeof(struct drvextra_cmd_parm));
5847 res = _FAIL;
5848 goto exit;
5849 }
5850 }
5851
5852 parm->ec_id = CUSTOMER_STR_WK_CID;
5853 parm->type = write;
5854 parm->size = write ? RTW_CUSTOMER_STR_LEN : 0;
5855 parm->pbuf = write ? str : NULL;
5856
5857 if (write)
5858 _rtw_memcpy(str, cstr, RTW_CUSTOMER_STR_LEN);
5859
5860 /* need enqueue, prepare cmd_obj and enqueue */
5861 cmdobj = (struct cmd_obj *)rtw_zmalloc(sizeof(*cmdobj));
5862 if (cmdobj == NULL) {
5863 res = _FAIL;
5864 rtw_mfree((u8 *)parm, sizeof(*parm));
5865 if (write)
5866 rtw_mfree(str, RTW_CUSTOMER_STR_LEN);
5867 goto exit;
5868 }
5869 cmdobj->padapter = adapter;
5870
5871 init_h2fwcmd_w_parm_no_rsp(cmdobj, parm, CMD_SET_DRV_EXTRA);
5872
5873 cmdobj->sctx = &sctx;
5874 rtw_sctx_init(&sctx, 2 * 1000);
5875
5876 res = rtw_enqueue_cmd(pcmdpriv, cmdobj);
5877
5878 if (res == _SUCCESS) {
5879 rtw_sctx_wait(&sctx, __func__);
5880 _rtw_mutex_lock_interruptible(&pcmdpriv->sctx_mutex);
5881 if (sctx.status == RTW_SCTX_SUBMITTED)
5882 cmdobj->sctx = NULL;
5883 _rtw_mutex_unlock(&pcmdpriv->sctx_mutex);
5884 if (sctx.status != RTW_SCTX_DONE_SUCCESS)
5885 res = _FAIL;
5886 }
5887
5888 exit:
5889 return res;
5890 }
5891
rtw_customer_str_req_cmd(_adapter * adapter)5892 inline u8 rtw_customer_str_req_cmd(_adapter *adapter)
5893 {
5894 return rtw_customer_str_cmd(adapter, 0, NULL);
5895 }
5896
rtw_customer_str_write_cmd(_adapter * adapter,const u8 * cstr)5897 inline u8 rtw_customer_str_write_cmd(_adapter *adapter, const u8 *cstr)
5898 {
5899 return rtw_customer_str_cmd(adapter, 1, cstr);
5900 }
5901 #endif /* CONFIG_RTW_CUSTOMER_STR */
5902
rtw_c2h_wk_cmd(_adapter * padapter,u8 * pbuf,u16 length,u8 type)5903 u8 rtw_c2h_wk_cmd(_adapter *padapter, u8 *pbuf, u16 length, u8 type)
5904 {
5905 struct cmd_obj *cmd;
5906 struct drvextra_cmd_parm *pdrvextra_cmd_parm;
5907 struct cmd_priv *pcmdpriv = &adapter_to_dvobj(padapter)->cmdpriv;
5908 u8 *extra_cmd_buf;
5909 u8 res = _SUCCESS;
5910
5911 cmd = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
5912 if (cmd == NULL) {
5913 res = _FAIL;
5914 goto exit;
5915 }
5916 cmd->padapter = padapter;
5917
5918 pdrvextra_cmd_parm = (struct drvextra_cmd_parm *)rtw_zmalloc(sizeof(struct drvextra_cmd_parm));
5919 if (pdrvextra_cmd_parm == NULL) {
5920 rtw_mfree((u8 *)cmd, sizeof(struct cmd_obj));
5921 res = _FAIL;
5922 goto exit;
5923 }
5924
5925 extra_cmd_buf = rtw_zmalloc(length);
5926 if (extra_cmd_buf == NULL) {
5927 rtw_mfree((u8 *)cmd, sizeof(struct cmd_obj));
5928 rtw_mfree((u8 *)pdrvextra_cmd_parm, sizeof(struct drvextra_cmd_parm));
5929 res = _FAIL;
5930 goto exit;
5931 }
5932
5933 _rtw_memcpy(extra_cmd_buf, pbuf, length);
5934 pdrvextra_cmd_parm->ec_id = C2H_WK_CID;
5935 pdrvextra_cmd_parm->type = type;
5936 pdrvextra_cmd_parm->size = length;
5937 pdrvextra_cmd_parm->pbuf = extra_cmd_buf;
5938
5939 init_h2fwcmd_w_parm_no_rsp(cmd, pdrvextra_cmd_parm, CMD_SET_DRV_EXTRA);
5940
5941 res = rtw_enqueue_cmd(pcmdpriv, cmd);
5942
5943 exit:
5944 return res;
5945 }
5946
5947 #define C2H_TYPE_PKT 1
rtw_c2h_packet_wk_cmd(_adapter * adapter,u8 * c2h_evt,u16 length)5948 inline u8 rtw_c2h_packet_wk_cmd(_adapter *adapter, u8 *c2h_evt, u16 length)
5949 {
5950 return rtw_c2h_wk_cmd(adapter, c2h_evt, length, C2H_TYPE_PKT);
5951 }
5952
_rtw_run_in_thread_cmd(_adapter * adapter,void (* func)(void *),void * context,s32 timeout_ms)5953 static u8 _rtw_run_in_thread_cmd(_adapter *adapter, void (*func)(void *), void *context, s32 timeout_ms)
5954 {
5955 struct cmd_priv *cmdpriv = &adapter_to_dvobj(adapter)->cmdpriv;
5956 struct cmd_obj *cmdobj;
5957 struct RunInThread_param *parm;
5958 struct submit_ctx sctx;
5959 s32 res = _SUCCESS;
5960
5961 cmdobj = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
5962 if (NULL == cmdobj) {
5963 res = _FAIL;
5964 goto exit;
5965 }
5966 cmdobj->padapter = adapter;
5967
5968 parm = (struct RunInThread_param *)rtw_zmalloc(sizeof(struct RunInThread_param));
5969 if (NULL == parm) {
5970 rtw_mfree((u8 *)cmdobj, sizeof(struct cmd_obj));
5971 res = _FAIL;
5972 goto exit;
5973 }
5974
5975 parm->func = func;
5976 parm->context = context;
5977 init_h2fwcmd_w_parm_no_rsp(cmdobj, parm, CMD_RUN_INTHREAD);
5978
5979 if (timeout_ms >= 0) {
5980 cmdobj->sctx = &sctx;
5981 rtw_sctx_init(&sctx, timeout_ms);
5982 }
5983
5984 res = rtw_enqueue_cmd(cmdpriv, cmdobj);
5985
5986 if (res == _SUCCESS && timeout_ms >= 0) {
5987 rtw_sctx_wait(&sctx, __func__);
5988 _rtw_mutex_lock_interruptible(&cmdpriv->sctx_mutex);
5989 if (sctx.status == RTW_SCTX_SUBMITTED)
5990 cmdobj->sctx = NULL;
5991 _rtw_mutex_unlock(&cmdpriv->sctx_mutex);
5992 if (sctx.status != RTW_SCTX_DONE_SUCCESS)
5993 res = _FAIL;
5994 }
5995
5996 exit:
5997 return res;
5998 }
rtw_run_in_thread_cmd(_adapter * adapter,void (* func)(void *),void * context)5999 u8 rtw_run_in_thread_cmd(_adapter *adapter, void (*func)(void *), void *context)
6000 {
6001 return _rtw_run_in_thread_cmd(adapter, func, context, -1);
6002 }
6003
rtw_run_in_thread_cmd_wait(_adapter * adapter,void (* func)(void *),void * context,s32 timeout_ms)6004 u8 rtw_run_in_thread_cmd_wait(_adapter *adapter, void (*func)(void *), void *context, s32 timeout_ms)
6005 {
6006 return _rtw_run_in_thread_cmd(adapter, func, context, timeout_ms);
6007 }
6008
6009
session_tracker_cmd(_adapter * adapter,u8 cmd,struct sta_info * sta,u8 * local_naddr,u8 * local_port,u8 * remote_naddr,u8 * remote_port)6010 u8 session_tracker_cmd(_adapter *adapter, u8 cmd, struct sta_info *sta, u8 *local_naddr, u8 *local_port, u8 *remote_naddr, u8 *remote_port)
6011 {
6012 struct cmd_priv *cmdpriv = &adapter_to_dvobj(adapter)->cmdpriv;
6013 struct cmd_obj *cmdobj;
6014 struct drvextra_cmd_parm *cmd_parm;
6015 struct st_cmd_parm *st_parm;
6016 u8 res = _SUCCESS;
6017
6018 cmdobj = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
6019 if (cmdobj == NULL) {
6020 res = _FAIL;
6021 goto exit;
6022 }
6023 cmdobj->padapter = adapter;
6024
6025 cmd_parm = (struct drvextra_cmd_parm *)rtw_zmalloc(sizeof(struct drvextra_cmd_parm));
6026 if (cmd_parm == NULL) {
6027 rtw_mfree((u8 *)cmdobj, sizeof(struct cmd_obj));
6028 res = _FAIL;
6029 goto exit;
6030 }
6031
6032 st_parm = (struct st_cmd_parm *)rtw_zmalloc(sizeof(struct st_cmd_parm));
6033 if (st_parm == NULL) {
6034 rtw_mfree((u8 *)cmdobj, sizeof(struct cmd_obj));
6035 rtw_mfree((u8 *)cmd_parm, sizeof(struct drvextra_cmd_parm));
6036 res = _FAIL;
6037 goto exit;
6038 }
6039
6040 st_parm->cmd = cmd;
6041 st_parm->sta = sta;
6042 if (cmd != ST_CMD_CHK) {
6043 _rtw_memcpy(&st_parm->local_naddr, local_naddr, 4);
6044 _rtw_memcpy(&st_parm->local_port, local_port, 2);
6045 _rtw_memcpy(&st_parm->remote_naddr, remote_naddr, 4);
6046 _rtw_memcpy(&st_parm->remote_port, remote_port, 2);
6047 }
6048
6049 cmd_parm->ec_id = SESSION_TRACKER_WK_CID;
6050 cmd_parm->type = 0;
6051 cmd_parm->size = sizeof(struct st_cmd_parm);
6052 cmd_parm->pbuf = (u8 *)st_parm;
6053 init_h2fwcmd_w_parm_no_rsp(cmdobj, cmd_parm, CMD_SET_DRV_EXTRA);
6054 cmdobj->no_io = 1;
6055
6056 res = rtw_enqueue_cmd(cmdpriv, cmdobj);
6057
6058 exit:
6059 return res;
6060 }
6061
session_tracker_chk_cmd(_adapter * adapter,struct sta_info * sta)6062 inline u8 session_tracker_chk_cmd(_adapter *adapter, struct sta_info *sta)
6063 {
6064 return session_tracker_cmd(adapter, ST_CMD_CHK, sta, NULL, NULL, NULL, NULL);
6065 }
6066
session_tracker_add_cmd(_adapter * adapter,struct sta_info * sta,u8 * local_naddr,u8 * local_port,u8 * remote_naddr,u8 * remote_port)6067 inline u8 session_tracker_add_cmd(_adapter *adapter, struct sta_info *sta, u8 *local_naddr, u8 *local_port, u8 *remote_naddr, u8 *remote_port)
6068 {
6069 return session_tracker_cmd(adapter, ST_CMD_ADD, sta, local_naddr, local_port, remote_naddr, remote_port);
6070 }
6071
session_tracker_del_cmd(_adapter * adapter,struct sta_info * sta,u8 * local_naddr,u8 * local_port,u8 * remote_naddr,u8 * remote_port)6072 inline u8 session_tracker_del_cmd(_adapter *adapter, struct sta_info *sta, u8 *local_naddr, u8 *local_port, u8 *remote_naddr, u8 *remote_port)
6073 {
6074 return session_tracker_cmd(adapter, ST_CMD_DEL, sta, local_naddr, local_port, remote_naddr, remote_port);
6075 }
6076
session_tracker_chk_for_sta(_adapter * adapter,struct sta_info * sta)6077 void session_tracker_chk_for_sta(_adapter *adapter, struct sta_info *sta)
6078 {
6079 struct st_ctl_t *st_ctl = &sta->st_ctl;
6080 int i;
6081 _list *plist, *phead, *pnext;
6082 _list dlist;
6083 struct session_tracker *st = NULL;
6084 u8 op_wfd_mode = MIRACAST_DISABLED;
6085
6086 if (DBG_SESSION_TRACKER)
6087 RTW_INFO(FUNC_ADPT_FMT" sta:%p\n", FUNC_ADPT_ARG(adapter), sta);
6088
6089 if (!(sta->state & WIFI_ASOC_STATE))
6090 goto exit;
6091
6092 for (i = 0; i < SESSION_TRACKER_REG_ID_NUM; i++) {
6093 if (st_ctl->reg[i].s_proto != 0)
6094 break;
6095 }
6096 if (i >= SESSION_TRACKER_REG_ID_NUM)
6097 goto chk_sta;
6098
6099 _rtw_init_listhead(&dlist);
6100
6101 _rtw_spinlock_bh(&st_ctl->tracker_q.lock);
6102
6103 phead = &st_ctl->tracker_q.queue;
6104 plist = get_next(phead);
6105 pnext = get_next(plist);
6106 while (rtw_end_of_queue_search(phead, plist) == _FALSE) {
6107 st = LIST_CONTAINOR(plist, struct session_tracker, list);
6108 plist = pnext;
6109 pnext = get_next(pnext);
6110
6111 if (st->status != ST_STATUS_ESTABLISH
6112 && rtw_get_passing_time_ms(st->set_time) > ST_EXPIRE_MS
6113 ) {
6114 rtw_list_delete(&st->list);
6115 rtw_list_insert_tail(&st->list, &dlist);
6116 }
6117
6118 /* TODO: check OS for status update */
6119 if (st->status == ST_STATUS_CHECK)
6120 st->status = ST_STATUS_ESTABLISH;
6121
6122 if (st->status != ST_STATUS_ESTABLISH)
6123 continue;
6124
6125 #ifdef CONFIG_WFD
6126 if (0)
6127 RTW_INFO(FUNC_ADPT_FMT" local:%u, remote:%u, rtsp:%u, %u, %u\n", FUNC_ADPT_ARG(adapter)
6128 , ntohs(st->local_port), ntohs(st->remote_port), adapter->wfd_info.rtsp_ctrlport, adapter->wfd_info.tdls_rtsp_ctrlport
6129 , adapter->wfd_info.peer_rtsp_ctrlport);
6130 if (ntohs(st->local_port) == adapter->wfd_info.rtsp_ctrlport)
6131 op_wfd_mode |= MIRACAST_SINK;
6132 if (ntohs(st->local_port) == adapter->wfd_info.tdls_rtsp_ctrlport)
6133 op_wfd_mode |= MIRACAST_SINK;
6134 if (ntohs(st->remote_port) == adapter->wfd_info.peer_rtsp_ctrlport)
6135 op_wfd_mode |= MIRACAST_SOURCE;
6136 #endif
6137 }
6138
6139 _rtw_spinunlock_bh(&st_ctl->tracker_q.lock);
6140
6141 plist = get_next(&dlist);
6142 while (rtw_end_of_queue_search(&dlist, plist) == _FALSE) {
6143 st = LIST_CONTAINOR(plist, struct session_tracker, list);
6144 plist = get_next(plist);
6145 rtw_mfree((u8 *)st, sizeof(struct session_tracker));
6146 }
6147
6148 chk_sta:
6149 if (STA_OP_WFD_MODE(sta) != op_wfd_mode) {
6150 STA_SET_OP_WFD_MODE(sta, op_wfd_mode);
6151 rtw_sta_media_status_rpt_cmd(adapter, sta, 1);
6152 }
6153
6154 exit:
6155 return;
6156 }
6157
session_tracker_chk_for_adapter(_adapter * adapter)6158 void session_tracker_chk_for_adapter(_adapter *adapter)
6159 {
6160 struct sta_priv *stapriv = &adapter->stapriv;
6161 struct sta_info *sta;
6162 int i;
6163 _list *plist, *phead;
6164 u8 op_wfd_mode = MIRACAST_DISABLED;
6165
6166 _rtw_spinlock_bh(&stapriv->sta_hash_lock);
6167
6168 for (i = 0; i < NUM_STA; i++) {
6169 phead = &(stapriv->sta_hash[i]);
6170 plist = get_next(phead);
6171
6172 while ((rtw_end_of_queue_search(phead, plist)) == _FALSE) {
6173 sta = LIST_CONTAINOR(plist, struct sta_info, hash_list);
6174 plist = get_next(plist);
6175
6176 session_tracker_chk_for_sta(adapter, sta);
6177
6178 op_wfd_mode |= STA_OP_WFD_MODE(sta);
6179 }
6180 }
6181
6182 _rtw_spinunlock_bh(&stapriv->sta_hash_lock);
6183
6184 #ifdef CONFIG_WFD
6185 adapter->wfd_info.op_wfd_mode = MIRACAST_MODE_REVERSE(op_wfd_mode);
6186 #endif
6187 }
6188
session_tracker_cmd_hdl(_adapter * adapter,struct st_cmd_parm * parm)6189 void session_tracker_cmd_hdl(_adapter *adapter, struct st_cmd_parm *parm)
6190 {
6191 u8 cmd = parm->cmd;
6192 struct sta_info *sta = parm->sta;
6193
6194 if (cmd == ST_CMD_CHK) {
6195 if (sta)
6196 session_tracker_chk_for_sta(adapter, sta);
6197 else
6198 session_tracker_chk_for_adapter(adapter);
6199
6200 goto exit;
6201
6202 } else if (cmd == ST_CMD_ADD || cmd == ST_CMD_DEL) {
6203 struct st_ctl_t *st_ctl;
6204 u32 local_naddr = parm->local_naddr;
6205 u16 local_port = parm->local_port;
6206 u32 remote_naddr = parm->remote_naddr;
6207 u16 remote_port = parm->remote_port;
6208 struct session_tracker *st = NULL;
6209 _list *plist, *phead;
6210 u8 free_st = 0;
6211 u8 alloc_st = 0;
6212
6213 if (DBG_SESSION_TRACKER)
6214 RTW_INFO(FUNC_ADPT_FMT" cmd:%u, sta:%p, local:"IP_FMT":"PORT_FMT", remote:"IP_FMT":"PORT_FMT"\n"
6215 , FUNC_ADPT_ARG(adapter), cmd, sta
6216 , IP_ARG(&local_naddr), PORT_ARG(&local_port)
6217 , IP_ARG(&remote_naddr), PORT_ARG(&remote_port)
6218 );
6219
6220 if (!(sta->state & WIFI_ASOC_STATE))
6221 goto exit;
6222
6223 st_ctl = &sta->st_ctl;
6224
6225 _rtw_spinlock_bh(&st_ctl->tracker_q.lock);
6226
6227 phead = &st_ctl->tracker_q.queue;
6228 plist = get_next(phead);
6229 while (rtw_end_of_queue_search(phead, plist) == _FALSE) {
6230 st = LIST_CONTAINOR(plist, struct session_tracker, list);
6231
6232 if (st->local_naddr == local_naddr
6233 && st->local_port == local_port
6234 && st->remote_naddr == remote_naddr
6235 && st->remote_port == remote_port)
6236 break;
6237
6238 plist = get_next(plist);
6239 }
6240
6241 if (rtw_end_of_queue_search(phead, plist) == _TRUE)
6242 st = NULL;
6243
6244 switch (cmd) {
6245 case ST_CMD_DEL:
6246 if (st) {
6247 rtw_list_delete(plist);
6248 free_st = 1;
6249 }
6250 goto unlock;
6251 case ST_CMD_ADD:
6252 if (!st)
6253 alloc_st = 1;
6254 }
6255
6256 unlock:
6257 _rtw_spinunlock_bh(&st_ctl->tracker_q.lock);
6258
6259 if (free_st) {
6260 rtw_mfree((u8 *)st, sizeof(struct session_tracker));
6261 goto exit;
6262 }
6263
6264 if (alloc_st) {
6265 st = (struct session_tracker *)rtw_zmalloc(sizeof(struct session_tracker));
6266 if (!st)
6267 goto exit;
6268
6269 st->local_naddr = local_naddr;
6270 st->local_port = local_port;
6271 st->remote_naddr = remote_naddr;
6272 st->remote_port = remote_port;
6273 st->set_time = rtw_get_current_time();
6274 st->status = ST_STATUS_CHECK;
6275
6276 _rtw_spinlock_bh(&st_ctl->tracker_q.lock);
6277 rtw_list_insert_tail(&st->list, phead);
6278 _rtw_spinunlock_bh(&st_ctl->tracker_q.lock);
6279 }
6280 }
6281
6282 exit:
6283 return;
6284 }
6285
6286 #if defined(CONFIG_RTW_MESH) && defined(RTW_PER_CMD_SUPPORT_FW)
rtw_req_per_cmd_hdl(_adapter * adapter)6287 static s32 rtw_req_per_cmd_hdl(_adapter *adapter)
6288 {
6289 struct dvobj_priv *dvobj = adapter_to_dvobj(adapter);
6290 struct macid_ctl_t *macid_ctl = dvobj_to_macidctl(dvobj);
6291 struct macid_bmp req_macid_bmp, *macid_bmp;
6292 u8 i, ret = _FAIL;
6293
6294 macid_bmp = &macid_ctl->if_g[adapter->iface_id];
6295 _rtw_memcpy(&req_macid_bmp, macid_bmp, sizeof(struct macid_bmp));
6296
6297 /* Clear none mesh's macid */
6298 for (i = 0; i < macid_ctl->num; i++) {
6299 u8 role;
6300 role = GET_H2CCMD_MSRRPT_PARM_ROLE(&macid_ctl->h2c_msr[i]);
6301 if (role != H2C_MSR_ROLE_MESH)
6302 rtw_macid_map_clr(&req_macid_bmp, i);
6303 }
6304
6305 /* group_macid: always be 0 in NIC, so only pass macid_bitmap.m0
6306 * rpt_type: 0 includes all info in 1, use 0 for now
6307 * macid_bitmap: pass m0 only for NIC
6308 */
6309 ret = rtw_hal_set_req_per_rpt_cmd(adapter, 0, 0, req_macid_bmp.m0);
6310
6311 return ret;
6312 }
6313
rtw_req_per_cmd(_adapter * adapter)6314 u8 rtw_req_per_cmd(_adapter *adapter)
6315 {
6316 struct cmd_obj *cmdobj;
6317 struct drvextra_cmd_parm *parm;
6318 struct cmd_priv *pcmdpriv = &adapter_to_dvobj(adapter)->cmdpriv;
6319 struct submit_ctx sctx;
6320 u8 res = _SUCCESS;
6321
6322 parm = (struct drvextra_cmd_parm *)rtw_zmalloc(sizeof(struct drvextra_cmd_parm));
6323 if (parm == NULL) {
6324 res = _FAIL;
6325 goto exit;
6326 }
6327
6328 parm->ec_id = REQ_PER_CMD_WK_CID;
6329 parm->type = 0;
6330 parm->size = 0;
6331 parm->pbuf = NULL;
6332
6333 cmdobj = (struct cmd_obj *)rtw_zmalloc(sizeof(*cmdobj));
6334 if (cmdobj == NULL) {
6335 res = _FAIL;
6336 rtw_mfree((u8 *)parm, sizeof(*parm));
6337 goto exit;
6338 }
6339 cmdobj->padapter = adapter;
6340
6341 init_h2fwcmd_w_parm_no_rsp(cmdobj, parm, CMD_SET_DRV_EXTRA);
6342
6343 res = rtw_enqueue_cmd(pcmdpriv, cmdobj);
6344
6345 exit:
6346 return res;
6347 }
6348 #endif
6349
6350
rtw_ac_parm_cmd_hdl(_adapter * padapter,u8 * _ac_parm_buf,int ac_type)6351 void rtw_ac_parm_cmd_hdl(_adapter *padapter, u8 *_ac_parm_buf, int ac_type)
6352 {
6353
6354 u32 ac_parm_buf;
6355
6356 _rtw_memcpy(&ac_parm_buf, _ac_parm_buf, sizeof(ac_parm_buf));
6357 switch (ac_type) {
6358 case XMIT_VO_QUEUE:
6359 RTW_INFO(FUNC_NDEV_FMT" AC_VO = 0x%08x\n", FUNC_ADPT_ARG(padapter), (unsigned int) ac_parm_buf);
6360 rtw_ap_set_edca(padapter, 3, ac_parm_buf);
6361 break;
6362
6363 case XMIT_VI_QUEUE:
6364 RTW_INFO(FUNC_NDEV_FMT" AC_VI = 0x%08x\n", FUNC_ADPT_ARG(padapter), (unsigned int) ac_parm_buf);
6365 rtw_ap_set_edca(padapter, 2, ac_parm_buf);
6366 break;
6367
6368 case XMIT_BE_QUEUE:
6369 RTW_INFO(FUNC_NDEV_FMT" AC_BE = 0x%08x\n", FUNC_ADPT_ARG(padapter), (unsigned int) ac_parm_buf);
6370 rtw_ap_set_edca(padapter, 0, ac_parm_buf);
6371 break;
6372
6373 case XMIT_BK_QUEUE:
6374 RTW_INFO(FUNC_NDEV_FMT" AC_BK = 0x%08x\n", FUNC_ADPT_ARG(padapter), (unsigned int) ac_parm_buf);
6375 rtw_ap_set_edca(padapter, 1, ac_parm_buf);
6376 break;
6377
6378 default:
6379 break;
6380 }
6381
6382 }
6383
rtw_drvextra_cmd_hdl(_adapter * padapter,unsigned char * pbuf)6384 u8 rtw_drvextra_cmd_hdl(_adapter *padapter, unsigned char *pbuf)
6385 {
6386 int ret = H2C_SUCCESS;
6387 struct drvextra_cmd_parm *pdrvextra_cmd;
6388
6389 if (!pbuf)
6390 return H2C_PARAMETERS_ERROR;
6391
6392 pdrvextra_cmd = (struct drvextra_cmd_parm *)pbuf;
6393
6394 switch (pdrvextra_cmd->ec_id) {
6395 case STA_MSTATUS_RPT_WK_CID:
6396 rtw_sta_media_status_rpt_cmd_hdl(padapter, (struct sta_media_status_rpt_cmd_parm *)pdrvextra_cmd->pbuf);
6397 break;
6398 #if 0 /*#ifdef CONFIG_CORE_DM_CHK_TIMER*/
6399 case DYNAMIC_CHK_WK_CID:/*only primary padapter go to this cmd, but execute dynamic_chk_wk_hdl() for two interfaces */
6400 rtw_dynamic_chk_wk_hdl(padapter);
6401 break;
6402 #endif
6403 #ifdef CONFIG_POWER_SAVING
6404 case POWER_SAVING_CTRL_WK_CID:
6405 power_saving_wk_hdl(padapter);
6406 break;
6407 #endif
6408 #ifdef CONFIG_LPS
6409 case LPS_CTRL_WK_CID:
6410 lps_ctrl_wk_hdl(padapter, (u8)pdrvextra_cmd->type, pdrvextra_cmd->pbuf);
6411 break;
6412 case DM_IN_LPS_WK_CID:
6413 rtw_dm_in_lps_hdl(padapter);
6414 break;
6415 case LPS_CHANGE_DTIM_CID:
6416 rtw_lps_change_dtim_hdl(padapter, (u8)pdrvextra_cmd->type);
6417 break;
6418 #endif
6419 #ifdef CONFIG_ANTENNA_DIVERSITY
6420 case ANT_SELECT_WK_CID:
6421 antenna_select_wk_hdl(padapter, pdrvextra_cmd->type);
6422 break;
6423 #endif
6424 #ifdef CONFIG_P2P_PS
6425 case P2P_PS_WK_CID:
6426 p2p_ps_wk_hdl(padapter, pdrvextra_cmd->type);
6427 break;
6428 #endif
6429 #ifdef CONFIG_AP_MODE
6430 case CHECK_HIQ_WK_CID:
6431 rtw_chk_hi_queue_hdl(padapter);
6432 break;
6433 #endif
6434 /* add for CONFIG_IEEE80211W, none 11w can use it */
6435 case RESET_SECURITYPRIV:
6436 reset_securitypriv_hdl(padapter);
6437 break;
6438 case FREE_ASSOC_RESOURCES:
6439 free_assoc_resources_hdl(padapter, (u8)pdrvextra_cmd->type);
6440 break;
6441 case C2H_WK_CID:
6442 switch (pdrvextra_cmd->type) {
6443 case C2H_TYPE_PKT:
6444 rtw_hal_c2h_pkt_hdl(padapter, pdrvextra_cmd->pbuf, pdrvextra_cmd->size);
6445 break;
6446 default:
6447 RTW_ERR("unknown C2H type:%d\n", pdrvextra_cmd->type);
6448 rtw_warn_on(1);
6449 break;
6450 }
6451 break;
6452
6453 #ifdef CONFIG_DFS_MASTER
6454 case DFS_RADAR_DETECT_WK_CID:
6455 rtw_dfs_rd_hdl(padapter);
6456 break;
6457 case DFS_RADAR_DETECT_EN_DEC_WK_CID:
6458 rtw_dfs_rd_en_decision(padapter, MLME_ACTION_NONE, 0);
6459 break;
6460 #endif
6461 case SESSION_TRACKER_WK_CID:
6462 session_tracker_cmd_hdl(padapter, (struct st_cmd_parm *)pdrvextra_cmd->pbuf);
6463 break;
6464 case TEST_H2C_CID:
6465 rtw_hal_fill_h2c_cmd(padapter, pdrvextra_cmd->pbuf[0], pdrvextra_cmd->size - 1, &pdrvextra_cmd->pbuf[1]);
6466 break;
6467 case MP_CMD_WK_CID:
6468 #ifdef CONFIG_MP_INCLUDED
6469 ret = rtw_mp_cmd_hdl(padapter, pdrvextra_cmd->type);
6470 #endif
6471 break;
6472 #ifdef CONFIG_RTW_CUSTOMER_STR
6473 case CUSTOMER_STR_WK_CID:
6474 ret = rtw_customer_str_cmd_hdl(padapter, pdrvextra_cmd->type, pdrvextra_cmd->pbuf);
6475 break;
6476 #endif
6477
6478 #ifdef CONFIG_IOCTL_CFG80211
6479 case MGNT_TX_WK_CID:
6480 ret = rtw_mgnt_tx_handler(padapter, pdrvextra_cmd->pbuf);
6481 break;
6482 #endif /* CONFIG_IOCTL_CFG80211 */
6483 #if defined(CONFIG_RTW_MESH) && defined(RTW_PER_CMD_SUPPORT_FW)
6484 case REQ_PER_CMD_WK_CID:
6485 ret = rtw_req_per_cmd_hdl(padapter);
6486 break;
6487 #endif
6488 #ifdef CONFIG_SUPPORT_STATIC_SMPS
6489 case SSMPS_WK_CID :
6490 rtw_ssmps_wk_hdl(padapter, (struct ssmps_cmd_parm *)pdrvextra_cmd->pbuf);
6491 break;
6492 #endif
6493 #ifdef CONFIG_CTRL_TXSS_BY_TP
6494 case TXSS_WK_CID :
6495 rtw_ctrl_txss_wk_hdl(padapter, (struct txss_cmd_parm *)pdrvextra_cmd->pbuf);
6496 break;
6497 #endif
6498 case AC_PARM_CMD_WK_CID:
6499 rtw_ac_parm_cmd_hdl(padapter, pdrvextra_cmd->pbuf, pdrvextra_cmd->type);
6500 break;
6501 #ifdef CONFIG_AP_MODE
6502 case STOP_AP_WK_CID:
6503 stop_ap_hdl(padapter);
6504 break;
6505 #endif
6506 #ifdef CONFIG_RTW_TOKEN_BASED_XMIT
6507 case TBTX_CONTROL_TX_WK_CID:
6508 tx_control_hdl(padapter);
6509 break;
6510 #endif
6511 #ifdef ROKU_PRIVATE
6512 case FIND_REMOTE_WK_CID:
6513 ret = issue_action_find_remote(padapter);
6514 break;
6515 #ifdef CONFIG_P2P
6516 case HIDE_SSID_WK_CID:
6517 issue_beacon(padapter, 0);
6518 break;
6519 #endif
6520 #endif
6521 default:
6522 break;
6523 }
6524
6525 if (pdrvextra_cmd->pbuf && pdrvextra_cmd->size > 0)
6526 rtw_mfree(pdrvextra_cmd->pbuf, pdrvextra_cmd->size);
6527
6528 return ret;
6529 }
6530
6531
rtw_disassoc_cmd_callback(_adapter * padapter,struct cmd_obj * pcmd)6532 void rtw_disassoc_cmd_callback(_adapter *padapter, struct cmd_obj *pcmd)
6533 {
6534 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
6535
6536
6537 if (pcmd->res != H2C_SUCCESS) {
6538 _rtw_spinlock_bh(&pmlmepriv->lock);
6539 set_fwstate(pmlmepriv, WIFI_ASOC_STATE);
6540 _rtw_spinunlock_bh(&pmlmepriv->lock);
6541 goto exit;
6542 }
6543 #ifdef CONFIG_BR_EXT
6544 else /* clear bridge database */
6545 nat25_db_cleanup(padapter);
6546 #endif /* CONFIG_BR_EXT */
6547
6548 /* free cmd */
6549 rtw_free_cmd_obj(pcmd);
6550
6551 exit:
6552 return;
6553 }
rtw_joinbss_cmd_callback(_adapter * padapter,struct cmd_obj * pcmd)6554 void rtw_joinbss_cmd_callback(_adapter *padapter, struct cmd_obj *pcmd)
6555 {
6556 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
6557
6558
6559 if (pcmd->res == H2C_DROPPED) {
6560 /* TODO: cancel timer and do timeout handler directly... */
6561 /* need to make timeout handlerOS independent */
6562 set_assoc_timer(pmlmepriv, 1); /*_set_timer(&pmlmepriv->assoc_timer, 1);*/
6563 } else if (pcmd->res != H2C_SUCCESS)
6564 set_assoc_timer(pmlmepriv, 1); /*_set_timer(&pmlmepriv->assoc_timer, 1);*/
6565
6566 rtw_free_cmd_obj(pcmd);
6567 }
6568
rtw_create_ibss_post_hdl(_adapter * padapter,int status)6569 void rtw_create_ibss_post_hdl(_adapter *padapter, int status)
6570 {
6571 struct wlan_network *pwlan = NULL;
6572 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
6573 WLAN_BSSID_EX *pdev_network = &padapter->registrypriv.dev_network;
6574 struct wlan_network *mlme_cur_network = &(pmlmepriv->cur_network);
6575
6576 if (status != H2C_SUCCESS)
6577 set_assoc_timer(pmlmepriv, 1); /*_set_timer(&pmlmepriv->assoc_timer, 1);*/
6578
6579 /*_cancel_timer_ex(&pmlmepriv->assoc_timer);*/
6580 cancel_assoc_timer(pmlmepriv);
6581
6582 _rtw_spinlock_bh(&pmlmepriv->lock);
6583
6584 {
6585 pwlan = _rtw_alloc_network(pmlmepriv);
6586 _rtw_spinlock_bh(&(pmlmepriv->scanned_queue.lock));
6587 if (pwlan == NULL) {
6588 pwlan = rtw_get_oldest_wlan_network(&pmlmepriv->scanned_queue);
6589 if (pwlan == NULL) {
6590 _rtw_spinunlock_bh(&(pmlmepriv->scanned_queue.lock));
6591 goto createbss_cmd_fail;
6592 }
6593 pwlan->last_scanned = rtw_get_current_time();
6594 } else
6595 rtw_list_insert_tail(&(pwlan->list), &pmlmepriv->scanned_queue.queue);
6596
6597 pdev_network->Length = get_WLAN_BSSID_EX_sz(pdev_network);
6598 _rtw_memcpy(&(pwlan->network), pdev_network, pdev_network->Length);
6599 /* pwlan->fixed = _TRUE; */
6600
6601 /* copy pdev_network information to pmlmepriv->cur_network */
6602 _rtw_memcpy(&mlme_cur_network->network, pdev_network, (get_WLAN_BSSID_EX_sz(pdev_network)));
6603
6604 #if 0
6605 /* reset DSConfig */
6606 mlme_cur_network->network.Configuration.DSConfig = (u32)rtw_ch2freq(pdev_network->Configuration.DSConfig);
6607 #endif
6608
6609 _clr_fwstate_(pmlmepriv, WIFI_UNDER_LINKING);
6610 _rtw_spinunlock_bh(&(pmlmepriv->scanned_queue.lock));
6611 /* we will set WIFI_ASOC_STATE when there is one more sat to join us (rtw_stassoc_event_callback) */
6612 }
6613
6614 createbss_cmd_fail:
6615 _rtw_spinunlock_bh(&pmlmepriv->lock);
6616 return;
6617 }
6618
6619
6620
rtw_setstaKey_cmdrsp_callback(_adapter * padapter,struct cmd_obj * pcmd)6621 void rtw_setstaKey_cmdrsp_callback(_adapter *padapter , struct cmd_obj *pcmd)
6622 {
6623
6624 struct sta_priv *pstapriv = &padapter->stapriv;
6625 struct set_stakey_rsp *psetstakey_rsp = (struct set_stakey_rsp *)(pcmd->rsp);
6626 struct sta_info *psta = rtw_get_stainfo(pstapriv, psetstakey_rsp->addr);
6627
6628
6629 if (psta == NULL) {
6630 goto exit;
6631 }
6632
6633 /* psta->phl_sta->aid = psta->phl_sta->macid = psetstakey_rsp->keyid; */ /* CAM_ID(CAM_ENTRY) */
6634
6635 exit:
6636
6637 rtw_free_cmd_obj(pcmd);
6638
6639
6640 }
6641
rtw_getrttbl_cmd_cmdrsp_callback(_adapter * padapter,struct cmd_obj * pcmd)6642 void rtw_getrttbl_cmd_cmdrsp_callback(_adapter *padapter, struct cmd_obj *pcmd)
6643 {
6644
6645 rtw_free_cmd_obj(pcmd);
6646 #ifdef CONFIG_MP_INCLUDED
6647 if (padapter->registrypriv.mp_mode == 1)
6648 padapter->mppriv.workparam.bcompleted = _TRUE;
6649 #endif
6650
6651
6652 }
6653
set_txq_params_cmd(_adapter * adapter,u32 ac_parm,u8 ac_type)6654 u8 set_txq_params_cmd(_adapter *adapter, u32 ac_parm, u8 ac_type)
6655 {
6656 struct cmd_obj *cmdobj;
6657 struct drvextra_cmd_parm *pdrvextra_cmd_parm;
6658 struct cmd_priv *pcmdpriv = &adapter_to_dvobj(adapter)->cmdpriv;
6659 u8 *ac_parm_buf = NULL;
6660 u8 sz;
6661 u8 res = _SUCCESS;
6662
6663
6664 cmdobj = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
6665 if (cmdobj == NULL) {
6666 res = _FAIL;
6667 goto exit;
6668 }
6669 cmdobj->padapter = adapter;
6670
6671 pdrvextra_cmd_parm = (struct drvextra_cmd_parm *)rtw_zmalloc(sizeof(struct drvextra_cmd_parm));
6672 if (pdrvextra_cmd_parm == NULL) {
6673 rtw_mfree((u8 *)cmdobj, sizeof(struct cmd_obj));
6674 res = _FAIL;
6675 goto exit;
6676 }
6677
6678 sz = sizeof(ac_parm);
6679 ac_parm_buf = rtw_zmalloc(sz);
6680 if (ac_parm_buf == NULL) {
6681 rtw_mfree((u8 *)cmdobj, sizeof(struct cmd_obj));
6682 rtw_mfree((u8 *)pdrvextra_cmd_parm, sizeof(struct drvextra_cmd_parm));
6683 res = _FAIL;
6684 goto exit;
6685 }
6686
6687 pdrvextra_cmd_parm->ec_id = AC_PARM_CMD_WK_CID;
6688 pdrvextra_cmd_parm->type = ac_type;
6689 pdrvextra_cmd_parm->size = sz;
6690 pdrvextra_cmd_parm->pbuf = ac_parm_buf;
6691
6692 _rtw_memcpy(ac_parm_buf, &ac_parm, sz);
6693
6694 init_h2fwcmd_w_parm_no_rsp(cmdobj, pdrvextra_cmd_parm, CMD_SET_DRV_EXTRA);
6695 res = rtw_enqueue_cmd(pcmdpriv, cmdobj);
6696
6697 exit:
6698 return res;
6699 }
6700
6701 char UNKNOWN_CID[16] = "UNKNOWN_EXTRA";
rtw_extra_name(struct drvextra_cmd_parm * pdrvextra_cmd)6702 char *rtw_extra_name(struct drvextra_cmd_parm *pdrvextra_cmd)
6703 {
6704 switch(pdrvextra_cmd->ec_id) {
6705 case NONE_WK_CID:
6706 return "NONE_WK_CID";
6707 break;
6708 case STA_MSTATUS_RPT_WK_CID:
6709 return "STA_MSTATUS_RPT_WK_CID";
6710 break;
6711 #if 0 /*#ifdef CONFIG_CORE_DM_CHK_TIMER*/
6712 case DYNAMIC_CHK_WK_CID:
6713 return "DYNAMIC_CHK_WK_CID";
6714 break;
6715 #endif
6716 case DM_CTRL_WK_CID:
6717 return "DM_CTRL_WK_CID";
6718 break;
6719 case PBC_POLLING_WK_CID:
6720 return "PBC_POLLING_WK_CID";
6721 break;
6722 #ifdef CONFIG_POWER_SAVING
6723 case POWER_SAVING_CTRL_WK_CID:
6724 return "POWER_SAVING_CTRL_WK_CID";
6725 #endif
6726 break;
6727 case LPS_CTRL_WK_CID:
6728 return "LPS_CTRL_WK_CID";
6729 break;
6730 case ANT_SELECT_WK_CID:
6731 return "ANT_SELECT_WK_CID";
6732 break;
6733 case P2P_PS_WK_CID:
6734 return "P2P_PS_WK_CID";
6735 break;
6736 case CHECK_HIQ_WK_CID:
6737 return "CHECK_HIQ_WK_CID";
6738 break;
6739 case C2H_WK_CID:
6740 return "C2H_WK_CID";
6741 break;
6742 case RESET_SECURITYPRIV:
6743 return "RESET_SECURITYPRIV";
6744 break;
6745 case FREE_ASSOC_RESOURCES:
6746 return "FREE_ASSOC_RESOURCES";
6747 break;
6748 case DM_IN_LPS_WK_CID:
6749 return "DM_IN_LPS_WK_CID";
6750 break;
6751 case LPS_CHANGE_DTIM_CID:
6752 return "LPS_CHANGE_DTIM_CID";
6753 break;
6754 case DFS_RADAR_DETECT_WK_CID:
6755 return "DFS_RADAR_DETECT_WK_CID";
6756 break;
6757 case DFS_RADAR_DETECT_EN_DEC_WK_CID:
6758 return "DFS_RADAR_DETECT_EN_DEC_WK_CID";
6759 break;
6760 case SESSION_TRACKER_WK_CID:
6761 return "SESSION_TRACKER_WK_CID";
6762 break;
6763 case TEST_H2C_CID:
6764 return "TEST_H2C_CID";
6765 break;
6766 case MP_CMD_WK_CID:
6767 return "MP_CMD_WK_CID";
6768 break;
6769 case CUSTOMER_STR_WK_CID:
6770 return "CUSTOMER_STR_WK_CID";
6771 break;
6772 case MGNT_TX_WK_CID:
6773 return "MGNT_TX_WK_CID";
6774 break;
6775 case REQ_PER_CMD_WK_CID:
6776 return "REQ_PER_CMD_WK_CID";
6777 break;
6778 case SSMPS_WK_CID:
6779 return "SSMPS_WK_CID";
6780 break;
6781 #ifdef CONFIG_CTRL_TXSS_BY_TP
6782 case TXSS_WK_CID:
6783 return "TXSS_WK_CID";
6784 break;
6785 #endif
6786 case AC_PARM_CMD_WK_CID:
6787 return "AC_PARM_CMD_WK_CID";
6788 break;
6789 #ifdef CONFIG_AP_MODE
6790 case STOP_AP_WK_CID:
6791 return "STOP_AP_WK_CID";
6792 break;
6793 #endif
6794 #ifdef CONFIG_RTW_TOKEN_BASED_XMIT
6795 case TBTX_CONTROL_TX_WK_CID:
6796 return "TBTX_CONTROL_TX_WK_CID";
6797 break;
6798 #endif
6799 #ifdef ROKU_PRIVATE
6800 case FIND_REMOTE_WK_CID:
6801 return "FIND_REMOTE_WK_CID";
6802 break;
6803 #ifdef CONFIG_P2P
6804 case HIDE_SSID_WK_CID:
6805 return "HIDE_SSID_WK_CID";
6806 break;
6807 #endif
6808 #endif
6809 case MAX_WK_CID:
6810 return "MAX_WK_CID";
6811 break;
6812 default:
6813 return UNKNOWN_CID;
6814 break;
6815 }
6816 return UNKNOWN_CID;
6817 }
6818
6819 char UNKNOWN_CMD[16] = "UNKNOWN_CMD";
rtw_cmd_name(struct cmd_obj * pcmd)6820 char *rtw_cmd_name(struct cmd_obj *pcmd)
6821 {
6822 struct rtw_evt_header *pev;
6823
6824 if (pcmd->cmdcode >= (sizeof(wlancmds) / sizeof(struct rtw_cmd)))
6825 return UNKNOWN_CMD;
6826
6827 if (pcmd->cmdcode == CMD_SET_MLME_EVT)
6828 return rtw_evt_name((struct rtw_evt_header*)pcmd->parmbuf);
6829
6830 if (pcmd->cmdcode == CMD_SET_DRV_EXTRA)
6831 return rtw_extra_name((struct drvextra_cmd_parm*)pcmd->parmbuf);
6832
6833 return wlancmds[pcmd->cmdcode].name;
6834 }
6835
6836 #ifdef ROKU_PRIVATE
rtw_find_remote_wk_cmd(_adapter * adapter)6837 u8 rtw_find_remote_wk_cmd(_adapter *adapter)
6838 {
6839 struct cmd_obj *cmdobj;
6840 struct drvextra_cmd_parm *pdrvextra_cmd_parm;
6841 struct cmd_priv *pcmdpriv = &adapter_to_dvobj(adapter)->cmdpriv;
6842 u8 res = _SUCCESS;
6843
6844 cmdobj = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
6845 if (cmdobj == NULL) {
6846 res = _FAIL;
6847 goto exit;
6848 }
6849
6850 cmdobj->padapter = adapter;
6851
6852 pdrvextra_cmd_parm = (struct drvextra_cmd_parm *)rtw_zmalloc(sizeof(struct drvextra_cmd_parm));
6853 if (pdrvextra_cmd_parm == NULL) {
6854 rtw_mfree((unsigned char *)cmdobj, sizeof(struct cmd_obj));
6855 res = _FAIL;
6856 goto exit;
6857 }
6858
6859 pdrvextra_cmd_parm->ec_id = FIND_REMOTE_WK_CID;
6860 pdrvextra_cmd_parm->type = 0;
6861 pdrvextra_cmd_parm->size = 0;
6862 pdrvextra_cmd_parm->pbuf = NULL;
6863 init_h2fwcmd_w_parm_no_rsp(cmdobj, pdrvextra_cmd_parm, CMD_SET_DRV_EXTRA);
6864
6865 res = rtw_enqueue_cmd(pcmdpriv, cmdobj);
6866
6867 exit:
6868 return res;
6869 }
6870
6871 #ifdef CONFIG_P2P
rtw_hide_ssid_wk_cmd(_adapter * adapter)6872 u8 rtw_hide_ssid_wk_cmd(_adapter *adapter)
6873 {
6874 struct cmd_obj *cmdobj;
6875 struct drvextra_cmd_parm *pdrvextra_cmd_parm;
6876 struct cmd_priv *pcmdpriv = &adapter_to_dvobj(adapter)->cmdpriv;
6877 u8 res = _SUCCESS;
6878
6879 cmdobj = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
6880 if (cmdobj == NULL) {
6881 res = _FAIL;
6882 goto exit;
6883 }
6884
6885 cmdobj->padapter = adapter;
6886
6887 pdrvextra_cmd_parm = (struct drvextra_cmd_parm *)rtw_zmalloc(sizeof(struct drvextra_cmd_parm));
6888 if (pdrvextra_cmd_parm == NULL) {
6889 rtw_mfree((unsigned char *)cmdobj, sizeof(struct cmd_obj));
6890 res = _FAIL;
6891 goto exit;
6892 }
6893
6894 pdrvextra_cmd_parm->ec_id = HIDE_SSID_WK_CID;
6895 pdrvextra_cmd_parm->type = 0;
6896 pdrvextra_cmd_parm->size = 0;
6897 pdrvextra_cmd_parm->pbuf = NULL;
6898 init_h2fwcmd_w_parm_no_rsp(cmdobj, pdrvextra_cmd_parm, CMD_SET_DRV_EXTRA);
6899
6900 res = rtw_enqueue_cmd(pcmdpriv, cmdobj);
6901
6902 exit:
6903 return res;
6904
6905 }
6906 #endif
6907 #endif
6908