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