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