• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
991 #ifdef CONFIG_80211D
992 /* Return corresponding country_chplan setting  */
rtw_joinbss_check_country_ie(_adapter * adapter,const WLAN_BSSID_EX * network,struct country_chplan * ent,WLAN_BSSID_EX * out_network)993 static bool rtw_joinbss_check_country_ie(_adapter *adapter, const WLAN_BSSID_EX *network, struct country_chplan *ent, WLAN_BSSID_EX *out_network)
994 {
995 	struct rf_ctl_t *rfctl = adapter_to_rfctl(adapter);
996 	bool ret = 0;
997 
998 	if (rfctl->regd_src == REGD_SRC_RTK_PRIV
999 		&& !rtw_rfctl_is_disable_sw_channel_plan(rfctl_to_dvobj(rfctl))
1000 	) {
1001 		struct mlme_priv *mlme = &adapter->mlmepriv;
1002 		const u8 *country_ie = NULL;
1003 		sint country_ie_len = 0;
1004 
1005 		if (rtw_iface_accept_country_ie(adapter)) {
1006 			country_ie = rtw_get_ie(BSS_EX_TLV_IES(network)
1007 				, WLAN_EID_COUNTRY, &country_ie_len, BSS_EX_TLV_IES_LEN(network));
1008 			if (country_ie) {
1009 				if (country_ie_len < 6) {
1010 					country_ie = NULL;
1011 					country_ie_len = 0;
1012 				} else
1013 					country_ie_len += 2;
1014 			}
1015 		}
1016 
1017 		if (country_ie) {
1018 			enum country_ie_slave_status status;
1019 
1020 			rtw_buf_update(&mlme->recv_country_ie, &mlme->recv_country_ie_len, country_ie, country_ie_len);
1021 
1022 			status = rtw_get_chplan_from_recv_country_ie(adapter
1023 				, network->Configuration.DSConfig > 14 ? BAND_ON_5G : BAND_ON_2_4G
1024 				, network->Configuration.DSConfig, country_ie, ent, NULL, __func__);
1025 			if (status != COUNTRY_IE_SLAVE_NOCOUNTRY)
1026 				ret = 1;
1027 
1028 			if (out_network) {
1029 				_rtw_memcpy(BSS_EX_IES(out_network) + BSS_EX_IES_LEN(out_network)
1030 					, country_ie, country_ie_len);
1031 				BSS_EX_IES_LEN(out_network) += country_ie_len;
1032 			}
1033 		} else
1034 			rtw_buf_free(&mlme->recv_country_ie, &mlme->recv_country_ie_len);
1035 	}
1036 
1037 	return ret;
1038 }
1039 #endif /* CONFIG_80211D */
1040 
rtw_joinbss_cmd(_adapter * padapter,struct wlan_network * pnetwork)1041 u8 rtw_joinbss_cmd(_adapter  *padapter, struct wlan_network *pnetwork)
1042 {
1043 	u8	*auth, res = _SUCCESS;
1044 	uint	t_len = 0;
1045 	WLAN_BSSID_EX		*psecnetwork;
1046 	struct cmd_obj		*pcmd;
1047 	struct cmd_priv		*pcmdpriv = &padapter->cmdpriv;
1048 	struct mlme_priv		*pmlmepriv = &padapter->mlmepriv;
1049 	struct qos_priv		*pqospriv = &pmlmepriv->qospriv;
1050 	struct security_priv	*psecuritypriv = &padapter->securitypriv;
1051 	struct registry_priv	*pregistrypriv = &padapter->registrypriv;
1052 #ifdef CONFIG_80211D
1053 	struct country_chplan country_ent;
1054 #endif
1055 	struct country_chplan *req_chplan = NULL;
1056 #ifdef CONFIG_80211N_HT
1057 	struct ht_priv			*phtpriv = &pmlmepriv->htpriv;
1058 #endif /* CONFIG_80211N_HT */
1059 #ifdef CONFIG_80211AC_VHT
1060 	struct vht_priv		*pvhtpriv = &pmlmepriv->vhtpriv;
1061 #endif /* CONFIG_80211AC_VHT */
1062 	NDIS_802_11_NETWORK_INFRASTRUCTURE ndis_network_mode = pnetwork->network.InfrastructureMode;
1063 	struct mlme_ext_priv	*pmlmeext = &padapter->mlmeextpriv;
1064 	struct mlme_ext_info	*pmlmeinfo = &(pmlmeext->mlmext_info);
1065 	struct rf_ctl_t *rfctl = adapter_to_rfctl(padapter);
1066 	u32 tmp_len;
1067 	u8 *ptmp = NULL;
1068 
1069 	rtw_led_control(padapter, LED_CTL_START_TO_LINK);
1070 
1071 	pcmd = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
1072 	if (pcmd == NULL) {
1073 		res = _FAIL;
1074 		goto exit;
1075 	}
1076 #if 0
1077 	/*  for IEs is pointer */
1078 	t_len = sizeof(u32) + sizeof(NDIS_802_11_MAC_ADDRESS) + 2 +
1079 		sizeof(NDIS_802_11_SSID) + sizeof(u32) +
1080 		sizeof(NDIS_802_11_RSSI) + sizeof(NDIS_802_11_NETWORK_TYPE) +
1081 		sizeof(NDIS_802_11_CONFIGURATION) +
1082 		sizeof(NDIS_802_11_NETWORK_INFRASTRUCTURE) +
1083 		sizeof(NDIS_802_11_RATES_EX) + sizeof(WLAN_PHY_INFO) + sizeof(u32) + MAX_IE_SZ;
1084 #endif
1085 	/* for IEs is fix buf size */
1086 	t_len = sizeof(WLAN_BSSID_EX);
1087 
1088 
1089 	/* for hidden ap to set fw_state here */
1090 	if (check_fwstate(pmlmepriv, WIFI_STATION_STATE | WIFI_ADHOC_STATE) != _TRUE) {
1091 		switch (ndis_network_mode) {
1092 		case Ndis802_11IBSS:
1093 			set_fwstate(pmlmepriv, WIFI_ADHOC_STATE);
1094 			break;
1095 
1096 		case Ndis802_11Infrastructure:
1097 			set_fwstate(pmlmepriv, WIFI_STATION_STATE);
1098 			break;
1099 
1100 		default:
1101 			rtw_warn_on(1);
1102 			break;
1103 		}
1104 	}
1105 
1106 	pmlmeinfo->assoc_AP_vendor = check_assoc_AP(pnetwork->network.IEs, pnetwork->network.IELength);
1107 
1108 	rtw_phydm_update_ap_vendor_ie(padapter);
1109 
1110 #ifdef CONFIG_80211AC_VHT
1111 	/* save AP beamform_cap info for BCM IOT issue */
1112 	if (pmlmeinfo->assoc_AP_vendor == HT_IOT_PEER_BROADCOM)
1113 		get_vht_bf_cap(pnetwork->network.IEs,
1114 			pnetwork->network.IELength,
1115 			&pvhtpriv->ap_bf_cap);
1116 #endif
1117 	/*
1118 		Modified by Arvin 2015/05/13
1119 		Solution for allocating a new WLAN_BSSID_EX to avoid race condition issue between disconnect and joinbss
1120 	*/
1121 	psecnetwork = (WLAN_BSSID_EX *)rtw_zmalloc(sizeof(WLAN_BSSID_EX));
1122 	if (psecnetwork == NULL) {
1123 		if (pcmd != NULL)
1124 			rtw_mfree((unsigned char *)pcmd, sizeof(struct	cmd_obj));
1125 
1126 		res = _FAIL;
1127 
1128 
1129 		goto exit;
1130 	}
1131 
1132 	_rtw_memset(psecnetwork, 0, t_len);
1133 
1134 	_rtw_memcpy(psecnetwork, &pnetwork->network, get_WLAN_BSSID_EX_sz(&pnetwork->network));
1135 
1136 	auth = &psecuritypriv->authenticator_ie[0];
1137 	psecuritypriv->authenticator_ie[0] = (unsigned char)psecnetwork->IELength;
1138 
1139 	if ((psecnetwork->IELength - 12) < (256 - 1))
1140 		_rtw_memcpy(&psecuritypriv->authenticator_ie[1], &psecnetwork->IEs[12], psecnetwork->IELength - 12);
1141 	else
1142 		_rtw_memcpy(&psecuritypriv->authenticator_ie[1], &psecnetwork->IEs[12], (256 - 1));
1143 
1144 	psecnetwork->IELength = 0;
1145 	/* Added by Albert 2009/02/18 */
1146 	/* If the the driver wants to use the bssid to create the connection. */
1147 	/* If not,  we have to copy the connecting AP's MAC address to it so that */
1148 	/* the driver just has the bssid information for PMKIDList searching. */
1149 
1150 	if (pmlmepriv->assoc_by_bssid == _FALSE)
1151 		_rtw_memcpy(&pmlmepriv->assoc_bssid[0], &pnetwork->network.MacAddress[0], ETH_ALEN);
1152 
1153 	/* copy fixed ie */
1154 	_rtw_memcpy(psecnetwork->IEs, pnetwork->network.IEs, 12);
1155 	psecnetwork->IELength = 12;
1156 
1157 	psecnetwork->IELength += rtw_restruct_sec_ie(padapter, psecnetwork->IEs + psecnetwork->IELength);
1158 
1159 
1160 	pqospriv->qos_option = 0;
1161 
1162 	if (pregistrypriv->wmm_enable) {
1163 #ifdef CONFIG_WMMPS_STA
1164 		rtw_uapsd_use_default_setting(padapter);
1165 #endif /* CONFIG_WMMPS_STA */
1166 		tmp_len = rtw_restruct_wmm_ie(padapter, &pnetwork->network.IEs[0], &psecnetwork->IEs[0], pnetwork->network.IELength, psecnetwork->IELength);
1167 
1168 		if (psecnetwork->IELength != tmp_len) {
1169 			psecnetwork->IELength = tmp_len;
1170 			pqospriv->qos_option = 1; /* There is WMM IE in this corresp. beacon */
1171 		} else {
1172 			pqospriv->qos_option = 0;/* There is no WMM IE in this corresp. beacon */
1173 		}
1174 	}
1175 
1176 #ifdef CONFIG_80211D
1177 	if (rtw_joinbss_check_country_ie(padapter, &pnetwork->network, &country_ent, psecnetwork))
1178 		req_chplan = &country_ent;
1179 #endif
1180 
1181 #ifdef CONFIG_80211N_HT
1182 	phtpriv->ht_option = _FALSE;
1183 	if (pregistrypriv->ht_enable && is_supported_ht(pregistrypriv->wireless_mode)) {
1184 		ptmp = rtw_get_ie(&pnetwork->network.IEs[12], _HT_CAPABILITY_IE_, &tmp_len, pnetwork->network.IELength - 12);
1185 		if (ptmp && tmp_len > 0) {
1186 			/*	Added by Albert 2010/06/23 */
1187 			/*	For the WEP mode, we will use the bg mode to do the connection to avoid some IOT issue. */
1188 			/*	Especially for Realtek 8192u SoftAP. */
1189 			if ((padapter->securitypriv.dot11PrivacyAlgrthm != _WEP40_) &&
1190 			    (padapter->securitypriv.dot11PrivacyAlgrthm != _WEP104_) &&
1191 			    (padapter->securitypriv.dot11PrivacyAlgrthm != _TKIP_)) {
1192 				rtw_ht_use_default_setting(padapter);
1193 
1194 				/* rtw_restructure_ht_ie */
1195 				rtw_restructure_ht_ie(padapter, &pnetwork->network.IEs[12], &psecnetwork->IEs[0],
1196 					pnetwork->network.IELength - 12, &psecnetwork->IELength,
1197 					pnetwork->network.Configuration.DSConfig, req_chplan);
1198 			}
1199 		}
1200 	}
1201 
1202 #ifdef CONFIG_80211AC_VHT
1203 	pvhtpriv->vht_option = _FALSE;
1204 	if (phtpriv->ht_option
1205 		&& REGSTY_IS_11AC_ENABLE(pregistrypriv)
1206 		&& is_supported_vht(pregistrypriv->wireless_mode)
1207 		&& ((req_chplan && COUNTRY_CHPLAN_EN_11AC(req_chplan))
1208 			|| (!req_chplan && RFCTL_REG_EN_11AC(rfctl)))
1209 	) {
1210 		u8 vht_enable = 0;
1211 
1212 		if (pnetwork->network.Configuration.DSConfig > 14)
1213 			vht_enable = 1;
1214 		else if ((REGSTY_IS_11AC_24G_ENABLE(pregistrypriv)) && (padapter->registrypriv.wifi_spec == 0))
1215 			vht_enable = 1;
1216 
1217 		if (vht_enable == 1)
1218 			rtw_restructure_vht_ie(padapter, &pnetwork->network.IEs[0], &psecnetwork->IEs[0],
1219 				pnetwork->network.IELength, &psecnetwork->IELength, req_chplan);
1220 	}
1221 #endif
1222 #endif /* CONFIG_80211N_HT */
1223 
1224 	rtw_append_extended_cap(padapter, &psecnetwork->IEs[0], &psecnetwork->IELength);
1225 
1226 #ifdef CONFIG_RTW_80211R
1227 	rtw_ft_validate_akm_type(padapter, pnetwork);
1228 #endif
1229 
1230 #if 0
1231 	psecuritypriv->supplicant_ie[0] = (u8)psecnetwork->IELength;
1232 
1233 	if (psecnetwork->IELength < (256 - 1))
1234 		_rtw_memcpy(&psecuritypriv->supplicant_ie[1], &psecnetwork->IEs[0], psecnetwork->IELength);
1235 	else
1236 		_rtw_memcpy(&psecuritypriv->supplicant_ie[1], &psecnetwork->IEs[0], (256 - 1));
1237 #endif
1238 
1239 	pcmd->cmdsz = sizeof(WLAN_BSSID_EX);
1240 
1241 	_rtw_init_listhead(&pcmd->list);
1242 	pcmd->cmdcode = CMD_JOINBSS;/* _JoinBss_CMD_ */
1243 	pcmd->parmbuf = (unsigned char *)psecnetwork;
1244 	pcmd->rsp = NULL;
1245 	pcmd->rspsz = 0;
1246 
1247 	res = rtw_enqueue_cmd(pcmdpriv, pcmd);
1248 
1249 exit:
1250 
1251 
1252 	return res;
1253 }
1254 
rtw_disassoc_cmd(_adapter * padapter,u32 deauth_timeout_ms,int flags)1255 u8 rtw_disassoc_cmd(_adapter *padapter, u32 deauth_timeout_ms, int flags) /* for sta_mode */
1256 {
1257 	struct cmd_obj *cmdobj = NULL;
1258 	struct disconnect_parm *param = NULL;
1259 	struct cmd_priv *cmdpriv = &padapter->cmdpriv;
1260 	struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
1261 	struct submit_ctx sctx;
1262 	u8 res = _SUCCESS;
1263 
1264 	/* prepare cmd parameter */
1265 	param = (struct disconnect_parm *)rtw_zmalloc(sizeof(*param));
1266 	if (param == NULL) {
1267 		res = _FAIL;
1268 		goto exit;
1269 	}
1270 	param->deauth_timeout_ms = deauth_timeout_ms;
1271 
1272 	if (flags & RTW_CMDF_DIRECTLY) {
1273 		/* no need to enqueue, do the cmd hdl directly and free cmd parameter */
1274 		if (disconnect_hdl(padapter, (u8 *)param) != H2C_SUCCESS)
1275 			res = _FAIL;
1276 		rtw_mfree((u8 *)param, sizeof(*param));
1277 
1278 	} else {
1279 		cmdobj = (struct cmd_obj *)rtw_zmalloc(sizeof(*cmdobj));
1280 		if (cmdobj == NULL) {
1281 			res = _FAIL;
1282 			rtw_mfree((u8 *)param, sizeof(*param));
1283 			goto exit;
1284 		}
1285 		init_h2fwcmd_w_parm_no_rsp(cmdobj, param, CMD_DISCONNECT);
1286 		if (flags & RTW_CMDF_WAIT_ACK) {
1287 			cmdobj->sctx = &sctx;
1288 			rtw_sctx_init(&sctx, 2000);
1289 		}
1290 		res = rtw_enqueue_cmd(cmdpriv, cmdobj);
1291 		if (res == _SUCCESS && (flags & RTW_CMDF_WAIT_ACK)) {
1292 			rtw_sctx_wait(&sctx, __func__);
1293 			_enter_critical_mutex(&pcmdpriv->sctx_mutex, NULL);
1294 			if (sctx.status == RTW_SCTX_SUBMITTED)
1295 				cmdobj->sctx = NULL;
1296 			_exit_critical_mutex(&pcmdpriv->sctx_mutex, NULL);
1297 		}
1298 	}
1299 
1300 exit:
1301 
1302 
1303 	return res;
1304 }
1305 
1306 #ifdef CONFIG_AP_MODE
rtw_stop_ap_cmd(_adapter * adapter,u8 flags)1307 u8 rtw_stop_ap_cmd(_adapter  *adapter, u8 flags)
1308 {
1309 	struct cmd_obj *cmdobj;
1310 	struct drvextra_cmd_parm *parm;
1311 	struct cmd_priv *pcmdpriv = &adapter->cmdpriv;
1312 	struct submit_ctx sctx;
1313 	u8 res = _SUCCESS;
1314 
1315 	if (flags & RTW_CMDF_DIRECTLY) {
1316 		/* no need to enqueue, do the cmd hdl directly and free cmd parameter */
1317 		if (H2C_SUCCESS != stop_ap_hdl(adapter))
1318 			res = _FAIL;
1319 	} else {
1320 		parm = (struct drvextra_cmd_parm *)rtw_zmalloc(sizeof(struct drvextra_cmd_parm));
1321 		if (parm == NULL) {
1322 			res = _FAIL;
1323 			goto exit;
1324 		}
1325 
1326 		parm->ec_id = STOP_AP_WK_CID;
1327 		parm->type = 0;
1328 		parm->size = 0;
1329 		parm->pbuf = NULL;
1330 
1331 		/* need enqueue, prepare cmd_obj and enqueue */
1332 		cmdobj = (struct cmd_obj *)rtw_zmalloc(sizeof(*cmdobj));
1333 		if (cmdobj == NULL) {
1334 			res = _FAIL;
1335 			goto exit;
1336 		}
1337 
1338 		init_h2fwcmd_w_parm_no_rsp(cmdobj, parm, CMD_SET_DRV_EXTRA);
1339 
1340 		if (flags & RTW_CMDF_WAIT_ACK) {
1341 			cmdobj->sctx = &sctx;
1342 			rtw_sctx_init(&sctx, 2000);
1343 		}
1344 
1345 		res = rtw_enqueue_cmd(pcmdpriv, cmdobj);
1346 
1347 		if (res == _SUCCESS && (flags & RTW_CMDF_WAIT_ACK)) {
1348 			rtw_sctx_wait(&sctx, __func__);
1349 			_enter_critical_mutex(&pcmdpriv->sctx_mutex, NULL);
1350 			if (sctx.status == RTW_SCTX_SUBMITTED)
1351 				cmdobj->sctx = NULL;
1352 			_exit_critical_mutex(&pcmdpriv->sctx_mutex, NULL);
1353 		}
1354 	}
1355 exit:
1356 	return res;
1357 }
1358 #endif /* CONFIG_AP_MODE */
1359 
1360 #ifdef CONFIG_RTW_TOKEN_BASED_XMIT
rtw_tx_control_cmd(_adapter * adapter)1361 u8 rtw_tx_control_cmd(_adapter *adapter)
1362 {
1363 	struct cmd_obj		*ph2c;
1364 	struct drvextra_cmd_parm	*pdrvextra_cmd_parm;
1365 	struct cmd_priv *pcmdpriv = &adapter->cmdpriv;
1366 
1367 	u8 res = _SUCCESS;
1368 
1369 	ph2c = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
1370 	if (ph2c == NULL){
1371 		res = _FAIL;
1372 		goto exit;
1373 	}
1374 
1375 	pdrvextra_cmd_parm = (struct drvextra_cmd_parm *)rtw_zmalloc(sizeof(struct drvextra_cmd_parm));
1376 	if (pdrvextra_cmd_parm == NULL) {
1377 		rtw_mfree((unsigned char *)ph2c, sizeof(struct cmd_obj));
1378 		res = _FAIL;
1379 		goto exit;
1380 	}
1381 
1382 	pdrvextra_cmd_parm->ec_id = TBTX_CONTROL_TX_WK_CID;
1383 	pdrvextra_cmd_parm->type = 0;
1384 	pdrvextra_cmd_parm->size = 0;
1385 	pdrvextra_cmd_parm->pbuf = NULL;
1386 	init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, CMD_SET_DRV_EXTRA);
1387 
1388 	res = rtw_enqueue_cmd(pcmdpriv, ph2c);
1389 
1390 exit:
1391 	return res;
1392 }
1393 #endif
1394 
rtw_setopmode_cmd(_adapter * adapter,NDIS_802_11_NETWORK_INFRASTRUCTURE networktype,u8 flags)1395 u8 rtw_setopmode_cmd(_adapter  *adapter, NDIS_802_11_NETWORK_INFRASTRUCTURE networktype, u8 flags)
1396 {
1397 	struct cmd_obj *cmdobj;
1398 	struct setopmode_parm *parm;
1399 	struct cmd_priv *pcmdpriv = &adapter->cmdpriv;
1400 	struct submit_ctx sctx;
1401 	u8 res = _SUCCESS;
1402 
1403 	/* prepare cmd parameter */
1404 	parm = (struct setopmode_parm *)rtw_zmalloc(sizeof(*parm));
1405 	if (parm == NULL) {
1406 		res = _FAIL;
1407 		goto exit;
1408 	}
1409 	parm->mode = (u8)networktype;
1410 
1411 	if (flags & RTW_CMDF_DIRECTLY) {
1412 		/* no need to enqueue, do the cmd hdl directly and free cmd parameter */
1413 		if (H2C_SUCCESS != setopmode_hdl(adapter, (u8 *)parm))
1414 			res = _FAIL;
1415 		rtw_mfree((u8 *)parm, sizeof(*parm));
1416 	} else {
1417 		/* need enqueue, prepare cmd_obj and enqueue */
1418 		cmdobj = (struct cmd_obj *)rtw_zmalloc(sizeof(*cmdobj));
1419 		if (cmdobj == NULL) {
1420 			res = _FAIL;
1421 			rtw_mfree((u8 *)parm, sizeof(*parm));
1422 			goto exit;
1423 		}
1424 
1425 		init_h2fwcmd_w_parm_no_rsp(cmdobj, parm, CMD_SET_OPMODE);
1426 
1427 		if (flags & RTW_CMDF_WAIT_ACK) {
1428 			cmdobj->sctx = &sctx;
1429 			rtw_sctx_init(&sctx, 2000);
1430 		}
1431 
1432 		res = rtw_enqueue_cmd(pcmdpriv, cmdobj);
1433 
1434 		if (res == _SUCCESS && (flags & RTW_CMDF_WAIT_ACK)) {
1435 			rtw_sctx_wait(&sctx, __func__);
1436 			_enter_critical_mutex(&pcmdpriv->sctx_mutex, NULL);
1437 			if (sctx.status == RTW_SCTX_SUBMITTED)
1438 				cmdobj->sctx = NULL;
1439 			_exit_critical_mutex(&pcmdpriv->sctx_mutex, NULL);
1440 		}
1441 	}
1442 
1443 exit:
1444 	return res;
1445 }
1446 
rtw_setstakey_cmd(_adapter * padapter,struct sta_info * sta,u8 key_type,bool enqueue)1447 u8 rtw_setstakey_cmd(_adapter *padapter, struct sta_info *sta, u8 key_type, bool enqueue)
1448 {
1449 	struct cmd_obj			*ph2c;
1450 	struct set_stakey_parm	*psetstakey_para;
1451 	struct cmd_priv			*pcmdpriv = &padapter->cmdpriv;
1452 	struct set_stakey_rsp		*psetstakey_rsp = NULL;
1453 
1454 	struct mlme_priv			*pmlmepriv = &padapter->mlmepriv;
1455 	struct security_priv		*psecuritypriv = &padapter->securitypriv;
1456 	u8 key_len =16;
1457 	u8	res = _SUCCESS;
1458 
1459 
1460 	psetstakey_para = (struct set_stakey_parm *)rtw_zmalloc(sizeof(struct set_stakey_parm));
1461 	if (psetstakey_para == NULL) {
1462 		res = _FAIL;
1463 		goto exit;
1464 	}
1465 
1466 	_rtw_memcpy(psetstakey_para->addr, sta->cmn.mac_addr, ETH_ALEN);
1467 
1468 	if (check_fwstate(pmlmepriv, WIFI_STATION_STATE))
1469 		psetstakey_para->algorithm = (unsigned char) psecuritypriv->dot11PrivacyAlgrthm;
1470 	else
1471 		GET_ENCRY_ALGO(psecuritypriv, sta, psetstakey_para->algorithm, _FALSE);
1472 
1473 	if ((psetstakey_para->algorithm == _GCMP_256_) || (psetstakey_para->algorithm == _CCMP_256_))
1474 		key_len = 32;
1475 
1476 	if (key_type == GROUP_KEY) {
1477 		_rtw_memcpy(&psetstakey_para->key, &psecuritypriv->dot118021XGrpKey[psecuritypriv->dot118021XGrpKeyid].skey, key_len);
1478 		psetstakey_para->gk = 1;
1479 	} else if (key_type == UNICAST_KEY)
1480 		_rtw_memcpy(&psetstakey_para->key, &sta->dot118021x_UncstKey, key_len);
1481 #ifdef CONFIG_TDLS
1482 	else if (key_type == TDLS_KEY) {
1483 		_rtw_memcpy(&psetstakey_para->key, sta->tpk.tk, key_len);
1484 		psetstakey_para->algorithm = (u8)sta->dot118021XPrivacy;
1485 	}
1486 #endif /* CONFIG_TDLS */
1487 
1488 	/* jeff: set this becasue at least sw key is ready */
1489 	padapter->securitypriv.busetkipkey = _TRUE;
1490 
1491 	if (enqueue) {
1492 		ph2c = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
1493 		if (ph2c == NULL) {
1494 			rtw_mfree((u8 *) psetstakey_para, sizeof(struct set_stakey_parm));
1495 			res = _FAIL;
1496 			goto exit;
1497 		}
1498 
1499 		psetstakey_rsp = (struct set_stakey_rsp *)rtw_zmalloc(sizeof(struct set_stakey_rsp));
1500 		if (psetstakey_rsp == NULL) {
1501 			rtw_mfree((u8 *) ph2c, sizeof(struct cmd_obj));
1502 			rtw_mfree((u8 *) psetstakey_para, sizeof(struct set_stakey_parm));
1503 			res = _FAIL;
1504 			goto exit;
1505 		}
1506 
1507 		init_h2fwcmd_w_parm_no_rsp(ph2c, psetstakey_para, CMD_SET_STAKEY);
1508 		ph2c->rsp = (u8 *) psetstakey_rsp;
1509 		ph2c->rspsz = sizeof(struct set_stakey_rsp);
1510 		res = rtw_enqueue_cmd(pcmdpriv, ph2c);
1511 	} else {
1512 		set_stakey_hdl(padapter, (u8 *)psetstakey_para);
1513 		rtw_mfree((u8 *) psetstakey_para, sizeof(struct set_stakey_parm));
1514 	}
1515 exit:
1516 
1517 
1518 	return res;
1519 }
1520 
rtw_clearstakey_cmd(_adapter * padapter,struct sta_info * sta,u8 enqueue)1521 u8 rtw_clearstakey_cmd(_adapter *padapter, struct sta_info *sta, u8 enqueue)
1522 {
1523 	struct cmd_obj			*ph2c;
1524 	struct set_stakey_parm	*psetstakey_para;
1525 	struct cmd_priv			*pcmdpriv = &padapter->cmdpriv;
1526 	struct set_stakey_rsp		*psetstakey_rsp = NULL;
1527 	s16 cam_id = 0;
1528 	u8	res = _SUCCESS;
1529 
1530 	if (!sta) {
1531 		RTW_ERR("%s sta == NULL\n", __func__);
1532 		goto exit;
1533 	}
1534 
1535 	if (!enqueue) {
1536 		while ((cam_id = rtw_camid_search(padapter, sta->cmn.mac_addr, -1, -1)) >= 0) {
1537 			RTW_PRINT("clear key for addr:"MAC_FMT", camid:%d\n", MAC_ARG(sta->cmn.mac_addr), cam_id);
1538 			clear_cam_entry(padapter, cam_id);
1539 			rtw_camid_free(padapter, cam_id);
1540 		}
1541 	} else {
1542 		ph2c = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
1543 		if (ph2c == NULL) {
1544 			res = _FAIL;
1545 			goto exit;
1546 		}
1547 
1548 		psetstakey_para = (struct set_stakey_parm *)rtw_zmalloc(sizeof(struct set_stakey_parm));
1549 		if (psetstakey_para == NULL) {
1550 			rtw_mfree((u8 *) ph2c, sizeof(struct	cmd_obj));
1551 			res = _FAIL;
1552 			goto exit;
1553 		}
1554 
1555 		psetstakey_rsp = (struct set_stakey_rsp *)rtw_zmalloc(sizeof(struct set_stakey_rsp));
1556 		if (psetstakey_rsp == NULL) {
1557 			rtw_mfree((u8 *) ph2c, sizeof(struct	cmd_obj));
1558 			rtw_mfree((u8 *) psetstakey_para, sizeof(struct set_stakey_parm));
1559 			res = _FAIL;
1560 			goto exit;
1561 		}
1562 
1563 		init_h2fwcmd_w_parm_no_rsp(ph2c, psetstakey_para, CMD_SET_STAKEY);
1564 		ph2c->rsp = (u8 *) psetstakey_rsp;
1565 		ph2c->rspsz = sizeof(struct set_stakey_rsp);
1566 
1567 		_rtw_memcpy(psetstakey_para->addr, sta->cmn.mac_addr, ETH_ALEN);
1568 
1569 		psetstakey_para->algorithm = _NO_PRIVACY_;
1570 
1571 		res = rtw_enqueue_cmd(pcmdpriv, ph2c);
1572 
1573 	}
1574 
1575 exit:
1576 
1577 
1578 	return res;
1579 }
1580 
rtw_addbareq_cmd(_adapter * padapter,u8 tid,u8 * addr)1581 u8 rtw_addbareq_cmd(_adapter *padapter, u8 tid, u8 *addr)
1582 {
1583 	struct cmd_priv		*pcmdpriv = &padapter->cmdpriv;
1584 	struct cmd_obj		*ph2c;
1585 	struct addBaReq_parm	*paddbareq_parm;
1586 
1587 	u8	res = _SUCCESS;
1588 
1589 
1590 	ph2c = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
1591 	if (ph2c == NULL) {
1592 		res = _FAIL;
1593 		goto exit;
1594 	}
1595 
1596 	paddbareq_parm = (struct addBaReq_parm *)rtw_zmalloc(sizeof(struct addBaReq_parm));
1597 	if (paddbareq_parm == NULL) {
1598 		rtw_mfree((unsigned char *)ph2c, sizeof(struct	cmd_obj));
1599 		res = _FAIL;
1600 		goto exit;
1601 	}
1602 
1603 	paddbareq_parm->tid = tid;
1604 	_rtw_memcpy(paddbareq_parm->addr, addr, ETH_ALEN);
1605 
1606 	init_h2fwcmd_w_parm_no_rsp(ph2c, paddbareq_parm, CMD_ADD_BAREQ);
1607 
1608 	/* RTW_INFO("rtw_addbareq_cmd, tid=%d\n", tid); */
1609 
1610 	/* rtw_enqueue_cmd(pcmdpriv, ph2c);	 */
1611 	res = rtw_enqueue_cmd(pcmdpriv, ph2c);
1612 
1613 exit:
1614 
1615 
1616 	return res;
1617 }
1618 
rtw_addbarsp_cmd(_adapter * padapter,u8 * addr,u16 tid,u8 status,u8 size,u16 start_seq)1619 u8 rtw_addbarsp_cmd(_adapter *padapter, u8 *addr, u16 tid, u8 status, u8 size, u16 start_seq)
1620 {
1621 	struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
1622 	struct cmd_obj *ph2c;
1623 	struct addBaRsp_parm *paddBaRsp_parm;
1624 	u8 res = _SUCCESS;
1625 
1626 
1627 	ph2c = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
1628 	if (ph2c == NULL) {
1629 		res = _FAIL;
1630 		goto exit;
1631 	}
1632 
1633 	paddBaRsp_parm = (struct addBaRsp_parm *)rtw_zmalloc(sizeof(struct addBaRsp_parm));
1634 
1635 	if (paddBaRsp_parm == NULL) {
1636 		rtw_mfree((unsigned char *)ph2c, sizeof(struct cmd_obj));
1637 		res = _FAIL;
1638 		goto exit;
1639 	}
1640 
1641 	_rtw_memcpy(paddBaRsp_parm->addr, addr, ETH_ALEN);
1642 	paddBaRsp_parm->tid = tid;
1643 	paddBaRsp_parm->status = status;
1644 	paddBaRsp_parm->size = size;
1645 	paddBaRsp_parm->start_seq = start_seq;
1646 
1647 	init_h2fwcmd_w_parm_no_rsp(ph2c, paddBaRsp_parm, CMD_ADD_BARSP);
1648 
1649 	res = rtw_enqueue_cmd(pcmdpriv, ph2c);
1650 
1651 exit:
1652 
1653 
1654 	return res;
1655 }
1656 /* add for CONFIG_IEEE80211W, none 11w can use it */
rtw_reset_securitypriv_cmd(_adapter * padapter)1657 u8 rtw_reset_securitypriv_cmd(_adapter *padapter)
1658 {
1659 	struct cmd_obj		*ph2c;
1660 	struct drvextra_cmd_parm  *pdrvextra_cmd_parm;
1661 	struct cmd_priv	*pcmdpriv = &padapter->cmdpriv;
1662 	u8	res = _SUCCESS;
1663 
1664 
1665 	ph2c = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
1666 	if (ph2c == NULL) {
1667 		res = _FAIL;
1668 		goto exit;
1669 	}
1670 
1671 	pdrvextra_cmd_parm = (struct drvextra_cmd_parm *)rtw_zmalloc(sizeof(struct drvextra_cmd_parm));
1672 	if (pdrvextra_cmd_parm == NULL) {
1673 		rtw_mfree((unsigned char *)ph2c, sizeof(struct cmd_obj));
1674 		res = _FAIL;
1675 		goto exit;
1676 	}
1677 
1678 	pdrvextra_cmd_parm->ec_id = RESET_SECURITYPRIV;
1679 	pdrvextra_cmd_parm->type = 0;
1680 	pdrvextra_cmd_parm->size = 0;
1681 	pdrvextra_cmd_parm->pbuf = NULL;
1682 
1683 	init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, CMD_SET_DRV_EXTRA);
1684 
1685 
1686 	/* rtw_enqueue_cmd(pcmdpriv, ph2c);	 */
1687 	res = rtw_enqueue_cmd(pcmdpriv, ph2c);
1688 
1689 exit:
1690 
1691 
1692 	return res;
1693 
1694 }
1695 
free_assoc_resources_hdl(_adapter * padapter,u8 lock_scanned_queue)1696 void free_assoc_resources_hdl(_adapter *padapter, u8 lock_scanned_queue)
1697 {
1698 	rtw_free_assoc_resources(padapter, lock_scanned_queue);
1699 }
1700 
rtw_free_assoc_resources_cmd(_adapter * padapter,u8 lock_scanned_queue,int flags)1701 u8 rtw_free_assoc_resources_cmd(_adapter *padapter, u8 lock_scanned_queue, int flags)
1702 {
1703 	struct cmd_obj *cmd;
1704 	struct drvextra_cmd_parm  *pdrvextra_cmd_parm;
1705 	struct cmd_priv	*pcmdpriv = &padapter->cmdpriv;
1706 	struct submit_ctx sctx;
1707 	u8	res = _SUCCESS;
1708 
1709 	if (flags & RTW_CMDF_DIRECTLY) {
1710 		free_assoc_resources_hdl(padapter, lock_scanned_queue);
1711 	}
1712 	else {
1713 		cmd = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
1714 		if (cmd == NULL) {
1715 			res = _FAIL;
1716 			goto exit;
1717 		}
1718 
1719 		pdrvextra_cmd_parm = (struct drvextra_cmd_parm *)rtw_zmalloc(sizeof(struct drvextra_cmd_parm));
1720 		if (pdrvextra_cmd_parm == NULL) {
1721 			rtw_mfree((unsigned char *)cmd, sizeof(struct cmd_obj));
1722 			res = _FAIL;
1723 			goto exit;
1724 		}
1725 
1726 		pdrvextra_cmd_parm->ec_id = FREE_ASSOC_RESOURCES;
1727 		pdrvextra_cmd_parm->type = lock_scanned_queue;
1728 		pdrvextra_cmd_parm->size = 0;
1729 		pdrvextra_cmd_parm->pbuf = NULL;
1730 
1731 		init_h2fwcmd_w_parm_no_rsp(cmd, pdrvextra_cmd_parm, CMD_SET_DRV_EXTRA);
1732 		if (flags & RTW_CMDF_WAIT_ACK) {
1733 			cmd->sctx = &sctx;
1734 			rtw_sctx_init(&sctx, 2000);
1735 		}
1736 
1737 		res = rtw_enqueue_cmd(pcmdpriv, cmd);
1738 
1739 		if (res == _SUCCESS && (flags & RTW_CMDF_WAIT_ACK)) {
1740 			rtw_sctx_wait(&sctx, __func__);
1741 			_enter_critical_mutex(&pcmdpriv->sctx_mutex, NULL);
1742 			if (sctx.status == RTW_SCTX_SUBMITTED)
1743 				cmd->sctx = NULL;
1744 			_exit_critical_mutex(&pcmdpriv->sctx_mutex, NULL);
1745 		}
1746 	}
1747 exit:
1748 	return res;
1749 
1750 }
1751 
rtw_dynamic_chk_wk_cmd(_adapter * padapter)1752 u8 rtw_dynamic_chk_wk_cmd(_adapter *padapter)
1753 {
1754 	struct cmd_obj		*ph2c;
1755 	struct drvextra_cmd_parm  *pdrvextra_cmd_parm;
1756 	struct cmd_priv	*pcmdpriv = &padapter->cmdpriv;
1757 	u8	res = _SUCCESS;
1758 
1759 
1760 	/* only  primary padapter does this cmd */
1761 
1762 	ph2c = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
1763 	if (ph2c == NULL) {
1764 		res = _FAIL;
1765 		goto exit;
1766 	}
1767 
1768 	pdrvextra_cmd_parm = (struct drvextra_cmd_parm *)rtw_zmalloc(sizeof(struct drvextra_cmd_parm));
1769 	if (pdrvextra_cmd_parm == NULL) {
1770 		rtw_mfree((unsigned char *)ph2c, sizeof(struct cmd_obj));
1771 		res = _FAIL;
1772 		goto exit;
1773 	}
1774 
1775 	pdrvextra_cmd_parm->ec_id = DYNAMIC_CHK_WK_CID;
1776 	pdrvextra_cmd_parm->type = 0;
1777 	pdrvextra_cmd_parm->size = 0;
1778 	pdrvextra_cmd_parm->pbuf = NULL;
1779 	init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, CMD_SET_DRV_EXTRA);
1780 
1781 
1782 	/* rtw_enqueue_cmd(pcmdpriv, ph2c);	 */
1783 	res = rtw_enqueue_cmd(pcmdpriv, ph2c);
1784 
1785 exit:
1786 
1787 
1788 	return res;
1789 
1790 }
1791 
rtw_iqk_cmd(_adapter * padapter,u8 flags)1792 u8 rtw_iqk_cmd(_adapter *padapter, u8 flags)
1793 {
1794 	struct cmd_obj *pcmdobj;
1795 	struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
1796 	struct submit_ctx sctx;
1797 	u8 res = _SUCCESS;
1798 
1799 	if (flags & RTW_CMDF_DIRECTLY) {
1800 		/* no need to enqueue, do the cmd hdl */
1801 		rtw_iqk_hdl(padapter, NULL);
1802 	} else {
1803 		/* need enqueue, prepare cmd_obj and enqueue */
1804 		pcmdobj = (struct cmd_obj *)rtw_zmalloc(sizeof(struct	cmd_obj));
1805 		if (pcmdobj == NULL) {
1806 			res = _FAIL;
1807 			goto exit;
1808 		}
1809 
1810 		init_h2fwcmd_w_parm_no_parm_rsp(pcmdobj, CMD_DO_IQK);
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 exit:
1829 
1830 	return res;
1831 }
1832 
rtw_set_chbw_cmd(_adapter * padapter,u8 ch,u8 bw,u8 ch_offset,u8 flags)1833 u8 rtw_set_chbw_cmd(_adapter *padapter, u8 ch, u8 bw, u8 ch_offset, u8 flags)
1834 {
1835 	struct cmd_obj *pcmdobj;
1836 	struct set_ch_parm *set_ch_parm;
1837 	struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
1838 	struct submit_ctx sctx;
1839 	u8 res = _SUCCESS;
1840 
1841 
1842 	RTW_INFO(FUNC_NDEV_FMT" ch:%u, bw:%u, ch_offset:%u\n",
1843 		 FUNC_NDEV_ARG(padapter->pnetdev), ch, bw, ch_offset);
1844 
1845 	/* check input parameter */
1846 
1847 	/* prepare cmd parameter */
1848 	set_ch_parm = (struct set_ch_parm *)rtw_zmalloc(sizeof(*set_ch_parm));
1849 	if (set_ch_parm == NULL) {
1850 		res = _FAIL;
1851 		goto exit;
1852 	}
1853 	set_ch_parm->ch = ch;
1854 	set_ch_parm->bw = bw;
1855 	set_ch_parm->ch_offset = ch_offset;
1856 
1857 	if (flags & RTW_CMDF_DIRECTLY) {
1858 		/* no need to enqueue, do the cmd hdl directly and free cmd parameter */
1859 		if (H2C_SUCCESS != rtw_set_chbw_hdl(padapter, (u8 *)set_ch_parm))
1860 			res = _FAIL;
1861 
1862 		rtw_mfree((u8 *)set_ch_parm, sizeof(*set_ch_parm));
1863 	} else {
1864 		/* need enqueue, prepare cmd_obj and enqueue */
1865 		pcmdobj = (struct cmd_obj *)rtw_zmalloc(sizeof(struct	cmd_obj));
1866 		if (pcmdobj == NULL) {
1867 			rtw_mfree((u8 *)set_ch_parm, sizeof(*set_ch_parm));
1868 			res = _FAIL;
1869 			goto exit;
1870 		}
1871 
1872 		init_h2fwcmd_w_parm_no_rsp(pcmdobj, set_ch_parm, CMD_SET_CHANNEL);
1873 
1874 		if (flags & RTW_CMDF_WAIT_ACK) {
1875 			pcmdobj->sctx = &sctx;
1876 			rtw_sctx_init(&sctx, 10 * 1000);
1877 		}
1878 
1879 		res = rtw_enqueue_cmd(pcmdpriv, pcmdobj);
1880 
1881 		if (res == _SUCCESS && (flags & RTW_CMDF_WAIT_ACK)) {
1882 			rtw_sctx_wait(&sctx, __func__);
1883 			_enter_critical_mutex(&pcmdpriv->sctx_mutex, NULL);
1884 			if (sctx.status == RTW_SCTX_SUBMITTED)
1885 				pcmdobj->sctx = NULL;
1886 			_exit_critical_mutex(&pcmdpriv->sctx_mutex, NULL);
1887 		}
1888 	}
1889 
1890 	/* do something based on res... */
1891 
1892 exit:
1893 
1894 	RTW_INFO(FUNC_NDEV_FMT" res:%u\n", FUNC_NDEV_ARG(padapter->pnetdev), res);
1895 
1896 
1897 	return res;
1898 }
1899 
_rtw_set_chplan_cmd(_adapter * adapter,int flags,u8 chplan,u8 chplan_6g,const struct country_chplan * country_ent,enum regd_src_t regd_src,enum rtw_regd_inr inr,const struct country_ie_slave_record * cisr)1900 static u8 _rtw_set_chplan_cmd(_adapter *adapter, int flags
1901 	, u8 chplan, u8 chplan_6g, const struct country_chplan *country_ent
1902 	, enum regd_src_t regd_src, enum rtw_regd_inr inr
1903 	, const struct country_ie_slave_record *cisr)
1904 {
1905 	struct cmd_obj *cmdobj;
1906 	struct SetChannelPlan_param *parm;
1907 	struct cmd_priv *pcmdpriv = &adapter->cmdpriv;
1908 	struct submit_ctx sctx;
1909 #ifdef PLATFORM_LINUX
1910 	bool rtnl_lock_needed = rtw_rtnl_lock_needed(adapter_to_dvobj(adapter));
1911 #endif
1912 	u8 res = _SUCCESS;
1913 
1914 	/* check if allow software config */
1915 	if (rtw_rfctl_is_disable_sw_channel_plan(adapter_to_dvobj(adapter)) == _TRUE) {
1916 		res = _FAIL;
1917 		goto exit;
1918 	}
1919 
1920 	if (country_ent) {
1921 		/* if country_entry is provided, replace chplan */
1922 		chplan = country_ent->chplan;
1923 		#if CONFIG_IEEE80211_BAND_6GHZ
1924 		chplan_6g = country_ent->chplan_6g;
1925 		#endif
1926 	}
1927 
1928 	/* prepare cmd parameter */
1929 	parm = (struct SetChannelPlan_param *)rtw_zmalloc(sizeof(*parm));
1930 	if (parm == NULL) {
1931 		res = _FAIL;
1932 		goto exit;
1933 	}
1934 	parm->regd_src = regd_src;
1935 	parm->inr = inr;
1936 	if (country_ent) {
1937 		_rtw_memcpy(&parm->country_ent, country_ent, sizeof(parm->country_ent));
1938 		parm->has_country = 1;
1939 	}
1940 	parm->channel_plan = chplan;
1941 #if CONFIG_IEEE80211_BAND_6GHZ
1942 	parm->channel_plan_6g = chplan_6g;
1943 #endif
1944 #ifdef CONFIG_80211D
1945 	if (cisr) {
1946 		_rtw_memcpy(&parm->cisr, cisr, sizeof(*cisr));
1947 		parm->has_cisr = 1;
1948 	}
1949 #endif
1950 #ifdef PLATFORM_LINUX
1951 	if (flags & (RTW_CMDF_DIRECTLY | RTW_CMDF_WAIT_ACK))
1952 		parm->rtnl_lock_needed = rtnl_lock_needed; /* synchronous call, follow caller's */
1953 	else
1954 		parm->rtnl_lock_needed = 1; /* asynchronous call, always needed */
1955 #endif
1956 
1957 	if (flags & RTW_CMDF_DIRECTLY) {
1958 		/* no need to enqueue, do the cmd hdl directly and free cmd parameter */
1959 		if (H2C_SUCCESS != rtw_set_chplan_hdl(adapter, (u8 *)parm))
1960 			res = _FAIL;
1961 		rtw_mfree((u8 *)parm, sizeof(*parm));
1962 	} else {
1963 		/* need enqueue, prepare cmd_obj and enqueue */
1964 		cmdobj = (struct cmd_obj *)rtw_zmalloc(sizeof(*cmdobj));
1965 		if (cmdobj == NULL) {
1966 			res = _FAIL;
1967 			rtw_mfree((u8 *)parm, sizeof(*parm));
1968 			goto exit;
1969 		}
1970 
1971 		init_h2fwcmd_w_parm_no_rsp(cmdobj, parm, CMD_SET_CHANPLAN);
1972 
1973 		if (flags & RTW_CMDF_WAIT_ACK) {
1974 			cmdobj->sctx = &sctx;
1975 			rtw_sctx_init(&sctx, 2000);
1976 		}
1977 
1978 		res = rtw_enqueue_cmd(pcmdpriv, cmdobj);
1979 
1980 		if (res == _SUCCESS && (flags & RTW_CMDF_WAIT_ACK)) {
1981 			rtw_sctx_wait(&sctx, __func__);
1982 			_enter_critical_mutex(&pcmdpriv->sctx_mutex, NULL);
1983 			if (sctx.status == RTW_SCTX_SUBMITTED)
1984 				cmdobj->sctx = NULL;
1985 			_exit_critical_mutex(&pcmdpriv->sctx_mutex, NULL);
1986 			if (sctx.status != RTW_SCTX_DONE_SUCCESS)
1987 				res = _FAIL;
1988 		}
1989 
1990 		/* allow set channel plan when cmd_thread is not running */
1991 		if (res != _SUCCESS && (flags & RTW_CMDF_WAIT_ACK)) {
1992 			parm = (struct SetChannelPlan_param *)rtw_zmalloc(sizeof(*parm));
1993 			if (parm == NULL) {
1994 				res = _FAIL;
1995 				goto exit;
1996 			}
1997 			parm->regd_src = regd_src;
1998 			parm->inr = inr;
1999 			if (country_ent) {
2000 				_rtw_memcpy(&parm->country_ent, country_ent, sizeof(parm->country_ent));
2001 				parm->has_country = 1;
2002 			}
2003 			parm->channel_plan = chplan;
2004 			#if CONFIG_IEEE80211_BAND_6GHZ
2005 			parm->channel_plan_6g = chplan_6g;
2006 			#endif
2007 			#ifdef CONFIG_80211D
2008 			if (cisr) {
2009 				_rtw_memcpy(&parm->cisr, cisr, sizeof(*cisr));
2010 				parm->has_cisr = 1;
2011 			}
2012 			#endif
2013 			#ifdef PLATFORM_LINUX
2014 			parm->rtnl_lock_needed = rtnl_lock_needed; /* synchronous call, follow caller's */
2015 			#endif
2016 
2017 			if (H2C_SUCCESS != rtw_set_chplan_hdl(adapter, (u8 *)parm))
2018 				res = _FAIL;
2019 			else
2020 				res = _SUCCESS;
2021 			rtw_mfree((u8 *)parm, sizeof(*parm));
2022 		}
2023 	}
2024 
2025 exit:
2026 	return res;
2027 }
2028 
rtw_set_chplan_cmd(_adapter * adapter,int flags,u8 chplan,u8 chplan_6g,enum rtw_regd_inr inr)2029 inline u8 rtw_set_chplan_cmd(_adapter *adapter, int flags, u8 chplan, u8 chplan_6g, enum rtw_regd_inr inr)
2030 {
2031 	return _rtw_set_chplan_cmd(adapter, flags, chplan, chplan_6g, NULL, REGD_SRC_RTK_PRIV, inr, NULL);
2032 }
2033 
rtw_set_country_cmd(_adapter * adapter,int flags,const char * country_code,enum rtw_regd_inr inr)2034 inline u8 rtw_set_country_cmd(_adapter *adapter, int flags, const char *country_code, enum rtw_regd_inr inr)
2035 {
2036 	struct country_chplan ent;
2037 
2038 	if (IS_ALPHA2_WORLDWIDE(country_code)) {
2039 		rtw_get_chplan_worldwide(&ent);
2040 		goto cmd;
2041 	}
2042 
2043 	if (is_alpha(country_code[0]) == _FALSE
2044 	    || is_alpha(country_code[1]) == _FALSE
2045 	   ) {
2046 		RTW_PRINT("%s input country_code is not alpha2\n", __func__);
2047 		return _FAIL;
2048 	}
2049 
2050 	if (!rtw_get_chplan_from_country(country_code, &ent)) {
2051 		RTW_PRINT("%s unsupported country_code:\"%c%c\"\n", __func__, country_code[0], country_code[1]);
2052 		return _FAIL;
2053 	}
2054 
2055 cmd:
2056 	RTW_PRINT("%s country_code:\"%c%c\"\n", __func__, country_code[0], country_code[1]);
2057 
2058 	return _rtw_set_chplan_cmd(adapter, flags, RTW_CHPLAN_UNSPECIFIED, RTW_CHPLAN_6G_UNSPECIFIED, &ent, REGD_SRC_RTK_PRIV, inr, NULL);
2059 }
2060 
2061 #ifdef CONFIG_REGD_SRC_FROM_OS
rtw_sync_os_regd_cmd(_adapter * adapter,int flags,const char * country_code,u8 dfs_region,enum rtw_regd_inr inr)2062 inline u8 rtw_sync_os_regd_cmd(_adapter *adapter, int flags, const char *country_code, u8 dfs_region, enum rtw_regd_inr inr)
2063 {
2064 	struct country_chplan ent;
2065 	struct country_chplan rtk_ent;
2066 	bool rtk_ent_exist;
2067 
2068 	rtk_ent_exist = rtw_get_chplan_from_country(country_code, &rtk_ent);
2069 
2070 	_rtw_memcpy(ent.alpha2, country_code, 2);
2071 
2072 	/*
2073 	* Regulation follows OS, the internal txpwr limit selection is searched by alpha2
2074 	*     "00" => WW, others use string mapping
2075 	* When  no matching txpwr limit selection is found, use
2076 	*     1. txpwr lmit selection associated with alpha2 inside driver regulation database
2077 	*     2. WW when driver has no support of this alpha2
2078 	*/
2079 
2080 	ent.chplan = rtk_ent_exist ? rtk_ent.chplan : RTW_CHPLAN_UNSPECIFIED;
2081 	#if CONFIG_IEEE80211_BAND_6GHZ
2082 	ent.chplan_6g = rtk_ent_exist ? rtk_ent.chplan_6g : RTW_CHPLAN_6G_UNSPECIFIED;
2083 	#endif
2084 	ent.edcca_mode_2g_override = rtk_ent_exist ? rtk_ent.edcca_mode_2g_override : RTW_EDCCA_DEF;
2085 	#if CONFIG_IEEE80211_BAND_5GHZ
2086 	ent.edcca_mode_5g_override = rtk_ent_exist ? rtk_ent.edcca_mode_5g_override : RTW_EDCCA_DEF;
2087 	#endif
2088 	#if CONFIG_IEEE80211_BAND_6GHZ
2089 	ent.edcca_mode_6g_override = rtk_ent_exist ? rtk_ent.edcca_mode_6g_override : RTW_EDCCA_DEF;
2090 	#endif
2091 	ent.txpwr_lmt_override = rtk_ent_exist ? rtk_ent.txpwr_lmt_override : TXPWR_LMT_DEF;
2092 	#if defined(CONFIG_80211AC_VHT) || defined(CONFIG_80211AX_HE)
2093 	ent.proto_en = CHPLAN_PROTO_EN_ALL;
2094 	#endif
2095 
2096 	/* TODO: dfs_region */
2097 
2098 	return _rtw_set_chplan_cmd(adapter, flags, RTW_CHPLAN_UNSPECIFIED, RTW_CHPLAN_6G_UNSPECIFIED, &ent, REGD_SRC_OS, inr, NULL);
2099 }
2100 #endif /* CONFIG_REGD_SRC_FROM_OS */
2101 
rtw_get_chplan_cmd(_adapter * adapter,int flags,struct get_chplan_resp ** chplan)2102 u8 rtw_get_chplan_cmd(_adapter *adapter, int flags, struct get_chplan_resp **chplan)
2103 {
2104 	struct cmd_obj *cmdobj;
2105 	struct get_channel_plan_param *parm;
2106 	struct cmd_priv *pcmdpriv = &adapter->cmdpriv;
2107 	struct submit_ctx sctx;
2108 	u8 res = _FAIL;
2109 
2110 	if (!(flags & (RTW_CMDF_DIRECTLY | RTW_CMDF_WAIT_ACK)))
2111 		goto exit;
2112 
2113 	/* prepare cmd parameter */
2114 	parm = rtw_zmalloc(sizeof(*parm));
2115 	if (parm == NULL)
2116 		goto exit;
2117 	parm->chplan = chplan;
2118 
2119 	if (flags & RTW_CMDF_DIRECTLY) {
2120 		/* no need to enqueue, do the cmd hdl directly and free cmd parameter */
2121 		if (H2C_SUCCESS == rtw_get_chplan_hdl(adapter, (u8 *)parm))
2122 			res = _SUCCESS;
2123 		rtw_mfree((u8 *)parm, sizeof(*parm));
2124 	} else {
2125 		/* need enqueue, prepare cmd_obj and enqueue */
2126 		cmdobj = (struct cmd_obj *)rtw_zmalloc(sizeof(*cmdobj));
2127 		if (cmdobj == NULL) {
2128 			rtw_mfree((u8 *)parm, sizeof(*parm));
2129 			goto exit;
2130 		}
2131 
2132 		init_h2fwcmd_w_parm_no_rsp(cmdobj, parm, CMD_GET_CHANPLAN);
2133 
2134 		if (flags & RTW_CMDF_WAIT_ACK) {
2135 			cmdobj->sctx = &sctx;
2136 			rtw_sctx_init(&sctx, 2000);
2137 		}
2138 
2139 		res = rtw_enqueue_cmd(pcmdpriv, cmdobj);
2140 
2141 		if (res == _SUCCESS && (flags & RTW_CMDF_WAIT_ACK)) {
2142 			rtw_sctx_wait(&sctx, __func__);
2143 			_enter_critical_mutex(&pcmdpriv->sctx_mutex, NULL);
2144 			if (sctx.status == RTW_SCTX_SUBMITTED)
2145 				cmdobj->sctx = NULL;
2146 			_exit_critical_mutex(&pcmdpriv->sctx_mutex, NULL);
2147 			if (sctx.status != RTW_SCTX_DONE_SUCCESS)
2148 				res = _FAIL;
2149 		}
2150 
2151 		/* allow get channel plan when cmd_thread is not running */
2152 		if (res != _SUCCESS && (flags & RTW_CMDF_WAIT_ACK)) {
2153 			parm = rtw_zmalloc(sizeof(*parm));
2154 			if (parm == NULL)
2155 				goto exit;
2156 			parm->chplan = chplan;
2157 
2158 			if (H2C_SUCCESS == rtw_get_chplan_hdl(adapter, (u8 *)parm))
2159 				res = _SUCCESS;
2160 
2161 			rtw_mfree((u8 *)parm, sizeof(*parm));
2162 		}
2163 	}
2164 
2165 exit:
2166 	return res;
2167 }
2168 
2169 #ifdef CONFIG_80211D
rtw_apply_recv_country_ie_cmd(_adapter * adapter,int flags,BAND_TYPE band,u8 opch,const u8 * country_ie)2170 inline u8 rtw_apply_recv_country_ie_cmd(_adapter *adapter, int flags, BAND_TYPE band,u8 opch, const u8 *country_ie)
2171 {
2172 	struct country_chplan ent;
2173 	struct country_ie_slave_record cisr;
2174 
2175 	rtw_get_chplan_from_recv_country_ie(adapter, band, opch, country_ie, &ent, &cisr, NULL);
2176 
2177 	return _rtw_set_chplan_cmd(adapter, flags, RTW_CHPLAN_UNSPECIFIED, RTW_CHPLAN_6G_UNSPECIFIED
2178 		, NULL, REGD_SRC_RTK_PRIV, RTW_REGD_SET_BY_COUNTRY_IE, &cisr);
2179 }
2180 #endif /* CONFIG_80211D */
2181 
rtw_led_blink_cmd(_adapter * padapter,void * pLed)2182 u8 rtw_led_blink_cmd(_adapter *padapter, void *pLed)
2183 {
2184 	struct	cmd_obj	*pcmdobj;
2185 	struct	LedBlink_param *ledBlink_param;
2186 	struct	cmd_priv   *pcmdpriv = &padapter->cmdpriv;
2187 
2188 	u8	res = _SUCCESS;
2189 
2190 
2191 
2192 	pcmdobj = (struct	cmd_obj *)rtw_zmalloc(sizeof(struct	cmd_obj));
2193 	if (pcmdobj == NULL) {
2194 		res = _FAIL;
2195 		goto exit;
2196 	}
2197 
2198 	ledBlink_param = (struct	LedBlink_param *)rtw_zmalloc(sizeof(struct	LedBlink_param));
2199 	if (ledBlink_param == NULL) {
2200 		rtw_mfree((u8 *)pcmdobj, sizeof(struct cmd_obj));
2201 		res = _FAIL;
2202 		goto exit;
2203 	}
2204 
2205 	ledBlink_param->pLed = pLed;
2206 
2207 	init_h2fwcmd_w_parm_no_rsp(pcmdobj, ledBlink_param, CMD_LEDBLINK);
2208 	res = rtw_enqueue_cmd(pcmdpriv, pcmdobj);
2209 
2210 exit:
2211 
2212 
2213 	return res;
2214 }
2215 
rtw_set_csa_cmd(_adapter * adapter)2216 u8 rtw_set_csa_cmd(_adapter *adapter)
2217 {
2218 	struct cmd_obj *cmdobj;
2219 	struct cmd_priv *cmdpriv = &adapter->cmdpriv;
2220 	u8	res = _SUCCESS;
2221 
2222 	cmdobj = rtw_zmalloc(sizeof(struct cmd_obj));
2223 	if (cmdobj == NULL) {
2224 		res = _FAIL;
2225 		goto exit;
2226 	}
2227 
2228 	init_h2fwcmd_w_parm_no_parm_rsp(cmdobj, CMD_SET_CHANSWITCH);
2229 	res = rtw_enqueue_cmd(cmdpriv, cmdobj);
2230 
2231 exit:
2232 	return res;
2233 }
2234 
rtw_set_ap_csa_cmd(_adapter * adapter)2235 u8 rtw_set_ap_csa_cmd(_adapter *adapter)
2236 {
2237 	u8 res = _SUCCESS;
2238 #ifdef CONFIG_AP_MODE
2239 	struct cmd_obj *cmdobj;
2240 	struct cmd_priv *cmdpriv = &adapter->cmdpriv;
2241 
2242 	RTW_INFO("%s\n", __FUNCTION__);
2243 
2244 	cmdobj = rtw_zmalloc(sizeof(struct cmd_obj));
2245 	if (cmdobj == NULL) {
2246 		res = _FAIL;
2247 		goto exit;
2248 	}
2249 
2250 	init_h2fwcmd_w_parm_no_parm_rsp(cmdobj, CMD_AP_CHANSWITCH);
2251 	res = rtw_enqueue_cmd(cmdpriv, cmdobj);
2252 
2253 exit:
2254 #endif /* CONFIG_AP_MODE */
2255 	return res;
2256 }
2257 
rtw_tdls_cmd(_adapter * padapter,u8 * addr,u8 option)2258 u8 rtw_tdls_cmd(_adapter *padapter, u8 *addr, u8 option)
2259 {
2260 	u8 res = _SUCCESS;
2261 #ifdef CONFIG_TDLS
2262 	struct	cmd_obj	*pcmdobj;
2263 	struct	TDLSoption_param	*TDLSoption;
2264 	struct	mlme_priv *pmlmepriv = &padapter->mlmepriv;
2265 	struct	cmd_priv   *pcmdpriv = &padapter->cmdpriv;
2266 
2267 	pcmdobj = (struct	cmd_obj *)rtw_zmalloc(sizeof(struct	cmd_obj));
2268 	if (pcmdobj == NULL) {
2269 		res = _FAIL;
2270 		goto exit;
2271 	}
2272 
2273 	TDLSoption = (struct TDLSoption_param *)rtw_zmalloc(sizeof(struct TDLSoption_param));
2274 	if (TDLSoption == NULL) {
2275 		rtw_mfree((u8 *)pcmdobj, sizeof(struct cmd_obj));
2276 		res = _FAIL;
2277 		goto exit;
2278 	}
2279 
2280 	_rtw_spinlock(&(padapter->tdlsinfo.cmd_lock));
2281 	if (addr != NULL)
2282 		_rtw_memcpy(TDLSoption->addr, addr, 6);
2283 	TDLSoption->option = option;
2284 	_rtw_spinunlock(&(padapter->tdlsinfo.cmd_lock));
2285 	init_h2fwcmd_w_parm_no_rsp(pcmdobj, TDLSoption, CMD_TDLS);
2286 	res = rtw_enqueue_cmd(pcmdpriv, pcmdobj);
2287 
2288 exit:
2289 #endif /* CONFIG_TDLS */
2290 
2291 	return res;
2292 }
2293 
rtw_enable_hw_update_tsf_cmd(_adapter * padapter)2294 u8 rtw_enable_hw_update_tsf_cmd(_adapter *padapter)
2295 {
2296 	struct cmd_obj *ph2c;
2297 	struct drvextra_cmd_parm	*pdrvextra_cmd_parm;
2298 	struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
2299 	u8	res = _SUCCESS;
2300 
2301 
2302 	ph2c = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
2303 	if (ph2c == NULL) {
2304 		res = _FAIL;
2305 		goto exit;
2306 	}
2307 
2308 	pdrvextra_cmd_parm = (struct drvextra_cmd_parm *)rtw_zmalloc(sizeof(struct drvextra_cmd_parm));
2309 	if (pdrvextra_cmd_parm == NULL) {
2310 		rtw_mfree((unsigned char *)ph2c, sizeof(struct cmd_obj));
2311 		res = _FAIL;
2312 		goto exit;
2313 	}
2314 
2315 	pdrvextra_cmd_parm->ec_id = EN_HW_UPDATE_TSF_WK_CID;
2316 	pdrvextra_cmd_parm->type = 0;
2317 	pdrvextra_cmd_parm->size = 0;
2318 	pdrvextra_cmd_parm->pbuf = NULL;
2319 
2320 	init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, CMD_SET_DRV_EXTRA);
2321 
2322 	res = rtw_enqueue_cmd(pcmdpriv, ph2c);
2323 
2324 exit:
2325 	return res;
2326 }
2327 
rtw_periodic_tsf_update_end_cmd(_adapter * adapter)2328 u8 rtw_periodic_tsf_update_end_cmd(_adapter *adapter)
2329 {
2330 	struct cmd_obj *cmdobj;
2331 	struct drvextra_cmd_parm *parm;
2332 	struct cmd_priv *cmdpriv = &adapter->cmdpriv;
2333 	u8 res = _SUCCESS;
2334 
2335 	cmdobj = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
2336 	if (cmdobj == NULL) {
2337 		res = _FAIL;
2338 		goto exit;
2339 	}
2340 
2341 	parm = (struct drvextra_cmd_parm *)rtw_zmalloc(sizeof(struct drvextra_cmd_parm));
2342 	if (parm == NULL) {
2343 		rtw_mfree((unsigned char *)cmdobj, sizeof(struct cmd_obj));
2344 		res = _FAIL;
2345 		goto exit;
2346 	}
2347 
2348 	parm->ec_id = PERIOD_TSF_UPDATE_END_WK_CID;
2349 	parm->type = 0;
2350 	parm->size = 0;
2351 	parm->pbuf = NULL;
2352 
2353 	init_h2fwcmd_w_parm_no_rsp(cmdobj, parm, CMD_SET_DRV_EXTRA);
2354 
2355 	res = rtw_enqueue_cmd(cmdpriv, cmdobj);
2356 
2357 exit:
2358 	return res;
2359 }
rtw_ssmps_wk_hdl(_adapter * adapter,struct ssmps_cmd_parm * ssmp_param)2360 u8 rtw_ssmps_wk_hdl(_adapter *adapter, struct ssmps_cmd_parm *ssmp_param)
2361 {
2362 	u8 res = _SUCCESS;
2363 	struct sta_info *sta = ssmp_param->sta;
2364 	u8 smps = ssmp_param->smps;
2365 
2366 	if (sta == NULL)
2367 		return _FALSE;
2368 
2369 	if (smps)
2370 		rtw_ssmps_enter(adapter, sta);
2371 	else
2372 		rtw_ssmps_leave(adapter, sta);
2373 	return res;
2374 }
2375 
rtw_ssmps_wk_cmd(_adapter * adapter,struct sta_info * sta,u8 smps,u8 enqueue)2376 u8 rtw_ssmps_wk_cmd(_adapter *adapter, struct sta_info *sta, u8 smps, u8 enqueue)
2377 {
2378 	struct cmd_obj *cmdobj;
2379 	struct drvextra_cmd_parm *cmd_parm;
2380 	struct ssmps_cmd_parm *ssmp_param;
2381 	struct cmd_priv	*pcmdpriv = &adapter->cmdpriv;
2382 	u8	res = _SUCCESS;
2383 
2384 	if (enqueue) {
2385 		cmdobj = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
2386 		if (cmdobj == NULL) {
2387 			res = _FAIL;
2388 			goto exit;
2389 		}
2390 
2391 		cmd_parm = (struct drvextra_cmd_parm *)rtw_zmalloc(sizeof(struct drvextra_cmd_parm));
2392 		if (cmd_parm == NULL) {
2393 			rtw_mfree((unsigned char *)cmdobj, sizeof(struct cmd_obj));
2394 			res = _FAIL;
2395 			goto exit;
2396 		}
2397 
2398 		ssmp_param = (struct ssmps_cmd_parm *)rtw_zmalloc(sizeof(struct ssmps_cmd_parm));
2399 		if (ssmp_param == NULL) {
2400 			rtw_mfree((u8 *)cmdobj, sizeof(struct cmd_obj));
2401 			rtw_mfree((u8 *)cmd_parm, sizeof(struct drvextra_cmd_parm));
2402 			res = _FAIL;
2403 			goto exit;
2404 		}
2405 
2406 		ssmp_param->smps = smps;
2407 		ssmp_param->sta = sta;
2408 
2409 		cmd_parm->ec_id = SSMPS_WK_CID;
2410 		cmd_parm->type = 0;
2411 		cmd_parm->size = sizeof(struct ssmps_cmd_parm);
2412 		cmd_parm->pbuf = (u8 *)ssmp_param;
2413 
2414 		init_h2fwcmd_w_parm_no_rsp(cmdobj, cmd_parm, CMD_SET_DRV_EXTRA);
2415 
2416 		res = rtw_enqueue_cmd(pcmdpriv, cmdobj);
2417 	} else {
2418 		struct ssmps_cmd_parm tmp_ssmp_param;
2419 
2420 		tmp_ssmp_param.smps = smps;
2421 		tmp_ssmp_param.sta = sta;
2422 		rtw_ssmps_wk_hdl(adapter, &tmp_ssmp_param);
2423 	}
2424 
2425 exit:
2426 	return res;
2427 }
2428 
2429 #ifdef CONFIG_SUPPORT_STATIC_SMPS
_ssmps_chk_by_tp(_adapter * adapter,u8 from_timer)2430 u8 _ssmps_chk_by_tp(_adapter *adapter, u8 from_timer)
2431 {
2432 	u8 enter_smps = _FALSE;
2433 	struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
2434 	struct mlme_ext_priv *pmlmeext = &(adapter->mlmeextpriv);
2435 	struct sta_priv *pstapriv = &adapter->stapriv;
2436 	struct sta_info *psta;
2437 	u32 tx_tp_mbits, rx_tp_mbits;
2438 
2439 	if (!MLME_IS_STA(adapter) ||
2440 		!hal_is_mimo_support(adapter) ||
2441 		!pmlmeext->ssmps_en ||
2442 		(pmlmeext->cur_channel > 14)
2443 	)
2444 		return enter_smps;
2445 
2446 	psta = rtw_get_stainfo(pstapriv, get_bssid(pmlmepriv));
2447 	if (psta == NULL) {
2448 		RTW_ERR(ADPT_FMT" sta == NULL\n", ADPT_ARG(adapter));
2449 		rtw_warn_on(1);
2450 		return enter_smps;
2451 	}
2452 
2453 	if (psta->cmn.mimo_type == RF_1T1R)
2454 		return enter_smps;
2455 
2456 	tx_tp_mbits = psta->sta_stats.tx_tp_kbits >> 10;
2457 	rx_tp_mbits = psta->sta_stats.rx_tp_kbits >> 10;
2458 
2459 	#ifdef DBG_STATIC_SMPS
2460 	if (pmlmeext->ssmps_test) {
2461 		enter_smps = (pmlmeext->ssmps_test_en == 1) ? _TRUE : _FALSE;
2462 	}
2463 	else
2464 	#endif
2465 	{
2466 		if ((tx_tp_mbits <= pmlmeext->ssmps_tx_tp_th) &&
2467 			(rx_tp_mbits <= pmlmeext->ssmps_rx_tp_th))
2468 			enter_smps = _TRUE;
2469 		else
2470 			enter_smps = _FALSE;
2471 	}
2472 
2473 	if (1) {
2474 		RTW_INFO(FUNC_ADPT_FMT" tx_tp:%d [%d], rx_tp:%d [%d] , SSMPS enter :%s\n",
2475 			FUNC_ADPT_ARG(adapter),
2476 			tx_tp_mbits, pmlmeext->ssmps_tx_tp_th,
2477 			rx_tp_mbits, pmlmeext->ssmps_rx_tp_th,
2478 			(enter_smps == _TRUE) ? "True" : "False");
2479 		#ifdef DBG_STATIC_SMPS
2480 		RTW_INFO(FUNC_ADPT_FMT" test:%d test_en:%d\n",
2481 			FUNC_ADPT_ARG(adapter),
2482 			pmlmeext->ssmps_test,
2483 			pmlmeext->ssmps_test_en);
2484 		#endif
2485 	}
2486 
2487 	if (enter_smps) {
2488 		if (!from_timer && psta->cmn.sm_ps != SM_PS_STATIC)
2489 			rtw_ssmps_enter(adapter, psta);
2490 	} else {
2491 		if (!from_timer && psta->cmn.sm_ps != SM_PS_DISABLE)
2492 			rtw_ssmps_leave(adapter, psta);
2493 		else {
2494 			u8 ps_change = _FALSE;
2495 
2496 			if (enter_smps && psta->cmn.sm_ps != SM_PS_STATIC)
2497 				ps_change = _TRUE;
2498 			else if (!enter_smps && psta->cmn.sm_ps != SM_PS_DISABLE)
2499 				ps_change = _TRUE;
2500 
2501 			if (ps_change)
2502 				rtw_ssmps_wk_cmd(adapter, psta, enter_smps, 1);
2503 		}
2504 	}
2505 
2506 	return enter_smps;
2507 }
2508 #endif /*CONFIG_SUPPORT_STATIC_SMPS*/
2509 
2510 #ifdef CONFIG_CTRL_TXSS_BY_TP
rtw_ctrl_txss_update_mimo_type(_adapter * adapter,struct sta_info * sta)2511 void rtw_ctrl_txss_update_mimo_type(_adapter *adapter, struct sta_info *sta)
2512 {
2513 	struct mlme_ext_priv *pmlmeext = &(adapter->mlmeextpriv);
2514 
2515 	pmlmeext->txss_momi_type_bk = sta->cmn.mimo_type;
2516 }
2517 
rtw_ctrl_txss(_adapter * adapter,struct sta_info * sta,bool tx_1ss)2518 u8 rtw_ctrl_txss(_adapter *adapter, struct sta_info *sta, bool tx_1ss)
2519 {
2520 	struct mlme_ext_priv *pmlmeext = &(adapter->mlmeextpriv);
2521 	struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(adapter);
2522 	u8 lps_changed = _FALSE;
2523 	u8 rst = _SUCCESS;
2524 
2525 	if (pmlmeext->txss_1ss == tx_1ss)
2526 		return _FALSE;
2527 
2528 	if (pwrpriv->bLeisurePs && pwrpriv->pwr_mode != PS_MODE_ACTIVE) {
2529 		lps_changed = _TRUE;
2530 		LPS_Leave(adapter, "LPS_CTRL_TXSS");
2531 	}
2532 
2533 	RTW_INFO(ADPT_FMT" STA [" MAC_FMT "] set tx to %d ss\n",
2534 		ADPT_ARG(adapter), MAC_ARG(sta->cmn.mac_addr),
2535 		(tx_1ss) ? 1 : rtw_get_sta_tx_nss(adapter, sta));
2536 
2537 	/*ra re-registed*/
2538 	sta->cmn.mimo_type = (tx_1ss) ? RF_1T1R : pmlmeext->txss_momi_type_bk;
2539 	rtw_phydm_ra_registed(adapter, sta);
2540 
2541 	/*configure trx mode*/
2542 	rtw_phydm_trx_cfg(adapter, tx_1ss);
2543 	pmlmeext->txss_1ss = tx_1ss;
2544 
2545 	if (lps_changed)
2546 		LPS_Enter(adapter, "LPS_CTRL_TXSS");
2547 
2548 	return rst;
2549 }
2550 
rtw_ctrl_txss_wk_hdl(_adapter * adapter,struct txss_cmd_parm * txss_param)2551 u8 rtw_ctrl_txss_wk_hdl(_adapter *adapter, struct txss_cmd_parm *txss_param)
2552 {
2553 	if (!txss_param->sta)
2554 		return _FALSE;
2555 
2556 	return rtw_ctrl_txss(adapter, txss_param->sta, txss_param->tx_1ss);
2557 }
2558 
rtw_ctrl_txss_wk_cmd(_adapter * adapter,struct sta_info * sta,bool tx_1ss,u8 flag)2559 u8 rtw_ctrl_txss_wk_cmd(_adapter *adapter, struct sta_info *sta, bool tx_1ss, u8 flag)
2560 {
2561 	struct cmd_obj *cmdobj;
2562 	struct drvextra_cmd_parm *cmd_parm;
2563 	struct txss_cmd_parm *txss_param;
2564 	struct cmd_priv *pcmdpriv = &adapter->cmdpriv;
2565 	struct submit_ctx sctx;
2566 	u8	res = _SUCCESS;
2567 
2568 	txss_param = (struct txss_cmd_parm *)rtw_zmalloc(sizeof(struct txss_cmd_parm));
2569 	if (txss_param == NULL) {
2570 		res = _FAIL;
2571 		goto exit;
2572 	}
2573 
2574 	txss_param->tx_1ss = tx_1ss;
2575 	txss_param->sta = sta;
2576 
2577 	if (flag & RTW_CMDF_DIRECTLY) {
2578 		res = rtw_ctrl_txss_wk_hdl(adapter, txss_param);
2579 		rtw_mfree((u8 *)txss_param, sizeof(*txss_param));
2580 	} else {
2581 		cmdobj = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
2582 		if (cmdobj == NULL) {
2583 			res = _FAIL;
2584 			goto exit;
2585 		}
2586 
2587 		cmd_parm = (struct drvextra_cmd_parm *)rtw_zmalloc(sizeof(struct drvextra_cmd_parm));
2588 		if (cmd_parm == NULL) {
2589 			rtw_mfree((u8 *)cmdobj, sizeof(struct cmd_obj));
2590 			res = _FAIL;
2591 			goto exit;
2592 		}
2593 
2594 		cmd_parm->ec_id = TXSS_WK_CID;
2595 		cmd_parm->type = 0;
2596 		cmd_parm->size = sizeof(struct txss_cmd_parm);
2597 		cmd_parm->pbuf = (u8 *)txss_param;
2598 
2599 		init_h2fwcmd_w_parm_no_rsp(cmdobj, cmd_parm, CMD_SET_DRV_EXTRA);
2600 
2601 		if (flag & RTW_CMDF_WAIT_ACK) {
2602 			cmdobj->sctx = &sctx;
2603 			rtw_sctx_init(&sctx, 10 * 1000);
2604 		}
2605 
2606 		res = rtw_enqueue_cmd(pcmdpriv, cmdobj);
2607 		if (res == _SUCCESS && (flag & RTW_CMDF_WAIT_ACK)) {
2608 			rtw_sctx_wait(&sctx, __func__);
2609 			_enter_critical_mutex(&pcmdpriv->sctx_mutex, NULL);
2610 			if (sctx.status == RTW_SCTX_SUBMITTED)
2611 				cmdobj->sctx = NULL;
2612 			_exit_critical_mutex(&pcmdpriv->sctx_mutex, NULL);
2613 			if (sctx.status != RTW_SCTX_DONE_SUCCESS)
2614 				res = _FAIL;
2615 		}
2616 	}
2617 
2618 exit:
2619 	return res;
2620 }
2621 
rtw_ctrl_tx_ss_by_tp(_adapter * adapter,u8 from_timer)2622 void rtw_ctrl_tx_ss_by_tp(_adapter *adapter, u8 from_timer)
2623 {
2624 	bool tx_1ss  = _FALSE; /*change tx from 2ss to 1ss*/
2625 	struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
2626 	struct mlme_ext_priv *pmlmeext = &(adapter->mlmeextpriv);
2627 	struct sta_priv *pstapriv = &adapter->stapriv;
2628 	struct sta_info *psta;
2629 	u32 tx_tp_mbits;
2630 
2631 	if (!MLME_IS_STA(adapter) ||
2632 		!hal_is_mimo_support(adapter) ||
2633 		!pmlmeext->txss_ctrl_en
2634 	)
2635 		return;
2636 
2637 	psta = rtw_get_stainfo(pstapriv, get_bssid(pmlmepriv));
2638 	if (psta == NULL) {
2639 		RTW_ERR(ADPT_FMT" sta == NULL\n", ADPT_ARG(adapter));
2640 		rtw_warn_on(1);
2641 		return;
2642 	}
2643 
2644 	tx_tp_mbits = psta->sta_stats.tx_tp_kbits >> 10;
2645 	if (tx_tp_mbits >= pmlmeext->txss_tp_th) {
2646 		tx_1ss = _FALSE;
2647 	} else {
2648 		if (pmlmeext->txss_tp_chk_cnt && --pmlmeext->txss_tp_chk_cnt)
2649 			tx_1ss = _FALSE;
2650 		else
2651 			tx_1ss = _TRUE;
2652 	}
2653 
2654 	if (1) {
2655 		RTW_INFO(FUNC_ADPT_FMT" tx_tp:%d [%d] tx_1ss(%d):%s\n",
2656 			FUNC_ADPT_ARG(adapter),
2657 			tx_tp_mbits, pmlmeext->txss_tp_th,
2658 			pmlmeext->txss_tp_chk_cnt,
2659 			(tx_1ss == _TRUE) ? "True" : "False");
2660 	}
2661 
2662 	if (pmlmeext->txss_1ss != tx_1ss) {
2663 		if (from_timer)
2664 			rtw_ctrl_txss_wk_cmd(adapter, psta, tx_1ss, 0);
2665 		else
2666 			rtw_ctrl_txss(adapter, psta, tx_1ss);
2667 	}
2668 }
2669 #ifdef DBG_CTRL_TXSS
dbg_ctrl_txss(_adapter * adapter,bool tx_1ss)2670 void dbg_ctrl_txss(_adapter *adapter, bool tx_1ss)
2671 {
2672 	struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
2673 	struct mlme_ext_priv *pmlmeext = &(adapter->mlmeextpriv);
2674 	struct sta_priv *pstapriv = &adapter->stapriv;
2675 	struct sta_info *psta;
2676 
2677 	if (!MLME_IS_STA(adapter) ||
2678 		!hal_is_mimo_support(adapter)
2679 	)
2680 		return;
2681 
2682 	psta = rtw_get_stainfo(pstapriv, get_bssid(pmlmepriv));
2683 	if (psta == NULL) {
2684 		RTW_ERR(ADPT_FMT" sta == NULL\n", ADPT_ARG(adapter));
2685 		rtw_warn_on(1);
2686 		return;
2687 	}
2688 
2689 	rtw_ctrl_txss(adapter, psta, tx_1ss);
2690 }
2691 #endif
2692 #endif /*CONFIG_CTRL_TXSS_BY_TP*/
2693 
2694 #ifdef CONFIG_LPS
2695 #ifdef CONFIG_LPS_CHK_BY_TP
2696 #ifdef LPS_BCN_CNT_MONITOR
_bcn_cnt_expected(struct sta_info * psta)2697 static u8 _bcn_cnt_expected(struct sta_info *psta)
2698 {
2699 	_adapter *adapter = psta->padapter;
2700 	struct mlme_ext_priv *pmlmeext = &adapter->mlmeextpriv;
2701 	struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
2702 	u8 dtim = rtw_get_bcn_dtim_period(adapter);
2703 	u8 bcn_cnt = 0;
2704 
2705 	if ((pmlmeinfo->bcn_interval !=0) && (dtim != 0))
2706 		bcn_cnt = 2000 / pmlmeinfo->bcn_interval / dtim * 4 / 5; /*2s*/
2707 	if (0)
2708 		RTW_INFO("%s bcn_cnt:%d\n", __func__, bcn_cnt);
2709 
2710 	if (bcn_cnt == 0) {
2711 		RTW_ERR(FUNC_ADPT_FMT" bcn_cnt == 0\n", FUNC_ADPT_ARG(adapter));
2712 		rtw_warn_on(1);
2713 	}
2714 
2715 	return bcn_cnt;
2716 }
2717 #endif
_lps_chk_by_tp(_adapter * adapter,u8 from_timer)2718 u8 _lps_chk_by_tp(_adapter *adapter, u8 from_timer)
2719 {
2720 	u8 enter_ps = _FALSE;
2721 	struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
2722 	struct sta_priv *pstapriv = &adapter->stapriv;
2723 	struct sta_info *psta;
2724 	struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(adapter);
2725 	u32 tx_tp_mbits, rx_tp_mbits, bi_tp_mbits;
2726 	u8 rx_bcn_cnt;
2727 
2728 	psta = rtw_get_stainfo(pstapriv, get_bssid(pmlmepriv));
2729 	if (psta == NULL) {
2730 		RTW_ERR(ADPT_FMT" sta == NULL\n", ADPT_ARG(adapter));
2731 		rtw_warn_on(1);
2732 		return enter_ps;
2733 	}
2734 
2735 	rx_bcn_cnt = rtw_get_bcn_cnt(psta->padapter);
2736 	psta->sta_stats.acc_tx_bytes = psta->sta_stats.tx_bytes;
2737 	psta->sta_stats.acc_rx_bytes = psta->sta_stats.rx_bytes;
2738 
2739 #if 1
2740 	tx_tp_mbits = psta->sta_stats.tx_tp_kbits >> 10;
2741 	rx_tp_mbits = psta->sta_stats.rx_tp_kbits >> 10;
2742 	bi_tp_mbits = tx_tp_mbits + rx_tp_mbits;
2743 #else
2744 	tx_tp_mbits = psta->sta_stats.smooth_tx_tp_kbits >> 10;
2745 	rx_tp_mbits = psta->sta_stats.smooth_rx_tp_kbits >> 10;
2746 	bi_tp_mbits = tx_tp_mbits + rx_tp_mbits;
2747 #endif
2748 
2749 	if ((bi_tp_mbits >= pwrpriv->lps_bi_tp_th) ||
2750 		(tx_tp_mbits >= pwrpriv->lps_tx_tp_th) ||
2751 		(rx_tp_mbits >= pwrpriv->lps_rx_tp_th)) {
2752 		enter_ps = _FALSE;
2753 		pwrpriv->lps_chk_cnt = pwrpriv->lps_chk_cnt_th;
2754 	}
2755 	else {
2756 #ifdef LPS_BCN_CNT_MONITOR
2757 		u8 bcn_cnt = _bcn_cnt_expected(psta);
2758 
2759 		if (bcn_cnt && (rx_bcn_cnt < bcn_cnt)) {
2760 			pwrpriv->lps_chk_cnt = 2;
2761 			RTW_ERR(FUNC_ADPT_FMT" BCN_CNT:%d(%d) invalid\n",
2762 				FUNC_ADPT_ARG(adapter), rx_bcn_cnt, bcn_cnt);
2763 		}
2764 #endif
2765 
2766 		if (pwrpriv->lps_chk_cnt && --pwrpriv->lps_chk_cnt)
2767 			enter_ps = _FALSE;
2768 		else
2769 			enter_ps = _TRUE;
2770 	}
2771 
2772 	if (1) {
2773 		RTW_INFO(FUNC_ADPT_FMT" tx_tp:%d [%d], rx_tp:%d [%d], bi_tp:%d [%d], enter_ps(%d):%s\n",
2774 			FUNC_ADPT_ARG(adapter),
2775 			tx_tp_mbits, pwrpriv->lps_tx_tp_th,
2776 			rx_tp_mbits, pwrpriv->lps_rx_tp_th,
2777 			bi_tp_mbits, pwrpriv->lps_bi_tp_th,
2778 			pwrpriv->lps_chk_cnt,
2779 			(enter_ps == _TRUE) ? "True" : "False");
2780 		RTW_INFO(FUNC_ADPT_FMT" tx_pkt_cnt :%d [%d], rx_pkt_cnt :%d [%d]\n",
2781 			FUNC_ADPT_ARG(adapter),
2782 			pmlmepriv->LinkDetectInfo.NumTxOkInPeriod,
2783 			pwrpriv->lps_tx_pkts,
2784 			pmlmepriv->LinkDetectInfo.NumRxUnicastOkInPeriod,
2785 			pwrpriv->lps_rx_pkts);
2786 		if (!adapter->bsta_tp_dump)
2787 			RTW_INFO(FUNC_ADPT_FMT" bcn_cnt:%d (per-%d second)\n",
2788 			FUNC_ADPT_ARG(adapter),
2789 			rx_bcn_cnt,
2790 			2);
2791 	}
2792 
2793 	if (enter_ps) {
2794 		if (!from_timer)
2795 			LPS_Enter(adapter, "TRAFFIC_IDLE");
2796 	} else {
2797 		if (!from_timer)
2798 			LPS_Leave(adapter, "TRAFFIC_BUSY");
2799 		else {
2800 			#ifdef CONFIG_CONCURRENT_MODE
2801 			#ifndef CONFIG_FW_MULTI_PORT_SUPPORT
2802 			if (adapter->hw_port == HW_PORT0)
2803 			#endif
2804 			#endif
2805 				rtw_lps_ctrl_wk_cmd(adapter, LPS_CTRL_TRAFFIC_BUSY, 0);
2806 		}
2807 	}
2808 
2809 	return enter_ps;
2810 }
2811 #endif
2812 
_lps_chk_by_pkt_cnts(_adapter * padapter,u8 from_timer,u8 bBusyTraffic)2813 static u8 _lps_chk_by_pkt_cnts(_adapter *padapter, u8 from_timer, u8 bBusyTraffic)
2814 {
2815 	struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
2816 	u8	bEnterPS = _FALSE;
2817 
2818 	/* check traffic for  powersaving. */
2819 	if (((pmlmepriv->LinkDetectInfo.NumRxUnicastOkInPeriod + pmlmepriv->LinkDetectInfo.NumTxOkInPeriod) > 8) ||
2820 		#ifdef CONFIG_LPS_SLOW_TRANSITION
2821 		(pmlmepriv->LinkDetectInfo.NumRxUnicastOkInPeriod > 2)
2822 		#else /* CONFIG_LPS_SLOW_TRANSITION */
2823 		(pmlmepriv->LinkDetectInfo.NumRxUnicastOkInPeriod > 4)
2824 		#endif /* CONFIG_LPS_SLOW_TRANSITION */
2825 	) {
2826 		#ifdef DBG_RX_COUNTER_DUMP
2827 		if (padapter->dump_rx_cnt_mode & DUMP_DRV_TRX_COUNTER_DATA)
2828 			RTW_INFO("(-)Tx = %d, Rx = %d\n", pmlmepriv->LinkDetectInfo.NumTxOkInPeriod, pmlmepriv->LinkDetectInfo.NumRxUnicastOkInPeriod);
2829 		#endif
2830 
2831 		bEnterPS = _FALSE;
2832 		#ifdef CONFIG_LPS_SLOW_TRANSITION
2833 		if (bBusyTraffic == _TRUE) {
2834 			if (pmlmepriv->LinkDetectInfo.TrafficTransitionCount <= 4)
2835 				pmlmepriv->LinkDetectInfo.TrafficTransitionCount = 4;
2836 
2837 			pmlmepriv->LinkDetectInfo.TrafficTransitionCount++;
2838 
2839 			/* RTW_INFO("Set TrafficTransitionCount to %d\n", pmlmepriv->LinkDetectInfo.TrafficTransitionCount); */
2840 
2841 			if (pmlmepriv->LinkDetectInfo.TrafficTransitionCount > 30/*TrafficTransitionLevel*/)
2842 				pmlmepriv->LinkDetectInfo.TrafficTransitionCount = 30;
2843 		}
2844 		#endif /* CONFIG_LPS_SLOW_TRANSITION */
2845 	} else {
2846 		#ifdef DBG_RX_COUNTER_DUMP
2847 		if (padapter->dump_rx_cnt_mode & DUMP_DRV_TRX_COUNTER_DATA)
2848 			RTW_INFO("(+)Tx = %d, Rx = %d\n", pmlmepriv->LinkDetectInfo.NumTxOkInPeriod, pmlmepriv->LinkDetectInfo.NumRxUnicastOkInPeriod);
2849 		#endif
2850 
2851 		#ifdef CONFIG_LPS_SLOW_TRANSITION
2852 		if (pmlmepriv->LinkDetectInfo.TrafficTransitionCount >= 2)
2853 			pmlmepriv->LinkDetectInfo.TrafficTransitionCount -= 2;
2854 		else
2855 			pmlmepriv->LinkDetectInfo.TrafficTransitionCount = 0;
2856 
2857 		if (pmlmepriv->LinkDetectInfo.TrafficTransitionCount == 0)
2858 			bEnterPS = _TRUE;
2859 		#else /* CONFIG_LPS_SLOW_TRANSITION */
2860 			bEnterPS = _TRUE;
2861 		#endif /* CONFIG_LPS_SLOW_TRANSITION */
2862 	}
2863 
2864 	#ifdef CONFIG_DYNAMIC_DTIM
2865 	if (pmlmepriv->LinkDetectInfo.LowPowerTransitionCount == 8)
2866 		bEnterPS = _FALSE;
2867 
2868 	RTW_INFO("LowPowerTransitionCount=%d\n", pmlmepriv->LinkDetectInfo.LowPowerTransitionCount);
2869 	#endif /* CONFIG_DYNAMIC_DTIM */
2870 
2871 	/* LeisurePS only work in infra mode. */
2872 	if (bEnterPS) {
2873 		if (!from_timer) {
2874 			#ifdef CONFIG_DYNAMIC_DTIM
2875 			if (pmlmepriv->LinkDetectInfo.LowPowerTransitionCount < 8)
2876 				adapter_to_pwrctl(padapter)->dtim = 1;
2877 			else
2878 				adapter_to_pwrctl(padapter)->dtim = 3;
2879 			#endif /* CONFIG_DYNAMIC_DTIM */
2880 			LPS_Enter(padapter, "TRAFFIC_IDLE");
2881 		} else {
2882 			/* do this at caller */
2883 			/* rtw_lps_ctrl_wk_cmd(adapter, LPS_CTRL_ENTER, 0); */
2884 			/* rtw_hal_dm_watchdog_in_lps(padapter); */
2885 		}
2886 
2887 		#ifdef CONFIG_DYNAMIC_DTIM
2888 		if (adapter_to_pwrctl(padapter)->bFwCurrentInPSMode == _TRUE)
2889 			pmlmepriv->LinkDetectInfo.LowPowerTransitionCount++;
2890 		#endif /* CONFIG_DYNAMIC_DTIM */
2891 	} else {
2892 		#ifdef CONFIG_DYNAMIC_DTIM
2893 		if (pmlmepriv->LinkDetectInfo.LowPowerTransitionCount != 8)
2894 			pmlmepriv->LinkDetectInfo.LowPowerTransitionCount = 0;
2895 		else
2896 			pmlmepriv->LinkDetectInfo.LowPowerTransitionCount++;
2897 		#endif /* CONFIG_DYNAMIC_DTIM */
2898 
2899 		if (!from_timer)
2900 			LPS_Leave(padapter, "TRAFFIC_BUSY");
2901 		else {
2902 			#ifdef CONFIG_CONCURRENT_MODE
2903 			#ifndef CONFIG_FW_MULTI_PORT_SUPPORT
2904 			if (padapter->hw_port == HW_PORT0)
2905 			#endif
2906 			#endif
2907 				rtw_lps_ctrl_wk_cmd(padapter, LPS_CTRL_TRAFFIC_BUSY, 0);
2908 		}
2909 	}
2910 
2911 	return bEnterPS;
2912 }
2913 #endif /* CONFIG_LPS */
2914 
2915 /* from_timer == 1 means driver is in LPS */
traffic_status_watchdog(_adapter * padapter,u8 from_timer)2916 u8 traffic_status_watchdog(_adapter *padapter, u8 from_timer)
2917 {
2918 	u8	bEnterPS = _FALSE;
2919 	u16 BusyThresholdHigh;
2920 	u16	BusyThresholdLow;
2921 	u16	BusyThreshold;
2922 	u8	bBusyTraffic = _FALSE, bTxBusyTraffic = _FALSE, bRxBusyTraffic = _FALSE;
2923 	u8	bHigherBusyTraffic = _FALSE, bHigherBusyRxTraffic = _FALSE, bHigherBusyTxTraffic = _FALSE;
2924 
2925 	struct mlme_priv		*pmlmepriv = &(padapter->mlmepriv);
2926 #ifdef CONFIG_TDLS
2927 	struct tdls_info *ptdlsinfo = &(padapter->tdlsinfo);
2928 	struct tdls_txmgmt txmgmt;
2929 	u8 baddr[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
2930 #endif /* CONFIG_TDLS */
2931 #ifdef CONFIG_TRAFFIC_PROTECT
2932 	RT_LINK_DETECT_T *link_detect = &pmlmepriv->LinkDetectInfo;
2933 #endif
2934 
2935 #ifdef CONFIG_BT_COEXIST
2936 	if (padapter->registrypriv.wifi_spec != 1) {
2937 		BusyThresholdHigh = 25;
2938 		BusyThresholdLow = 10;
2939 	} else
2940 #endif /* CONFIG_BT_COEXIST */
2941 	{
2942 		BusyThresholdHigh = 100;
2943 		BusyThresholdLow = 75;
2944 	}
2945 	BusyThreshold = BusyThresholdHigh;
2946 
2947 
2948 	/*  */
2949 	/* Determine if our traffic is busy now */
2950 	/*  */
2951 	if ((check_fwstate(pmlmepriv, WIFI_ASOC_STATE) == _TRUE)
2952 	    /*&& !MgntInitAdapterInProgress(pMgntInfo)*/) {
2953 		/* if we raise bBusyTraffic in last watchdog, using lower threshold. */
2954 		if (pmlmepriv->LinkDetectInfo.bBusyTraffic)
2955 			BusyThreshold = BusyThresholdLow;
2956 
2957 		if (pmlmepriv->LinkDetectInfo.NumRxOkInPeriod > BusyThreshold ||
2958 		    pmlmepriv->LinkDetectInfo.NumTxOkInPeriod > BusyThreshold) {
2959 			bBusyTraffic = _TRUE;
2960 
2961 			if (pmlmepriv->LinkDetectInfo.NumRxOkInPeriod > pmlmepriv->LinkDetectInfo.NumTxOkInPeriod)
2962 				bRxBusyTraffic = _TRUE;
2963 			else
2964 				bTxBusyTraffic = _TRUE;
2965 		}
2966 
2967 		/* Higher Tx/Rx data. */
2968 		if (pmlmepriv->LinkDetectInfo.NumRxOkInPeriod > 4000 ||
2969 		    pmlmepriv->LinkDetectInfo.NumTxOkInPeriod > 4000) {
2970 			bHigherBusyTraffic = _TRUE;
2971 
2972 			if (pmlmepriv->LinkDetectInfo.NumRxOkInPeriod > pmlmepriv->LinkDetectInfo.NumTxOkInPeriod)
2973 				bHigherBusyRxTraffic = _TRUE;
2974 			else
2975 				bHigherBusyTxTraffic = _TRUE;
2976 		}
2977 
2978 #ifdef CONFIG_TRAFFIC_PROTECT
2979 #define TX_ACTIVE_TH 10
2980 #define RX_ACTIVE_TH 20
2981 #define TRAFFIC_PROTECT_PERIOD_MS 4500
2982 
2983 		if (link_detect->NumTxOkInPeriod > TX_ACTIVE_TH
2984 		    || link_detect->NumRxUnicastOkInPeriod > RX_ACTIVE_TH) {
2985 
2986 			RTW_INFO(FUNC_ADPT_FMT" acqiure wake_lock for %u ms(tx:%d,rx_unicast:%d)\n",
2987 				 FUNC_ADPT_ARG(padapter),
2988 				 TRAFFIC_PROTECT_PERIOD_MS,
2989 				 link_detect->NumTxOkInPeriod,
2990 				 link_detect->NumRxUnicastOkInPeriod);
2991 
2992 			rtw_lock_traffic_suspend_timeout(TRAFFIC_PROTECT_PERIOD_MS);
2993 		}
2994 #endif
2995 
2996 #ifdef CONFIG_TDLS
2997 #ifdef CONFIG_TDLS_AUTOSETUP
2998 		/* TDLS_WATCHDOG_PERIOD * 2sec, periodically send */
2999 		if (hal_chk_wl_func(padapter, WL_FUNC_TDLS) == _TRUE) {
3000 			if ((ptdlsinfo->watchdog_count % TDLS_WATCHDOG_PERIOD) == 0) {
3001 				_rtw_memcpy(txmgmt.peer, baddr, ETH_ALEN);
3002 				issue_tdls_dis_req(padapter, &txmgmt);
3003 			}
3004 			ptdlsinfo->watchdog_count++;
3005 		}
3006 #endif /* CONFIG_TDLS_AUTOSETUP */
3007 #endif /* CONFIG_TDLS */
3008 
3009 #ifdef CONFIG_SUPPORT_STATIC_SMPS
3010 		_ssmps_chk_by_tp(padapter, from_timer);
3011 #endif
3012 #ifdef CONFIG_CTRL_TXSS_BY_TP
3013 		rtw_ctrl_tx_ss_by_tp(padapter, from_timer);
3014 #endif
3015 
3016 #ifdef CONFIG_LPS
3017 		if (adapter_to_pwrctl(padapter)->bLeisurePs && MLME_IS_STA(padapter)) {
3018 			#ifdef CONFIG_LPS_CHK_BY_TP
3019 			if (adapter_to_pwrctl(padapter)->lps_chk_by_tp)
3020 				bEnterPS = _lps_chk_by_tp(padapter, from_timer);
3021 			else
3022 			#endif /*CONFIG_LPS_CHK_BY_TP*/
3023 				bEnterPS = _lps_chk_by_pkt_cnts(padapter, from_timer, bBusyTraffic);
3024 		}
3025 #endif /* CONFIG_LPS */
3026 
3027 	} else {
3028 #ifdef CONFIG_LPS
3029 		if (!from_timer && rtw_mi_get_assoc_if_num(padapter) == 0)
3030 			LPS_Leave(padapter, "NON_LINKED");
3031 #endif
3032 	}
3033 
3034 	session_tracker_chk_cmd(padapter, NULL);
3035 
3036 #ifdef CONFIG_BEAMFORMING
3037 #ifdef RTW_BEAMFORMING_VERSION_2
3038 	rtw_bf_update_traffic(padapter);
3039 #endif /* RTW_BEAMFORMING_VERSION_2 */
3040 #endif /* CONFIG_BEAMFORMING */
3041 
3042 	pmlmepriv->LinkDetectInfo.NumRxOkInPeriod = 0;
3043 	pmlmepriv->LinkDetectInfo.NumTxOkInPeriod = 0;
3044 	pmlmepriv->LinkDetectInfo.NumRxUnicastOkInPeriod = 0;
3045 	pmlmepriv->LinkDetectInfo.bBusyTraffic = bBusyTraffic;
3046 	pmlmepriv->LinkDetectInfo.bTxBusyTraffic = bTxBusyTraffic;
3047 	pmlmepriv->LinkDetectInfo.bRxBusyTraffic = bRxBusyTraffic;
3048 	pmlmepriv->LinkDetectInfo.bHigherBusyTraffic = bHigherBusyTraffic;
3049 	pmlmepriv->LinkDetectInfo.bHigherBusyRxTraffic = bHigherBusyRxTraffic;
3050 	pmlmepriv->LinkDetectInfo.bHigherBusyTxTraffic = bHigherBusyTxTraffic;
3051 
3052 	return bEnterPS;
3053 
3054 }
3055 
3056 #ifdef CONFIG_AP_MODE
3057 /* for 11n Logo 4.2.31/4.2.32 */
dynamic_update_bcn_check(_adapter * padapter)3058 static void dynamic_update_bcn_check(_adapter *padapter)
3059 {
3060 	struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
3061 	struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
3062 
3063 	if (!padapter->registrypriv.wifi_spec)
3064 		return;
3065 
3066 	if (!padapter->registrypriv.ht_enable || !is_supported_ht(padapter->registrypriv.wireless_mode))
3067 		return;
3068 
3069 	if (!MLME_IS_AP(padapter))
3070 		return;
3071 
3072 	if (pmlmeext->bstart_bss) {
3073 		/* In 10 * 2 = 20s, there are no legacy AP, update HT info  */
3074 		static u8 count = 1;
3075 
3076 		if (count % 10 == 0) {
3077 			count = 1;
3078 #ifdef CONFIG_80211N_HT
3079 			if (_FALSE == ATOMIC_READ(&pmlmepriv->olbc)
3080 				&& _FALSE == ATOMIC_READ(&pmlmepriv->olbc_ht)) {
3081 
3082 				if (rtw_ht_operation_update(padapter) > 0) {
3083 					update_beacon(padapter, _HT_CAPABILITY_IE_, NULL, _FALSE, 0);
3084 					update_beacon(padapter, _HT_ADD_INFO_IE_, NULL, _TRUE, 0);
3085 				}
3086 			}
3087 #endif /* CONFIG_80211N_HT */
3088 		}
3089 
3090 #ifdef CONFIG_80211N_HT
3091 		/* In 2s, there are any legacy AP, update HT info, and then reset count  */
3092 
3093 		if (_FALSE != ATOMIC_READ(&pmlmepriv->olbc)
3094 			&& _FALSE != ATOMIC_READ(&pmlmepriv->olbc_ht)) {
3095 
3096 			if (rtw_ht_operation_update(padapter) > 0) {
3097 				update_beacon(padapter, _HT_CAPABILITY_IE_, NULL, _FALSE, 0);
3098 				update_beacon(padapter, _HT_ADD_INFO_IE_, NULL, _TRUE, 0);
3099 
3100 			}
3101 			ATOMIC_SET(&pmlmepriv->olbc, _FALSE);
3102 			ATOMIC_SET(&pmlmepriv->olbc_ht, _FALSE);
3103 			count = 0;
3104 		}
3105 #endif /* CONFIG_80211N_HT */
3106 		count ++;
3107 	}
3108 }
3109 #endif /* CONFIG_AP_MODE */
3110 
rtw_iface_dynamic_chk_wk_hdl(_adapter * padapter)3111 void rtw_iface_dynamic_chk_wk_hdl(_adapter *padapter)
3112 {
3113 	#ifdef CONFIG_AP_MODE
3114 	#ifdef CONFIG_ACTIVE_KEEP_ALIVE_CHECK
3115 	if (MLME_IS_AP(padapter) || MLME_IS_MESH(padapter)) {
3116 		expire_timeout_chk(padapter);
3117 		#ifdef CONFIG_RTW_MESH
3118 		if (MLME_IS_MESH(padapter) && MLME_IS_ASOC(padapter))
3119 			rtw_mesh_peer_status_chk(padapter);
3120 		#endif
3121 	}
3122 	#endif /* CONFIG_ACTIVE_KEEP_ALIVE_CHECK */
3123 
3124 	dynamic_update_bcn_check(padapter);
3125 
3126 	#endif /* CONFIG_AP_MODE */
3127 
3128 	linked_status_chk(padapter, 0);
3129 	traffic_status_watchdog(padapter, 0);
3130 
3131 	/* for debug purpose */
3132 	_linked_info_dump(padapter);
3133 
3134 #ifdef CONFIG_RTW_CFGVENDOR_RSSIMONITOR
3135         rtw_cfgvendor_rssi_monitor_evt(padapter);
3136 #endif
3137 
3138 
3139 }
rtw_dynamic_chk_wk_hdl(_adapter * padapter)3140 void rtw_dynamic_chk_wk_hdl(_adapter *padapter)
3141 {
3142 	rtw_mi_dynamic_chk_wk_hdl(padapter);
3143 #ifdef CONFIG_MP_INCLUDED
3144 	if (rtw_mp_mode_check(padapter) == _FALSE)
3145 #endif
3146 	{
3147 #ifdef DBG_CONFIG_ERROR_DETECT
3148 		rtw_hal_sreset_xmit_status_check(padapter);
3149 		rtw_hal_sreset_linked_status_check(padapter);
3150 #endif
3151 	}
3152 
3153 	/* if(check_fwstate(pmlmepriv, WIFI_UNDER_LINKING|WIFI_UNDER_SURVEY)==_FALSE) */
3154 	{
3155 #ifdef DBG_RX_COUNTER_DUMP
3156 		rtw_dump_rx_counters(padapter);
3157 #endif
3158 		dm_DynamicUsbTxAgg(padapter, 0);
3159 	}
3160 	rtw_hal_dm_watchdog(padapter);
3161 
3162 	/* check_hw_pbc(padapter, pdrvextra_cmd->pbuf, pdrvextra_cmd->type); */
3163 
3164 #ifdef CONFIG_BT_COEXIST
3165 	/* BT-Coexist */
3166 	rtw_btcoex_Handler(padapter);
3167 #endif
3168 
3169 #ifdef CONFIG_RTW_MULTI_AP
3170 	rtw_ch_util_rpt(padapter);
3171 #endif
3172 
3173 #ifdef CONFIG_DFS_MASTER
3174 	rtw_chset_chk_non_ocp_finish(adapter_to_rfctl(padapter));
3175 #endif
3176 
3177 #ifdef CONFIG_IPS_CHECK_IN_WD
3178 	/* always call rtw_ps_processor() at last one. */
3179 	rtw_ps_processor(padapter);
3180 #endif
3181 
3182 #ifdef CONFIG_MCC_MODE
3183 	rtw_hal_mcc_sw_status_check(padapter);
3184 #endif /* CONFIG_MCC_MODE */
3185 
3186 	rtw_hal_periodic_tsf_update_chk(padapter);
3187 }
3188 
3189 #ifdef CONFIG_LPS
3190 struct lps_ctrl_wk_parm {
3191 	s8 lps_level;
3192 	#ifdef CONFIG_LPS_1T1R
3193 	s8 lps_1t1r;
3194 	#endif
3195 };
3196 
lps_ctrl_wk_hdl(_adapter * padapter,u8 lps_ctrl_type,u8 * buf)3197 void lps_ctrl_wk_hdl(_adapter *padapter, u8 lps_ctrl_type, u8 *buf)
3198 {
3199 	struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(padapter);
3200 	struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
3201 	struct lps_ctrl_wk_parm *parm = (struct lps_ctrl_wk_parm *)buf;
3202 	u8	mstatus;
3203 
3204 	if ((check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) == _TRUE)
3205 	    || (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE) == _TRUE))
3206 		return;
3207 
3208 	switch (lps_ctrl_type) {
3209 	case LPS_CTRL_SCAN:
3210 		/* RTW_INFO("LPS_CTRL_SCAN\n"); */
3211 #ifdef CONFIG_BT_COEXIST
3212 		rtw_btcoex_ScanNotify(padapter, _TRUE);
3213 #endif /* CONFIG_BT_COEXIST */
3214 		if (check_fwstate(pmlmepriv, WIFI_ASOC_STATE) == _TRUE) {
3215 			/* connect */
3216 			LPS_Leave(padapter, "LPS_CTRL_SCAN");
3217 		}
3218 		break;
3219 	case LPS_CTRL_JOINBSS:
3220 		/* RTW_INFO("LPS_CTRL_JOINBSS\n"); */
3221 		LPS_Leave(padapter, "LPS_CTRL_JOINBSS");
3222 		break;
3223 	case LPS_CTRL_CONNECT:
3224 		/* RTW_INFO("LPS_CTRL_CONNECT\n"); */
3225 		mstatus = 1;/* connect */
3226 		/* Reset LPS Setting */
3227 		pwrpriv->LpsIdleCount = 0;
3228 		rtw_hal_set_hwreg(padapter, HW_VAR_H2C_FW_JOINBSSRPT, (u8 *)(&mstatus));
3229 #ifdef CONFIG_BT_COEXIST
3230 		rtw_btcoex_MediaStatusNotify(padapter, mstatus);
3231 #endif /* CONFIG_BT_COEXIST */
3232 		break;
3233 	case LPS_CTRL_DISCONNECT:
3234 		/* RTW_INFO("LPS_CTRL_DISCONNECT\n"); */
3235 		mstatus = 0;/* disconnect */
3236 #ifdef CONFIG_BT_COEXIST
3237 		rtw_btcoex_MediaStatusNotify(padapter, mstatus);
3238 #endif /* CONFIG_BT_COEXIST */
3239 		LPS_Leave(padapter, "LPS_CTRL_DISCONNECT");
3240 		rtw_hal_set_hwreg(padapter, HW_VAR_H2C_FW_JOINBSSRPT, (u8 *)(&mstatus));
3241 		break;
3242 	case LPS_CTRL_SPECIAL_PACKET:
3243 		/* RTW_INFO("LPS_CTRL_SPECIAL_PACKET\n"); */
3244 		rtw_set_lps_deny(padapter, LPS_DELAY_MS);
3245 #ifdef CONFIG_BT_COEXIST
3246 		rtw_btcoex_SpecialPacketNotify(padapter, PACKET_DHCP);
3247 #endif /* CONFIG_BT_COEXIST */
3248 		LPS_Leave(padapter, "LPS_CTRL_SPECIAL_PACKET");
3249 		break;
3250 	case LPS_CTRL_LEAVE:
3251 		LPS_Leave(padapter, "LPS_CTRL_LEAVE");
3252 		break;
3253 	case LPS_CTRL_LEAVE_SET_OPTION:
3254 		LPS_Leave(padapter, "LPS_CTRL_LEAVE_SET_OPTION");
3255 		if (parm) {
3256 			if (parm->lps_level >= 0)
3257 				pwrpriv->lps_level = parm->lps_level;
3258 			#ifdef CONFIG_LPS_1T1R
3259 			if (parm->lps_1t1r >= 0)
3260 				pwrpriv->lps_1t1r = parm->lps_1t1r;
3261 			#endif
3262 		}
3263 		break;
3264 	case LPS_CTRL_LEAVE_CFG80211_PWRMGMT:
3265 		LPS_Leave(padapter, "CFG80211_PWRMGMT");
3266 		break;
3267 	case LPS_CTRL_TRAFFIC_BUSY:
3268 		LPS_Leave(padapter, "LPS_CTRL_TRAFFIC_BUSY");
3269 		break;
3270 	case LPS_CTRL_TX_TRAFFIC_LEAVE:
3271 		LPS_Leave(padapter, "LPS_CTRL_TX_TRAFFIC_LEAVE");
3272 		break;
3273 	case LPS_CTRL_RX_TRAFFIC_LEAVE:
3274 		LPS_Leave(padapter, "LPS_CTRL_RX_TRAFFIC_LEAVE");
3275 		break;
3276 	case LPS_CTRL_ENTER:
3277 		LPS_Enter(padapter, "TRAFFIC_IDLE_1");
3278 		break;
3279 	default:
3280 		break;
3281 	}
3282 
3283 }
3284 
_rtw_lps_ctrl_wk_cmd(_adapter * adapter,u8 lps_ctrl_type,s8 lps_level,s8 lps_1t1r,u8 flags)3285 static u8 _rtw_lps_ctrl_wk_cmd(_adapter *adapter, u8 lps_ctrl_type, s8 lps_level, s8 lps_1t1r, u8 flags)
3286 {
3287 	struct cmd_obj *cmdobj;
3288 	struct drvextra_cmd_parm *parm;
3289 	struct lps_ctrl_wk_parm *wk_parm = NULL;
3290 	struct cmd_priv	*pcmdpriv = &adapter->cmdpriv;
3291 	struct submit_ctx sctx;
3292 	u8	res = _SUCCESS;
3293 
3294 	if (lps_ctrl_type == LPS_CTRL_LEAVE_SET_OPTION) {
3295 		wk_parm = rtw_zmalloc(sizeof(*wk_parm));
3296 		if (wk_parm == NULL) {
3297 			res = _FAIL;
3298 			goto exit;
3299 		}
3300 		wk_parm->lps_level = lps_level;
3301 		#ifdef CONFIG_LPS_1T1R
3302 		wk_parm->lps_1t1r = lps_1t1r;
3303 		#endif
3304 	}
3305 
3306 	if (flags & RTW_CMDF_DIRECTLY) {
3307 		/* no need to enqueue, do the cmd hdl directly */
3308 		lps_ctrl_wk_hdl(adapter, lps_ctrl_type, (u8 *)wk_parm);
3309 		if (wk_parm)
3310 			rtw_mfree(wk_parm, sizeof(*wk_parm));
3311 	} else {
3312 		/* need enqueue, prepare cmd_obj and enqueue */
3313 		parm = rtw_zmalloc(sizeof(*parm));
3314 		if (parm == NULL) {
3315 			if (wk_parm)
3316 				rtw_mfree(wk_parm, sizeof(*wk_parm));
3317 			res = _FAIL;
3318 			goto exit;
3319 		}
3320 
3321 		parm->ec_id = LPS_CTRL_WK_CID;
3322 		parm->type = lps_ctrl_type;
3323 		parm->size = wk_parm ? sizeof(*wk_parm) : 0;
3324 		parm->pbuf = (u8 *)wk_parm;
3325 
3326 		cmdobj = rtw_zmalloc(sizeof(*cmdobj));
3327 		if (cmdobj == NULL) {
3328 			rtw_mfree(parm, sizeof(*parm));
3329 			if (wk_parm)
3330 				rtw_mfree(wk_parm, sizeof(*wk_parm));
3331 			res = _FAIL;
3332 			goto exit;
3333 		}
3334 
3335 		init_h2fwcmd_w_parm_no_rsp(cmdobj, parm, CMD_SET_DRV_EXTRA);
3336 
3337 		if (flags & RTW_CMDF_WAIT_ACK) {
3338 			cmdobj->sctx = &sctx;
3339 			rtw_sctx_init(&sctx, 2000);
3340 		}
3341 
3342 		res = rtw_enqueue_cmd(pcmdpriv, cmdobj);
3343 
3344 		if (res == _SUCCESS && (flags & RTW_CMDF_WAIT_ACK)) {
3345 			rtw_sctx_wait(&sctx, __func__);
3346 			_enter_critical_mutex(&pcmdpriv->sctx_mutex, NULL);
3347 			if (sctx.status == RTW_SCTX_SUBMITTED)
3348 				cmdobj->sctx = NULL;
3349 			_exit_critical_mutex(&pcmdpriv->sctx_mutex, NULL);
3350 			if (sctx.status != RTW_SCTX_DONE_SUCCESS)
3351 				res = _FAIL;
3352 		}
3353 	}
3354 
3355 exit:
3356 	return res;
3357 }
3358 
rtw_lps_ctrl_wk_cmd(_adapter * adapter,u8 lps_ctrl_type,u8 flags)3359 u8 rtw_lps_ctrl_wk_cmd(_adapter *adapter, u8 lps_ctrl_type, u8 flags)
3360 {
3361 	return _rtw_lps_ctrl_wk_cmd(adapter, lps_ctrl_type, -1, -1, flags);
3362 }
3363 
rtw_lps_ctrl_leave_set_level_cmd(_adapter * adapter,u8 lps_level,u8 flags)3364 u8 rtw_lps_ctrl_leave_set_level_cmd(_adapter *adapter, u8 lps_level, u8 flags)
3365 {
3366 	return _rtw_lps_ctrl_wk_cmd(adapter, LPS_CTRL_LEAVE_SET_OPTION, lps_level, -1, flags);
3367 }
3368 
3369 #ifdef CONFIG_LPS_1T1R
rtw_lps_ctrl_leave_set_1t1r_cmd(_adapter * adapter,u8 lps_1t1r,u8 flags)3370 u8 rtw_lps_ctrl_leave_set_1t1r_cmd(_adapter *adapter, u8 lps_1t1r, u8 flags)
3371 {
3372 	return _rtw_lps_ctrl_wk_cmd(adapter, LPS_CTRL_LEAVE_SET_OPTION, -1, lps_1t1r, flags);
3373 }
3374 #endif
3375 
rtw_dm_in_lps_hdl(_adapter * padapter)3376 void rtw_dm_in_lps_hdl(_adapter *padapter)
3377 {
3378 	rtw_hal_set_hwreg(padapter, HW_VAR_DM_IN_LPS_LCLK, NULL);
3379 }
3380 
rtw_dm_in_lps_wk_cmd(_adapter * padapter)3381 u8 rtw_dm_in_lps_wk_cmd(_adapter *padapter)
3382 {
3383 	struct cmd_obj	*ph2c;
3384 	struct drvextra_cmd_parm	*pdrvextra_cmd_parm;
3385 	struct cmd_priv	*pcmdpriv = &padapter->cmdpriv;
3386 	u8	res = _SUCCESS;
3387 
3388 
3389 	ph2c = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
3390 	if (ph2c == NULL) {
3391 		res = _FAIL;
3392 		goto exit;
3393 	}
3394 
3395 	pdrvextra_cmd_parm = (struct drvextra_cmd_parm *)rtw_zmalloc(sizeof(struct drvextra_cmd_parm));
3396 	if (pdrvextra_cmd_parm == NULL) {
3397 		rtw_mfree((unsigned char *)ph2c, sizeof(struct cmd_obj));
3398 		res = _FAIL;
3399 		goto exit;
3400 	}
3401 
3402 	pdrvextra_cmd_parm->ec_id = DM_IN_LPS_WK_CID;
3403 	pdrvextra_cmd_parm->type = 0;
3404 	pdrvextra_cmd_parm->size = 0;
3405 	pdrvextra_cmd_parm->pbuf = NULL;
3406 
3407 	init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, CMD_SET_DRV_EXTRA);
3408 
3409 	res = rtw_enqueue_cmd(pcmdpriv, ph2c);
3410 
3411 exit:
3412 
3413 	return res;
3414 
3415 }
3416 
rtw_lps_change_dtim_hdl(_adapter * padapter,u8 dtim)3417 void rtw_lps_change_dtim_hdl(_adapter *padapter, u8 dtim)
3418 {
3419 	struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(padapter);
3420 
3421 	if (dtim <= 0 || dtim > 16)
3422 		return;
3423 
3424 #ifdef CONFIG_BT_COEXIST
3425 	if (rtw_btcoex_IsBtControlLps(padapter) == _TRUE)
3426 		return;
3427 #endif
3428 
3429 #ifdef CONFIG_LPS_LCLK
3430 	_enter_pwrlock(&pwrpriv->lock);
3431 #endif
3432 
3433 	if (pwrpriv->dtim != dtim) {
3434 		RTW_INFO("change DTIM from %d to %d, bFwCurrentInPSMode=%d, ps_mode=%d\n", pwrpriv->dtim, dtim,
3435 			 pwrpriv->bFwCurrentInPSMode, pwrpriv->pwr_mode);
3436 
3437 		pwrpriv->dtim = dtim;
3438 	}
3439 
3440 	if ((pwrpriv->bFwCurrentInPSMode == _TRUE) && (pwrpriv->pwr_mode > PS_MODE_ACTIVE)) {
3441 		u8 ps_mode = pwrpriv->pwr_mode;
3442 
3443 		/* RTW_INFO("change DTIM from %d to %d, ps_mode=%d\n", pwrpriv->dtim, dtim, ps_mode); */
3444 
3445 		rtw_exec_lps(padapter, ps_mode);
3446 	}
3447 
3448 #ifdef CONFIG_LPS_LCLK
3449 	_exit_pwrlock(&pwrpriv->lock);
3450 #endif
3451 
3452 }
3453 
3454 #endif
3455 
rtw_lps_change_dtim_cmd(_adapter * padapter,u8 dtim)3456 u8 rtw_lps_change_dtim_cmd(_adapter *padapter, u8 dtim)
3457 {
3458 	struct cmd_obj	*ph2c;
3459 	struct drvextra_cmd_parm	*pdrvextra_cmd_parm;
3460 	struct cmd_priv	*pcmdpriv = &padapter->cmdpriv;
3461 	u8	res = _SUCCESS;
3462 	/*
3463 	#ifdef CONFIG_CONCURRENT_MODE
3464 		if (padapter->hw_port != HW_PORT0)
3465 			return res;
3466 	#endif
3467 	*/
3468 	{
3469 		ph2c = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
3470 		if (ph2c == NULL) {
3471 			res = _FAIL;
3472 			goto exit;
3473 		}
3474 
3475 		pdrvextra_cmd_parm = (struct drvextra_cmd_parm *)rtw_zmalloc(sizeof(struct drvextra_cmd_parm));
3476 		if (pdrvextra_cmd_parm == NULL) {
3477 			rtw_mfree((unsigned char *)ph2c, sizeof(struct cmd_obj));
3478 			res = _FAIL;
3479 			goto exit;
3480 		}
3481 
3482 		pdrvextra_cmd_parm->ec_id = LPS_CHANGE_DTIM_CID;
3483 		pdrvextra_cmd_parm->type = dtim;
3484 		pdrvextra_cmd_parm->size = 0;
3485 		pdrvextra_cmd_parm->pbuf = NULL;
3486 
3487 		init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, CMD_SET_DRV_EXTRA);
3488 
3489 		res = rtw_enqueue_cmd(pcmdpriv, ph2c);
3490 	}
3491 
3492 exit:
3493 
3494 	return res;
3495 
3496 }
3497 
3498 #if (RATE_ADAPTIVE_SUPPORT == 1)
rpt_timer_setting_wk_hdl(_adapter * padapter,u16 minRptTime)3499 void rpt_timer_setting_wk_hdl(_adapter *padapter, u16 minRptTime)
3500 {
3501 	rtw_hal_set_hwreg(padapter, HW_VAR_RPT_TIMER_SETTING, (u8 *)(&minRptTime));
3502 }
3503 
rtw_rpt_timer_cfg_cmd(_adapter * padapter,u16 minRptTime)3504 u8 rtw_rpt_timer_cfg_cmd(_adapter *padapter, u16 minRptTime)
3505 {
3506 	struct cmd_obj		*ph2c;
3507 	struct drvextra_cmd_parm	*pdrvextra_cmd_parm;
3508 	struct cmd_priv	*pcmdpriv = &padapter->cmdpriv;
3509 
3510 	u8	res = _SUCCESS;
3511 
3512 	ph2c = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
3513 	if (ph2c == NULL) {
3514 		res = _FAIL;
3515 		goto exit;
3516 	}
3517 
3518 	pdrvextra_cmd_parm = (struct drvextra_cmd_parm *)rtw_zmalloc(sizeof(struct drvextra_cmd_parm));
3519 	if (pdrvextra_cmd_parm == NULL) {
3520 		rtw_mfree((unsigned char *)ph2c, sizeof(struct cmd_obj));
3521 		res = _FAIL;
3522 		goto exit;
3523 	}
3524 
3525 	pdrvextra_cmd_parm->ec_id = RTP_TIMER_CFG_WK_CID;
3526 	pdrvextra_cmd_parm->type = minRptTime;
3527 	pdrvextra_cmd_parm->size = 0;
3528 	pdrvextra_cmd_parm->pbuf = NULL;
3529 	init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, CMD_SET_DRV_EXTRA);
3530 	res = rtw_enqueue_cmd(pcmdpriv, ph2c);
3531 exit:
3532 
3533 
3534 	return res;
3535 
3536 }
3537 
3538 #endif
3539 
3540 #ifdef CONFIG_ANTENNA_DIVERSITY
antenna_select_wk_hdl(_adapter * padapter,u8 antenna)3541 void antenna_select_wk_hdl(_adapter *padapter, u8 antenna)
3542 {
3543 	rtw_hal_set_odm_var(padapter, HAL_ODM_ANTDIV_SELECT, &antenna, _TRUE);
3544 }
3545 
rtw_antenna_select_cmd(_adapter * padapter,u8 antenna,u8 enqueue)3546 u8 rtw_antenna_select_cmd(_adapter *padapter, u8 antenna, u8 enqueue)
3547 {
3548 	struct cmd_obj		*ph2c;
3549 	struct drvextra_cmd_parm	*pdrvextra_cmd_parm;
3550 	struct cmd_priv	*pcmdpriv = &padapter->cmdpriv;
3551 	struct dvobj_priv *dvobj = adapter_to_dvobj(padapter);
3552 	u8	bSupportAntDiv = _FALSE;
3553 	u8	res = _SUCCESS;
3554 	int	i;
3555 
3556 	rtw_hal_get_def_var(padapter, HAL_DEF_IS_SUPPORT_ANT_DIV, &(bSupportAntDiv));
3557 	if (_FALSE == bSupportAntDiv)
3558 		return _FAIL;
3559 
3560 	for (i = 0; i < dvobj->iface_nums; i++) {
3561 		if (rtw_linked_check(dvobj->padapters[i]))
3562 			return _FAIL;
3563 	}
3564 
3565 	if (_TRUE == enqueue) {
3566 		ph2c = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
3567 		if (ph2c == NULL) {
3568 			res = _FAIL;
3569 			goto exit;
3570 		}
3571 
3572 		pdrvextra_cmd_parm = (struct drvextra_cmd_parm *)rtw_zmalloc(sizeof(struct drvextra_cmd_parm));
3573 		if (pdrvextra_cmd_parm == NULL) {
3574 			rtw_mfree((unsigned char *)ph2c, sizeof(struct cmd_obj));
3575 			res = _FAIL;
3576 			goto exit;
3577 		}
3578 
3579 		pdrvextra_cmd_parm->ec_id = ANT_SELECT_WK_CID;
3580 		pdrvextra_cmd_parm->type = antenna;
3581 		pdrvextra_cmd_parm->size = 0;
3582 		pdrvextra_cmd_parm->pbuf = NULL;
3583 		init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, CMD_SET_DRV_EXTRA);
3584 
3585 		res = rtw_enqueue_cmd(pcmdpriv, ph2c);
3586 	} else
3587 		antenna_select_wk_hdl(padapter, antenna);
3588 exit:
3589 
3590 
3591 	return res;
3592 
3593 }
3594 #endif
3595 
rtw_dm_ra_mask_hdl(_adapter * padapter,struct sta_info * psta)3596 void rtw_dm_ra_mask_hdl(_adapter *padapter, struct sta_info *psta)
3597 {
3598 	if (psta)
3599 		set_sta_rate(padapter, psta);
3600 }
3601 
rtw_dm_ra_mask_wk_cmd(_adapter * padapter,u8 * psta)3602 u8 rtw_dm_ra_mask_wk_cmd(_adapter *padapter, u8 *psta)
3603 {
3604 	struct cmd_obj	*ph2c;
3605 	struct drvextra_cmd_parm	*pdrvextra_cmd_parm;
3606 	struct cmd_priv	*pcmdpriv = &padapter->cmdpriv;
3607 	u8	res = _SUCCESS;
3608 
3609 
3610 	ph2c = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
3611 	if (ph2c == NULL) {
3612 		res = _FAIL;
3613 		goto exit;
3614 	}
3615 
3616 	pdrvextra_cmd_parm = (struct drvextra_cmd_parm *)rtw_zmalloc(sizeof(struct drvextra_cmd_parm));
3617 	if (pdrvextra_cmd_parm == NULL) {
3618 		rtw_mfree((unsigned char *)ph2c, sizeof(struct cmd_obj));
3619 		res = _FAIL;
3620 		goto exit;
3621 	}
3622 
3623 	pdrvextra_cmd_parm->ec_id = DM_RA_MSK_WK_CID;
3624 	pdrvextra_cmd_parm->type = 0;
3625 	pdrvextra_cmd_parm->size = 0;
3626 	pdrvextra_cmd_parm->pbuf = psta;
3627 
3628 	init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, CMD_SET_DRV_EXTRA);
3629 
3630 	res = rtw_enqueue_cmd(pcmdpriv, ph2c);
3631 
3632 exit:
3633 
3634 	return res;
3635 
3636 }
3637 
power_saving_wk_hdl(_adapter * padapter)3638 void power_saving_wk_hdl(_adapter *padapter)
3639 {
3640 	rtw_ps_processor(padapter);
3641 }
3642 
3643 /* add for CONFIG_IEEE80211W, none 11w can use it */
reset_securitypriv_hdl(_adapter * padapter)3644 void reset_securitypriv_hdl(_adapter *padapter)
3645 {
3646 	rtw_reset_securitypriv(padapter);
3647 }
3648 
3649 #ifdef CONFIG_P2P
p2p_protocol_wk_cmd(_adapter * padapter,int intCmdType)3650 u8 p2p_protocol_wk_cmd(_adapter *padapter, int intCmdType)
3651 {
3652 	struct cmd_obj	*ph2c;
3653 	struct drvextra_cmd_parm	*pdrvextra_cmd_parm;
3654 	struct wifidirect_info	*pwdinfo = &(padapter->wdinfo);
3655 	struct cmd_priv	*pcmdpriv = &padapter->cmdpriv;
3656 	u8	res = _SUCCESS;
3657 
3658 
3659 	if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE))
3660 		return res;
3661 
3662 	ph2c = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
3663 	if (ph2c == NULL) {
3664 		res = _FAIL;
3665 		goto exit;
3666 	}
3667 
3668 	pdrvextra_cmd_parm = (struct drvextra_cmd_parm *)rtw_zmalloc(sizeof(struct drvextra_cmd_parm));
3669 	if (pdrvextra_cmd_parm == NULL) {
3670 		rtw_mfree((unsigned char *)ph2c, sizeof(struct cmd_obj));
3671 		res = _FAIL;
3672 		goto exit;
3673 	}
3674 
3675 	pdrvextra_cmd_parm->ec_id = P2P_PROTO_WK_CID;
3676 	pdrvextra_cmd_parm->type = intCmdType;	/*	As the command tppe. */
3677 	pdrvextra_cmd_parm->size = 0;
3678 	pdrvextra_cmd_parm->pbuf = NULL;		/*	Must be NULL here */
3679 
3680 	init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, CMD_SET_DRV_EXTRA);
3681 
3682 	res = rtw_enqueue_cmd(pcmdpriv, ph2c);
3683 
3684 exit:
3685 
3686 
3687 	return res;
3688 
3689 }
3690 #endif /* CONFIG_P2P */
3691 
3692 #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)3693 static struct rtw_roch_parm *rtw_alloc_roch_parm(_adapter *adapter
3694 	, u64 cookie, struct wireless_dev *wdev
3695 	, struct ieee80211_channel *ch, enum nl80211_channel_type ch_type
3696 	, unsigned int duration
3697 	, u8 flags
3698 )
3699 {
3700 	struct rtw_roch_parm *roch_parm;
3701 	bool cancel = duration ? 0 : 1;
3702 
3703 	roch_parm = (struct rtw_roch_parm *)rtw_zmalloc(sizeof(struct rtw_roch_parm));
3704 	if (!roch_parm)
3705 		return NULL;
3706 
3707 	roch_parm->cookie = cookie;
3708 	roch_parm->wdev = wdev;
3709 	if (!cancel) {
3710 		_rtw_memcpy(&roch_parm->ch, ch, sizeof(struct ieee80211_channel));
3711 		roch_parm->ch_type = ch_type;
3712 		roch_parm->duration = duration;
3713 	}
3714 
3715 	return roch_parm;
3716 }
3717 
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)3718 inline u8 rtw_roch_cmd(_adapter *adapter
3719 	, u64 cookie, struct wireless_dev *wdev
3720 	, struct ieee80211_channel *ch, enum nl80211_channel_type ch_type
3721 	, unsigned int duration
3722 	, u8 flags
3723 )
3724 {
3725 	struct rtw_roch_parm *roch_parm;
3726 
3727 	roch_parm = rtw_alloc_roch_parm(adapter, cookie, wdev, ch, ch_type, duration, flags);
3728 	if (!roch_parm)
3729 		return _FAIL;
3730 
3731 	return rtw_roch_wk_cmd(adapter, ROCH_RO_CH_WK, roch_parm, flags);
3732 }
3733 
rtw_cancel_roch_cmd(_adapter * adapter,u64 cookie,struct wireless_dev * wdev,u8 flags)3734 inline u8 rtw_cancel_roch_cmd(_adapter *adapter, u64 cookie, struct wireless_dev *wdev, u8 flags)
3735 {
3736 	struct rtw_roch_parm *roch_parm;
3737 
3738 	roch_parm = rtw_alloc_roch_parm(adapter, cookie, wdev, NULL, 0, 0, flags);
3739 	if (!roch_parm)
3740 		return _FAIL;
3741 
3742 	return rtw_roch_wk_cmd(adapter, ROCH_CANCEL_RO_CH_WK, roch_parm, flags);
3743 }
3744 
rtw_mgnt_tx_cmd(_adapter * adapter,u8 tx_ch,u8 no_cck,const u8 * buf,size_t len,int wait_ack,u8 flags)3745 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)
3746 {
3747 	struct cmd_obj *cmdobj;
3748 	struct drvextra_cmd_parm *parm;
3749 	struct mgnt_tx_parm *mgnt_parm;
3750 	struct cmd_priv *pcmdpriv = &adapter->cmdpriv;
3751 	struct submit_ctx sctx;
3752 	u8	res = _SUCCESS;
3753 
3754 	mgnt_parm = (struct mgnt_tx_parm *)rtw_zmalloc(sizeof(struct mgnt_tx_parm));
3755 	if (mgnt_parm == NULL) {
3756 		res = _FAIL;
3757 			goto exit;
3758 	}
3759 
3760 	mgnt_parm->tx_ch = tx_ch;
3761 	mgnt_parm->no_cck = no_cck;
3762 	mgnt_parm->buf = buf;
3763 	mgnt_parm->len = len;
3764 	mgnt_parm->wait_ack = wait_ack;
3765 
3766 	if (flags & RTW_CMDF_DIRECTLY) {
3767 		/* no need to enqueue, do the cmd hdl directly and free cmd parameter */
3768 		if (H2C_SUCCESS != rtw_mgnt_tx_handler(adapter, (u8 *)mgnt_parm))
3769 			res = _FAIL;
3770 		rtw_mfree((u8 *)mgnt_parm, sizeof(*mgnt_parm));
3771 	} else {
3772 		/* need enqueue, prepare cmd_obj and enqueue */
3773 		parm = (struct drvextra_cmd_parm *)rtw_zmalloc(sizeof(struct drvextra_cmd_parm));
3774 		if (parm == NULL) {
3775 			rtw_mfree((u8 *)mgnt_parm, sizeof(*mgnt_parm));
3776 			res = _FAIL;
3777 			goto exit;
3778 		}
3779 
3780 		parm->ec_id = MGNT_TX_WK_CID;
3781 		parm->type = 0;
3782 		parm->size = sizeof(*mgnt_parm);
3783 		parm->pbuf = (u8 *)mgnt_parm;
3784 
3785 		cmdobj = (struct cmd_obj *)rtw_zmalloc(sizeof(*cmdobj));
3786 		if (cmdobj == NULL) {
3787 			res = _FAIL;
3788 			rtw_mfree((u8 *)mgnt_parm, sizeof(*mgnt_parm));
3789 			rtw_mfree((u8 *)parm, sizeof(*parm));
3790 			goto exit;
3791 		}
3792 
3793 		init_h2fwcmd_w_parm_no_rsp(cmdobj, parm, CMD_SET_DRV_EXTRA);
3794 
3795 		if (flags & RTW_CMDF_WAIT_ACK) {
3796 			cmdobj->sctx = &sctx;
3797 			rtw_sctx_init(&sctx, 10 * 1000);
3798 		}
3799 
3800 		res = rtw_enqueue_cmd(pcmdpriv, cmdobj);
3801 
3802 		if (res == _SUCCESS && (flags & RTW_CMDF_WAIT_ACK)) {
3803 			rtw_sctx_wait(&sctx, __func__);
3804 			_enter_critical_mutex(&pcmdpriv->sctx_mutex, NULL);
3805 			if (sctx.status == RTW_SCTX_SUBMITTED)
3806 				cmdobj->sctx = NULL;
3807 			_exit_critical_mutex(&pcmdpriv->sctx_mutex, NULL);
3808 			if (sctx.status != RTW_SCTX_DONE_SUCCESS)
3809 				res = _FAIL;
3810 		}
3811 	}
3812 
3813 exit:
3814 	return res;
3815 }
3816 #endif
3817 
rtw_ps_cmd(_adapter * padapter)3818 u8 rtw_ps_cmd(_adapter *padapter)
3819 {
3820 	struct cmd_obj		*ppscmd;
3821 	struct drvextra_cmd_parm	*pdrvextra_cmd_parm;
3822 	struct cmd_priv	*pcmdpriv = &padapter->cmdpriv;
3823 
3824 	u8	res = _SUCCESS;
3825 
3826 #ifdef CONFIG_CONCURRENT_MODE
3827 	if (!is_primary_adapter(padapter))
3828 		goto exit;
3829 #endif
3830 
3831 	ppscmd = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
3832 	if (ppscmd == NULL) {
3833 		res = _FAIL;
3834 		goto exit;
3835 	}
3836 
3837 	pdrvextra_cmd_parm = (struct drvextra_cmd_parm *)rtw_zmalloc(sizeof(struct drvextra_cmd_parm));
3838 	if (pdrvextra_cmd_parm == NULL) {
3839 		rtw_mfree((unsigned char *)ppscmd, sizeof(struct cmd_obj));
3840 		res = _FAIL;
3841 		goto exit;
3842 	}
3843 
3844 	pdrvextra_cmd_parm->ec_id = POWER_SAVING_CTRL_WK_CID;
3845 	pdrvextra_cmd_parm->type = 0;
3846 	pdrvextra_cmd_parm->size = 0;
3847 	pdrvextra_cmd_parm->pbuf = NULL;
3848 	init_h2fwcmd_w_parm_no_rsp(ppscmd, pdrvextra_cmd_parm, CMD_SET_DRV_EXTRA);
3849 
3850 	res = rtw_enqueue_cmd(pcmdpriv, ppscmd);
3851 
3852 exit:
3853 
3854 
3855 	return res;
3856 
3857 }
3858 
3859 #if CONFIG_DFS
rtw_dfs_ch_switch_hdl(struct dvobj_priv * dvobj)3860 void rtw_dfs_ch_switch_hdl(struct dvobj_priv *dvobj)
3861 {
3862 	struct rf_ctl_t *rfctl = dvobj_to_rfctl(dvobj);
3863 	_adapter *pri_adapter = dvobj_get_primary_adapter(dvobj);
3864 	struct mlme_ext_priv *pmlmeext = &pri_adapter->mlmeextpriv;
3865 	u8 ifbmp_m = rtw_mi_get_ap_mesh_ifbmp(pri_adapter);
3866 	u8 ifbmp_s = rtw_mi_get_ld_sta_ifbmp(pri_adapter);
3867 	s16 req_ch;
3868 	u8 req_bw = CHANNEL_WIDTH_20, req_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE, csa_timer = _FALSE;
3869 	u8 need_discon = _FALSE;
3870 
3871 	rtw_hal_macid_sleep_all_used(pri_adapter);
3872 
3873 	if (rtw_chset_search_ch(rfctl->channel_set, rfctl->csa_ch) >= 0
3874 		&& !rtw_chset_is_ch_non_ocp(rfctl->channel_set, rfctl->csa_ch)
3875 	) {
3876 		/* CSA channel available and valid */
3877 		req_ch = rfctl->csa_ch;
3878 		RTW_INFO("%s valid CSA ch%u\n", __func__, rfctl->csa_ch);
3879 		csa_timer = _TRUE;
3880 	} else if (ifbmp_m) {
3881 		/* no available or valid CSA channel, having AP/MESH ifaces */
3882 		req_ch = REQ_CH_NONE;
3883 		need_discon = _TRUE;
3884 		RTW_INFO("%s ch sel by AP/MESH ifaces\n", __func__);
3885 	} else {
3886 		/* no available or valid CSA channel and no AP/MESH ifaces */
3887 		if (!IsSupported24G(dvobj_to_regsty(dvobj)->wireless_mode)
3888 			#ifdef CONFIG_DFS_MASTER
3889 			|| rfctl->radar_detected
3890 			#endif
3891 		)
3892 			req_ch = 36;
3893 		else
3894 			req_ch = 1;
3895 		need_discon = _TRUE;
3896 		RTW_INFO("%s switch to ch%d, then disconnect with AP\n", __func__, req_ch);
3897 	}
3898 
3899 	if (!need_discon) {
3900 		/* fault tolerant for AP */
3901 		if(rfctl->csa_ch_width == 1 || rfctl->csa_ch_width == 2 || rfctl->csa_ch_width == 3) {
3902 			if (rtw_get_offset_by_chbw(req_ch, CHANNEL_WIDTH_80, &req_offset)) {
3903 				/*  always use 80 Mhz to connect if ch/bw/offset is valid */
3904 				req_bw = CHANNEL_WIDTH_80;
3905 			} else {
3906 				req_bw = CHANNEL_WIDTH_20;
3907 				req_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
3908 			}
3909 		} else if(rfctl->csa_ch_offset == 1) {
3910 			req_bw = CHANNEL_WIDTH_40;
3911 			req_offset = HAL_PRIME_CHNL_OFFSET_LOWER;
3912 		} else if(rfctl->csa_ch_offset == 3) {
3913 			req_bw = CHANNEL_WIDTH_40;
3914 			req_offset = HAL_PRIME_CHNL_OFFSET_UPPER;
3915 		} else{
3916 			req_bw = CHANNEL_WIDTH_20;
3917 			req_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
3918 		}
3919 	}
3920 
3921 	RTW_INFO("req_ch=%d, req_bw=%d, req_offset=%d, ifbmp_m=0x%02x, ifbmp_s=0x%02x\n"
3922 		, req_ch, req_bw, req_offset, ifbmp_m, ifbmp_s);
3923 
3924 	/* check all STA ifaces status */
3925 	if (ifbmp_s) {
3926 		_adapter *iface;
3927 		int i;
3928 
3929 		for (i = 0; i < dvobj->iface_nums; i++) {
3930 			iface = dvobj->padapters[i];
3931 			if (!iface || !(ifbmp_s & BIT(iface->iface_id)))
3932 				continue;
3933 
3934 			if (need_discon) {
3935 				/* CSA channel not available or not valid, then disconnect */
3936 				set_fwstate(&iface->mlmepriv,  WIFI_OP_CH_SWITCHING);
3937 				issue_deauth(iface, get_bssid(&iface->mlmepriv), WLAN_REASON_DEAUTH_LEAVING);
3938 			} else {
3939 				/* update STA mode ch/bw/offset */
3940 				iface->mlmeextpriv.cur_channel = req_ch;
3941 				iface->mlmeextpriv.cur_bwmode = req_bw;
3942 				iface->mlmeextpriv.cur_ch_offset = req_offset;
3943 				/* updaet STA mode DSConfig , ap mode will update in rtw_change_bss_chbw_cmd */
3944 				iface->mlmepriv.cur_network.network.Configuration.DSConfig = req_ch;
3945 				set_fwstate(&iface->mlmepriv, WIFI_CSA_UPDATE_BEACON);
3946 
3947 				#ifdef CONFIG_80211D
3948 				if (iface->mlmepriv.recv_country_ie) {
3949 					if (rtw_apply_recv_country_ie_cmd(iface, RTW_CMDF_DIRECTLY
3950 						, req_ch > 14 ? BAND_ON_5G : BAND_ON_2_4G, req_ch
3951 						, iface->mlmepriv.recv_country_ie) != _SUCCESS
3952 					)
3953 						RTW_WARN(FUNC_ADPT_FMT" rtw_apply_recv_country_ie_cmd() fail\n", FUNC_ADPT_ARG(iface));
3954 				}
3955 				#endif
3956 			}
3957 		}
3958 	}
3959 
3960 	if (csa_timer) {
3961 		RTW_INFO("pmlmeext->csa_timer 70 seconds\n");
3962 		/* wait 70 seconds for receiving beacons */
3963 		_set_timer(&pmlmeext->csa_timer, CAC_TIME_MS + 10000);
3964 	}
3965 
3966 #ifdef CONFIG_AP_MODE
3967 	if (ifbmp_m) {
3968 		u8 execlude = 0;
3969 
3970 		if (need_discon)
3971 			execlude = ifbmp_s;
3972 		/* trigger channel selection with consideraton of asoc STA ifaces */
3973 		rtw_change_bss_chbw_cmd(dvobj_get_primary_adapter(dvobj), RTW_CMDF_DIRECTLY
3974 			, ifbmp_m, execlude, req_ch, REQ_BW_ORI, REQ_OFFSET_NONE);
3975 	} else
3976 #endif
3977 	{
3978 		/* no AP/MESH iface, switch DFS status and channel directly */
3979 		rtw_warn_on(req_ch <= 0);
3980 		#ifdef CONFIG_DFS_MASTER
3981 		if (need_discon)
3982 			rtw_dfs_rd_en_decision(pri_adapter, MLME_OPCH_SWITCH, ifbmp_s);
3983 		else
3984 			rtw_dfs_rd_en_decision(pri_adapter, MLME_OPCH_SWITCH, 0);
3985 		#endif
3986 		LeaveAllPowerSaveModeDirect(pri_adapter);
3987 		set_channel_bwmode(pri_adapter, req_ch, req_offset, req_bw);
3988 		/* update union ch/bw/offset for STA only */
3989 		rtw_mi_update_union_chan_inf(pri_adapter, req_ch, req_offset, req_bw);
3990 		rtw_rfctl_update_op_mode(rfctl, 0, 0);
3991 	}
3992 
3993 	/* make asoc STA ifaces disconnect */
3994 	if (ifbmp_s && need_discon) {
3995 		_adapter *iface;
3996 		int i;
3997 
3998 		for (i = 0; i < dvobj->iface_nums; i++) {
3999 			iface = dvobj->padapters[i];
4000 			if (!iface || !(ifbmp_s & BIT(iface->iface_id)))
4001 				continue;
4002 			rtw_disassoc_cmd(iface, 0, RTW_CMDF_DIRECTLY);
4003 			rtw_indicate_disconnect(iface, 0, _FALSE);
4004 			rtw_free_assoc_resources(iface, _TRUE);
4005 			rtw_free_network_queue(iface, _TRUE);
4006 		}
4007 	}
4008 
4009 	rfctl->csa_ch = 0;
4010 	rfctl->csa_switch_cnt = 0;
4011 	rfctl->csa_ch_offset = 0;
4012 	rfctl->csa_ch_width = 0;
4013 	rfctl->csa_ch_freq_seg0 = 0;
4014 	rfctl->csa_ch_freq_seg1 = 0;
4015 
4016 	rtw_hal_macid_wakeup_all_used(pri_adapter);
4017 	rtw_mi_os_xmit_schedule(pri_adapter);
4018 }
4019 #endif /* CONFIG_DFS */
4020 
4021 #ifdef CONFIG_AP_MODE
4022 
rtw_chk_hi_queue_hdl(_adapter * padapter)4023 static void rtw_chk_hi_queue_hdl(_adapter *padapter)
4024 {
4025 	struct sta_info *psta_bmc;
4026 	struct sta_priv *pstapriv = &padapter->stapriv;
4027 	systime start = rtw_get_current_time();
4028 	u8 empty = _FALSE;
4029 
4030 	psta_bmc = rtw_get_bcmc_stainfo(padapter);
4031 	if (!psta_bmc)
4032 		return;
4033 
4034 	rtw_hal_get_hwreg(padapter, HW_VAR_CHK_HI_QUEUE_EMPTY, &empty);
4035 
4036 	while (_FALSE == empty && rtw_get_passing_time_ms(start) < rtw_get_wait_hiq_empty_ms()) {
4037 		rtw_msleep_os(100);
4038 		rtw_hal_get_hwreg(padapter, HW_VAR_CHK_HI_QUEUE_EMPTY, &empty);
4039 	}
4040 
4041 	if (psta_bmc->sleepq_len == 0) {
4042 		if (empty == _SUCCESS) {
4043 			bool update_tim = _FALSE;
4044 
4045 			if (rtw_tim_map_is_set(padapter, pstapriv->tim_bitmap, 0))
4046 				update_tim = _TRUE;
4047 
4048 			rtw_tim_map_clear(padapter, pstapriv->tim_bitmap, 0);
4049 			rtw_tim_map_clear(padapter, pstapriv->sta_dz_bitmap, 0);
4050 
4051 			if (update_tim == _TRUE)
4052 				_update_beacon(padapter, _TIM_IE_, NULL, _TRUE, 0,"bmc sleepq and HIQ empty");
4053 		} else /* re check again */
4054 			rtw_chk_hi_queue_cmd(padapter);
4055 
4056 	}
4057 
4058 }
4059 
rtw_chk_hi_queue_cmd(_adapter * padapter)4060 u8 rtw_chk_hi_queue_cmd(_adapter *padapter)
4061 {
4062 	struct cmd_obj	*ph2c;
4063 	struct drvextra_cmd_parm	*pdrvextra_cmd_parm;
4064 	struct cmd_priv	*pcmdpriv = &padapter->cmdpriv;
4065 	u8	res = _SUCCESS;
4066 
4067 	ph2c = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
4068 	if (ph2c == NULL) {
4069 		res = _FAIL;
4070 		goto exit;
4071 	}
4072 
4073 	pdrvextra_cmd_parm = (struct drvextra_cmd_parm *)rtw_zmalloc(sizeof(struct drvextra_cmd_parm));
4074 	if (pdrvextra_cmd_parm == NULL) {
4075 		rtw_mfree((unsigned char *)ph2c, sizeof(struct cmd_obj));
4076 		res = _FAIL;
4077 		goto exit;
4078 	}
4079 
4080 	pdrvextra_cmd_parm->ec_id = CHECK_HIQ_WK_CID;
4081 	pdrvextra_cmd_parm->type = 0;
4082 	pdrvextra_cmd_parm->size = 0;
4083 	pdrvextra_cmd_parm->pbuf = NULL;
4084 
4085 	init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, CMD_SET_DRV_EXTRA);
4086 
4087 	res = rtw_enqueue_cmd(pcmdpriv, ph2c);
4088 
4089 exit:
4090 
4091 	return res;
4092 
4093 }
4094 
4095 #ifdef CONFIG_DFS_MASTER
rtw_dfs_rd_hdl(_adapter * adapter)4096 u8 rtw_dfs_rd_hdl(_adapter *adapter)
4097 {
4098 	struct dvobj_priv *dvobj = adapter_to_dvobj(adapter);
4099 	struct rf_ctl_t *rfctl = adapter_to_rfctl(adapter);
4100 	u8 cch;
4101 
4102 	if (!rfctl->radar_detect_enabled)
4103 		goto exit;
4104 
4105 	cch = rtw_get_center_ch(rfctl->radar_detect_ch, rfctl->radar_detect_bw, rfctl->radar_detect_offset);
4106 
4107 	if (dvobj->oper_channel != rfctl->radar_detect_ch
4108 		|| rtw_get_passing_time_ms(rtw_get_on_oper_ch_time(adapter)) < 300
4109 	) {
4110 		/* offchannel, bypass radar detect */
4111 		goto cac_status_chk;
4112 	}
4113 
4114 	if (IS_CH_WAITING(rfctl) && !IS_UNDER_CAC(rfctl)) {
4115 		/* non_ocp, bypass radar detect */
4116 		goto cac_status_chk;
4117 	}
4118 
4119 	if (!rfctl->dbg_dfs_fake_radar_detect_cnt
4120 		&& rtw_odm_radar_detect(adapter) != _TRUE)
4121 		goto cac_status_chk;
4122 
4123 	if (!rfctl->dbg_dfs_fake_radar_detect_cnt
4124 		&& rfctl->dbg_dfs_radar_detect_trigger_non
4125 	) {
4126 		/* radar detect debug mode, trigger no mlme flow */
4127 		RTW_INFO("%s radar detected on test mode, trigger no mlme flow\n", __func__);
4128 		goto cac_status_chk;
4129 	}
4130 
4131 	if (rfctl->dbg_dfs_fake_radar_detect_cnt != 0) {
4132 		RTW_INFO("%s fake radar detected, cnt:%d\n", __func__
4133 			, rfctl->dbg_dfs_fake_radar_detect_cnt);
4134 		rfctl->dbg_dfs_fake_radar_detect_cnt--;
4135 	} else
4136 		RTW_INFO("%s radar detected\n", __func__);
4137 
4138 	rfctl->radar_detected = 1;
4139 
4140 	rtw_chset_update_non_ocp(rfctl->channel_set
4141 		, rfctl->radar_detect_ch, rfctl->radar_detect_bw, rfctl->radar_detect_offset);
4142 
4143 	if (IS_UNDER_CAC(rfctl))
4144 		rtw_nlrtw_cac_abort_event(adapter, cch, rfctl->radar_detect_bw);
4145 	rtw_nlrtw_radar_detect_event(adapter, cch, rfctl->radar_detect_bw);
4146 
4147 	rtw_dfs_ch_switch_hdl(dvobj);
4148 
4149 	if (rfctl->radar_detect_enabled)
4150 		goto set_timer;
4151 	goto exit;
4152 
4153 cac_status_chk:
4154 
4155 	if (!IS_CAC_STOPPED(rfctl)
4156 		&& ((IS_UNDER_CAC(rfctl) && rfctl->cac_force_stop)
4157 			|| !IS_CH_WAITING(rfctl)
4158 			)
4159 	) {
4160 		u8 pause = 0x00;
4161 
4162 		rtw_hal_set_hwreg(adapter, HW_VAR_TXPAUSE, &pause);
4163 		rfctl->cac_start_time = rfctl->cac_end_time = RTW_CAC_STOPPED;
4164 		rtw_nlrtw_cac_finish_event(adapter, cch, rfctl->radar_detect_bw);
4165 
4166 		if (rtw_mi_check_fwstate(adapter, WIFI_UNDER_LINKING|WIFI_UNDER_SURVEY) == _FALSE) {
4167 			u8 doiqk = _TRUE;
4168 			u8 u_ch, u_bw, u_offset;
4169 
4170 			rtw_hal_set_hwreg(adapter , HW_VAR_DO_IQK , &doiqk);
4171 
4172 			if (rtw_mi_get_ch_setting_union(adapter, &u_ch, &u_bw, &u_offset))
4173 				set_channel_bwmode(adapter, u_ch, u_offset, u_bw);
4174 			else
4175 				rtw_warn_on(1);
4176 
4177 			doiqk = _FALSE;
4178 			rtw_hal_set_hwreg(adapter , HW_VAR_DO_IQK , &doiqk);
4179 
4180 			#ifdef CONFIG_AP_MODE
4181 			ResumeTxBeacon(adapter);
4182 			rtw_mi_tx_beacon_hdl(adapter);
4183 			#endif
4184 		}
4185 	}
4186 
4187 set_timer:
4188 	_set_timer(&rfctl->radar_detect_timer
4189 		, rtw_odm_radar_detect_polling_int_ms(dvobj));
4190 
4191 exit:
4192 	return H2C_SUCCESS;
4193 }
4194 
rtw_dfs_rd_cmd(_adapter * adapter,bool enqueue)4195 u8 rtw_dfs_rd_cmd(_adapter *adapter, bool enqueue)
4196 {
4197 	struct cmd_obj *cmdobj;
4198 	struct drvextra_cmd_parm *parm;
4199 	struct cmd_priv *cmdpriv = &adapter->cmdpriv;
4200 	u8 res = _FAIL;
4201 
4202 	if (enqueue) {
4203 		cmdobj = rtw_zmalloc(sizeof(struct cmd_obj));
4204 		if (cmdobj == NULL)
4205 			goto exit;
4206 
4207 		parm = rtw_zmalloc(sizeof(struct drvextra_cmd_parm));
4208 		if (parm == NULL) {
4209 			rtw_mfree(cmdobj, sizeof(struct cmd_obj));
4210 			goto exit;
4211 		}
4212 
4213 		parm->ec_id = DFS_RADAR_DETECT_WK_CID;
4214 		parm->type = 0;
4215 		parm->size = 0;
4216 		parm->pbuf = NULL;
4217 
4218 		init_h2fwcmd_w_parm_no_rsp(cmdobj, parm, CMD_SET_DRV_EXTRA);
4219 		res = rtw_enqueue_cmd(cmdpriv, cmdobj);
4220 	} else {
4221 		rtw_dfs_rd_hdl(adapter);
4222 		res = _SUCCESS;
4223 	}
4224 
4225 exit:
4226 	return res;
4227 }
4228 
rtw_dfs_rd_timer_hdl(void * ctx)4229 void rtw_dfs_rd_timer_hdl(void *ctx)
4230 {
4231 	struct rf_ctl_t *rfctl = (struct rf_ctl_t *)ctx;
4232 	struct dvobj_priv *dvobj = rfctl_to_dvobj(rfctl);
4233 
4234 	rtw_dfs_rd_cmd(dvobj_get_primary_adapter(dvobj), _TRUE);
4235 }
4236 
rtw_dfs_rd_enable(struct rf_ctl_t * rfctl,u8 ch,u8 bw,u8 offset,bool bypass_cac)4237 static void rtw_dfs_rd_enable(struct rf_ctl_t *rfctl, u8 ch, u8 bw, u8 offset, bool bypass_cac)
4238 {
4239 	struct dvobj_priv *dvobj = rfctl_to_dvobj(rfctl);
4240 	_adapter *adapter = dvobj_get_primary_adapter(dvobj);
4241 
4242 	RTW_INFO("%s on %u,%u,%u\n", __func__, ch, bw, offset);
4243 
4244 	if (bypass_cac)
4245 		rfctl->cac_start_time = rfctl->cac_end_time = RTW_CAC_STOPPED;
4246 	else if (rtw_is_cac_reset_needed(rfctl, ch, bw, offset) == _TRUE)
4247 		rtw_reset_cac(rfctl, ch, bw, offset);
4248 
4249 	rfctl->radar_detect_by_others = _FALSE;
4250 	rfctl->radar_detect_ch = ch;
4251 	rfctl->radar_detect_bw = bw;
4252 	rfctl->radar_detect_offset = offset;
4253 
4254 	rfctl->radar_detected = 0;
4255 
4256 	if (IS_CH_WAITING(rfctl))
4257 		StopTxBeacon(adapter);
4258 
4259 	if (!rfctl->radar_detect_enabled) {
4260 		RTW_INFO("%s set radar_detect_enabled\n", __func__);
4261 		rfctl->radar_detect_enabled = 1;
4262 		#ifdef CONFIG_LPS
4263 		LPS_Leave(adapter, "RADAR_DETECT_EN");
4264 		#endif
4265 		_set_timer(&rfctl->radar_detect_timer
4266 			, rtw_odm_radar_detect_polling_int_ms(dvobj));
4267 
4268 		if (rtw_rfctl_overlap_radar_detect_ch(rfctl)) {
4269 			if (IS_CH_WAITING(rfctl)) {
4270 				u8 pause = 0xFF;
4271 
4272 				rtw_hal_set_hwreg(adapter, HW_VAR_TXPAUSE, &pause);
4273 			}
4274 			rtw_odm_radar_detect_enable(adapter);
4275 		}
4276 	}
4277 }
4278 
rtw_dfs_rd_disable(struct rf_ctl_t * rfctl,u8 ch,u8 bw,u8 offset,bool by_others)4279 static void rtw_dfs_rd_disable(struct rf_ctl_t *rfctl, u8 ch, u8 bw, u8 offset, bool by_others)
4280 {
4281 	_adapter *adapter = dvobj_get_primary_adapter(rfctl_to_dvobj(rfctl));
4282 
4283 	rfctl->radar_detect_by_others = by_others;
4284 
4285 	if (rfctl->radar_detect_enabled) {
4286 		bool overlap_radar_detect_ch = rtw_rfctl_overlap_radar_detect_ch(rfctl);
4287 
4288 		RTW_INFO("%s clear radar_detect_enabled\n", __func__);
4289 
4290 		rfctl->radar_detect_enabled = 0;
4291 		rfctl->radar_detected = 0;
4292 		rfctl->radar_detect_ch = 0;
4293 		rfctl->radar_detect_bw = 0;
4294 		rfctl->radar_detect_offset = 0;
4295 		rfctl->cac_start_time = rfctl->cac_end_time = RTW_CAC_STOPPED;
4296 		_cancel_timer_ex(&rfctl->radar_detect_timer);
4297 
4298 		if (rtw_mi_check_fwstate(adapter, WIFI_UNDER_LINKING|WIFI_UNDER_SURVEY) == _FALSE) {
4299 			ResumeTxBeacon(adapter);
4300 			rtw_mi_tx_beacon_hdl(adapter);
4301 		}
4302 
4303 		if (overlap_radar_detect_ch) {
4304 			u8 pause = 0x00;
4305 
4306 			rtw_hal_set_hwreg(adapter, HW_VAR_TXPAUSE, &pause);
4307 			rtw_odm_radar_detect_disable(adapter);
4308 		}
4309 	}
4310 
4311 	if (by_others) {
4312 		rfctl->radar_detect_ch = ch;
4313 		rfctl->radar_detect_bw = bw;
4314 		rfctl->radar_detect_offset = offset;
4315 	} else {
4316 		rfctl->radar_detect_ch = 0;
4317 		rfctl->radar_detect_bw = 0;
4318 		rfctl->radar_detect_offset = 0;
4319 	}
4320 }
4321 
rtw_dfs_rd_en_decision(_adapter * adapter,u8 mlme_act,u8 excl_ifbmp)4322 void rtw_dfs_rd_en_decision(_adapter *adapter, u8 mlme_act, u8 excl_ifbmp)
4323 {
4324 	struct dvobj_priv *dvobj = adapter_to_dvobj(adapter);
4325 	struct rf_ctl_t *rfctl = adapter_to_rfctl(adapter);
4326 	struct mlme_ext_priv *mlmeext = &adapter->mlmeextpriv;
4327 	struct mi_state mstate;
4328 	u8 ifbmp;
4329 	u8 u_ch, u_bw, u_offset;
4330 	bool ld_sta_in_dfs = _FALSE;
4331 	bool sync_ch = _FALSE; /* _FALSE: asign channel directly */
4332 	bool needed = _FALSE;
4333 
4334 	if (mlme_act == MLME_OPCH_SWITCH
4335 		|| mlme_act == MLME_ACTION_NONE
4336 	) {
4337 		ifbmp = ~excl_ifbmp;
4338 		rtw_mi_status_by_ifbmp(dvobj, ifbmp, &mstate);
4339 		rtw_mi_get_ch_setting_union_by_ifbmp(dvobj, ifbmp, &u_ch, &u_bw, &u_offset);
4340 	} else {
4341 		ifbmp = ~excl_ifbmp & ~BIT(adapter->iface_id);
4342 		rtw_mi_status_by_ifbmp(dvobj, ifbmp, &mstate);
4343 		rtw_mi_get_ch_setting_union_by_ifbmp(dvobj, ifbmp, &u_ch, &u_bw, &u_offset);
4344 		if (u_ch != 0 && !MLME_IS_OPCH_SW(adapter)
4345 			&& CHK_MLME_STATE(adapter, WIFI_UNDER_LINKING | WIFI_ASOC_STATE))
4346 			sync_ch = _TRUE;
4347 
4348 		switch (mlme_act) {
4349 		case MLME_STA_CONNECTING:
4350 			MSTATE_STA_LG_NUM(&mstate)++;
4351 			break;
4352 		case MLME_STA_CONNECTED:
4353 			MSTATE_STA_LD_NUM(&mstate)++;
4354 			break;
4355 		case MLME_STA_DISCONNECTED:
4356 			break;
4357 #ifdef CONFIG_AP_MODE
4358 		case MLME_AP_STARTED:
4359 			MSTATE_AP_NUM(&mstate)++;
4360 			break;
4361 		case MLME_AP_STOPPED:
4362 			break;
4363 #endif
4364 #ifdef CONFIG_RTW_MESH
4365 		case MLME_MESH_STARTED:
4366 			MSTATE_MESH_NUM(&mstate)++;
4367 			break;
4368 		case MLME_MESH_STOPPED:
4369 			break;
4370 #endif
4371 		default:
4372 			rtw_warn_on(1);
4373 			break;
4374 		}
4375 
4376 		if (sync_ch == _TRUE) {
4377 			if (!rtw_is_chbw_grouped(mlmeext->cur_channel, mlmeext->cur_bwmode, mlmeext->cur_ch_offset, u_ch, u_bw, u_offset)) {
4378 				RTW_WARN(FUNC_ADPT_FMT" can't sync %u,%u,%u with %u,%u,%u\n", FUNC_ADPT_ARG(adapter)
4379 					, mlmeext->cur_channel, mlmeext->cur_bwmode, mlmeext->cur_ch_offset, u_ch, u_bw, u_offset);
4380 				goto apply;
4381 			}
4382 
4383 			rtw_sync_chbw(&mlmeext->cur_channel, &mlmeext->cur_bwmode, &mlmeext->cur_ch_offset
4384 				, &u_ch, &u_bw, &u_offset);
4385 		} else {
4386 			u_ch = mlmeext->cur_channel;
4387 			u_bw = mlmeext->cur_bwmode;
4388 			u_offset = mlmeext->cur_ch_offset;
4389 		}
4390 	}
4391 
4392 	if (MSTATE_STA_LG_NUM(&mstate) > 0) {
4393 		/* STA mode is linking */
4394 		goto apply;
4395 	}
4396 
4397 	if (MSTATE_STA_LD_NUM(&mstate) > 0) {
4398 		if (rtw_chset_is_dfs_chbw(rfctl->channel_set, u_ch, u_bw, u_offset)) {
4399 			/*
4400 			* if operate as slave w/o radar detect,
4401 			* rely on AP on which STA mode connects
4402 			*/
4403 			if (IS_DFS_SLAVE_WITH_RD(rfctl) && !rtw_rfctl_dfs_domain_unknown(rfctl))
4404 				needed = _TRUE;
4405 			ld_sta_in_dfs = _TRUE;
4406 		}
4407 		goto apply;
4408 	}
4409 
4410 	if (!MSTATE_AP_NUM(&mstate) && !MSTATE_MESH_NUM(&mstate)) {
4411 		/* No working AP/Mesh mode */
4412 		goto apply;
4413 	}
4414 
4415 	if (rtw_chset_is_dfs_chbw(rfctl->channel_set, u_ch, u_bw, u_offset))
4416 		needed = _TRUE;
4417 
4418 apply:
4419 
4420 	RTW_INFO(FUNC_ADPT_FMT" needed:%d, mlme_act:%u, excl_ifbmp:0x%02x\n"
4421 		, FUNC_ADPT_ARG(adapter), needed, mlme_act, excl_ifbmp);
4422 	RTW_INFO(FUNC_ADPT_FMT" ld_sta_num:%u, lg_sta_num:%u, ap_num:%u, mesh_num:%u, %u,%u,%u\n"
4423 		, FUNC_ADPT_ARG(adapter), MSTATE_STA_LD_NUM(&mstate), MSTATE_STA_LG_NUM(&mstate)
4424 		, MSTATE_AP_NUM(&mstate), MSTATE_MESH_NUM(&mstate)
4425 		, u_ch, u_bw, u_offset);
4426 
4427 	if (needed == _TRUE)
4428 		rtw_dfs_rd_enable(rfctl, u_ch, u_bw, u_offset, ld_sta_in_dfs);
4429 	else
4430 		rtw_dfs_rd_disable(rfctl, u_ch, u_bw, u_offset, ld_sta_in_dfs);
4431 }
4432 
rtw_dfs_rd_en_decision_cmd(_adapter * adapter)4433 u8 rtw_dfs_rd_en_decision_cmd(_adapter *adapter)
4434 {
4435 	struct cmd_obj *cmdobj;
4436 	struct drvextra_cmd_parm *parm;
4437 	struct cmd_priv *cmdpriv = &adapter->cmdpriv;
4438 	u8 res = _FAIL;
4439 
4440 	cmdobj = rtw_zmalloc(sizeof(struct cmd_obj));
4441 	if (cmdobj == NULL)
4442 		goto exit;
4443 
4444 	parm = rtw_zmalloc(sizeof(struct drvextra_cmd_parm));
4445 	if (parm == NULL) {
4446 		rtw_mfree(cmdobj, sizeof(struct cmd_obj));
4447 		goto exit;
4448 	}
4449 
4450 	parm->ec_id = DFS_RADAR_DETECT_EN_DEC_WK_CID;
4451 	parm->type = 0;
4452 	parm->size = 0;
4453 	parm->pbuf = NULL;
4454 
4455 	init_h2fwcmd_w_parm_no_rsp(cmdobj, parm, CMD_SET_DRV_EXTRA);
4456 	res = rtw_enqueue_cmd(cmdpriv, cmdobj);
4457 
4458 exit:
4459 	return res;
4460 }
4461 #endif /* CONFIG_DFS_MASTER */
4462 
4463 #endif /* CONFIG_AP_MODE */
4464 
4465 #ifdef CONFIG_BT_COEXIST
4466 struct btinfo {
4467 	u8 cid;
4468 	u8 len;
4469 
4470 	u8 bConnection:1;
4471 	u8 bSCOeSCO:1;
4472 	u8 bInQPage:1;
4473 	u8 bACLBusy:1;
4474 	u8 bSCOBusy:1;
4475 	u8 bHID:1;
4476 	u8 bA2DP:1;
4477 	u8 bFTP:1;
4478 
4479 	u8 retry_cnt:4;
4480 	u8 rsvd_34:1;
4481 	u8 rsvd_35:1;
4482 	u8 rsvd_36:1;
4483 	u8 rsvd_37:1;
4484 
4485 	u8 rssi;
4486 
4487 	u8 rsvd_50:1;
4488 	u8 rsvd_51:1;
4489 	u8 rsvd_52:1;
4490 	u8 rsvd_53:1;
4491 	u8 rsvd_54:1;
4492 	u8 rsvd_55:1;
4493 	u8 eSCO_SCO:1;
4494 	u8 Master_Slave:1;
4495 
4496 	u8 rsvd_6;
4497 	u8 rsvd_7;
4498 };
4499 
btinfo_evt_dump(void * sel,void * buf)4500 void btinfo_evt_dump(void *sel, void *buf)
4501 {
4502 	struct btinfo *info = (struct btinfo *)buf;
4503 
4504 	RTW_PRINT_SEL(sel, "cid:0x%02x, len:%u\n", info->cid, info->len);
4505 
4506 	if (info->len > 2)
4507 		RTW_PRINT_SEL(sel, "byte2:%s%s%s%s%s%s%s%s\n"
4508 			      , info->bConnection ? "bConnection " : ""
4509 			      , info->bSCOeSCO ? "bSCOeSCO " : ""
4510 			      , info->bInQPage ? "bInQPage " : ""
4511 			      , info->bACLBusy ? "bACLBusy " : ""
4512 			      , info->bSCOBusy ? "bSCOBusy " : ""
4513 			      , info->bHID ? "bHID " : ""
4514 			      , info->bA2DP ? "bA2DP " : ""
4515 			      , info->bFTP ? "bFTP" : ""
4516 			     );
4517 
4518 	if (info->len > 3)
4519 		RTW_PRINT_SEL(sel, "retry_cnt:%u\n", info->retry_cnt);
4520 
4521 	if (info->len > 4)
4522 		RTW_PRINT_SEL(sel, "rssi:%u\n", info->rssi);
4523 
4524 	if (info->len > 5)
4525 		RTW_PRINT_SEL(sel, "byte5:%s%s\n"
4526 			      , info->eSCO_SCO ? "eSCO_SCO " : ""
4527 			      , info->Master_Slave ? "Master_Slave " : ""
4528 			     );
4529 }
4530 
rtw_btinfo_hdl(_adapter * adapter,u8 * buf,u16 buf_len)4531 static void rtw_btinfo_hdl(_adapter *adapter, u8 *buf, u16 buf_len)
4532 {
4533 #define BTINFO_WIFI_FETCH 0x23
4534 #define BTINFO_BT_AUTO_RPT 0x27
4535 #ifdef CONFIG_BT_COEXIST_SOCKET_TRX
4536 	struct btinfo_8761ATV *info = (struct btinfo_8761ATV *)buf;
4537 #else /* !CONFIG_BT_COEXIST_SOCKET_TRX */
4538 	struct btinfo *info = (struct btinfo *)buf;
4539 #endif /* CONFIG_BT_COEXIST_SOCKET_TRX */
4540 	u8 cmd_idx;
4541 	u8 len;
4542 
4543 	cmd_idx = info->cid;
4544 
4545 	if (info->len > buf_len - 2) {
4546 		rtw_warn_on(1);
4547 		len = buf_len - 2;
4548 	} else
4549 		len = info->len;
4550 
4551 	/* #define DBG_PROC_SET_BTINFO_EVT */
4552 #ifdef DBG_PROC_SET_BTINFO_EVT
4553 #ifdef CONFIG_BT_COEXIST_SOCKET_TRX
4554 	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"
4555 		, __func__, buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7]);
4556 #else/* !CONFIG_BT_COEXIST_SOCKET_TRX */
4557 	btinfo_evt_dump(RTW_DBGDUMP, info);
4558 #endif /* CONFIG_BT_COEXIST_SOCKET_TRX */
4559 #endif /* DBG_PROC_SET_BTINFO_EVT */
4560 
4561 	/* transform BT-FW btinfo to WiFI-FW C2H format and notify */
4562 	if (cmd_idx == BTINFO_WIFI_FETCH)
4563 		buf[1] = 0;
4564 	else if (cmd_idx == BTINFO_BT_AUTO_RPT)
4565 		buf[1] = 2;
4566 #ifdef CONFIG_BT_COEXIST_SOCKET_TRX
4567 	else if (0x01 == cmd_idx || 0x02 == cmd_idx)
4568 		buf[1] = buf[0];
4569 #endif /* CONFIG_BT_COEXIST_SOCKET_TRX */
4570 	rtw_btcoex_BtInfoNotify(adapter , len + 1, &buf[1]);
4571 }
4572 
rtw_btinfo_cmd(_adapter * adapter,u8 * buf,u16 len)4573 u8 rtw_btinfo_cmd(_adapter *adapter, u8 *buf, u16 len)
4574 {
4575 	struct cmd_obj *ph2c;
4576 	struct drvextra_cmd_parm *pdrvextra_cmd_parm;
4577 	u8 *btinfo;
4578 	struct cmd_priv *pcmdpriv = &adapter->cmdpriv;
4579 	u8	res = _SUCCESS;
4580 
4581 	ph2c = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
4582 	if (ph2c == NULL) {
4583 		res = _FAIL;
4584 		goto exit;
4585 	}
4586 
4587 	pdrvextra_cmd_parm = (struct drvextra_cmd_parm *)rtw_zmalloc(sizeof(struct drvextra_cmd_parm));
4588 	if (pdrvextra_cmd_parm == NULL) {
4589 		rtw_mfree((u8 *)ph2c, sizeof(struct cmd_obj));
4590 		res = _FAIL;
4591 		goto exit;
4592 	}
4593 
4594 	btinfo = rtw_zmalloc(len);
4595 	if (btinfo == NULL) {
4596 		rtw_mfree((u8 *)ph2c, sizeof(struct cmd_obj));
4597 		rtw_mfree((u8 *)pdrvextra_cmd_parm, sizeof(struct drvextra_cmd_parm));
4598 		res = _FAIL;
4599 		goto exit;
4600 	}
4601 
4602 	pdrvextra_cmd_parm->ec_id = BTINFO_WK_CID;
4603 	pdrvextra_cmd_parm->type = 0;
4604 	pdrvextra_cmd_parm->size = len;
4605 	pdrvextra_cmd_parm->pbuf = btinfo;
4606 
4607 	_rtw_memcpy(btinfo, buf, len);
4608 
4609 	init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, CMD_SET_DRV_EXTRA);
4610 
4611 	res = rtw_enqueue_cmd(pcmdpriv, ph2c);
4612 
4613 exit:
4614 	return res;
4615 }
4616 
rtw_btc_reduce_wl_txpwr_hdl(_adapter * adapter,u32 pwr_lvl)4617 static void rtw_btc_reduce_wl_txpwr_hdl(_adapter *adapter, u32 pwr_lvl)
4618 {
4619 	rtw_btcoex_set_reduced_wl_pwr_lvl(adapter, pwr_lvl);
4620 	rtw_btcoex_do_reduce_wl_pwr_lvl(adapter);
4621 
4622 	RTW_INFO(FUNC_ADPT_FMT ": BTC reduce WL TxPwr %d dB!\n",
4623 		 FUNC_ADPT_ARG(adapter), pwr_lvl);
4624 }
4625 
rtw_btc_reduce_wl_txpwr_cmd(_adapter * adapter,u32 val)4626 u8 rtw_btc_reduce_wl_txpwr_cmd(_adapter *adapter, u32 val)
4627 {
4628 	struct cmd_obj *pcmdobj;
4629 	struct drvextra_cmd_parm *pdrvextra_cmd_parm;
4630 	struct cmd_priv *pcmdpriv = &adapter->cmdpriv;
4631 	u8	res = _SUCCESS;
4632 
4633 	pcmdobj = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
4634 	if (pcmdobj == NULL) {
4635 		res = _FAIL;
4636 		goto exit;
4637 	}
4638 
4639 	pdrvextra_cmd_parm = (struct drvextra_cmd_parm *)rtw_zmalloc(sizeof(struct drvextra_cmd_parm));
4640 	if (pdrvextra_cmd_parm == NULL) {
4641 		rtw_mfree((u8 *)pcmdobj, sizeof(struct cmd_obj));
4642 		res = _FAIL;
4643 		goto exit;
4644 	}
4645 
4646 	pdrvextra_cmd_parm->ec_id = BTC_REDUCE_WL_TXPWR_CID;
4647 	pdrvextra_cmd_parm->type = val;
4648 	pdrvextra_cmd_parm->size = 0;
4649 	pdrvextra_cmd_parm->pbuf = NULL;
4650 
4651 	init_h2fwcmd_w_parm_no_rsp(pcmdobj, pdrvextra_cmd_parm, CMD_SET_DRV_EXTRA);
4652 
4653 	res = rtw_enqueue_cmd(pcmdpriv, pcmdobj);
4654 
4655 exit:
4656 	return res;
4657 }
4658 #endif /* CONFIG_BT_COEXIST */
4659 
rtw_test_h2c_cmd(_adapter * adapter,u8 * buf,u8 len)4660 u8 rtw_test_h2c_cmd(_adapter *adapter, u8 *buf, u8 len)
4661 {
4662 	struct cmd_obj *pcmdobj;
4663 	struct drvextra_cmd_parm *pdrvextra_cmd_parm;
4664 	u8 *ph2c_content;
4665 	struct cmd_priv *pcmdpriv = &adapter->cmdpriv;
4666 	u8	res = _SUCCESS;
4667 
4668 	pcmdobj = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
4669 	if (pcmdobj == NULL) {
4670 		res = _FAIL;
4671 		goto exit;
4672 	}
4673 
4674 	pdrvextra_cmd_parm = (struct drvextra_cmd_parm *)rtw_zmalloc(sizeof(struct drvextra_cmd_parm));
4675 	if (pdrvextra_cmd_parm == NULL) {
4676 		rtw_mfree((u8 *)pcmdobj, sizeof(struct cmd_obj));
4677 		res = _FAIL;
4678 		goto exit;
4679 	}
4680 
4681 	ph2c_content = rtw_zmalloc(len);
4682 	if (ph2c_content == NULL) {
4683 		rtw_mfree((u8 *)pcmdobj, sizeof(struct cmd_obj));
4684 		rtw_mfree((u8 *)pdrvextra_cmd_parm, sizeof(struct drvextra_cmd_parm));
4685 		res = _FAIL;
4686 		goto exit;
4687 	}
4688 
4689 	pdrvextra_cmd_parm->ec_id = TEST_H2C_CID;
4690 	pdrvextra_cmd_parm->type = 0;
4691 	pdrvextra_cmd_parm->size = len;
4692 	pdrvextra_cmd_parm->pbuf = ph2c_content;
4693 
4694 	_rtw_memcpy(ph2c_content, buf, len);
4695 
4696 	init_h2fwcmd_w_parm_no_rsp(pcmdobj, pdrvextra_cmd_parm, CMD_SET_DRV_EXTRA);
4697 
4698 	res = rtw_enqueue_cmd(pcmdpriv, pcmdobj);
4699 
4700 exit:
4701 	return res;
4702 }
4703 
4704 #ifdef CONFIG_MP_INCLUDED
rtw_mp_cmd_hdl(_adapter * padapter,u8 mp_cmd_id)4705 static s32 rtw_mp_cmd_hdl(_adapter *padapter, u8 mp_cmd_id)
4706 {
4707 	HAL_DATA_TYPE	*pHalData = GET_HAL_DATA(padapter);
4708 	int ret = H2C_SUCCESS;
4709 	uint status = _SUCCESS;
4710 
4711 	if (mp_cmd_id == MP_START) {
4712 		if (padapter->registrypriv.mp_mode == 0) {
4713 			rtw_intf_stop(padapter);
4714 			rtw_hal_deinit(padapter);
4715 			padapter->registrypriv.mp_mode = 1;
4716 #ifdef CONFIG_BT_COEXIST
4717 		padapter->mppriv.CureFuseBTCoex = pHalData->EEPROMBluetoothCoexist;
4718 		pHalData->EEPROMBluetoothCoexist = _FALSE;
4719 #endif
4720 #ifdef CONFIG_RF_POWER_TRIM
4721 			if (!IS_HARDWARE_TYPE_8814A(padapter) && !IS_HARDWARE_TYPE_8822B(padapter)
4722 				&& !IS_HARDWARE_TYPE_8822C(padapter) && !IS_HARDWARE_TYPE_8723F(padapter)) {
4723 				padapter->registrypriv.RegPwrTrimEnable = 1;
4724 				rtw_hal_read_chip_info(padapter);
4725 			}
4726 #endif /*CONFIG_RF_POWER_TRIM*/
4727 			rtw_reset_drv_sw(padapter);
4728 #ifdef CONFIG_NEW_NETDEV_HDL
4729 			if (!rtw_is_hw_init_completed(padapter)) {
4730 				status = rtw_hal_init(padapter);
4731 				if (status == _FAIL) {
4732 					ret = H2C_REJECTED;
4733 					goto exit;
4734 				}
4735 				rtw_hal_iface_init(padapter);
4736 			}
4737 #else
4738 			status = rtw_hal_init(padapter);
4739 			if (status == _FAIL) {
4740 				ret = H2C_REJECTED;
4741 				goto exit;
4742 			}
4743 #endif /*CONFIG_NEW_NETDEV_HDL*/
4744 #ifndef RTW_HALMAC
4745 			rtw_intf_start(padapter);
4746 #endif /* !RTW_HALMAC */
4747 #ifdef RTW_HALMAC /*for New IC*/
4748 			MPT_InitializeAdapter(padapter, 1);
4749 #endif /* CONFIG_MP_INCLUDED */
4750 		}
4751 
4752 		if (padapter->registrypriv.mp_mode == 0) {
4753 			ret = H2C_REJECTED;
4754 			goto exit;
4755 		}
4756 
4757 		if (padapter->mppriv.mode == MP_OFF) {
4758 			if (mp_start_test(padapter) == _FAIL) {
4759 				ret = H2C_REJECTED;
4760 				goto exit;
4761 			}
4762 			padapter->mppriv.mode = MP_ON;
4763 			MPT_PwrCtlDM(padapter, 0);
4764 		}
4765 		padapter->mppriv.bmac_filter = _FALSE;
4766 #ifdef CONFIG_RTL8723B
4767 #ifdef CONFIG_USB_HCI
4768 		rtw_write32(padapter, 0x765, 0x0000);
4769 		rtw_write32(padapter, 0x948, 0x0280);
4770 #else
4771 		rtw_write32(padapter, 0x765, 0x0000);
4772 		rtw_write32(padapter, 0x948, 0x0000);
4773 #endif
4774 #ifdef CONFIG_FOR_RTL8723BS_VQ0
4775 		rtw_write32(padapter, 0x765, 0x0000);
4776 		rtw_write32(padapter, 0x948, 0x0280);
4777 #endif
4778 		rtw_write8(padapter, 0x66, 0x27); /*Open BT uart Log*/
4779 		rtw_write8(padapter, 0xc50, 0x20); /*for RX init Gain*/
4780 #endif
4781 		odm_write_dig(&pHalData->odmpriv, 0x20);
4782 
4783 	} else if (mp_cmd_id == MP_STOP) {
4784 		if (padapter->registrypriv.mp_mode == 1) {
4785 			MPT_DeInitAdapter(padapter);
4786 			rtw_intf_stop(padapter);
4787 			rtw_hal_deinit(padapter);
4788 			padapter->registrypriv.mp_mode = 0;
4789 #ifdef CONFIG_BT_COEXIST
4790 			pHalData->EEPROMBluetoothCoexist = padapter->mppriv.CureFuseBTCoex;
4791 #endif
4792 			rtw_reset_drv_sw(padapter);
4793 #ifdef CONFIG_NEW_NETDEV_HDL
4794 			if (!rtw_is_hw_init_completed(padapter)) {
4795 				status = rtw_hal_init(padapter);
4796 				if (status == _FAIL) {
4797 					ret = H2C_REJECTED;
4798 					goto exit;
4799 				}
4800 				rtw_hal_iface_init(padapter);
4801 			}
4802 #else
4803 			status = rtw_hal_init(padapter);
4804 			if (status == _FAIL) {
4805 				ret = H2C_REJECTED;
4806 				goto exit;
4807 			}
4808 #endif /*CONFIG_NEW_NETDEV_HDL*/
4809 #ifndef RTW_HALMAC
4810 			rtw_intf_start(padapter);
4811 #endif /* !RTW_HALMAC */
4812 		}
4813 
4814 		if (padapter->mppriv.mode != MP_OFF) {
4815 			mp_stop_test(padapter);
4816 			padapter->mppriv.mode = MP_OFF;
4817 		}
4818 
4819 	} else {
4820 		RTW_INFO(FUNC_ADPT_FMT"invalid id:%d\n", FUNC_ADPT_ARG(padapter), mp_cmd_id);
4821 		ret = H2C_PARAMETERS_ERROR;
4822 		rtw_warn_on(1);
4823 	}
4824 
4825 exit:
4826 	return ret;
4827 }
4828 
rtw_mp_cmd(_adapter * adapter,u8 mp_cmd_id,u8 flags)4829 u8 rtw_mp_cmd(_adapter *adapter, u8 mp_cmd_id, u8 flags)
4830 {
4831 	struct cmd_obj *cmdobj;
4832 	struct drvextra_cmd_parm *parm;
4833 	struct cmd_priv *pcmdpriv = &adapter->cmdpriv;
4834 	struct submit_ctx sctx;
4835 	u8	res = _SUCCESS;
4836 
4837 	parm = (struct drvextra_cmd_parm *)rtw_zmalloc(sizeof(struct drvextra_cmd_parm));
4838 	if (parm == NULL) {
4839 		res = _FAIL;
4840 		goto exit;
4841 	}
4842 
4843 	parm->ec_id = MP_CMD_WK_CID;
4844 	parm->type = mp_cmd_id;
4845 	parm->size = 0;
4846 	parm->pbuf = NULL;
4847 
4848 	if (flags & RTW_CMDF_DIRECTLY) {
4849 		/* no need to enqueue, do the cmd hdl directly and free cmd parameter */
4850 		if (H2C_SUCCESS != rtw_mp_cmd_hdl(adapter, mp_cmd_id))
4851 			res = _FAIL;
4852 		rtw_mfree((u8 *)parm, sizeof(*parm));
4853 	} else {
4854 		/* need enqueue, prepare cmd_obj and enqueue */
4855 		cmdobj = (struct cmd_obj *)rtw_zmalloc(sizeof(*cmdobj));
4856 		if (cmdobj == NULL) {
4857 			res = _FAIL;
4858 			rtw_mfree((u8 *)parm, sizeof(*parm));
4859 			goto exit;
4860 		}
4861 
4862 		init_h2fwcmd_w_parm_no_rsp(cmdobj, parm, CMD_SET_DRV_EXTRA);
4863 
4864 		if (flags & RTW_CMDF_WAIT_ACK) {
4865 			cmdobj->sctx = &sctx;
4866 			rtw_sctx_init(&sctx, 10 * 1000);
4867 		}
4868 
4869 		res = rtw_enqueue_cmd(pcmdpriv, cmdobj);
4870 
4871 		if (res == _SUCCESS && (flags & RTW_CMDF_WAIT_ACK)) {
4872 			rtw_sctx_wait(&sctx, __func__);
4873 			_enter_critical_mutex(&pcmdpriv->sctx_mutex, NULL);
4874 			if (sctx.status == RTW_SCTX_SUBMITTED)
4875 				cmdobj->sctx = NULL;
4876 			_exit_critical_mutex(&pcmdpriv->sctx_mutex, NULL);
4877 			if (sctx.status != RTW_SCTX_DONE_SUCCESS)
4878 				res = _FAIL;
4879 		}
4880 	}
4881 
4882 exit:
4883 	return res;
4884 }
4885 #endif	/*CONFIG_MP_INCLUDED*/
4886 
4887 #ifdef CONFIG_RTW_CUSTOMER_STR
rtw_customer_str_cmd_hdl(_adapter * adapter,u8 write,const u8 * cstr)4888 static s32 rtw_customer_str_cmd_hdl(_adapter *adapter, u8 write, const u8 *cstr)
4889 {
4890 	int ret = H2C_SUCCESS;
4891 
4892 	if (write)
4893 		ret = rtw_hal_h2c_customer_str_write(adapter, cstr);
4894 	else
4895 		ret = rtw_hal_h2c_customer_str_req(adapter);
4896 
4897 	return ret == _SUCCESS ? H2C_SUCCESS : H2C_REJECTED;
4898 }
4899 
rtw_customer_str_cmd(_adapter * adapter,u8 write,const u8 * cstr)4900 static u8 rtw_customer_str_cmd(_adapter *adapter, u8 write, const u8 *cstr)
4901 {
4902 	struct cmd_obj *cmdobj;
4903 	struct drvextra_cmd_parm *parm;
4904 	u8 *str = NULL;
4905 	struct cmd_priv *pcmdpriv = &adapter->cmdpriv;
4906 	struct submit_ctx sctx;
4907 	u8 res = _SUCCESS;
4908 
4909 	parm = (struct drvextra_cmd_parm *)rtw_zmalloc(sizeof(struct drvextra_cmd_parm));
4910 	if (parm == NULL) {
4911 		res = _FAIL;
4912 		goto exit;
4913 	}
4914 
4915 	if (write) {
4916 		str = rtw_zmalloc(RTW_CUSTOMER_STR_LEN);
4917 		if (str == NULL) {
4918 			rtw_mfree((u8 *)parm, sizeof(struct drvextra_cmd_parm));
4919 			res = _FAIL;
4920 			goto exit;
4921 		}
4922 	}
4923 
4924 	parm->ec_id = CUSTOMER_STR_WK_CID;
4925 	parm->type = write;
4926 	parm->size = write ? RTW_CUSTOMER_STR_LEN : 0;
4927 	parm->pbuf = write ? str : NULL;
4928 
4929 	if (write)
4930 		_rtw_memcpy(str, cstr, RTW_CUSTOMER_STR_LEN);
4931 
4932 	/* need enqueue, prepare cmd_obj and enqueue */
4933 	cmdobj = (struct cmd_obj *)rtw_zmalloc(sizeof(*cmdobj));
4934 	if (cmdobj == NULL) {
4935 		res = _FAIL;
4936 		rtw_mfree((u8 *)parm, sizeof(*parm));
4937 		if (write)
4938 			rtw_mfree(str, RTW_CUSTOMER_STR_LEN);
4939 		goto exit;
4940 	}
4941 
4942 	init_h2fwcmd_w_parm_no_rsp(cmdobj, parm, CMD_SET_DRV_EXTRA);
4943 
4944 	cmdobj->sctx = &sctx;
4945 	rtw_sctx_init(&sctx, 2 * 1000);
4946 
4947 	res = rtw_enqueue_cmd(pcmdpriv, cmdobj);
4948 
4949 	if (res == _SUCCESS) {
4950 		rtw_sctx_wait(&sctx, __func__);
4951 		_enter_critical_mutex(&pcmdpriv->sctx_mutex, NULL);
4952 		if (sctx.status == RTW_SCTX_SUBMITTED)
4953 			cmdobj->sctx = NULL;
4954 		_exit_critical_mutex(&pcmdpriv->sctx_mutex, NULL);
4955 		if (sctx.status != RTW_SCTX_DONE_SUCCESS)
4956 			res = _FAIL;
4957 	}
4958 
4959 exit:
4960 	return res;
4961 }
4962 
rtw_customer_str_req_cmd(_adapter * adapter)4963 inline u8 rtw_customer_str_req_cmd(_adapter *adapter)
4964 {
4965 	return rtw_customer_str_cmd(adapter, 0, NULL);
4966 }
4967 
rtw_customer_str_write_cmd(_adapter * adapter,const u8 * cstr)4968 inline u8 rtw_customer_str_write_cmd(_adapter *adapter, const u8 *cstr)
4969 {
4970 	return rtw_customer_str_cmd(adapter, 1, cstr);
4971 }
4972 #endif /* CONFIG_RTW_CUSTOMER_STR */
4973 
rtw_c2h_wk_cmd(PADAPTER padapter,u8 * pbuf,u16 length,u8 type)4974 u8 rtw_c2h_wk_cmd(PADAPTER padapter, u8 *pbuf, u16 length, u8 type)
4975 {
4976 	struct cmd_obj *ph2c;
4977 	struct drvextra_cmd_parm *pdrvextra_cmd_parm;
4978 	struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
4979 	u8 *extra_cmd_buf;
4980 	u8 res = _SUCCESS;
4981 
4982 	ph2c = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
4983 	if (ph2c == NULL) {
4984 		res = _FAIL;
4985 		goto exit;
4986 	}
4987 
4988 	pdrvextra_cmd_parm = (struct drvextra_cmd_parm *)rtw_zmalloc(sizeof(struct drvextra_cmd_parm));
4989 	if (pdrvextra_cmd_parm == NULL) {
4990 		rtw_mfree((u8 *)ph2c, sizeof(struct cmd_obj));
4991 		res = _FAIL;
4992 		goto exit;
4993 	}
4994 
4995 	extra_cmd_buf = rtw_zmalloc(length);
4996 	if (extra_cmd_buf == NULL) {
4997 		rtw_mfree((u8 *)ph2c, sizeof(struct cmd_obj));
4998 		rtw_mfree((u8 *)pdrvextra_cmd_parm, sizeof(struct drvextra_cmd_parm));
4999 		res = _FAIL;
5000 		goto exit;
5001 	}
5002 
5003 	_rtw_memcpy(extra_cmd_buf, pbuf, length);
5004 	pdrvextra_cmd_parm->ec_id = C2H_WK_CID;
5005 	pdrvextra_cmd_parm->type = type;
5006 	pdrvextra_cmd_parm->size = length;
5007 	pdrvextra_cmd_parm->pbuf = extra_cmd_buf;
5008 
5009 	init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, CMD_SET_DRV_EXTRA);
5010 
5011 	res = rtw_enqueue_cmd(pcmdpriv, ph2c);
5012 
5013 exit:
5014 	return res;
5015 }
5016 
5017 #ifdef CONFIG_FW_C2H_REG
rtw_c2h_reg_wk_cmd(_adapter * adapter,u8 * c2h_evt)5018 inline u8 rtw_c2h_reg_wk_cmd(_adapter *adapter, u8 *c2h_evt)
5019 {
5020 	return rtw_c2h_wk_cmd(adapter, c2h_evt, c2h_evt ? C2H_REG_LEN : 0, C2H_TYPE_REG);
5021 }
5022 #endif
5023 
5024 #ifdef CONFIG_FW_C2H_PKT
rtw_c2h_packet_wk_cmd(_adapter * adapter,u8 * c2h_evt,u16 length)5025 inline u8 rtw_c2h_packet_wk_cmd(_adapter *adapter, u8 *c2h_evt, u16 length)
5026 {
5027 	return rtw_c2h_wk_cmd(adapter, c2h_evt, length, C2H_TYPE_PKT);
5028 }
5029 #endif
5030 
_rtw_run_in_thread_cmd(_adapter * adapter,void (* func)(void *),void * context,s32 timeout_ms)5031 static u8 _rtw_run_in_thread_cmd(_adapter *adapter, void (*func)(void *), void *context, s32 timeout_ms)
5032 {
5033 	struct cmd_priv *cmdpriv = &adapter->cmdpriv;
5034 	struct cmd_obj *cmdobj;
5035 	struct RunInThread_param *parm;
5036 	struct submit_ctx sctx;
5037 	s32 res = _SUCCESS;
5038 
5039 	cmdobj = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
5040 	if (NULL == cmdobj) {
5041 		res = _FAIL;
5042 		goto exit;
5043 	}
5044 
5045 	parm = (struct RunInThread_param *)rtw_zmalloc(sizeof(struct RunInThread_param));
5046 	if (NULL == parm) {
5047 		rtw_mfree((u8 *)cmdobj, sizeof(struct cmd_obj));
5048 		res = _FAIL;
5049 		goto exit;
5050 	}
5051 
5052 	parm->func = func;
5053 	parm->context = context;
5054 	init_h2fwcmd_w_parm_no_rsp(cmdobj, parm, CMD_RUN_INTHREAD);
5055 
5056 	if (timeout_ms >= 0) {
5057 		cmdobj->sctx = &sctx;
5058 		rtw_sctx_init(&sctx, timeout_ms);
5059 	}
5060 
5061 	res = rtw_enqueue_cmd(cmdpriv, cmdobj);
5062 
5063 	if (res == _SUCCESS && timeout_ms >= 0) {
5064 		rtw_sctx_wait(&sctx, __func__);
5065 		_enter_critical_mutex(&cmdpriv->sctx_mutex, NULL);
5066 		if (sctx.status == RTW_SCTX_SUBMITTED)
5067 			cmdobj->sctx = NULL;
5068 		_exit_critical_mutex(&cmdpriv->sctx_mutex, NULL);
5069 		if (sctx.status != RTW_SCTX_DONE_SUCCESS)
5070 			res = _FAIL;
5071 	}
5072 
5073 exit:
5074 	return res;
5075 }
5076 
rtw_run_in_thread_cmd(_adapter * adapter,void (* func)(void *),void * context)5077 u8 rtw_run_in_thread_cmd(_adapter *adapter, void (*func)(void *), void *context)
5078 {
5079 	return _rtw_run_in_thread_cmd(adapter, func, context, -1);
5080 }
5081 
rtw_run_in_thread_cmd_wait(_adapter * adapter,void (* func)(void *),void * context,s32 timeout_ms)5082 u8 rtw_run_in_thread_cmd_wait(_adapter *adapter, void (*func)(void *), void *context, s32 timeout_ms)
5083 {
5084 	return _rtw_run_in_thread_cmd(adapter, func, context, timeout_ms);
5085 }
5086 
5087 #ifdef CONFIG_FW_C2H_REG
c2h_evt_hdl(_adapter * adapter,u8 * c2h_evt,c2h_id_filter filter)5088 s32 c2h_evt_hdl(_adapter *adapter, u8 *c2h_evt, c2h_id_filter filter)
5089 {
5090 	s32 ret = _FAIL;
5091 	u8 buf[C2H_REG_LEN] = {0};
5092 	u8 id, seq, plen;
5093 	u8 *payload;
5094 
5095 	if (!c2h_evt) {
5096 		/* No c2h event in cmd_obj, read c2h event before handling*/
5097 		if (rtw_hal_c2h_evt_read(adapter, buf) != _SUCCESS)
5098 			goto exit;
5099 		c2h_evt = buf;
5100 	}
5101 
5102 	rtw_hal_c2h_reg_hdr_parse(adapter, c2h_evt, &id, &seq, &plen, &payload);
5103 
5104 	if (filter && filter(adapter, id, seq, plen, payload) == _FALSE)
5105 		goto exit;
5106 
5107 	ret = rtw_hal_c2h_handler(adapter, id, seq, plen, payload);
5108 
5109 exit:
5110 	return ret;
5111 }
5112 #endif /* CONFIG_FW_C2H_REG */
5113 
session_tracker_cmd(_adapter * adapter,u8 cmd,struct sta_info * sta,u8 * local_naddr,u8 * local_port,u8 * remote_naddr,u8 * remote_port)5114 u8 session_tracker_cmd(_adapter *adapter, u8 cmd, struct sta_info *sta, u8 *local_naddr, u8 *local_port, u8 *remote_naddr, u8 *remote_port)
5115 {
5116 	struct cmd_priv	*cmdpriv = &adapter->cmdpriv;
5117 	struct cmd_obj *cmdobj;
5118 	struct drvextra_cmd_parm *cmd_parm;
5119 	struct st_cmd_parm *st_parm;
5120 	u8	res = _SUCCESS;
5121 
5122 	cmdobj = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
5123 	if (cmdobj == NULL) {
5124 		res = _FAIL;
5125 		goto exit;
5126 	}
5127 
5128 	cmd_parm = (struct drvextra_cmd_parm *)rtw_zmalloc(sizeof(struct drvextra_cmd_parm));
5129 	if (cmd_parm == NULL) {
5130 		rtw_mfree((u8 *)cmdobj, sizeof(struct cmd_obj));
5131 		res = _FAIL;
5132 		goto exit;
5133 	}
5134 
5135 	st_parm = (struct st_cmd_parm *)rtw_zmalloc(sizeof(struct st_cmd_parm));
5136 	if (st_parm == NULL) {
5137 		rtw_mfree((u8 *)cmdobj, sizeof(struct cmd_obj));
5138 		rtw_mfree((u8 *)cmd_parm, sizeof(struct drvextra_cmd_parm));
5139 		res = _FAIL;
5140 		goto exit;
5141 	}
5142 
5143 	st_parm->cmd = cmd;
5144 	st_parm->sta = sta;
5145 	if (cmd != ST_CMD_CHK) {
5146 		_rtw_memcpy(&st_parm->local_naddr, local_naddr, 4);
5147 		_rtw_memcpy(&st_parm->local_port, local_port, 2);
5148 		_rtw_memcpy(&st_parm->remote_naddr, remote_naddr, 4);
5149 		_rtw_memcpy(&st_parm->remote_port, remote_port, 2);
5150 	}
5151 
5152 	cmd_parm->ec_id = SESSION_TRACKER_WK_CID;
5153 	cmd_parm->type = 0;
5154 	cmd_parm->size = sizeof(struct st_cmd_parm);
5155 	cmd_parm->pbuf = (u8 *)st_parm;
5156 	init_h2fwcmd_w_parm_no_rsp(cmdobj, cmd_parm, CMD_SET_DRV_EXTRA);
5157 	cmdobj->no_io = 1;
5158 
5159 	res = rtw_enqueue_cmd(cmdpriv, cmdobj);
5160 
5161 exit:
5162 	return res;
5163 }
5164 
session_tracker_chk_cmd(_adapter * adapter,struct sta_info * sta)5165 inline u8 session_tracker_chk_cmd(_adapter *adapter, struct sta_info *sta)
5166 {
5167 	return session_tracker_cmd(adapter, ST_CMD_CHK, sta, NULL, NULL, NULL, NULL);
5168 }
5169 
session_tracker_add_cmd(_adapter * adapter,struct sta_info * sta,u8 * local_naddr,u8 * local_port,u8 * remote_naddr,u8 * remote_port)5170 inline u8 session_tracker_add_cmd(_adapter *adapter, struct sta_info *sta, u8 *local_naddr, u8 *local_port, u8 *remote_naddr, u8 *remote_port)
5171 {
5172 	return session_tracker_cmd(adapter, ST_CMD_ADD, sta, local_naddr, local_port, remote_naddr, remote_port);
5173 }
5174 
session_tracker_del_cmd(_adapter * adapter,struct sta_info * sta,u8 * local_naddr,u8 * local_port,u8 * remote_naddr,u8 * remote_port)5175 inline u8 session_tracker_del_cmd(_adapter *adapter, struct sta_info *sta, u8 *local_naddr, u8 *local_port, u8 *remote_naddr, u8 *remote_port)
5176 {
5177 	return session_tracker_cmd(adapter, ST_CMD_DEL, sta, local_naddr, local_port, remote_naddr, remote_port);
5178 }
5179 
session_tracker_chk_for_sta(_adapter * adapter,struct sta_info * sta)5180 void session_tracker_chk_for_sta(_adapter *adapter, struct sta_info *sta)
5181 {
5182 	struct st_ctl_t *st_ctl = &sta->st_ctl;
5183 	int i;
5184 	_irqL irqL;
5185 	_list *plist, *phead, *pnext;
5186 	_list dlist;
5187 	struct session_tracker *st = NULL;
5188 	u8 op_wfd_mode = MIRACAST_DISABLED;
5189 
5190 	if (DBG_SESSION_TRACKER)
5191 		RTW_INFO(FUNC_ADPT_FMT" sta:%p\n", FUNC_ADPT_ARG(adapter), sta);
5192 
5193 	if (!(sta->state & WIFI_ASOC_STATE))
5194 		goto exit;
5195 
5196 	for (i = 0; i < SESSION_TRACKER_REG_ID_NUM; i++) {
5197 		if (st_ctl->reg[i].s_proto != 0)
5198 			break;
5199 	}
5200 	if (i >= SESSION_TRACKER_REG_ID_NUM)
5201 		goto chk_sta;
5202 
5203 	_rtw_init_listhead(&dlist);
5204 
5205 	_enter_critical_bh(&st_ctl->tracker_q.lock, &irqL);
5206 
5207 	phead = &st_ctl->tracker_q.queue;
5208 	plist = get_next(phead);
5209 	pnext = get_next(plist);
5210 	while (rtw_end_of_queue_search(phead, plist) == _FALSE) {
5211 		st = LIST_CONTAINOR(plist, struct session_tracker, list);
5212 		plist = pnext;
5213 		pnext = get_next(pnext);
5214 
5215 		if (st->status != ST_STATUS_ESTABLISH
5216 			&& rtw_get_passing_time_ms(st->set_time) > ST_EXPIRE_MS
5217 		) {
5218 			rtw_list_delete(&st->list);
5219 			rtw_list_insert_tail(&st->list, &dlist);
5220 		}
5221 
5222 		/* TODO: check OS for status update */
5223 		if (st->status == ST_STATUS_CHECK)
5224 			st->status = ST_STATUS_ESTABLISH;
5225 
5226 		if (st->status != ST_STATUS_ESTABLISH)
5227 			continue;
5228 
5229 		#ifdef CONFIG_WFD
5230 		if (0)
5231 			RTW_INFO(FUNC_ADPT_FMT" local:%u, remote:%u, rtsp:%u, %u, %u\n", FUNC_ADPT_ARG(adapter)
5232 				, ntohs(st->local_port), ntohs(st->remote_port), adapter->wfd_info.rtsp_ctrlport, adapter->wfd_info.tdls_rtsp_ctrlport
5233 				, adapter->wfd_info.peer_rtsp_ctrlport);
5234 		if (ntohs(st->local_port) == adapter->wfd_info.rtsp_ctrlport)
5235 			op_wfd_mode |= MIRACAST_SINK;
5236 		if (ntohs(st->local_port) == adapter->wfd_info.tdls_rtsp_ctrlport)
5237 			op_wfd_mode |= MIRACAST_SINK;
5238 		if (ntohs(st->remote_port) == adapter->wfd_info.peer_rtsp_ctrlport)
5239 			op_wfd_mode |= MIRACAST_SOURCE;
5240 		#endif
5241 	}
5242 
5243 	_exit_critical_bh(&st_ctl->tracker_q.lock, &irqL);
5244 
5245 	plist = get_next(&dlist);
5246 	while (rtw_end_of_queue_search(&dlist, plist) == _FALSE) {
5247 		st = LIST_CONTAINOR(plist, struct session_tracker, list);
5248 		plist = get_next(plist);
5249 		rtw_mfree((u8 *)st, sizeof(struct session_tracker));
5250 	}
5251 
5252 chk_sta:
5253 	if (STA_OP_WFD_MODE(sta) != op_wfd_mode) {
5254 		STA_SET_OP_WFD_MODE(sta, op_wfd_mode);
5255 		rtw_sta_media_status_rpt_cmd(adapter, sta, 1);
5256 	}
5257 
5258 exit:
5259 	return;
5260 }
5261 
session_tracker_chk_for_adapter(_adapter * adapter)5262 void session_tracker_chk_for_adapter(_adapter *adapter)
5263 {
5264 	struct sta_priv *stapriv = &adapter->stapriv;
5265 	struct sta_info *sta;
5266 	int i;
5267 	_irqL irqL;
5268 	_list *plist, *phead;
5269 	u8 op_wfd_mode = MIRACAST_DISABLED;
5270 
5271 	_enter_critical_bh(&stapriv->sta_hash_lock, &irqL);
5272 
5273 	for (i = 0; i < NUM_STA; i++) {
5274 		phead = &(stapriv->sta_hash[i]);
5275 		plist = get_next(phead);
5276 
5277 		while ((rtw_end_of_queue_search(phead, plist)) == _FALSE) {
5278 			sta = LIST_CONTAINOR(plist, struct sta_info, hash_list);
5279 			plist = get_next(plist);
5280 
5281 			session_tracker_chk_for_sta(adapter, sta);
5282 
5283 			op_wfd_mode |= STA_OP_WFD_MODE(sta);
5284 		}
5285 	}
5286 
5287 	_exit_critical_bh(&stapriv->sta_hash_lock, &irqL);
5288 
5289 #ifdef CONFIG_WFD
5290 	adapter->wfd_info.op_wfd_mode = MIRACAST_MODE_REVERSE(op_wfd_mode);
5291 #endif
5292 }
5293 
session_tracker_cmd_hdl(_adapter * adapter,struct st_cmd_parm * parm)5294 void session_tracker_cmd_hdl(_adapter *adapter, struct st_cmd_parm *parm)
5295 {
5296 	u8 cmd = parm->cmd;
5297 	struct sta_info *sta = parm->sta;
5298 
5299 	if (cmd == ST_CMD_CHK) {
5300 		if (sta)
5301 			session_tracker_chk_for_sta(adapter, sta);
5302 		else
5303 			session_tracker_chk_for_adapter(adapter);
5304 
5305 		goto exit;
5306 
5307 	} else if (cmd == ST_CMD_ADD || cmd == ST_CMD_DEL) {
5308 		struct st_ctl_t *st_ctl;
5309 		u32 local_naddr = parm->local_naddr;
5310 		u16 local_port = parm->local_port;
5311 		u32 remote_naddr = parm->remote_naddr;
5312 		u16 remote_port = parm->remote_port;
5313 		struct session_tracker *st = NULL;
5314 		_irqL irqL;
5315 		_list *plist, *phead;
5316 		u8 free_st = 0;
5317 		u8 alloc_st = 0;
5318 
5319 		if (DBG_SESSION_TRACKER)
5320 			RTW_INFO(FUNC_ADPT_FMT" cmd:%u, sta:%p, local:"IP_FMT":"PORT_FMT", remote:"IP_FMT":"PORT_FMT"\n"
5321 				, FUNC_ADPT_ARG(adapter), cmd, sta
5322 				, IP_ARG(&local_naddr), PORT_ARG(&local_port)
5323 				, IP_ARG(&remote_naddr), PORT_ARG(&remote_port)
5324 			);
5325 
5326 		if (!(sta->state & WIFI_ASOC_STATE))
5327 			goto exit;
5328 
5329 		st_ctl = &sta->st_ctl;
5330 
5331 		_enter_critical_bh(&st_ctl->tracker_q.lock, &irqL);
5332 
5333 		phead = &st_ctl->tracker_q.queue;
5334 		plist = get_next(phead);
5335 		while (rtw_end_of_queue_search(phead, plist) == _FALSE) {
5336 			st = LIST_CONTAINOR(plist, struct session_tracker, list);
5337 
5338 			if (st->local_naddr == local_naddr
5339 				&& st->local_port == local_port
5340 				&& st->remote_naddr == remote_naddr
5341 				&& st->remote_port == remote_port)
5342 				break;
5343 
5344 			plist = get_next(plist);
5345 		}
5346 
5347 		if (rtw_end_of_queue_search(phead, plist) == _TRUE)
5348 			st = NULL;
5349 
5350 		switch (cmd) {
5351 		case ST_CMD_DEL:
5352 			if (st) {
5353 				rtw_list_delete(plist);
5354 				free_st = 1;
5355 			}
5356 			goto unlock;
5357 		case ST_CMD_ADD:
5358 			if (!st)
5359 				alloc_st = 1;
5360 		}
5361 
5362 unlock:
5363 		_exit_critical_bh(&st_ctl->tracker_q.lock, &irqL);
5364 
5365 		if (free_st) {
5366 			rtw_mfree((u8 *)st, sizeof(struct session_tracker));
5367 			goto exit;
5368 		}
5369 
5370 		if (alloc_st) {
5371 			st = (struct session_tracker *)rtw_zmalloc(sizeof(struct session_tracker));
5372 			if (!st)
5373 				goto exit;
5374 
5375 			st->local_naddr = local_naddr;
5376 			st->local_port = local_port;
5377 			st->remote_naddr = remote_naddr;
5378 			st->remote_port = remote_port;
5379 			st->set_time = rtw_get_current_time();
5380 			st->status = ST_STATUS_CHECK;
5381 
5382 			_enter_critical_bh(&st_ctl->tracker_q.lock, &irqL);
5383 			rtw_list_insert_tail(&st->list, phead);
5384 			_exit_critical_bh(&st_ctl->tracker_q.lock, &irqL);
5385 		}
5386 	}
5387 
5388 exit:
5389 	return;
5390 }
5391 
5392 #if defined(CONFIG_RTW_MESH) && defined(RTW_PER_CMD_SUPPORT_FW)
rtw_req_per_cmd_hdl(_adapter * adapter)5393 static s32 rtw_req_per_cmd_hdl(_adapter *adapter)
5394 {
5395 	struct dvobj_priv *dvobj = adapter_to_dvobj(adapter);
5396 	struct macid_ctl_t *macid_ctl = dvobj_to_macidctl(dvobj);
5397 	struct macid_bmp req_macid_bmp, *macid_bmp;
5398 	u8 i, ret = _FAIL;
5399 
5400 	macid_bmp = &macid_ctl->if_g[adapter->iface_id];
5401 	_rtw_memcpy(&req_macid_bmp, macid_bmp, sizeof(struct macid_bmp));
5402 
5403 	/* Clear none mesh's macid */
5404 	for (i = 0; i < macid_ctl->num; i++) {
5405 		u8 role;
5406 		role = GET_H2CCMD_MSRRPT_PARM_ROLE(&macid_ctl->h2c_msr[i]);
5407 		if (role != H2C_MSR_ROLE_MESH)
5408 			rtw_macid_map_clr(&req_macid_bmp, i);
5409 	}
5410 
5411 	/* group_macid: always be 0 in NIC, so only pass macid_bitmap.m0
5412 	 * rpt_type: 0 includes all info in 1, use 0 for now
5413 	 * macid_bitmap: pass m0 only for NIC
5414 	 */
5415 	ret = rtw_hal_set_req_per_rpt_cmd(adapter, 0, 0, req_macid_bmp.m0);
5416 
5417 	return ret;
5418 }
5419 
rtw_req_per_cmd(_adapter * adapter)5420 u8 rtw_req_per_cmd(_adapter *adapter)
5421 {
5422 	struct cmd_obj *cmdobj;
5423 	struct drvextra_cmd_parm *parm;
5424 	struct cmd_priv *pcmdpriv = &adapter->cmdpriv;
5425 	struct submit_ctx sctx;
5426 	u8 res = _SUCCESS;
5427 
5428 	parm = (struct drvextra_cmd_parm *)rtw_zmalloc(sizeof(struct drvextra_cmd_parm));
5429 	if (parm == NULL) {
5430 		res = _FAIL;
5431 		goto exit;
5432 	}
5433 
5434 	parm->ec_id = REQ_PER_CMD_WK_CID;
5435 	parm->type = 0;
5436 	parm->size = 0;
5437 	parm->pbuf = NULL;
5438 
5439 	cmdobj = (struct cmd_obj *)rtw_zmalloc(sizeof(*cmdobj));
5440 	if (cmdobj == NULL) {
5441 		res = _FAIL;
5442 		rtw_mfree((u8 *)parm, sizeof(*parm));
5443 		goto exit;
5444 	}
5445 
5446 	init_h2fwcmd_w_parm_no_rsp(cmdobj, parm, CMD_SET_DRV_EXTRA);
5447 
5448 	res = rtw_enqueue_cmd(pcmdpriv, cmdobj);
5449 
5450 exit:
5451 	return res;
5452 }
5453 #endif
5454 
5455 
rtw_ac_parm_cmd_hdl(_adapter * padapter,u8 * _ac_parm_buf,int ac_type)5456 void rtw_ac_parm_cmd_hdl(_adapter *padapter, u8 *_ac_parm_buf, int ac_type)
5457 {
5458 
5459 	u32 ac_parm_buf;
5460 
5461 	_rtw_memcpy(&ac_parm_buf, _ac_parm_buf, sizeof(ac_parm_buf));
5462 	switch (ac_type) {
5463 	case XMIT_VO_QUEUE:
5464 		RTW_INFO(FUNC_NDEV_FMT" AC_VO = 0x%08x\n", FUNC_ADPT_ARG(padapter), (unsigned int) ac_parm_buf);
5465 		rtw_hal_set_hwreg(padapter, HW_VAR_AC_PARAM_VO, (u8 *)(&ac_parm_buf));
5466 		break;
5467 
5468 	case XMIT_VI_QUEUE:
5469 		RTW_INFO(FUNC_NDEV_FMT" AC_VI = 0x%08x\n", FUNC_ADPT_ARG(padapter), (unsigned int) ac_parm_buf);
5470 		rtw_hal_set_hwreg(padapter, HW_VAR_AC_PARAM_VI, (u8 *)(&ac_parm_buf));
5471 		break;
5472 
5473 	case XMIT_BE_QUEUE:
5474 		RTW_INFO(FUNC_NDEV_FMT" AC_BE = 0x%08x\n", FUNC_ADPT_ARG(padapter), (unsigned int) ac_parm_buf);
5475 		rtw_hal_set_hwreg(padapter, HW_VAR_AC_PARAM_BE, (u8 *)(&ac_parm_buf));
5476 		break;
5477 
5478 	case XMIT_BK_QUEUE:
5479 		RTW_INFO(FUNC_NDEV_FMT" AC_BK = 0x%08x\n", FUNC_ADPT_ARG(padapter), (unsigned int) ac_parm_buf);
5480 		rtw_hal_set_hwreg(padapter, HW_VAR_AC_PARAM_BK, (u8 *)(&ac_parm_buf));
5481 		break;
5482 
5483 	default:
5484 		break;
5485 	}
5486 
5487 }
5488 
5489 
rtw_drvextra_cmd_hdl(_adapter * padapter,unsigned char * pbuf)5490 u8 rtw_drvextra_cmd_hdl(_adapter *padapter, unsigned char *pbuf)
5491 {
5492 	int ret = H2C_SUCCESS;
5493 	struct drvextra_cmd_parm *pdrvextra_cmd;
5494 
5495 	if (!pbuf)
5496 		return H2C_PARAMETERS_ERROR;
5497 
5498 	pdrvextra_cmd = (struct drvextra_cmd_parm *)pbuf;
5499 
5500 	switch (pdrvextra_cmd->ec_id) {
5501 	case STA_MSTATUS_RPT_WK_CID:
5502 		rtw_sta_media_status_rpt_cmd_hdl(padapter, (struct sta_media_status_rpt_cmd_parm *)pdrvextra_cmd->pbuf);
5503 		break;
5504 
5505 	case DYNAMIC_CHK_WK_CID:/*only  primary padapter go to this cmd, but execute dynamic_chk_wk_hdl() for two interfaces */
5506 		rtw_dynamic_chk_wk_hdl(padapter);
5507 		break;
5508 	case POWER_SAVING_CTRL_WK_CID:
5509 		power_saving_wk_hdl(padapter);
5510 		break;
5511 #ifdef CONFIG_LPS
5512 	case LPS_CTRL_WK_CID:
5513 		lps_ctrl_wk_hdl(padapter, (u8)pdrvextra_cmd->type, pdrvextra_cmd->pbuf);
5514 		break;
5515 	case DM_IN_LPS_WK_CID:
5516 		rtw_dm_in_lps_hdl(padapter);
5517 		break;
5518 	case LPS_CHANGE_DTIM_CID:
5519 		rtw_lps_change_dtim_hdl(padapter, (u8)pdrvextra_cmd->type);
5520 		break;
5521 #endif
5522 #if (RATE_ADAPTIVE_SUPPORT == 1)
5523 	case RTP_TIMER_CFG_WK_CID:
5524 		rpt_timer_setting_wk_hdl(padapter, pdrvextra_cmd->type);
5525 		break;
5526 #endif
5527 #ifdef CONFIG_ANTENNA_DIVERSITY
5528 	case ANT_SELECT_WK_CID:
5529 		antenna_select_wk_hdl(padapter, pdrvextra_cmd->type);
5530 		break;
5531 #endif
5532 #ifdef CONFIG_P2P_PS
5533 	case P2P_PS_WK_CID:
5534 		p2p_ps_wk_hdl(padapter, pdrvextra_cmd->type);
5535 		break;
5536 #endif
5537 #ifdef CONFIG_P2P
5538 	case P2P_PROTO_WK_CID:
5539 		/*
5540 		* Commented by Albert 2011/07/01
5541 		* I used the type_size as the type command
5542 		*/
5543 		ret = p2p_protocol_wk_hdl(padapter, pdrvextra_cmd->type, pdrvextra_cmd->pbuf);
5544 		break;
5545 #endif
5546 #ifdef CONFIG_AP_MODE
5547 	case CHECK_HIQ_WK_CID:
5548 		rtw_chk_hi_queue_hdl(padapter);
5549 		break;
5550 #endif
5551 	/* add for CONFIG_IEEE80211W, none 11w can use it */
5552 	case RESET_SECURITYPRIV:
5553 		reset_securitypriv_hdl(padapter);
5554 		break;
5555 	case FREE_ASSOC_RESOURCES:
5556 		free_assoc_resources_hdl(padapter, (u8)pdrvextra_cmd->type);
5557 		break;
5558 	case C2H_WK_CID:
5559 		switch (pdrvextra_cmd->type) {
5560 		#ifdef CONFIG_FW_C2H_REG
5561 		case C2H_TYPE_REG:
5562 			c2h_evt_hdl(padapter, pdrvextra_cmd->pbuf, NULL);
5563 			break;
5564 		#endif
5565 		#ifdef CONFIG_FW_C2H_PKT
5566 		case C2H_TYPE_PKT:
5567 			rtw_hal_c2h_pkt_hdl(padapter, pdrvextra_cmd->pbuf, pdrvextra_cmd->size);
5568 			break;
5569 		#endif
5570 		default:
5571 			RTW_ERR("unknown C2H type:%d\n", pdrvextra_cmd->type);
5572 			rtw_warn_on(1);
5573 			break;
5574 		}
5575 		break;
5576 #ifdef CONFIG_BEAMFORMING
5577 	case BEAMFORMING_WK_CID:
5578 		beamforming_wk_hdl(padapter, pdrvextra_cmd->type, pdrvextra_cmd->pbuf);
5579 		break;
5580 #endif
5581 	case DM_RA_MSK_WK_CID:
5582 		rtw_dm_ra_mask_hdl(padapter, (struct sta_info *)pdrvextra_cmd->pbuf);
5583 		break;
5584 #ifdef CONFIG_BT_COEXIST
5585 	case BTINFO_WK_CID:
5586 		rtw_btinfo_hdl(padapter, pdrvextra_cmd->pbuf, pdrvextra_cmd->size);
5587 		break;
5588 	case BTC_REDUCE_WL_TXPWR_CID:
5589 		rtw_btc_reduce_wl_txpwr_hdl(padapter, pdrvextra_cmd->type);
5590 		break;
5591 #endif
5592 #ifdef CONFIG_DFS_MASTER
5593 	case DFS_RADAR_DETECT_WK_CID:
5594 		rtw_dfs_rd_hdl(padapter);
5595 		break;
5596 	case DFS_RADAR_DETECT_EN_DEC_WK_CID:
5597 		rtw_dfs_rd_en_decision(padapter, MLME_ACTION_NONE, 0);
5598 		break;
5599 #endif
5600 	case SESSION_TRACKER_WK_CID:
5601 		session_tracker_cmd_hdl(padapter, (struct st_cmd_parm *)pdrvextra_cmd->pbuf);
5602 		break;
5603 	case EN_HW_UPDATE_TSF_WK_CID:
5604 		rtw_hal_set_hwreg(padapter, HW_VAR_EN_HW_UPDATE_TSF, NULL);
5605 		break;
5606 	case PERIOD_TSF_UPDATE_END_WK_CID:
5607 		rtw_hal_periodic_tsf_update_chk(padapter);
5608 		break;
5609 	case TEST_H2C_CID:
5610 		rtw_hal_fill_h2c_cmd(padapter, pdrvextra_cmd->pbuf[0], pdrvextra_cmd->size - 1, &pdrvextra_cmd->pbuf[1]);
5611 		break;
5612 	case MP_CMD_WK_CID:
5613 #ifdef CONFIG_MP_INCLUDED
5614 		ret = rtw_mp_cmd_hdl(padapter, pdrvextra_cmd->type);
5615 #endif
5616 		break;
5617 #ifdef CONFIG_RTW_CUSTOMER_STR
5618 	case CUSTOMER_STR_WK_CID:
5619 		ret = rtw_customer_str_cmd_hdl(padapter, pdrvextra_cmd->type, pdrvextra_cmd->pbuf);
5620 		break;
5621 #endif
5622 
5623 #ifdef CONFIG_RTW_REPEATER_SON
5624 	case RSON_SCAN_WK_CID:
5625 		rtw_rson_scan_cmd_hdl(padapter, pdrvextra_cmd->type);
5626 		break;
5627 #endif
5628 
5629 #ifdef CONFIG_IOCTL_CFG80211
5630 	case MGNT_TX_WK_CID:
5631 		ret = rtw_mgnt_tx_handler(padapter, pdrvextra_cmd->pbuf);
5632 		break;
5633 #endif /* CONFIG_IOCTL_CFG80211 */
5634 
5635 #if (defined(CONFIG_P2P) && defined(CONFIG_CONCURRENT_MODE)) || defined(CONFIG_IOCTL_CFG80211)
5636 	case ROCH_WK_CID:
5637 		ret = rtw_roch_wk_hdl(padapter, pdrvextra_cmd->type, pdrvextra_cmd->pbuf);
5638 		break;
5639 #endif /* (defined(CONFIG_P2P) && defined(CONFIG_CONCURRENT_MODE)) || defined(CONFIG_IOCTL_CFG80211) */
5640 
5641 #ifdef CONFIG_MCC_MODE
5642 	case MCC_CMD_WK_CID:
5643 		ret = rtw_mcc_cmd_hdl(padapter, pdrvextra_cmd->type, pdrvextra_cmd->pbuf);
5644 		break;
5645 #endif /* CONFIG_MCC_MODE */
5646 #if defined(CONFIG_RTW_MESH) && defined(RTW_PER_CMD_SUPPORT_FW)
5647 	case REQ_PER_CMD_WK_CID:
5648 		ret = rtw_req_per_cmd_hdl(padapter);
5649 		break;
5650 #endif
5651 #ifdef CONFIG_SUPPORT_STATIC_SMPS
5652 	case SSMPS_WK_CID :
5653 		rtw_ssmps_wk_hdl(padapter, (struct ssmps_cmd_parm *)pdrvextra_cmd->pbuf);
5654 		break;
5655 #endif
5656 #ifdef CONFIG_CTRL_TXSS_BY_TP
5657 	case TXSS_WK_CID :
5658 		rtw_ctrl_txss_wk_hdl(padapter, (struct txss_cmd_parm *)pdrvextra_cmd->pbuf);
5659 		break;
5660 #endif
5661 	case AC_PARM_CMD_WK_CID:
5662 		rtw_ac_parm_cmd_hdl(padapter, pdrvextra_cmd->pbuf, pdrvextra_cmd->type);
5663 		break;
5664 #ifdef CONFIG_AP_MODE
5665 	case STOP_AP_WK_CID:
5666 		stop_ap_hdl(padapter);
5667 		break;
5668 #endif
5669 #ifdef CONFIG_RTW_TOKEN_BASED_XMIT
5670 	case TBTX_CONTROL_TX_WK_CID:
5671 		tx_control_hdl(padapter);
5672 		break;
5673 #endif
5674 	default:
5675 		break;
5676 	}
5677 
5678 	if (pdrvextra_cmd->pbuf && pdrvextra_cmd->size > 0)
5679 		rtw_mfree(pdrvextra_cmd->pbuf, pdrvextra_cmd->size);
5680 
5681 	return ret;
5682 }
5683 
rtw_survey_cmd_callback(_adapter * padapter,struct cmd_obj * pcmd)5684 void rtw_survey_cmd_callback(_adapter	*padapter ,  struct cmd_obj *pcmd)
5685 {
5686 	struct	mlme_priv *pmlmepriv = &padapter->mlmepriv;
5687 
5688 
5689 	if (pcmd->res == H2C_DROPPED) {
5690 		/* TODO: cancel timer and do timeout handler directly... */
5691 		/* need to make timeout handlerOS independent */
5692 		mlme_set_scan_to_timer(pmlmepriv, 1);
5693 	} else if (pcmd->res != H2C_SUCCESS) {
5694 		mlme_set_scan_to_timer(pmlmepriv, 1);
5695 	}
5696 
5697 	/* free cmd */
5698 	rtw_free_cmd_obj(pcmd);
5699 
5700 }
rtw_disassoc_cmd_callback(_adapter * padapter,struct cmd_obj * pcmd)5701 void rtw_disassoc_cmd_callback(_adapter	*padapter,  struct cmd_obj *pcmd)
5702 {
5703 	_irqL	irqL;
5704 	struct	mlme_priv *pmlmepriv = &padapter->mlmepriv;
5705 
5706 
5707 	if (pcmd->res != H2C_SUCCESS) {
5708 		_enter_critical_bh(&pmlmepriv->lock, &irqL);
5709 		set_fwstate(pmlmepriv, WIFI_ASOC_STATE);
5710 		_exit_critical_bh(&pmlmepriv->lock, &irqL);
5711 		goto exit;
5712 	}
5713 #ifdef CONFIG_BR_EXT
5714 	else /* clear bridge database */
5715 		nat25_db_cleanup(padapter);
5716 #endif /* CONFIG_BR_EXT */
5717 
5718 	/* free cmd */
5719 	rtw_free_cmd_obj(pcmd);
5720 
5721 exit:
5722 	return;
5723 }
5724 
rtw_joinbss_cmd_callback(_adapter * padapter,struct cmd_obj * pcmd)5725 void rtw_joinbss_cmd_callback(_adapter	*padapter,  struct cmd_obj *pcmd)
5726 {
5727 	struct	mlme_priv *pmlmepriv = &padapter->mlmepriv;
5728 
5729 
5730 	if (pcmd->res == H2C_DROPPED) {
5731 		/* TODO: cancel timer and do timeout handler directly... */
5732 		/* need to make timeout handlerOS independent */
5733 		_set_timer(&pmlmepriv->assoc_timer, 1);
5734 	} else if (pcmd->res != H2C_SUCCESS)
5735 		_set_timer(&pmlmepriv->assoc_timer, 1);
5736 
5737 	rtw_free_cmd_obj(pcmd);
5738 
5739 }
5740 
rtw_create_ibss_post_hdl(_adapter * padapter,int status)5741 void rtw_create_ibss_post_hdl(_adapter *padapter, int status)
5742 {
5743 	_irqL irqL;
5744 	struct wlan_network *pwlan = NULL;
5745 	struct	mlme_priv *pmlmepriv = &padapter->mlmepriv;
5746 	WLAN_BSSID_EX *pdev_network = &padapter->registrypriv.dev_network;
5747 	struct wlan_network *mlme_cur_network = &(pmlmepriv->cur_network);
5748 
5749 	if (status != H2C_SUCCESS)
5750 		_set_timer(&pmlmepriv->assoc_timer, 1);
5751 
5752 	_cancel_timer_ex(&pmlmepriv->assoc_timer);
5753 
5754 	_enter_critical_bh(&pmlmepriv->lock, &irqL);
5755 
5756 	{
5757 		_irqL irqL;
5758 
5759 		pwlan = _rtw_alloc_network(pmlmepriv);
5760 		_enter_critical_bh(&(pmlmepriv->scanned_queue.lock), &irqL);
5761 		if (pwlan == NULL) {
5762 			pwlan = rtw_get_oldest_wlan_network(&pmlmepriv->scanned_queue);
5763 			if (pwlan == NULL) {
5764 				_exit_critical_bh(&(pmlmepriv->scanned_queue.lock), &irqL);
5765 				goto createbss_cmd_fail;
5766 			}
5767 			pwlan->last_scanned = rtw_get_current_time();
5768 		} else
5769 			rtw_list_insert_tail(&(pwlan->list), &pmlmepriv->scanned_queue.queue);
5770 
5771 		pdev_network->Length = get_WLAN_BSSID_EX_sz(pdev_network);
5772 		_rtw_memcpy(&(pwlan->network), pdev_network, pdev_network->Length);
5773 		/* pwlan->fixed = _TRUE; */
5774 
5775 		/* copy pdev_network information to pmlmepriv->cur_network */
5776 		_rtw_memcpy(&mlme_cur_network->network, pdev_network, (get_WLAN_BSSID_EX_sz(pdev_network)));
5777 
5778 #if 0
5779 		/* reset DSConfig */
5780 		mlme_cur_network->network.Configuration.DSConfig = (u32)rtw_ch2freq(pdev_network->Configuration.DSConfig);
5781 #endif
5782 
5783 		_clr_fwstate_(pmlmepriv, WIFI_UNDER_LINKING);
5784 		_exit_critical_bh(&(pmlmepriv->scanned_queue.lock), &irqL);
5785 		/* we will set WIFI_ASOC_STATE when there is one more sat to join us (rtw_stassoc_event_callback) */
5786 	}
5787 
5788 createbss_cmd_fail:
5789 	_exit_critical_bh(&pmlmepriv->lock, &irqL);
5790 	return;
5791 }
5792 
5793 
5794 
rtw_setstaKey_cmdrsp_callback(_adapter * padapter,struct cmd_obj * pcmd)5795 void rtw_setstaKey_cmdrsp_callback(_adapter	*padapter ,  struct cmd_obj *pcmd)
5796 {
5797 
5798 	struct sta_priv *pstapriv = &padapter->stapriv;
5799 	struct set_stakey_rsp *psetstakey_rsp = (struct set_stakey_rsp *)(pcmd->rsp);
5800 	struct sta_info	*psta = rtw_get_stainfo(pstapriv, psetstakey_rsp->addr);
5801 
5802 
5803 	if (psta == NULL) {
5804 		goto exit;
5805 	}
5806 
5807 	/* psta->cmn.aid = psta->cmn.mac_id = psetstakey_rsp->keyid; */ /* CAM_ID(CAM_ENTRY) */
5808 
5809 exit:
5810 
5811 	rtw_free_cmd_obj(pcmd);
5812 
5813 
5814 }
5815 
rtw_getrttbl_cmd_cmdrsp_callback(_adapter * padapter,struct cmd_obj * pcmd)5816 void rtw_getrttbl_cmd_cmdrsp_callback(_adapter	*padapter,  struct cmd_obj *pcmd)
5817 {
5818 
5819 	rtw_free_cmd_obj(pcmd);
5820 #ifdef CONFIG_MP_INCLUDED
5821 	if (padapter->registrypriv.mp_mode == 1)
5822 		padapter->mppriv.workparam.bcompleted = _TRUE;
5823 #endif
5824 
5825 
5826 }
5827 
set_txq_params_cmd(_adapter * adapter,u32 ac_parm,u8 ac_type)5828 u8 set_txq_params_cmd(_adapter *adapter, u32 ac_parm, u8 ac_type)
5829 {
5830 	struct cmd_obj *cmdobj;
5831 	struct drvextra_cmd_parm *pdrvextra_cmd_parm;
5832 	struct cmd_priv *pcmdpriv = &adapter->cmdpriv;
5833 	u8 *ac_parm_buf = NULL;
5834 	u8 sz;
5835 	u8 res = _SUCCESS;
5836 
5837 
5838 	cmdobj = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
5839 	if (cmdobj == NULL) {
5840 		res = _FAIL;
5841 		goto exit;
5842 	}
5843 
5844 	pdrvextra_cmd_parm = (struct drvextra_cmd_parm *)rtw_zmalloc(sizeof(struct drvextra_cmd_parm));
5845 	if (pdrvextra_cmd_parm == NULL) {
5846 		rtw_mfree((u8 *)cmdobj, sizeof(struct cmd_obj));
5847 		res = _FAIL;
5848 		goto exit;
5849 	}
5850 
5851 	sz = sizeof(ac_parm);
5852 	ac_parm_buf = rtw_zmalloc(sz);
5853 	if (ac_parm_buf == NULL) {
5854 		rtw_mfree((u8 *)cmdobj, sizeof(struct cmd_obj));
5855 		rtw_mfree((u8 *)pdrvextra_cmd_parm, sizeof(struct drvextra_cmd_parm));
5856 		res = _FAIL;
5857 		goto exit;
5858 	}
5859 
5860 	pdrvextra_cmd_parm->ec_id = AC_PARM_CMD_WK_CID;
5861 	pdrvextra_cmd_parm->type = ac_type;
5862 	pdrvextra_cmd_parm->size = sz;
5863 	pdrvextra_cmd_parm->pbuf = ac_parm_buf;
5864 
5865 	_rtw_memcpy(ac_parm_buf, &ac_parm, sz);
5866 
5867 	init_h2fwcmd_w_parm_no_rsp(cmdobj, pdrvextra_cmd_parm, CMD_SET_DRV_EXTRA);
5868 	res = rtw_enqueue_cmd(pcmdpriv, cmdobj);
5869 
5870 exit:
5871 	return res;
5872 }
5873 
5874 /* Driver writes beacon length to REG for FW adjusting beacon receive time */
5875 #ifdef CONFIG_WRITE_BCN_LEN_TO_FW
rtw_write_bcnlen_to_fw_cmd(_adapter * padapter,u16 bcn_len)5876 u8 rtw_write_bcnlen_to_fw_cmd(_adapter *padapter, u16 bcn_len)
5877 {
5878 	struct cmd_obj *pcmd;
5879 	struct write_bcnlen_param *parm;
5880 	struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
5881 	u8 res = _SUCCESS;
5882 
5883 	pcmd = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
5884 	if (pcmd == NULL) {
5885 		res = _FAIL;
5886 		goto exit;
5887 	}
5888 
5889 	parm = (struct write_bcnlen_param *)rtw_zmalloc(sizeof(struct write_bcnlen_param));
5890 	if (parm == NULL) {
5891 		rtw_mfree((unsigned char *)pcmd, sizeof(struct cmd_obj));
5892 		res = _FAIL;
5893 		goto exit;
5894 	}
5895 
5896 	parm->bcn_len = bcn_len;
5897 	init_h2fwcmd_w_parm_no_rsp(pcmd, parm, CMD_WRITE_BCN_LEN);
5898 	res = rtw_enqueue_cmd(pcmdpriv, pcmd);
5899 
5900 exit:
5901 	return res;
5902 }
5903 #endif /* CONFIG_WRITE_BCN_LEN_TO_FW */
5904 
rtw_reqtxrpt_cmd(_adapter * adapter,u8 macid)5905 u8 rtw_reqtxrpt_cmd(_adapter *adapter, u8 macid)
5906 {
5907 	struct cmd_obj *cmdobj;
5908 	struct reqtxrpt_param *parm;
5909 	struct cmd_priv *pcmdpriv = &adapter->cmdpriv;
5910 	struct submit_ctx sctx;
5911 	u8 flags = RTW_CMDF_WAIT_ACK;
5912 	u8 res = _FAIL;
5913 
5914 	/* prepare cmd parameter */
5915 	parm = rtw_zmalloc(sizeof(*parm));
5916 	if (parm == NULL)
5917 		goto exit;
5918 	parm->macid = macid;
5919 
5920 	/* need enqueue, prepare cmd_obj and enqueue */
5921 	cmdobj = rtw_zmalloc(sizeof(*cmdobj));
5922 	if (cmdobj == NULL) {
5923 		rtw_mfree((u8 *)parm, sizeof(*parm));
5924 		goto exit;
5925 	}
5926 
5927 	init_h2fwcmd_w_parm_no_rsp(cmdobj, parm, CMD_REQ_TXRPT);
5928 
5929 	if (flags & RTW_CMDF_WAIT_ACK) {
5930 		cmdobj->sctx = &sctx;
5931 		rtw_sctx_init(&sctx, 2000);
5932 	}
5933 
5934 	res = rtw_enqueue_cmd(pcmdpriv, cmdobj);
5935 
5936 	if (res == _SUCCESS && (flags & RTW_CMDF_WAIT_ACK)) {
5937 		rtw_sctx_wait(&sctx, __func__);
5938 		_enter_critical_mutex(&pcmdpriv->sctx_mutex, NULL);
5939 		if (sctx.status == RTW_SCTX_SUBMITTED)
5940 			cmdobj->sctx = NULL;
5941 		_exit_critical_mutex(&pcmdpriv->sctx_mutex, NULL);
5942 		if (sctx.status != RTW_SCTX_DONE_SUCCESS)
5943 			res = _FAIL;
5944 	}
5945 
5946 exit:
5947 	return res;
5948 }
5949 
5950