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