rtw_cmd.c revision 7552d72a5c34a8d55037ce0c1a8cd8c3a7e86341
1/******************************************************************************
2 *
3 * Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved.
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 * You should have received a copy of the GNU General Public License along with
15 * this program; if not, write to the Free Software Foundation, Inc.,
16 * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
17 *
18 *
19 ******************************************************************************/
20#define _RTW_CMD_C_
21
22#include <osdep_service.h>
23#include <drv_types.h>
24#include <recv_osdep.h>
25#include <cmd_osdep.h>
26#include <mlme_osdep.h>
27#include <rtw_br_ext.h>
28#include <rtw_mlme_ext.h>
29
30/*
31Caller and the rtw_cmd_thread can protect cmd_q by spin_lock.
32No irqsave is necessary.
33*/
34
35int	_rtw_init_cmd_priv (struct	cmd_priv *pcmdpriv)
36{
37	int res = _SUCCESS;
38
39_func_enter_;
40
41	_rtw_init_sema(&(pcmdpriv->cmd_queue_sema), 0);
42	/* _rtw_init_sema(&(pcmdpriv->cmd_done_sema), 0); */
43	_rtw_init_sema(&(pcmdpriv->terminate_cmdthread_sema), 0);
44
45
46	_rtw_init_queue(&(pcmdpriv->cmd_queue));
47
48	/* allocate DMA-able/Non-Page memory for cmd_buf and rsp_buf */
49
50	pcmdpriv->cmd_seq = 1;
51
52	pcmdpriv->cmd_allocated_buf = rtw_zmalloc(MAX_CMDSZ + CMDBUFF_ALIGN_SZ);
53
54	if (pcmdpriv->cmd_allocated_buf == NULL) {
55		res = _FAIL;
56		goto exit;
57	}
58
59	pcmdpriv->cmd_buf = pcmdpriv->cmd_allocated_buf  +  CMDBUFF_ALIGN_SZ - ((size_t)(pcmdpriv->cmd_allocated_buf) & (CMDBUFF_ALIGN_SZ-1));
60
61	pcmdpriv->rsp_allocated_buf = rtw_zmalloc(MAX_RSPSZ + 4);
62
63	if (pcmdpriv->rsp_allocated_buf == NULL) {
64		res = _FAIL;
65		goto exit;
66	}
67
68	pcmdpriv->rsp_buf = pcmdpriv->rsp_allocated_buf  +  4 - ((size_t)(pcmdpriv->rsp_allocated_buf) & 3);
69
70	pcmdpriv->cmd_issued_cnt = 0;
71	pcmdpriv->cmd_done_cnt = 0;
72	pcmdpriv->rsp_cnt = 0;
73exit:
74_func_exit_;
75	return res;
76}
77
78static void c2h_wk_callback(struct work_struct *work);
79
80int _rtw_init_evt_priv(struct evt_priv *pevtpriv)
81{
82	int res = _SUCCESS;
83
84_func_enter_;
85
86	/* allocate DMA-able/Non-Page memory for cmd_buf and rsp_buf */
87	ATOMIC_SET(&pevtpriv->event_seq, 0);
88	pevtpriv->evt_done_cnt = 0;
89
90	_init_workitem(&pevtpriv->c2h_wk, c2h_wk_callback, NULL);
91	pevtpriv->c2h_wk_alive = false;
92	pevtpriv->c2h_queue = rtw_cbuf_alloc(C2H_QUEUE_MAX_LEN+1);
93
94_func_exit_;
95
96	return res;
97}
98
99void rtw_free_evt_priv(struct	evt_priv *pevtpriv)
100{
101_func_enter_;
102
103	RT_TRACE(_module_rtl871x_cmd_c_, _drv_info_, ("+rtw_free_evt_priv\n"));
104
105	_cancel_workitem_sync(&pevtpriv->c2h_wk);
106	while (pevtpriv->c2h_wk_alive)
107		rtw_msleep_os(10);
108
109	while (!rtw_cbuf_empty(pevtpriv->c2h_queue)) {
110		void *c2h = rtw_cbuf_pop(pevtpriv->c2h_queue);
111		if (c2h != NULL && c2h != (void *)pevtpriv)
112			kfree(c2h);
113	}
114	RT_TRACE(_module_rtl871x_cmd_c_, _drv_info_, ("-rtw_free_evt_priv\n"));
115
116_func_exit_;
117}
118
119void _rtw_free_cmd_priv (struct	cmd_priv *pcmdpriv)
120{
121_func_enter_;
122
123	if (pcmdpriv) {
124		_rtw_spinlock_free(&(pcmdpriv->cmd_queue.lock));
125		_rtw_free_sema(&(pcmdpriv->cmd_queue_sema));
126		_rtw_free_sema(&(pcmdpriv->terminate_cmdthread_sema));
127
128		if (pcmdpriv->cmd_allocated_buf)
129			kfree(pcmdpriv->cmd_allocated_buf);
130
131		if (pcmdpriv->rsp_allocated_buf)
132			kfree(pcmdpriv->rsp_allocated_buf);
133	}
134_func_exit_;
135}
136
137/*
138Calling Context:
139
140rtw_enqueue_cmd can only be called between kernel thread,
141since only spin_lock is used.
142
143ISR/Call-Back functions can't call this sub-function.
144
145*/
146
147int	_rtw_enqueue_cmd(struct __queue *queue, struct cmd_obj *obj)
148{
149	unsigned long irqL;
150
151_func_enter_;
152
153	if (obj == NULL)
154		goto exit;
155
156	/* _enter_critical_bh(&queue->lock, &irqL); */
157	_enter_critical(&queue->lock, &irqL);
158
159	rtw_list_insert_tail(&obj->list, &queue->queue);
160
161	/* _exit_critical_bh(&queue->lock, &irqL); */
162	_exit_critical(&queue->lock, &irqL);
163
164exit:
165
166_func_exit_;
167
168	return _SUCCESS;
169}
170
171struct	cmd_obj	*_rtw_dequeue_cmd(struct __queue *queue)
172{
173	unsigned long irqL;
174	struct cmd_obj *obj;
175
176_func_enter_;
177
178	/* _enter_critical_bh(&(queue->lock), &irqL); */
179	_enter_critical(&queue->lock, &irqL);
180	if (rtw_is_list_empty(&(queue->queue))) {
181		obj = NULL;
182	} else {
183		obj = LIST_CONTAINOR(get_next(&(queue->queue)), struct cmd_obj, list);
184		rtw_list_delete(&obj->list);
185	}
186
187	/* _exit_critical_bh(&(queue->lock), &irqL); */
188	_exit_critical(&queue->lock, &irqL);
189
190_func_exit_;
191
192	return obj;
193}
194
195u32	rtw_init_cmd_priv(struct cmd_priv *pcmdpriv)
196{
197	u32	res;
198_func_enter_;
199	res = _rtw_init_cmd_priv (pcmdpriv);
200_func_exit_;
201	return res;
202}
203
204u32	rtw_init_evt_priv (struct	evt_priv *pevtpriv)
205{
206	int	res;
207_func_enter_;
208	res = _rtw_init_evt_priv(pevtpriv);
209_func_exit_;
210	return res;
211}
212
213void rtw_free_cmd_priv(struct	cmd_priv *pcmdpriv)
214{
215_func_enter_;
216	RT_TRACE(_module_rtl871x_cmd_c_, _drv_info_, ("rtw_free_cmd_priv\n"));
217	_rtw_free_cmd_priv(pcmdpriv);
218_func_exit_;
219}
220
221static int rtw_cmd_filter(struct cmd_priv *pcmdpriv, struct cmd_obj *cmd_obj)
222{
223	u8 bAllow = false; /* set to true to allow enqueuing cmd when hw_init_completed is false */
224
225	/* To decide allow or not */
226	if ((pcmdpriv->padapter->pwrctrlpriv.bHWPwrPindetect) &&
227	    (!pcmdpriv->padapter->registrypriv.usbss_enable)) {
228		if (cmd_obj->cmdcode == GEN_CMD_CODE(_Set_Drv_Extra)) {
229			struct drvextra_cmd_parm	*pdrvextra_cmd_parm = (struct drvextra_cmd_parm	*)cmd_obj->parmbuf;
230			if (pdrvextra_cmd_parm->ec_id == POWER_SAVING_CTRL_WK_CID)
231				bAllow = true;
232		}
233	}
234
235	if (cmd_obj->cmdcode == GEN_CMD_CODE(_SetChannelPlan))
236		bAllow = true;
237
238	if ((!pcmdpriv->padapter->hw_init_completed && !bAllow) ||
239	    !pcmdpriv->cmdthd_running)	/* com_thread not running */
240		return _FAIL;
241	return _SUCCESS;
242}
243
244u32 rtw_enqueue_cmd(struct cmd_priv *pcmdpriv, struct cmd_obj *cmd_obj)
245{
246	int res = _FAIL;
247	struct adapter *padapter = pcmdpriv->padapter;
248
249_func_enter_;
250
251	if (cmd_obj == NULL)
252		goto exit;
253
254	cmd_obj->padapter = padapter;
255
256	res = rtw_cmd_filter(pcmdpriv, cmd_obj);
257	if (_FAIL == res) {
258		rtw_free_cmd_obj(cmd_obj);
259		goto exit;
260	}
261
262	res = _rtw_enqueue_cmd(&pcmdpriv->cmd_queue, cmd_obj);
263
264	if (res == _SUCCESS)
265		_rtw_up_sema(&pcmdpriv->cmd_queue_sema);
266
267exit:
268
269_func_exit_;
270
271	return res;
272}
273
274struct	cmd_obj	*rtw_dequeue_cmd(struct cmd_priv *pcmdpriv)
275{
276	struct cmd_obj *cmd_obj;
277
278_func_enter_;
279
280	cmd_obj = _rtw_dequeue_cmd(&pcmdpriv->cmd_queue);
281
282_func_exit_;
283	return cmd_obj;
284}
285
286void rtw_cmd_clr_isr(struct	cmd_priv *pcmdpriv)
287{
288_func_enter_;
289	pcmdpriv->cmd_done_cnt++;
290	/* _rtw_up_sema(&(pcmdpriv->cmd_done_sema)); */
291_func_exit_;
292}
293
294void rtw_free_cmd_obj(struct cmd_obj *pcmd)
295{
296_func_enter_;
297
298	if ((pcmd->cmdcode != _JoinBss_CMD_) && (pcmd->cmdcode != _CreateBss_CMD_)) {
299		/* free parmbuf in cmd_obj */
300		kfree(pcmd->parmbuf);
301	}
302
303	if (pcmd->rsp != NULL) {
304		if (pcmd->rspsz != 0) {
305			/* free rsp in cmd_obj */
306			kfree(pcmd->rsp);
307		}
308	}
309
310	/* free cmd_obj */
311	kfree(pcmd);
312
313_func_exit_;
314}
315
316int rtw_cmd_thread(void *context)
317{
318	u8 ret;
319	struct cmd_obj *pcmd;
320	u8 *pcmdbuf;
321	u8 (*cmd_hdl)(struct adapter *padapter, u8 *pbuf);
322	void (*pcmd_callback)(struct adapter *dev, struct cmd_obj *pcmd);
323	struct adapter *padapter = (struct adapter *)context;
324	struct cmd_priv *pcmdpriv = &(padapter->cmdpriv);
325
326_func_enter_;
327
328	thread_enter("RTW_CMD_THREAD");
329
330	pcmdbuf = pcmdpriv->cmd_buf;
331
332	pcmdpriv->cmdthd_running = true;
333	_rtw_up_sema(&pcmdpriv->terminate_cmdthread_sema);
334
335	RT_TRACE(_module_rtl871x_cmd_c_, _drv_info_, ("start r871x rtw_cmd_thread !!!!\n"));
336
337	while (1) {
338		if (_rtw_down_sema(&pcmdpriv->cmd_queue_sema) == _FAIL)
339			break;
340
341		if (padapter->bDriverStopped ||
342		    padapter->bSurpriseRemoved) {
343			DBG_88E("%s: DriverStopped(%d) SurpriseRemoved(%d) break at line %d\n",
344				__func__, padapter->bDriverStopped, padapter->bSurpriseRemoved, __LINE__);
345			break;
346		}
347_next:
348		if (padapter->bDriverStopped ||
349		    padapter->bSurpriseRemoved) {
350			DBG_88E("%s: DriverStopped(%d) SurpriseRemoved(%d) break at line %d\n",
351				__func__, padapter->bDriverStopped, padapter->bSurpriseRemoved, __LINE__);
352			break;
353		}
354
355		pcmd = rtw_dequeue_cmd(pcmdpriv);
356		if (!pcmd)
357			continue;
358
359		if (_FAIL == rtw_cmd_filter(pcmdpriv, pcmd)) {
360			pcmd->res = H2C_DROPPED;
361			goto post_process;
362		}
363
364		pcmdpriv->cmd_issued_cnt++;
365
366		pcmd->cmdsz = _RND4((pcmd->cmdsz));/* _RND4 */
367
368		memcpy(pcmdbuf, pcmd->parmbuf, pcmd->cmdsz);
369
370		if (pcmd->cmdcode < ARRAY_SIZE(wlancmds)) {
371			cmd_hdl = wlancmds[pcmd->cmdcode].h2cfuns;
372
373			if (cmd_hdl) {
374				ret = cmd_hdl(pcmd->padapter, pcmdbuf);
375				pcmd->res = ret;
376			}
377
378			pcmdpriv->cmd_seq++;
379		} else {
380			pcmd->res = H2C_PARAMETERS_ERROR;
381		}
382
383		cmd_hdl = NULL;
384
385post_process:
386
387		/* call callback function for post-processed */
388		if (pcmd->cmdcode < ARRAY_SIZE(rtw_cmd_callback)) {
389			pcmd_callback = rtw_cmd_callback[pcmd->cmdcode].callback;
390			if (pcmd_callback == NULL) {
391				RT_TRACE(_module_rtl871x_cmd_c_, _drv_info_, ("mlme_cmd_hdl(): pcmd_callback = 0x%p, cmdcode = 0x%x\n", pcmd_callback, pcmd->cmdcode));
392				rtw_free_cmd_obj(pcmd);
393			} else {
394				/* todo: !!! fill rsp_buf to pcmd->rsp if (pcmd->rsp!= NULL) */
395				pcmd_callback(pcmd->padapter, pcmd);/* need conider that free cmd_obj in rtw_cmd_callback */
396			}
397		} else {
398			RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_, ("%s: cmdcode = 0x%x callback not defined!\n", __func__, pcmd->cmdcode));
399			rtw_free_cmd_obj(pcmd);
400		}
401
402		flush_signals_thread();
403
404		goto _next;
405	}
406	pcmdpriv->cmdthd_running = false;
407
408	/*  free all cmd_obj resources */
409	do {
410		pcmd = rtw_dequeue_cmd(pcmdpriv);
411		if (pcmd == NULL)
412			break;
413
414		/* DBG_88E("%s: leaving... drop cmdcode:%u\n", __func__, pcmd->cmdcode); */
415
416		rtw_free_cmd_obj(pcmd);
417	} while (1);
418
419	_rtw_up_sema(&pcmdpriv->terminate_cmdthread_sema);
420
421_func_exit_;
422
423	thread_exit();
424}
425
426u8 rtw_setstandby_cmd(struct adapter *padapter, uint action)
427{
428	struct cmd_obj *ph2c;
429	struct usb_suspend_parm *psetusbsuspend;
430	struct cmd_priv	*pcmdpriv = &padapter->cmdpriv;
431
432	u8 ret = _SUCCESS;
433
434_func_enter_;
435
436	ph2c = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
437	if (ph2c == NULL) {
438		ret = _FAIL;
439		goto exit;
440	}
441
442	psetusbsuspend = (struct usb_suspend_parm *)rtw_zmalloc(sizeof(struct usb_suspend_parm));
443	if (psetusbsuspend == NULL) {
444		kfree(ph2c);
445		ret = _FAIL;
446		goto exit;
447	}
448
449	psetusbsuspend->action = action;
450
451	init_h2fwcmd_w_parm_no_rsp(ph2c, psetusbsuspend, GEN_CMD_CODE(_SetUsbSuspend));
452
453	ret = rtw_enqueue_cmd(pcmdpriv, ph2c);
454
455exit:
456
457_func_exit_;
458
459	return ret;
460}
461
462/*
463rtw_sitesurvey_cmd(~)
464	### NOTE:#### (!!!!)
465	MUST TAKE CARE THAT BEFORE CALLING THIS FUNC, YOU SHOULD HAVE LOCKED pmlmepriv->lock
466*/
467u8 rtw_sitesurvey_cmd(struct adapter  *padapter, struct ndis_802_11_ssid *ssid, int ssid_num,
468	struct rtw_ieee80211_channel *ch, int ch_num)
469{
470	u8 res = _FAIL;
471	struct cmd_obj		*ph2c;
472	struct sitesurvey_parm	*psurveyPara;
473	struct cmd_priv		*pcmdpriv = &padapter->cmdpriv;
474	struct mlme_priv	*pmlmepriv = &padapter->mlmepriv;
475
476_func_enter_;
477	if (check_fwstate(pmlmepriv, _FW_LINKED) == true) {
478		rtw_lps_ctrl_wk_cmd(padapter, LPS_CTRL_SCAN, 1);
479	}
480
481	if (check_fwstate(pmlmepriv, _FW_LINKED) == true) {
482		p2p_ps_wk_cmd(padapter, P2P_PS_SCAN, 1);
483	}
484
485	ph2c = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
486	if (ph2c == NULL)
487		return _FAIL;
488
489	psurveyPara = (struct sitesurvey_parm *)rtw_zmalloc(sizeof(struct sitesurvey_parm));
490	if (psurveyPara == NULL) {
491		kfree(ph2c);
492		return _FAIL;
493	}
494
495	rtw_free_network_queue(padapter, false);
496
497	RT_TRACE(_module_rtl871x_cmd_c_, _drv_info_, ("%s: flush network queue\n", __func__));
498
499	init_h2fwcmd_w_parm_no_rsp(ph2c, psurveyPara, GEN_CMD_CODE(_SiteSurvey));
500
501	/* psurveyPara->bsslimit = 48; */
502	psurveyPara->scan_mode = pmlmepriv->scan_mode;
503
504	/* prepare ssid list */
505	if (ssid) {
506		int i;
507		for (i = 0; i < ssid_num && i < RTW_SSID_SCAN_AMOUNT; i++) {
508			if (ssid[i].SsidLength) {
509				memcpy(&psurveyPara->ssid[i], &ssid[i], sizeof(struct ndis_802_11_ssid));
510				psurveyPara->ssid_num++;
511				if (0)
512				DBG_88E(FUNC_ADPT_FMT" ssid:(%s, %d)\n", FUNC_ADPT_ARG(padapter),
513					psurveyPara->ssid[i].Ssid, psurveyPara->ssid[i].SsidLength);
514			}
515		}
516	}
517
518	/* prepare channel list */
519	if (ch) {
520		int i;
521		for (i = 0; i < ch_num && i < RTW_CHANNEL_SCAN_AMOUNT; i++) {
522			if (ch[i].hw_value && !(ch[i].flags & RTW_IEEE80211_CHAN_DISABLED)) {
523				memcpy(&psurveyPara->ch[i], &ch[i], sizeof(struct rtw_ieee80211_channel));
524				psurveyPara->ch_num++;
525				if (0)
526				DBG_88E(FUNC_ADPT_FMT" ch:%u\n", FUNC_ADPT_ARG(padapter),
527					psurveyPara->ch[i].hw_value);
528			}
529		}
530	}
531
532	set_fwstate(pmlmepriv, _FW_UNDER_SURVEY);
533
534	res = rtw_enqueue_cmd(pcmdpriv, ph2c);
535
536	if (res == _SUCCESS) {
537		pmlmepriv->scan_start_time = rtw_get_current_time();
538
539		_set_timer(&pmlmepriv->scan_to_timer, SCANNING_TIMEOUT);
540
541		rtw_led_control(padapter, LED_CTL_SITE_SURVEY);
542
543		pmlmepriv->scan_interval = SCAN_INTERVAL;/*  30*2 sec = 60sec */
544	} else {
545		_clr_fwstate_(pmlmepriv, _FW_UNDER_SURVEY);
546	}
547
548_func_exit_;
549
550	return res;
551}
552
553u8 rtw_setdatarate_cmd(struct adapter *padapter, u8 *rateset)
554{
555	struct cmd_obj *ph2c;
556	struct setdatarate_parm *pbsetdataratepara;
557	struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
558	u8	res = _SUCCESS;
559
560_func_enter_;
561
562	ph2c = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
563	if (ph2c == NULL) {
564		res = _FAIL;
565		goto exit;
566	}
567
568	pbsetdataratepara = (struct setdatarate_parm *)rtw_zmalloc(sizeof(struct setdatarate_parm));
569	if (pbsetdataratepara == NULL) {
570		kfree(ph2c);
571		res = _FAIL;
572		goto exit;
573	}
574
575	init_h2fwcmd_w_parm_no_rsp(ph2c, pbsetdataratepara, GEN_CMD_CODE(_SetDataRate));
576	pbsetdataratepara->mac_id = 5;
577	memcpy(pbsetdataratepara->datarates, rateset, NumRates);
578	res = rtw_enqueue_cmd(pcmdpriv, ph2c);
579exit:
580
581_func_exit_;
582
583	return res;
584}
585
586u8 rtw_setbasicrate_cmd(struct adapter *padapter, u8 *rateset)
587{
588	struct cmd_obj *ph2c;
589	struct setbasicrate_parm *pssetbasicratepara;
590	struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
591	u8	res = _SUCCESS;
592
593_func_enter_;
594
595	ph2c = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
596	if (ph2c == NULL) {
597		res = _FAIL;
598		goto exit;
599	}
600	pssetbasicratepara = (struct setbasicrate_parm *)rtw_zmalloc(sizeof(struct setbasicrate_parm));
601
602	if (pssetbasicratepara == NULL) {
603		kfree(ph2c);
604		res = _FAIL;
605		goto exit;
606	}
607
608	init_h2fwcmd_w_parm_no_rsp(ph2c, pssetbasicratepara, _SetBasicRate_CMD_);
609
610	memcpy(pssetbasicratepara->basicrates, rateset, NumRates);
611
612	res = rtw_enqueue_cmd(pcmdpriv, ph2c);
613exit:
614
615_func_exit_;
616
617	return res;
618}
619
620
621/*
622unsigned char rtw_setphy_cmd(unsigned char  *adapter)
623
6241.  be called only after rtw_update_registrypriv_dev_network(~) or mp testing program
6252.  for AdHoc/Ap mode or mp mode?
626
627*/
628u8 rtw_setphy_cmd(struct adapter *padapter, u8 modem, u8 ch)
629{
630	struct cmd_obj *ph2c;
631	struct setphy_parm *psetphypara;
632	struct cmd_priv	*pcmdpriv = &padapter->cmdpriv;
633	u8	res = _SUCCESS;
634
635_func_enter_;
636
637	ph2c = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
638	if (ph2c == NULL) {
639		res = _FAIL;
640		goto exit;
641		}
642	psetphypara = (struct setphy_parm *)rtw_zmalloc(sizeof(struct setphy_parm));
643
644	if (psetphypara == NULL) {
645		kfree(ph2c);
646		res = _FAIL;
647		goto exit;
648	}
649
650	init_h2fwcmd_w_parm_no_rsp(ph2c, psetphypara, _SetPhy_CMD_);
651
652	RT_TRACE(_module_rtl871x_cmd_c_, _drv_info_, ("CH =%d, modem =%d", ch, modem));
653
654	psetphypara->modem = modem;
655	psetphypara->rfchannel = ch;
656
657	res = rtw_enqueue_cmd(pcmdpriv, ph2c);
658exit:
659_func_exit_;
660	return res;
661}
662
663u8 rtw_setbbreg_cmd(struct adapter *padapter, u8 offset, u8 val)
664{
665	struct cmd_obj *ph2c;
666	struct writeBB_parm *pwritebbparm;
667	struct cmd_priv	*pcmdpriv = &padapter->cmdpriv;
668	u8	res = _SUCCESS;
669
670_func_enter_;
671	ph2c = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
672	if (ph2c == NULL) {
673		res = _FAIL;
674		goto exit;
675		}
676	pwritebbparm = (struct writeBB_parm *)rtw_zmalloc(sizeof(struct writeBB_parm));
677
678	if (pwritebbparm == NULL) {
679		kfree(ph2c);
680		res = _FAIL;
681		goto exit;
682	}
683
684	init_h2fwcmd_w_parm_no_rsp(ph2c, pwritebbparm, GEN_CMD_CODE(_SetBBReg));
685
686	pwritebbparm->offset = offset;
687	pwritebbparm->value = val;
688
689	res = rtw_enqueue_cmd(pcmdpriv, ph2c);
690exit:
691_func_exit_;
692	return res;
693}
694
695u8 rtw_getbbreg_cmd(struct adapter  *padapter, u8 offset, u8 *pval)
696{
697	struct cmd_obj *ph2c;
698	struct readBB_parm *prdbbparm;
699	struct cmd_priv	*pcmdpriv = &padapter->cmdpriv;
700	u8	res = _SUCCESS;
701
702_func_enter_;
703	ph2c = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
704	if (ph2c == NULL) {
705		res = _FAIL;
706		goto exit;
707		}
708	prdbbparm = (struct readBB_parm *)rtw_zmalloc(sizeof(struct readBB_parm));
709
710	if (prdbbparm == NULL) {
711		kfree(ph2c);
712		return _FAIL;
713	}
714
715	_rtw_init_listhead(&ph2c->list);
716	ph2c->cmdcode = GEN_CMD_CODE(_GetBBReg);
717	ph2c->parmbuf = (unsigned char *)prdbbparm;
718	ph2c->cmdsz =  sizeof(struct readBB_parm);
719	ph2c->rsp = pval;
720	ph2c->rspsz = sizeof(struct readBB_rsp);
721
722	prdbbparm->offset = offset;
723
724	res = rtw_enqueue_cmd(pcmdpriv, ph2c);
725exit:
726_func_exit_;
727	return res;
728}
729
730u8 rtw_setrfreg_cmd(struct adapter  *padapter, u8 offset, u32 val)
731{
732	struct cmd_obj *ph2c;
733	struct writeRF_parm *pwriterfparm;
734	struct cmd_priv	*pcmdpriv = &padapter->cmdpriv;
735	u8	res = _SUCCESS;
736_func_enter_;
737	ph2c = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
738	if (ph2c == NULL) {
739		res = _FAIL;
740		goto exit;
741	}
742	pwriterfparm = (struct writeRF_parm *)rtw_zmalloc(sizeof(struct writeRF_parm));
743
744	if (pwriterfparm == NULL) {
745		kfree(ph2c);
746		res = _FAIL;
747		goto exit;
748	}
749
750	init_h2fwcmd_w_parm_no_rsp(ph2c, pwriterfparm, GEN_CMD_CODE(_SetRFReg));
751
752	pwriterfparm->offset = offset;
753	pwriterfparm->value = val;
754
755	res = rtw_enqueue_cmd(pcmdpriv, ph2c);
756exit:
757_func_exit_;
758	return res;
759}
760
761u8 rtw_getrfreg_cmd(struct adapter  *padapter, u8 offset, u8 *pval)
762{
763	struct cmd_obj *ph2c;
764	struct readRF_parm *prdrfparm;
765	struct cmd_priv	*pcmdpriv = &padapter->cmdpriv;
766	u8	res = _SUCCESS;
767
768_func_enter_;
769
770	ph2c = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
771	if (ph2c == NULL) {
772		res = _FAIL;
773		goto exit;
774	}
775
776	prdrfparm = (struct readRF_parm *)rtw_zmalloc(sizeof(struct readRF_parm));
777	if (prdrfparm == NULL) {
778		kfree(ph2c);
779		res = _FAIL;
780		goto exit;
781	}
782
783	_rtw_init_listhead(&ph2c->list);
784	ph2c->cmdcode = GEN_CMD_CODE(_GetRFReg);
785	ph2c->parmbuf = (unsigned char *)prdrfparm;
786	ph2c->cmdsz =  sizeof(struct readRF_parm);
787	ph2c->rsp = pval;
788	ph2c->rspsz = sizeof(struct readRF_rsp);
789
790	prdrfparm->offset = offset;
791
792	res = rtw_enqueue_cmd(pcmdpriv, ph2c);
793
794exit:
795
796_func_exit_;
797
798	return res;
799}
800
801void rtw_getbbrfreg_cmdrsp_callback(struct adapter *padapter,  struct cmd_obj *pcmd)
802{
803 _func_enter_;
804
805	kfree(pcmd->parmbuf);
806	kfree(pcmd);
807
808	if (padapter->registrypriv.mp_mode == 1)
809		padapter->mppriv.workparam.bcompleted = true;
810_func_exit_;
811}
812
813void rtw_readtssi_cmdrsp_callback(struct adapter *padapter,  struct cmd_obj *pcmd)
814{
815 _func_enter_;
816
817	kfree(pcmd->parmbuf);
818	kfree(pcmd);
819
820	if (padapter->registrypriv.mp_mode == 1)
821		padapter->mppriv.workparam.bcompleted = true;
822_func_exit_;
823}
824
825u8 rtw_createbss_cmd(struct adapter  *padapter)
826{
827	struct cmd_obj *pcmd;
828	struct cmd_priv	*pcmdpriv = &padapter->cmdpriv;
829	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
830	struct wlan_bssid_ex *pdev_network = &padapter->registrypriv.dev_network;
831	u8	res = _SUCCESS;
832
833_func_enter_;
834
835	rtw_led_control(padapter, LED_CTL_START_TO_LINK);
836
837	if (pmlmepriv->assoc_ssid.SsidLength == 0)
838		RT_TRACE(_module_rtl871x_cmd_c_, _drv_info_, (" createbss for Any SSid:%s\n", pmlmepriv->assoc_ssid.Ssid));
839	else
840		RT_TRACE(_module_rtl871x_cmd_c_, _drv_info_, (" createbss for SSid:%s\n", pmlmepriv->assoc_ssid.Ssid));
841
842	pcmd = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
843	if (pcmd == NULL) {
844		res = _FAIL;
845		goto exit;
846	}
847
848	_rtw_init_listhead(&pcmd->list);
849	pcmd->cmdcode = _CreateBss_CMD_;
850	pcmd->parmbuf = (unsigned char *)pdev_network;
851	pcmd->cmdsz = get_wlan_bssid_ex_sz((struct wlan_bssid_ex *)pdev_network);
852	pcmd->rsp = NULL;
853	pcmd->rspsz = 0;
854	pdev_network->Length = pcmd->cmdsz;
855	res = rtw_enqueue_cmd(pcmdpriv, pcmd);
856exit:
857
858_func_exit_;
859
860	return res;
861}
862
863u8 rtw_createbss_cmd_ex(struct adapter  *padapter, unsigned char *pbss, unsigned int sz)
864{
865	struct cmd_obj *pcmd;
866	struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
867	u8	res = _SUCCESS;
868
869_func_enter_;
870
871	pcmd = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
872	if (pcmd == NULL) {
873		res = _FAIL;
874		goto exit;
875	}
876
877	_rtw_init_listhead(&pcmd->list);
878	pcmd->cmdcode = GEN_CMD_CODE(_CreateBss);
879	pcmd->parmbuf = pbss;
880	pcmd->cmdsz =  sz;
881	pcmd->rsp = NULL;
882	pcmd->rspsz = 0;
883
884	res = rtw_enqueue_cmd(pcmdpriv, pcmd);
885
886exit:
887
888_func_exit_;
889
890	return res;
891}
892
893u8 rtw_joinbss_cmd(struct adapter  *padapter, struct wlan_network *pnetwork)
894{
895	u8	res = _SUCCESS;
896	uint	t_len = 0;
897	struct wlan_bssid_ex		*psecnetwork;
898	struct cmd_obj		*pcmd;
899	struct cmd_priv		*pcmdpriv = &padapter->cmdpriv;
900	struct mlme_priv	*pmlmepriv = &padapter->mlmepriv;
901	struct qos_priv		*pqospriv = &pmlmepriv->qospriv;
902	struct security_priv	*psecuritypriv = &padapter->securitypriv;
903	struct registry_priv	*pregistrypriv = &padapter->registrypriv;
904	struct ht_priv		*phtpriv = &pmlmepriv->htpriv;
905	enum ndis_802_11_network_infra ndis_network_mode = pnetwork->network.InfrastructureMode;
906	struct mlme_ext_priv	*pmlmeext = &padapter->mlmeextpriv;
907	struct mlme_ext_info	*pmlmeinfo = &(pmlmeext->mlmext_info);
908
909_func_enter_;
910
911	rtw_led_control(padapter, LED_CTL_START_TO_LINK);
912
913	if (pmlmepriv->assoc_ssid.SsidLength == 0) {
914		RT_TRACE(_module_rtl871x_cmd_c_, _drv_info_, ("+Join cmd: Any SSid\n"));
915	} else {
916		RT_TRACE(_module_rtl871x_cmd_c_, _drv_notice_, ("+Join cmd: SSid =[%s]\n", pmlmepriv->assoc_ssid.Ssid));
917	}
918
919	pcmd = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
920	if (pcmd == NULL) {
921		res = _FAIL;
922		RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_, ("rtw_joinbss_cmd: memory allocate for cmd_obj fail!!!\n"));
923		goto exit;
924	}
925	/* for IEs is fix buf size */
926	t_len = sizeof(struct wlan_bssid_ex);
927
928
929	/* for hidden ap to set fw_state here */
930	if (!check_fwstate(pmlmepriv, WIFI_STATION_STATE|WIFI_ADHOC_STATE)) {
931		switch (ndis_network_mode) {
932		case Ndis802_11IBSS:
933			set_fwstate(pmlmepriv, WIFI_ADHOC_STATE);
934			break;
935		case Ndis802_11Infrastructure:
936			set_fwstate(pmlmepriv, WIFI_STATION_STATE);
937			break;
938		case Ndis802_11APMode:
939		case Ndis802_11AutoUnknown:
940		case Ndis802_11InfrastructureMax:
941			break;
942		}
943	}
944
945	psecnetwork = (struct wlan_bssid_ex *)&psecuritypriv->sec_bss;
946	if (psecnetwork == NULL) {
947		if (pcmd != NULL)
948			kfree(pcmd);
949
950		res = _FAIL;
951
952		RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_, ("rtw_joinbss_cmd :psecnetwork == NULL!!!\n"));
953
954		goto exit;
955	}
956
957	_rtw_memset(psecnetwork, 0, t_len);
958
959	memcpy(psecnetwork, &pnetwork->network, get_wlan_bssid_ex_sz(&pnetwork->network));
960
961	psecuritypriv->authenticator_ie[0] = (unsigned char)psecnetwork->IELength;
962
963	if ((psecnetwork->IELength-12) < (256-1)) {
964		memcpy(&psecuritypriv->authenticator_ie[1], &psecnetwork->IEs[12], psecnetwork->IELength-12);
965	} else {
966		memcpy(&psecuritypriv->authenticator_ie[1], &psecnetwork->IEs[12], (256-1));
967	}
968
969	psecnetwork->IELength = 0;
970	/*  Added by Albert 2009/02/18 */
971	/*  If the the driver wants to use the bssid to create the connection. */
972	/*  If not,  we have to copy the connecting AP's MAC address to it so that */
973	/*  the driver just has the bssid information for PMKIDList searching. */
974
975	if (!pmlmepriv->assoc_by_bssid)
976		memcpy(&pmlmepriv->assoc_bssid[0], &pnetwork->network.MacAddress[0], ETH_ALEN);
977
978	psecnetwork->IELength = rtw_restruct_sec_ie(padapter, &pnetwork->network.IEs[0], &psecnetwork->IEs[0], pnetwork->network.IELength);
979
980
981	pqospriv->qos_option = 0;
982
983	if (pregistrypriv->wmm_enable) {
984		u32 tmp_len;
985
986		tmp_len = rtw_restruct_wmm_ie(padapter, &pnetwork->network.IEs[0], &psecnetwork->IEs[0], pnetwork->network.IELength, psecnetwork->IELength);
987
988		if (psecnetwork->IELength != tmp_len) {
989			psecnetwork->IELength = tmp_len;
990			pqospriv->qos_option = 1; /* There is WMM IE in this corresp. beacon */
991		} else {
992			pqospriv->qos_option = 0;/* There is no WMM IE in this corresp. beacon */
993		}
994	}
995
996	phtpriv->ht_option = false;
997	if (pregistrypriv->ht_enable) {
998		/* 	Added by Albert 2010/06/23 */
999		/* 	For the WEP mode, we will use the bg mode to do the connection to avoid some IOT issue. */
1000		/* 	Especially for Realtek 8192u SoftAP. */
1001		if ((padapter->securitypriv.dot11PrivacyAlgrthm != _WEP40_) &&
1002		    (padapter->securitypriv.dot11PrivacyAlgrthm != _WEP104_) &&
1003		    (padapter->securitypriv.dot11PrivacyAlgrthm != _TKIP_)) {
1004			/* rtw_restructure_ht_ie */
1005			rtw_restructure_ht_ie(padapter, &pnetwork->network.IEs[0], &psecnetwork->IEs[0],
1006									pnetwork->network.IELength, &psecnetwork->IELength);
1007		}
1008	}
1009
1010	pmlmeinfo->assoc_AP_vendor = check_assoc_AP(pnetwork->network.IEs, pnetwork->network.IELength);
1011
1012	if (pmlmeinfo->assoc_AP_vendor == HT_IOT_PEER_TENDA)
1013		padapter->pwrctrlpriv.smart_ps = 0;
1014	else
1015		padapter->pwrctrlpriv.smart_ps = padapter->registrypriv.smart_ps;
1016
1017	DBG_88E("%s: smart_ps =%d\n", __func__, padapter->pwrctrlpriv.smart_ps);
1018
1019	pcmd->cmdsz = get_wlan_bssid_ex_sz(psecnetwork);/* get cmdsz before endian conversion */
1020
1021	_rtw_init_listhead(&pcmd->list);
1022	pcmd->cmdcode = _JoinBss_CMD_;/* GEN_CMD_CODE(_JoinBss) */
1023	pcmd->parmbuf = (unsigned char *)psecnetwork;
1024	pcmd->rsp = NULL;
1025	pcmd->rspsz = 0;
1026
1027	res = rtw_enqueue_cmd(pcmdpriv, pcmd);
1028
1029exit:
1030
1031_func_exit_;
1032
1033	return res;
1034}
1035
1036u8 rtw_disassoc_cmd(struct adapter *padapter, u32 deauth_timeout_ms, bool enqueue) /* for sta_mode */
1037{
1038	struct cmd_obj *cmdobj = NULL;
1039	struct disconnect_parm *param = NULL;
1040	struct cmd_priv *cmdpriv = &padapter->cmdpriv;
1041	u8 res = _SUCCESS;
1042
1043_func_enter_;
1044
1045	RT_TRACE(_module_rtl871x_cmd_c_, _drv_notice_, ("+rtw_disassoc_cmd\n"));
1046
1047	/* prepare cmd parameter */
1048	param = (struct disconnect_parm *)rtw_zmalloc(sizeof(*param));
1049	if (param == NULL) {
1050		res = _FAIL;
1051		goto exit;
1052	}
1053	param->deauth_timeout_ms = deauth_timeout_ms;
1054
1055	if (enqueue) {
1056		/* need enqueue, prepare cmd_obj and enqueue */
1057		cmdobj = (struct cmd_obj *)rtw_zmalloc(sizeof(*cmdobj));
1058		if (cmdobj == NULL) {
1059			res = _FAIL;
1060			kfree(param);
1061			goto exit;
1062		}
1063		init_h2fwcmd_w_parm_no_rsp(cmdobj, param, _DisConnect_CMD_);
1064		res = rtw_enqueue_cmd(cmdpriv, cmdobj);
1065	} else {
1066		/* no need to enqueue, do the cmd hdl directly and free cmd parameter */
1067		if (H2C_SUCCESS != disconnect_hdl(padapter, (u8 *)param))
1068			res = _FAIL;
1069		kfree(param);
1070	}
1071
1072exit:
1073
1074_func_exit_;
1075
1076	return res;
1077}
1078
1079u8 rtw_setopmode_cmd(struct adapter  *padapter, enum ndis_802_11_network_infra networktype)
1080{
1081	struct	cmd_obj *ph2c;
1082	struct	setopmode_parm *psetop;
1083
1084	struct	cmd_priv   *pcmdpriv = &padapter->cmdpriv;
1085	u8	res = _SUCCESS;
1086
1087_func_enter_;
1088
1089	ph2c = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
1090	if (ph2c == NULL) {
1091		res = false;
1092		goto exit;
1093	}
1094	psetop = (struct setopmode_parm *)rtw_zmalloc(sizeof(struct setopmode_parm));
1095
1096	if (psetop == NULL) {
1097		kfree(ph2c);
1098		res = false;
1099		goto exit;
1100	}
1101
1102	init_h2fwcmd_w_parm_no_rsp(ph2c, psetop, _SetOpMode_CMD_);
1103	psetop->mode = (u8)networktype;
1104
1105	res = rtw_enqueue_cmd(pcmdpriv, ph2c);
1106
1107exit:
1108
1109_func_exit_;
1110
1111	return res;
1112}
1113
1114u8 rtw_setstakey_cmd(struct adapter *padapter, u8 *psta, u8 unicast_key)
1115{
1116	struct cmd_obj *ph2c;
1117	struct set_stakey_parm *psetstakey_para;
1118	struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
1119	struct set_stakey_rsp *psetstakey_rsp = NULL;
1120
1121	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1122	struct security_priv *psecuritypriv = &padapter->securitypriv;
1123	struct sta_info *sta = (struct sta_info *)psta;
1124	u8	res = _SUCCESS;
1125
1126_func_enter_;
1127
1128	ph2c = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
1129	if (ph2c == NULL) {
1130		res = _FAIL;
1131		goto exit;
1132	}
1133
1134	psetstakey_para = (struct set_stakey_parm *)rtw_zmalloc(sizeof(struct set_stakey_parm));
1135	if (psetstakey_para == NULL) {
1136		kfree(ph2c);
1137		res = _FAIL;
1138		goto exit;
1139	}
1140
1141	psetstakey_rsp = (struct set_stakey_rsp *)rtw_zmalloc(sizeof(struct set_stakey_rsp));
1142	if (psetstakey_rsp == NULL) {
1143		kfree(ph2c);
1144		kfree(psetstakey_para);
1145		res = _FAIL;
1146		goto exit;
1147	}
1148
1149	init_h2fwcmd_w_parm_no_rsp(ph2c, psetstakey_para, _SetStaKey_CMD_);
1150	ph2c->rsp = (u8 *)psetstakey_rsp;
1151	ph2c->rspsz = sizeof(struct set_stakey_rsp);
1152
1153	memcpy(psetstakey_para->addr, sta->hwaddr, ETH_ALEN);
1154
1155	if (check_fwstate(pmlmepriv, WIFI_STATION_STATE))
1156		psetstakey_para->algorithm = (unsigned char) psecuritypriv->dot11PrivacyAlgrthm;
1157	else
1158		GET_ENCRY_ALGO(psecuritypriv, sta, psetstakey_para->algorithm, false);
1159
1160	if (unicast_key)
1161		memcpy(&psetstakey_para->key, &sta->dot118021x_UncstKey, 16);
1162	else
1163		memcpy(&psetstakey_para->key, &psecuritypriv->dot118021XGrpKey[psecuritypriv->dot118021XGrpKeyid].skey, 16);
1164
1165	/* jeff: set this because at least sw key is ready */
1166	padapter->securitypriv.busetkipkey = true;
1167
1168	res = rtw_enqueue_cmd(pcmdpriv, ph2c);
1169
1170exit:
1171
1172_func_exit_;
1173
1174	return res;
1175}
1176
1177u8 rtw_clearstakey_cmd(struct adapter *padapter, u8 *psta, u8 entry, u8 enqueue)
1178{
1179	struct cmd_obj *ph2c;
1180	struct set_stakey_parm	*psetstakey_para;
1181	struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
1182	struct set_stakey_rsp *psetstakey_rsp = NULL;
1183	struct sta_info *sta = (struct sta_info *)psta;
1184	u8	res = _SUCCESS;
1185
1186_func_enter_;
1187
1188	if (!enqueue) {
1189		clear_cam_entry(padapter, entry);
1190	} else {
1191		ph2c = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
1192		if (ph2c == NULL) {
1193			res = _FAIL;
1194			goto exit;
1195		}
1196
1197		psetstakey_para = (struct set_stakey_parm *)rtw_zmalloc(sizeof(struct set_stakey_parm));
1198		if (psetstakey_para == NULL) {
1199			kfree(ph2c);
1200			res = _FAIL;
1201			goto exit;
1202		}
1203
1204		psetstakey_rsp = (struct set_stakey_rsp *)rtw_zmalloc(sizeof(struct set_stakey_rsp));
1205		if (psetstakey_rsp == NULL) {
1206			kfree(ph2c);
1207			kfree(psetstakey_para);
1208			res = _FAIL;
1209			goto exit;
1210		}
1211
1212		init_h2fwcmd_w_parm_no_rsp(ph2c, psetstakey_para, _SetStaKey_CMD_);
1213		ph2c->rsp = (u8 *)psetstakey_rsp;
1214		ph2c->rspsz = sizeof(struct set_stakey_rsp);
1215
1216		memcpy(psetstakey_para->addr, sta->hwaddr, ETH_ALEN);
1217
1218		psetstakey_para->algorithm = _NO_PRIVACY_;
1219
1220		psetstakey_para->id = entry;
1221
1222		res = rtw_enqueue_cmd(pcmdpriv, ph2c);
1223	}
1224exit:
1225
1226_func_exit_;
1227
1228	return res;
1229}
1230
1231u8 rtw_setrttbl_cmd(struct adapter  *padapter, struct setratable_parm *prate_table)
1232{
1233	struct cmd_obj *ph2c;
1234	struct setratable_parm *psetrttblparm;
1235	struct cmd_priv	*pcmdpriv = &padapter->cmdpriv;
1236	u8	res = _SUCCESS;
1237_func_enter_;
1238
1239	ph2c = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
1240	if (ph2c == NULL) {
1241		res = _FAIL;
1242		goto exit;
1243	}
1244	psetrttblparm = (struct setratable_parm *)rtw_zmalloc(sizeof(struct setratable_parm));
1245
1246	if (psetrttblparm == NULL) {
1247		kfree(ph2c);
1248		res = _FAIL;
1249		goto exit;
1250	}
1251
1252	init_h2fwcmd_w_parm_no_rsp(ph2c, psetrttblparm, GEN_CMD_CODE(_SetRaTable));
1253
1254	memcpy(psetrttblparm, prate_table, sizeof(struct setratable_parm));
1255
1256	res = rtw_enqueue_cmd(pcmdpriv, ph2c);
1257exit:
1258_func_exit_;
1259	return res;
1260}
1261
1262u8 rtw_getrttbl_cmd(struct adapter  *padapter, struct getratable_rsp *pval)
1263{
1264	struct cmd_obj *ph2c;
1265	struct getratable_parm *pgetrttblparm;
1266	struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
1267	u8	res = _SUCCESS;
1268_func_enter_;
1269
1270	ph2c = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
1271	if (ph2c == NULL) {
1272		res = _FAIL;
1273		goto exit;
1274	}
1275	pgetrttblparm = (struct getratable_parm *)rtw_zmalloc(sizeof(struct getratable_parm));
1276
1277	if (pgetrttblparm == NULL) {
1278		kfree(ph2c);
1279		res = _FAIL;
1280		goto exit;
1281	}
1282
1283/* 	init_h2fwcmd_w_parm_no_rsp(ph2c, psetrttblparm, GEN_CMD_CODE(_SetRaTable)); */
1284
1285	_rtw_init_listhead(&ph2c->list);
1286	ph2c->cmdcode = GEN_CMD_CODE(_GetRaTable);
1287	ph2c->parmbuf = (unsigned char *)pgetrttblparm;
1288	ph2c->cmdsz =  sizeof(struct getratable_parm);
1289	ph2c->rsp = (u8 *)pval;
1290	ph2c->rspsz = sizeof(struct getratable_rsp);
1291
1292	pgetrttblparm->rsvd = 0x0;
1293
1294	res = rtw_enqueue_cmd(pcmdpriv, ph2c);
1295exit:
1296_func_exit_;
1297	return res;
1298}
1299
1300u8 rtw_setassocsta_cmd(struct adapter  *padapter, u8 *mac_addr)
1301{
1302	struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
1303	struct cmd_obj *ph2c;
1304	struct set_assocsta_parm *psetassocsta_para;
1305	struct set_stakey_rsp *psetassocsta_rsp = NULL;
1306
1307	u8	res = _SUCCESS;
1308
1309_func_enter_;
1310
1311	ph2c = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
1312	if (ph2c == NULL) {
1313		res = _FAIL;
1314		goto exit;
1315	}
1316
1317	psetassocsta_para = (struct set_assocsta_parm *)rtw_zmalloc(sizeof(struct set_assocsta_parm));
1318	if (psetassocsta_para == NULL) {
1319		kfree(ph2c);
1320		res = _FAIL;
1321		goto exit;
1322	}
1323
1324	psetassocsta_rsp = (struct set_stakey_rsp *)rtw_zmalloc(sizeof(struct set_assocsta_rsp));
1325	if (psetassocsta_rsp == NULL) {
1326		kfree(ph2c);
1327		kfree(psetassocsta_para);
1328		return _FAIL;
1329	}
1330
1331	init_h2fwcmd_w_parm_no_rsp(ph2c, psetassocsta_para, _SetAssocSta_CMD_);
1332	ph2c->rsp = (u8 *)psetassocsta_rsp;
1333	ph2c->rspsz = sizeof(struct set_assocsta_rsp);
1334
1335	memcpy(psetassocsta_para->addr, mac_addr, ETH_ALEN);
1336
1337	res = rtw_enqueue_cmd(pcmdpriv, ph2c);
1338
1339exit:
1340
1341_func_exit_;
1342
1343	return res;
1344 }
1345
1346u8 rtw_addbareq_cmd(struct adapter *padapter, u8 tid, u8 *addr)
1347{
1348	struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
1349	struct cmd_obj *ph2c;
1350	struct addBaReq_parm *paddbareq_parm;
1351	u8	res = _SUCCESS;
1352
1353_func_enter_;
1354
1355	ph2c = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
1356	if (ph2c == NULL) {
1357		res = _FAIL;
1358		goto exit;
1359	}
1360
1361	paddbareq_parm = (struct addBaReq_parm *)rtw_zmalloc(sizeof(struct addBaReq_parm));
1362	if (paddbareq_parm == NULL) {
1363		kfree(ph2c);
1364		res = _FAIL;
1365		goto exit;
1366	}
1367
1368	paddbareq_parm->tid = tid;
1369	memcpy(paddbareq_parm->addr, addr, ETH_ALEN);
1370
1371	init_h2fwcmd_w_parm_no_rsp(ph2c, paddbareq_parm, GEN_CMD_CODE(_AddBAReq));
1372
1373	/* DBG_88E("rtw_addbareq_cmd, tid =%d\n", tid); */
1374
1375	/* rtw_enqueue_cmd(pcmdpriv, ph2c); */
1376	res = rtw_enqueue_cmd(pcmdpriv, ph2c);
1377
1378exit:
1379
1380_func_exit_;
1381
1382	return res;
1383}
1384
1385u8 rtw_dynamic_chk_wk_cmd(struct adapter *padapter)
1386{
1387	struct cmd_obj *ph2c;
1388	struct drvextra_cmd_parm *pdrvextra_cmd_parm;
1389	struct cmd_priv	*pcmdpriv = &padapter->cmdpriv;
1390	u8	res = _SUCCESS;
1391
1392_func_enter_;
1393
1394	ph2c = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
1395	if (ph2c == NULL) {
1396		res = _FAIL;
1397		goto exit;
1398	}
1399
1400	pdrvextra_cmd_parm = (struct drvextra_cmd_parm *)rtw_zmalloc(sizeof(struct drvextra_cmd_parm));
1401	if (pdrvextra_cmd_parm == NULL) {
1402		kfree(ph2c);
1403		res = _FAIL;
1404		goto exit;
1405	}
1406
1407	pdrvextra_cmd_parm->ec_id = DYNAMIC_CHK_WK_CID;
1408	pdrvextra_cmd_parm->type_size = 0;
1409	pdrvextra_cmd_parm->pbuf = (u8 *)padapter;
1410
1411	init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, GEN_CMD_CODE(_Set_Drv_Extra));
1412
1413
1414	/* rtw_enqueue_cmd(pcmdpriv, ph2c); */
1415	res = rtw_enqueue_cmd(pcmdpriv, ph2c);
1416exit:
1417_func_exit_;
1418	return res;
1419}
1420
1421u8 rtw_set_ch_cmd(struct adapter *padapter, u8 ch, u8 bw, u8 ch_offset, u8 enqueue)
1422{
1423	struct cmd_obj *pcmdobj;
1424	struct set_ch_parm *set_ch_parm;
1425	struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
1426
1427	u8 res = _SUCCESS;
1428
1429_func_enter_;
1430
1431	DBG_88E(FUNC_NDEV_FMT" ch:%u, bw:%u, ch_offset:%u\n",
1432		FUNC_NDEV_ARG(padapter->pnetdev), ch, bw, ch_offset);
1433
1434	/* check input parameter */
1435
1436	/* prepare cmd parameter */
1437	set_ch_parm = (struct set_ch_parm *)rtw_zmalloc(sizeof(*set_ch_parm));
1438	if (set_ch_parm == NULL) {
1439		res = _FAIL;
1440		goto exit;
1441	}
1442	set_ch_parm->ch = ch;
1443	set_ch_parm->bw = bw;
1444	set_ch_parm->ch_offset = ch_offset;
1445
1446	if (enqueue) {
1447		/* need enqueue, prepare cmd_obj and enqueue */
1448		pcmdobj = (struct cmd_obj *)rtw_zmalloc(sizeof(struct	cmd_obj));
1449		if (pcmdobj == NULL) {
1450			kfree(set_ch_parm);
1451			res = _FAIL;
1452			goto exit;
1453		}
1454
1455		init_h2fwcmd_w_parm_no_rsp(pcmdobj, set_ch_parm, GEN_CMD_CODE(_SetChannel));
1456		res = rtw_enqueue_cmd(pcmdpriv, pcmdobj);
1457	} else {
1458		/* no need to enqueue, do the cmd hdl directly and free cmd parameter */
1459		if (H2C_SUCCESS != set_ch_hdl(padapter, (u8 *)set_ch_parm))
1460			res = _FAIL;
1461
1462		kfree(set_ch_parm);
1463	}
1464
1465	/* do something based on res... */
1466
1467exit:
1468
1469	DBG_88E(FUNC_NDEV_FMT" res:%u\n", FUNC_NDEV_ARG(padapter->pnetdev), res);
1470
1471_func_exit_;
1472
1473	return res;
1474}
1475
1476u8 rtw_set_chplan_cmd(struct adapter *padapter, u8 chplan, u8 enqueue)
1477{
1478	struct	cmd_obj *pcmdobj;
1479	struct	SetChannelPlan_param *setChannelPlan_param;
1480	struct	cmd_priv   *pcmdpriv = &padapter->cmdpriv;
1481
1482	u8	res = _SUCCESS;
1483
1484_func_enter_;
1485
1486	RT_TRACE(_module_rtl871x_cmd_c_, _drv_notice_, ("+rtw_set_chplan_cmd\n"));
1487
1488	/* check input parameter */
1489	if (!rtw_is_channel_plan_valid(chplan)) {
1490		res = _FAIL;
1491		goto exit;
1492	}
1493
1494	/* prepare cmd parameter */
1495	setChannelPlan_param = (struct	SetChannelPlan_param *)rtw_zmalloc(sizeof(struct SetChannelPlan_param));
1496	if (setChannelPlan_param == NULL) {
1497		res = _FAIL;
1498		goto exit;
1499	}
1500	setChannelPlan_param->channel_plan = chplan;
1501
1502	if (enqueue) {
1503		/* need enqueue, prepare cmd_obj and enqueue */
1504		pcmdobj = (struct cmd_obj *)rtw_zmalloc(sizeof(struct	cmd_obj));
1505		if (pcmdobj == NULL) {
1506			kfree(setChannelPlan_param);
1507			res = _FAIL;
1508			goto exit;
1509		}
1510
1511		init_h2fwcmd_w_parm_no_rsp(pcmdobj, setChannelPlan_param, GEN_CMD_CODE(_SetChannelPlan));
1512		res = rtw_enqueue_cmd(pcmdpriv, pcmdobj);
1513	} else {
1514		/* no need to enqueue, do the cmd hdl directly and free cmd parameter */
1515		if (H2C_SUCCESS != set_chplan_hdl(padapter, (unsigned char *)setChannelPlan_param))
1516			res = _FAIL;
1517
1518		kfree(setChannelPlan_param);
1519	}
1520
1521	/* do something based on res... */
1522	if (res == _SUCCESS)
1523		padapter->mlmepriv.ChannelPlan = chplan;
1524
1525exit:
1526
1527_func_exit_;
1528
1529	return res;
1530}
1531
1532u8 rtw_led_blink_cmd(struct adapter *padapter, struct LED_871x *pLed)
1533{
1534	struct	cmd_obj *pcmdobj;
1535	struct	LedBlink_param *ledBlink_param;
1536	struct	cmd_priv   *pcmdpriv = &padapter->cmdpriv;
1537
1538	u8	res = _SUCCESS;
1539
1540_func_enter_;
1541
1542	RT_TRACE(_module_rtl871x_cmd_c_, _drv_notice_, ("+rtw_led_blink_cmd\n"));
1543
1544	pcmdobj = (struct cmd_obj *)rtw_zmalloc(sizeof(struct	cmd_obj));
1545	if (pcmdobj == NULL) {
1546		res = _FAIL;
1547		goto exit;
1548	}
1549
1550	ledBlink_param = (struct	LedBlink_param *)rtw_zmalloc(sizeof(struct	LedBlink_param));
1551	if (ledBlink_param == NULL) {
1552		kfree(pcmdobj);
1553		res = _FAIL;
1554		goto exit;
1555	}
1556
1557	ledBlink_param->pLed = pLed;
1558
1559	init_h2fwcmd_w_parm_no_rsp(pcmdobj, ledBlink_param, GEN_CMD_CODE(_LedBlink));
1560	res = rtw_enqueue_cmd(pcmdpriv, pcmdobj);
1561
1562exit:
1563
1564_func_exit_;
1565
1566	return res;
1567}
1568
1569u8 rtw_set_csa_cmd(struct adapter *padapter, u8 new_ch_no)
1570{
1571	struct	cmd_obj *pcmdobj;
1572	struct	SetChannelSwitch_param *setChannelSwitch_param;
1573	struct	cmd_priv   *pcmdpriv = &padapter->cmdpriv;
1574
1575	u8	res = _SUCCESS;
1576
1577_func_enter_;
1578
1579	RT_TRACE(_module_rtl871x_cmd_c_, _drv_notice_, ("+rtw_set_csa_cmd\n"));
1580
1581	pcmdobj = (struct cmd_obj *)rtw_zmalloc(sizeof(struct	cmd_obj));
1582	if (pcmdobj == NULL) {
1583		res = _FAIL;
1584		goto exit;
1585	}
1586
1587	setChannelSwitch_param = (struct SetChannelSwitch_param *)rtw_zmalloc(sizeof(struct	SetChannelSwitch_param));
1588	if (setChannelSwitch_param == NULL) {
1589		kfree(pcmdobj);
1590		res = _FAIL;
1591		goto exit;
1592	}
1593
1594	setChannelSwitch_param->new_ch_no = new_ch_no;
1595
1596	init_h2fwcmd_w_parm_no_rsp(pcmdobj, setChannelSwitch_param, GEN_CMD_CODE(_SetChannelSwitch));
1597	res = rtw_enqueue_cmd(pcmdpriv, pcmdobj);
1598
1599exit:
1600
1601_func_exit_;
1602
1603	return res;
1604}
1605
1606u8 rtw_tdls_cmd(struct adapter *padapter, u8 *addr, u8 option)
1607{
1608	return _SUCCESS;
1609}
1610
1611static void traffic_status_watchdog(struct adapter *padapter)
1612{
1613	u8	bEnterPS;
1614	u8	bBusyTraffic = false, bTxBusyTraffic = false, bRxBusyTraffic = false;
1615	u8	bHigherBusyTraffic = false, bHigherBusyRxTraffic = false, bHigherBusyTxTraffic = false;
1616	struct mlme_priv		*pmlmepriv = &(padapter->mlmepriv);
1617
1618	/*  */
1619	/*  Determine if our traffic is busy now */
1620	/*  */
1621	if (check_fwstate(pmlmepriv, _FW_LINKED)) {
1622		if (pmlmepriv->LinkDetectInfo.NumRxOkInPeriod > 100 ||
1623		    pmlmepriv->LinkDetectInfo.NumTxOkInPeriod > 100) {
1624			bBusyTraffic = true;
1625
1626			if (pmlmepriv->LinkDetectInfo.NumRxOkInPeriod > pmlmepriv->LinkDetectInfo.NumTxOkInPeriod)
1627				bRxBusyTraffic = true;
1628			else
1629				bTxBusyTraffic = true;
1630		}
1631
1632		/*  Higher Tx/Rx data. */
1633		if (pmlmepriv->LinkDetectInfo.NumRxOkInPeriod > 4000 ||
1634		    pmlmepriv->LinkDetectInfo.NumTxOkInPeriod > 4000) {
1635			bHigherBusyTraffic = true;
1636
1637			if (pmlmepriv->LinkDetectInfo.NumRxOkInPeriod > pmlmepriv->LinkDetectInfo.NumTxOkInPeriod)
1638				bHigherBusyRxTraffic = true;
1639			else
1640				bHigherBusyTxTraffic = true;
1641		}
1642
1643		/*  check traffic for  powersaving. */
1644		if (((pmlmepriv->LinkDetectInfo.NumRxUnicastOkInPeriod + pmlmepriv->LinkDetectInfo.NumTxOkInPeriod) > 8) ||
1645		    (pmlmepriv->LinkDetectInfo.NumRxUnicastOkInPeriod > 2))
1646			bEnterPS = false;
1647		else
1648			bEnterPS = true;
1649
1650		/*  LeisurePS only work in infra mode. */
1651		if (bEnterPS)
1652			LPS_Enter(padapter);
1653		else
1654			LPS_Leave(padapter);
1655	} else {
1656		LPS_Leave(padapter);
1657	}
1658
1659	pmlmepriv->LinkDetectInfo.NumRxOkInPeriod = 0;
1660	pmlmepriv->LinkDetectInfo.NumTxOkInPeriod = 0;
1661	pmlmepriv->LinkDetectInfo.NumRxUnicastOkInPeriod = 0;
1662	pmlmepriv->LinkDetectInfo.bBusyTraffic = bBusyTraffic;
1663	pmlmepriv->LinkDetectInfo.bTxBusyTraffic = bTxBusyTraffic;
1664	pmlmepriv->LinkDetectInfo.bRxBusyTraffic = bRxBusyTraffic;
1665	pmlmepriv->LinkDetectInfo.bHigherBusyTraffic = bHigherBusyTraffic;
1666	pmlmepriv->LinkDetectInfo.bHigherBusyRxTraffic = bHigherBusyRxTraffic;
1667	pmlmepriv->LinkDetectInfo.bHigherBusyTxTraffic = bHigherBusyTxTraffic;
1668}
1669
1670static void dynamic_chk_wk_hdl(struct adapter *padapter, u8 *pbuf, int sz)
1671{
1672	struct mlme_priv *pmlmepriv;
1673
1674	padapter = (struct adapter *)pbuf;
1675	pmlmepriv = &(padapter->mlmepriv);
1676
1677#ifdef CONFIG_88EU_AP_MODE
1678	if (check_fwstate(pmlmepriv, WIFI_AP_STATE) == true)
1679		expire_timeout_chk(padapter);
1680#endif
1681
1682	rtw_hal_sreset_xmit_status_check(padapter);
1683
1684	linked_status_chk(padapter);
1685	traffic_status_watchdog(padapter);
1686
1687	rtw_hal_dm_watchdog(padapter);
1688}
1689
1690static void lps_ctrl_wk_hdl(struct adapter *padapter, u8 lps_ctrl_type)
1691{
1692	struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv;
1693	struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
1694	u8	mstatus;
1695
1696_func_enter_;
1697
1698	if ((check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) == true) ||
1699	    (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE) == true))
1700		return;
1701
1702	switch (lps_ctrl_type) {
1703	case LPS_CTRL_SCAN:
1704		if (check_fwstate(pmlmepriv, _FW_LINKED) == true) {
1705			/* connect */
1706			LPS_Leave(padapter);
1707		}
1708		break;
1709	case LPS_CTRL_JOINBSS:
1710		LPS_Leave(padapter);
1711		break;
1712	case LPS_CTRL_CONNECT:
1713		mstatus = 1;/* connect */
1714		/*  Reset LPS Setting */
1715		padapter->pwrctrlpriv.LpsIdleCount = 0;
1716		rtw_hal_set_hwreg(padapter, HW_VAR_H2C_FW_JOINBSSRPT, (u8 *)(&mstatus));
1717		break;
1718	case LPS_CTRL_DISCONNECT:
1719		mstatus = 0;/* disconnect */
1720		LPS_Leave(padapter);
1721		rtw_hal_set_hwreg(padapter, HW_VAR_H2C_FW_JOINBSSRPT, (u8 *)(&mstatus));
1722		break;
1723	case LPS_CTRL_SPECIAL_PACKET:
1724		/* DBG_88E("LPS_CTRL_SPECIAL_PACKET\n"); */
1725		pwrpriv->DelayLPSLastTimeStamp = rtw_get_current_time();
1726		LPS_Leave(padapter);
1727		break;
1728	case LPS_CTRL_LEAVE:
1729		LPS_Leave(padapter);
1730		break;
1731	default:
1732		break;
1733	}
1734
1735_func_exit_;
1736}
1737
1738u8 rtw_lps_ctrl_wk_cmd(struct adapter *padapter, u8 lps_ctrl_type, u8 enqueue)
1739{
1740	struct cmd_obj	*ph2c;
1741	struct drvextra_cmd_parm	*pdrvextra_cmd_parm;
1742	struct cmd_priv	*pcmdpriv = &padapter->cmdpriv;
1743	/* struct pwrctrl_priv *pwrctrlpriv = &padapter->pwrctrlpriv; */
1744	u8	res = _SUCCESS;
1745
1746_func_enter_;
1747
1748	/* if (!pwrctrlpriv->bLeisurePs) */
1749	/* 	return res; */
1750
1751	if (enqueue) {
1752		ph2c = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
1753		if (ph2c == NULL) {
1754			res = _FAIL;
1755			goto exit;
1756		}
1757
1758		pdrvextra_cmd_parm = (struct drvextra_cmd_parm *)rtw_zmalloc(sizeof(struct drvextra_cmd_parm));
1759		if (pdrvextra_cmd_parm == NULL) {
1760			kfree(ph2c);
1761			res = _FAIL;
1762			goto exit;
1763		}
1764
1765		pdrvextra_cmd_parm->ec_id = LPS_CTRL_WK_CID;
1766		pdrvextra_cmd_parm->type_size = lps_ctrl_type;
1767		pdrvextra_cmd_parm->pbuf = NULL;
1768
1769		init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, GEN_CMD_CODE(_Set_Drv_Extra));
1770
1771		res = rtw_enqueue_cmd(pcmdpriv, ph2c);
1772	} else {
1773		lps_ctrl_wk_hdl(padapter, lps_ctrl_type);
1774	}
1775
1776exit:
1777
1778_func_exit_;
1779
1780	return res;
1781}
1782
1783static void rpt_timer_setting_wk_hdl(struct adapter *padapter, u16 min_time)
1784{
1785	rtw_hal_set_hwreg(padapter, HW_VAR_RPT_TIMER_SETTING, (u8 *)(&min_time));
1786}
1787
1788u8 rtw_rpt_timer_cfg_cmd(struct adapter *padapter, u16 min_time)
1789{
1790	struct cmd_obj		*ph2c;
1791	struct drvextra_cmd_parm	*pdrvextra_cmd_parm;
1792	struct cmd_priv	*pcmdpriv = &padapter->cmdpriv;
1793
1794	u8	res = _SUCCESS;
1795
1796_func_enter_;
1797	ph2c = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
1798	if (ph2c == NULL) {
1799		res = _FAIL;
1800		goto exit;
1801	}
1802
1803	pdrvextra_cmd_parm = (struct drvextra_cmd_parm *)rtw_zmalloc(sizeof(struct drvextra_cmd_parm));
1804	if (pdrvextra_cmd_parm == NULL) {
1805		kfree(ph2c);
1806		res = _FAIL;
1807		goto exit;
1808	}
1809
1810	pdrvextra_cmd_parm->ec_id = RTP_TIMER_CFG_WK_CID;
1811	pdrvextra_cmd_parm->type_size = min_time;
1812	pdrvextra_cmd_parm->pbuf = NULL;
1813	init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, GEN_CMD_CODE(_Set_Drv_Extra));
1814	res = rtw_enqueue_cmd(pcmdpriv, ph2c);
1815exit:
1816
1817_func_exit_;
1818
1819	return res;
1820}
1821
1822static void antenna_select_wk_hdl(struct adapter *padapter, u8 antenna)
1823{
1824	rtw_hal_set_hwreg(padapter, HW_VAR_ANTENNA_DIVERSITY_SELECT, (u8 *)(&antenna));
1825}
1826
1827u8 rtw_antenna_select_cmd(struct adapter *padapter, u8 antenna, u8 enqueue)
1828{
1829	struct cmd_obj		*ph2c;
1830	struct drvextra_cmd_parm	*pdrvextra_cmd_parm;
1831	struct cmd_priv	*pcmdpriv = &padapter->cmdpriv;
1832	u8	support_ant_div;
1833	u8	res = _SUCCESS;
1834
1835_func_enter_;
1836	rtw_hal_get_def_var(padapter, HAL_DEF_IS_SUPPORT_ANT_DIV, &support_ant_div);
1837	if (!support_ant_div)
1838		return res;
1839
1840	if (enqueue) {
1841		ph2c = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
1842		if (ph2c == NULL) {
1843			res = _FAIL;
1844			goto exit;
1845		}
1846
1847		pdrvextra_cmd_parm = (struct drvextra_cmd_parm *)rtw_zmalloc(sizeof(struct drvextra_cmd_parm));
1848		if (pdrvextra_cmd_parm == NULL) {
1849			kfree(ph2c);
1850			res = _FAIL;
1851			goto exit;
1852		}
1853
1854		pdrvextra_cmd_parm->ec_id = ANT_SELECT_WK_CID;
1855		pdrvextra_cmd_parm->type_size = antenna;
1856		pdrvextra_cmd_parm->pbuf = NULL;
1857		init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, GEN_CMD_CODE(_Set_Drv_Extra));
1858
1859		res = rtw_enqueue_cmd(pcmdpriv, ph2c);
1860	} else {
1861		antenna_select_wk_hdl(padapter, antenna);
1862	}
1863exit:
1864
1865_func_exit_;
1866
1867	return res;
1868}
1869
1870static void power_saving_wk_hdl(struct adapter *padapter, u8 *pbuf, int sz)
1871{
1872	 rtw_ps_processor(padapter);
1873}
1874
1875#ifdef CONFIG_88EU_P2P
1876u8 p2p_protocol_wk_cmd(struct adapter *padapter, int intCmdType)
1877{
1878	struct cmd_obj	*ph2c;
1879	struct drvextra_cmd_parm	*pdrvextra_cmd_parm;
1880	struct wifidirect_info	*pwdinfo = &(padapter->wdinfo);
1881	struct cmd_priv	*pcmdpriv = &padapter->cmdpriv;
1882	u8	res = _SUCCESS;
1883
1884_func_enter_;
1885
1886	if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE))
1887		return res;
1888
1889	ph2c = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
1890	if (ph2c == NULL) {
1891		res = _FAIL;
1892		goto exit;
1893	}
1894
1895	pdrvextra_cmd_parm = (struct drvextra_cmd_parm *)rtw_zmalloc(sizeof(struct drvextra_cmd_parm));
1896	if (pdrvextra_cmd_parm == NULL) {
1897		kfree(ph2c);
1898		res = _FAIL;
1899		goto exit;
1900	}
1901
1902	pdrvextra_cmd_parm->ec_id = P2P_PROTO_WK_CID;
1903	pdrvextra_cmd_parm->type_size = intCmdType;	/* 	As the command tppe. */
1904	pdrvextra_cmd_parm->pbuf = NULL;		/* 	Must be NULL here */
1905
1906	init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, GEN_CMD_CODE(_Set_Drv_Extra));
1907
1908	res = rtw_enqueue_cmd(pcmdpriv, ph2c);
1909
1910exit:
1911
1912_func_exit_;
1913
1914	return res;
1915}
1916#endif /* CONFIG_88EU_P2P */
1917
1918u8 rtw_ps_cmd(struct adapter *padapter)
1919{
1920	struct cmd_obj		*ppscmd;
1921	struct drvextra_cmd_parm	*pdrvextra_cmd_parm;
1922	struct cmd_priv	*pcmdpriv = &padapter->cmdpriv;
1923
1924	u8	res = _SUCCESS;
1925_func_enter_;
1926
1927	ppscmd = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
1928	if (ppscmd == NULL) {
1929		res = _FAIL;
1930		goto exit;
1931	}
1932
1933	pdrvextra_cmd_parm = (struct drvextra_cmd_parm *)rtw_zmalloc(sizeof(struct drvextra_cmd_parm));
1934	if (pdrvextra_cmd_parm == NULL) {
1935		kfree(ppscmd);
1936		res = _FAIL;
1937		goto exit;
1938	}
1939
1940	pdrvextra_cmd_parm->ec_id = POWER_SAVING_CTRL_WK_CID;
1941	pdrvextra_cmd_parm->pbuf = NULL;
1942	init_h2fwcmd_w_parm_no_rsp(ppscmd, pdrvextra_cmd_parm, GEN_CMD_CODE(_Set_Drv_Extra));
1943
1944	res = rtw_enqueue_cmd(pcmdpriv, ppscmd);
1945
1946exit:
1947
1948_func_exit_;
1949
1950	return res;
1951}
1952
1953#ifdef CONFIG_88EU_AP_MODE
1954
1955static void rtw_chk_hi_queue_hdl(struct adapter *padapter)
1956{
1957	int cnt = 0;
1958	struct sta_info *psta_bmc;
1959	struct sta_priv *pstapriv = &padapter->stapriv;
1960
1961	psta_bmc = rtw_get_bcmc_stainfo(padapter);
1962	if (!psta_bmc)
1963		return;
1964
1965	if (psta_bmc->sleepq_len == 0) {
1966		u8 val = 0;
1967
1968		/* while ((rtw_read32(padapter, 0x414)&0x00ffff00)!= 0) */
1969		/* while ((rtw_read32(padapter, 0x414)&0x0000ff00)!= 0) */
1970
1971		rtw_hal_get_hwreg(padapter, HW_VAR_CHK_HI_QUEUE_EMPTY, &val);
1972
1973		while (!val) {
1974			rtw_msleep_os(100);
1975
1976			cnt++;
1977
1978			if (cnt > 10)
1979				break;
1980
1981			rtw_hal_get_hwreg(padapter, HW_VAR_CHK_HI_QUEUE_EMPTY, &val);
1982		}
1983
1984		if (cnt <= 10) {
1985			pstapriv->tim_bitmap &= ~BIT(0);
1986			pstapriv->sta_dz_bitmap &= ~BIT(0);
1987
1988			update_beacon(padapter, _TIM_IE_, NULL, false);
1989		} else { /* re check again */
1990			rtw_chk_hi_queue_cmd(padapter);
1991		}
1992	}
1993}
1994
1995u8 rtw_chk_hi_queue_cmd(struct adapter *padapter)
1996{
1997	struct cmd_obj	*ph2c;
1998	struct drvextra_cmd_parm	*pdrvextra_cmd_parm;
1999	struct cmd_priv	*pcmdpriv = &padapter->cmdpriv;
2000	u8	res = _SUCCESS;
2001
2002	ph2c = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
2003	if (ph2c == NULL) {
2004		res = _FAIL;
2005		goto exit;
2006	}
2007
2008	pdrvextra_cmd_parm = (struct drvextra_cmd_parm *)rtw_zmalloc(sizeof(struct drvextra_cmd_parm));
2009	if (pdrvextra_cmd_parm == NULL) {
2010		kfree(ph2c);
2011		res = _FAIL;
2012		goto exit;
2013	}
2014
2015	pdrvextra_cmd_parm->ec_id = CHECK_HIQ_WK_CID;
2016	pdrvextra_cmd_parm->type_size = 0;
2017	pdrvextra_cmd_parm->pbuf = NULL;
2018
2019	init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, GEN_CMD_CODE(_Set_Drv_Extra));
2020
2021	res = rtw_enqueue_cmd(pcmdpriv, ph2c);
2022exit:
2023	return res;
2024}
2025#endif
2026
2027u8 rtw_c2h_wk_cmd(struct adapter *padapter, u8 *c2h_evt)
2028{
2029	struct cmd_obj *ph2c;
2030	struct drvextra_cmd_parm *pdrvextra_cmd_parm;
2031	struct cmd_priv	*pcmdpriv = &padapter->cmdpriv;
2032	u8	res = _SUCCESS;
2033
2034	ph2c = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
2035	if (ph2c == NULL) {
2036		res = _FAIL;
2037		goto exit;
2038	}
2039
2040	pdrvextra_cmd_parm = (struct drvextra_cmd_parm *)rtw_zmalloc(sizeof(struct drvextra_cmd_parm));
2041	if (pdrvextra_cmd_parm == NULL) {
2042		kfree(ph2c);
2043		res = _FAIL;
2044		goto exit;
2045	}
2046
2047	pdrvextra_cmd_parm->ec_id = C2H_WK_CID;
2048	pdrvextra_cmd_parm->type_size = c2h_evt ? 16 : 0;
2049	pdrvextra_cmd_parm->pbuf = c2h_evt;
2050
2051	init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, GEN_CMD_CODE(_Set_Drv_Extra));
2052
2053	res = rtw_enqueue_cmd(pcmdpriv, ph2c);
2054
2055exit:
2056
2057	return res;
2058}
2059
2060static s32 c2h_evt_hdl(struct adapter *adapter, struct c2h_evt_hdr *c2h_evt, c2h_id_filter filter)
2061{
2062	s32 ret = _FAIL;
2063	u8 buf[16];
2064
2065	if (!c2h_evt) {
2066		/* No c2h event in cmd_obj, read c2h event before handling*/
2067		if (c2h_evt_read(adapter, buf) == _SUCCESS) {
2068			c2h_evt = (struct c2h_evt_hdr *)buf;
2069
2070			if (filter && filter(c2h_evt->id) == false)
2071				goto exit;
2072
2073			ret = rtw_hal_c2h_handler(adapter, c2h_evt);
2074		}
2075	} else {
2076		if (filter && filter(c2h_evt->id) == false)
2077			goto exit;
2078
2079		ret = rtw_hal_c2h_handler(adapter, c2h_evt);
2080	}
2081exit:
2082	return ret;
2083}
2084
2085static void c2h_wk_callback(struct work_struct *work)
2086{
2087	struct evt_priv *evtpriv = container_of(work, struct evt_priv, c2h_wk);
2088	struct adapter *adapter = container_of(evtpriv, struct adapter, evtpriv);
2089	struct c2h_evt_hdr *c2h_evt;
2090	c2h_id_filter ccx_id_filter = rtw_hal_c2h_id_filter_ccx(adapter);
2091
2092	evtpriv->c2h_wk_alive = true;
2093
2094	while (!rtw_cbuf_empty(evtpriv->c2h_queue)) {
2095		if ((c2h_evt = (struct c2h_evt_hdr *)rtw_cbuf_pop(evtpriv->c2h_queue)) != NULL) {
2096			/* This C2H event is read, clear it */
2097			c2h_evt_clear(adapter);
2098		} else if ((c2h_evt = (struct c2h_evt_hdr *)rtw_malloc(16)) != NULL) {
2099			/* This C2H event is not read, read & clear now */
2100			if (c2h_evt_read(adapter, (u8 *)c2h_evt) != _SUCCESS)
2101				continue;
2102		}
2103
2104		/* Special pointer to trigger c2h_evt_clear only */
2105		if ((void *)c2h_evt == (void *)evtpriv)
2106			continue;
2107
2108		if (!c2h_evt_exist(c2h_evt)) {
2109			kfree(c2h_evt);
2110			continue;
2111		}
2112
2113		if (ccx_id_filter(c2h_evt->id) == true) {
2114			/* Handle CCX report here */
2115			rtw_hal_c2h_handler(adapter, c2h_evt);
2116			kfree(c2h_evt);
2117		} else {
2118#ifdef CONFIG_88EU_P2P
2119			/* Enqueue into cmd_thread for others */
2120			rtw_c2h_wk_cmd(adapter, (u8 *)c2h_evt);
2121#endif
2122		}
2123	}
2124
2125	evtpriv->c2h_wk_alive = false;
2126}
2127
2128u8 rtw_drvextra_cmd_hdl(struct adapter *padapter, unsigned char *pbuf)
2129{
2130	struct drvextra_cmd_parm *pdrvextra_cmd;
2131
2132	if (!pbuf)
2133		return H2C_PARAMETERS_ERROR;
2134
2135	pdrvextra_cmd = (struct drvextra_cmd_parm *)pbuf;
2136
2137	switch (pdrvextra_cmd->ec_id) {
2138	case DYNAMIC_CHK_WK_CID:
2139		dynamic_chk_wk_hdl(padapter, pdrvextra_cmd->pbuf, pdrvextra_cmd->type_size);
2140		break;
2141	case POWER_SAVING_CTRL_WK_CID:
2142		power_saving_wk_hdl(padapter, pdrvextra_cmd->pbuf, pdrvextra_cmd->type_size);
2143		break;
2144	case LPS_CTRL_WK_CID:
2145		lps_ctrl_wk_hdl(padapter, (u8)pdrvextra_cmd->type_size);
2146		break;
2147	case RTP_TIMER_CFG_WK_CID:
2148		rpt_timer_setting_wk_hdl(padapter, pdrvextra_cmd->type_size);
2149		break;
2150	case ANT_SELECT_WK_CID:
2151		antenna_select_wk_hdl(padapter, pdrvextra_cmd->type_size);
2152		break;
2153#ifdef CONFIG_88EU_P2P
2154	case P2P_PS_WK_CID:
2155		p2p_ps_wk_hdl(padapter, pdrvextra_cmd->type_size);
2156		break;
2157	case P2P_PROTO_WK_CID:
2158		/* 	Commented by Albert 2011/07/01 */
2159		/* 	I used the type_size as the type command */
2160		p2p_protocol_wk_hdl(padapter, pdrvextra_cmd->type_size);
2161		break;
2162#endif
2163#ifdef CONFIG_88EU_AP_MODE
2164	case CHECK_HIQ_WK_CID:
2165		rtw_chk_hi_queue_hdl(padapter);
2166		break;
2167#endif /* CONFIG_88EU_AP_MODE */
2168	case C2H_WK_CID:
2169		c2h_evt_hdl(padapter, (struct c2h_evt_hdr *)pdrvextra_cmd->pbuf, NULL);
2170		break;
2171	default:
2172		break;
2173	}
2174
2175	if (pdrvextra_cmd->pbuf && pdrvextra_cmd->type_size > 0)
2176		kfree(pdrvextra_cmd->pbuf);
2177
2178	return H2C_SUCCESS;
2179}
2180
2181void rtw_survey_cmd_callback(struct adapter *padapter,  struct cmd_obj *pcmd)
2182{
2183	struct	mlme_priv *pmlmepriv = &padapter->mlmepriv;
2184
2185_func_enter_;
2186
2187	if (pcmd->res == H2C_DROPPED) {
2188		/* TODO: cancel timer and do timeout handler directly... */
2189		/* need to make timeout handlerOS independent */
2190		_set_timer(&pmlmepriv->scan_to_timer, 1);
2191		} else if (pcmd->res != H2C_SUCCESS) {
2192		_set_timer(&pmlmepriv->scan_to_timer, 1);
2193		RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_, ("\n ********Error: MgntActrtw_set_802_11_bssid_LIST_SCAN Fail ************\n\n."));
2194	}
2195
2196	/*  free cmd */
2197	rtw_free_cmd_obj(pcmd);
2198
2199_func_exit_;
2200}
2201void rtw_disassoc_cmd_callback(struct adapter *padapter, struct cmd_obj *pcmd)
2202{
2203	unsigned long	irqL;
2204	struct	mlme_priv *pmlmepriv = &padapter->mlmepriv;
2205
2206_func_enter_;
2207
2208	if (pcmd->res != H2C_SUCCESS) {
2209		_enter_critical_bh(&pmlmepriv->lock, &irqL);
2210		set_fwstate(pmlmepriv, _FW_LINKED);
2211		_exit_critical_bh(&pmlmepriv->lock, &irqL);
2212
2213		RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_, ("\n ***Error: disconnect_cmd_callback Fail ***\n."));
2214
2215		goto exit;
2216	} else /* clear bridge database */
2217		nat25_db_cleanup(padapter);
2218
2219	/*  free cmd */
2220	rtw_free_cmd_obj(pcmd);
2221
2222exit:
2223
2224_func_exit_;
2225}
2226
2227void rtw_joinbss_cmd_callback(struct adapter *padapter,  struct cmd_obj *pcmd)
2228{
2229	struct	mlme_priv *pmlmepriv = &padapter->mlmepriv;
2230
2231_func_enter_;
2232
2233	if (pcmd->res == H2C_DROPPED) {
2234		/* TODO: cancel timer and do timeout handler directly... */
2235		/* need to make timeout handlerOS independent */
2236		_set_timer(&pmlmepriv->assoc_timer, 1);
2237	} else if (pcmd->res != H2C_SUCCESS) {
2238		RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_, ("********Error:rtw_select_and_join_from_scanned_queue Wait Sema  Fail ************\n"));
2239		_set_timer(&pmlmepriv->assoc_timer, 1);
2240	}
2241
2242	rtw_free_cmd_obj(pcmd);
2243
2244_func_exit_;
2245}
2246
2247void rtw_createbss_cmd_callback(struct adapter *padapter, struct cmd_obj *pcmd)
2248{
2249	unsigned long irqL;
2250	u8 timer_cancelled;
2251	struct sta_info *psta = NULL;
2252	struct wlan_network *pwlan = NULL;
2253	struct	mlme_priv *pmlmepriv = &padapter->mlmepriv;
2254	struct wlan_bssid_ex *pnetwork = (struct wlan_bssid_ex *)pcmd->parmbuf;
2255	struct wlan_network *tgt_network = &(pmlmepriv->cur_network);
2256
2257_func_enter_;
2258
2259	if ((pcmd->res != H2C_SUCCESS)) {
2260		RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_, ("\n ********Error: rtw_createbss_cmd_callback  Fail ************\n\n."));
2261		_set_timer(&pmlmepriv->assoc_timer, 1);
2262	}
2263
2264	_cancel_timer(&pmlmepriv->assoc_timer, &timer_cancelled);
2265
2266	_enter_critical_bh(&pmlmepriv->lock, &irqL);
2267
2268	if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) {
2269		psta = rtw_get_stainfo(&padapter->stapriv, pnetwork->MacAddress);
2270		if (!psta) {
2271			psta = rtw_alloc_stainfo(&padapter->stapriv, pnetwork->MacAddress);
2272			if (psta == NULL) {
2273				RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_, ("\nCan't alloc sta_info when createbss_cmd_callback\n"));
2274				goto createbss_cmd_fail ;
2275			}
2276		}
2277
2278		rtw_indicate_connect(padapter);
2279	} else {
2280		unsigned long	irqL;
2281
2282		pwlan = _rtw_alloc_network(pmlmepriv);
2283		_enter_critical_bh(&(pmlmepriv->scanned_queue.lock), &irqL);
2284		if (pwlan == NULL) {
2285			pwlan = rtw_get_oldest_wlan_network(&pmlmepriv->scanned_queue);
2286			if (pwlan == NULL) {
2287				RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_, ("\n Error:  can't get pwlan in rtw_joinbss_event_callback\n"));
2288				_exit_critical_bh(&(pmlmepriv->scanned_queue.lock), &irqL);
2289				goto createbss_cmd_fail;
2290			}
2291			pwlan->last_scanned = rtw_get_current_time();
2292		} else {
2293			rtw_list_insert_tail(&(pwlan->list), &pmlmepriv->scanned_queue.queue);
2294		}
2295
2296		pnetwork->Length = get_wlan_bssid_ex_sz(pnetwork);
2297		memcpy(&(pwlan->network), pnetwork, pnetwork->Length);
2298
2299		memcpy(&tgt_network->network, pnetwork, (get_wlan_bssid_ex_sz(pnetwork)));
2300
2301		_clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING);
2302
2303		_exit_critical_bh(&(pmlmepriv->scanned_queue.lock), &irqL);
2304		/*  we will set _FW_LINKED when there is one more sat to join us (rtw_stassoc_event_callback) */
2305	}
2306
2307createbss_cmd_fail:
2308
2309	_exit_critical_bh(&pmlmepriv->lock, &irqL);
2310
2311	rtw_free_cmd_obj(pcmd);
2312
2313_func_exit_;
2314}
2315
2316void rtw_setstaKey_cmdrsp_callback(struct adapter *padapter,  struct cmd_obj *pcmd)
2317{
2318	struct sta_priv *pstapriv = &padapter->stapriv;
2319	struct set_stakey_rsp *psetstakey_rsp = (struct set_stakey_rsp *)(pcmd->rsp);
2320	struct sta_info *psta = rtw_get_stainfo(pstapriv, psetstakey_rsp->addr);
2321
2322_func_enter_;
2323
2324	if (psta == NULL) {
2325		RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_, ("\nERROR: rtw_setstaKey_cmdrsp_callback => can't get sta_info\n\n"));
2326		goto exit;
2327	}
2328exit:
2329	rtw_free_cmd_obj(pcmd);
2330_func_exit_;
2331}
2332
2333void rtw_setassocsta_cmdrsp_callback(struct adapter *padapter,  struct cmd_obj *pcmd)
2334{
2335	unsigned long	irqL;
2336	struct sta_priv *pstapriv = &padapter->stapriv;
2337	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
2338	struct set_assocsta_parm *passocsta_parm = (struct set_assocsta_parm *)(pcmd->parmbuf);
2339	struct set_assocsta_rsp *passocsta_rsp = (struct set_assocsta_rsp *)(pcmd->rsp);
2340	struct sta_info *psta = rtw_get_stainfo(pstapriv, passocsta_parm->addr);
2341
2342_func_enter_;
2343
2344	if (psta == NULL) {
2345		RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_, ("\nERROR: setassocsta_cmdrsp_callbac => can't get sta_info\n\n"));
2346		goto exit;
2347	}
2348
2349	psta->aid = passocsta_rsp->cam_id;
2350	psta->mac_id = passocsta_rsp->cam_id;
2351
2352	_enter_critical_bh(&pmlmepriv->lock, &irqL);
2353
2354	if ((check_fwstate(pmlmepriv, WIFI_MP_STATE) == true) && (check_fwstate(pmlmepriv, _FW_UNDER_LINKING) == true))
2355		_clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING);
2356
2357	set_fwstate(pmlmepriv, _FW_LINKED);
2358	_exit_critical_bh(&pmlmepriv->lock, &irqL);
2359
2360exit:
2361	rtw_free_cmd_obj(pcmd);
2362
2363_func_exit_;
2364}
2365