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