rtw_cmd.c revision 2f3c7d5362fb54876a274bcdf9d91d3d02caa4bd
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_mlme_ext.h>
28
29/*
30Caller and the rtw_cmd_thread can protect cmd_q by spin_lock.
31No irqsave is necessary.
32*/
33
34int _rtw_init_cmd_priv(struct cmd_priv *pcmdpriv)
35{
36	int res = _SUCCESS;
37
38
39	sema_init(&(pcmdpriv->cmd_queue_sema), 0);
40	/* sema_init(&(pcmdpriv->cmd_done_sema), 0); */
41	sema_init(&(pcmdpriv->terminate_cmdthread_sema), 0);
42
43
44	_rtw_init_queue(&(pcmdpriv->cmd_queue));
45
46	/* allocate DMA-able/Non-Page memory for cmd_buf and rsp_buf */
47
48	pcmdpriv->cmd_seq = 1;
49
50	pcmdpriv->cmd_allocated_buf = kzalloc(MAX_CMDSZ + CMDBUFF_ALIGN_SZ, GFP_KERNEL);
51
52	if (pcmdpriv->cmd_allocated_buf == NULL) {
53		res = _FAIL;
54		goto exit;
55	}
56
57	pcmdpriv->cmd_buf = pcmdpriv->cmd_allocated_buf  +  CMDBUFF_ALIGN_SZ - ((size_t)(pcmdpriv->cmd_allocated_buf) & (CMDBUFF_ALIGN_SZ-1));
58
59	pcmdpriv->rsp_allocated_buf = kzalloc(MAX_RSPSZ + 4, GFP_KERNEL);
60
61	if (pcmdpriv->rsp_allocated_buf == NULL) {
62		res = _FAIL;
63		goto exit;
64	}
65
66	pcmdpriv->rsp_buf = pcmdpriv->rsp_allocated_buf  +  4 - ((size_t)(pcmdpriv->rsp_allocated_buf) & 3);
67
68	pcmdpriv->cmd_issued_cnt = 0;
69	pcmdpriv->cmd_done_cnt = 0;
70	pcmdpriv->rsp_cnt = 0;
71exit:
72	return res;
73}
74
75void _rtw_free_cmd_priv(struct cmd_priv *pcmdpriv)
76{
77
78	if (pcmdpriv) {
79		kfree(pcmdpriv->cmd_allocated_buf);
80		kfree(pcmdpriv->rsp_allocated_buf);
81	}
82}
83
84/*
85Calling Context:
86
87rtw_enqueue_cmd can only be called between kernel thread,
88since only spin_lock is used.
89
90ISR/Call-Back functions can't call this sub-function.
91
92*/
93
94int _rtw_enqueue_cmd(struct __queue *queue, struct cmd_obj *obj)
95{
96	unsigned long irqL;
97
98
99	if (obj == NULL)
100		goto exit;
101
102	spin_lock_irqsave(&queue->lock, irqL);
103
104	list_add_tail(&obj->list, &queue->queue);
105
106	spin_unlock_irqrestore(&queue->lock, irqL);
107
108exit:
109
110
111	return _SUCCESS;
112}
113
114struct	cmd_obj	*_rtw_dequeue_cmd(struct __queue *queue)
115{
116	unsigned long irqL;
117	struct cmd_obj *obj;
118
119
120	spin_lock_irqsave(&queue->lock, irqL);
121	if (list_empty(&(queue->queue))) {
122		obj = NULL;
123	} else {
124		obj = container_of((&queue->queue)->next, struct cmd_obj, list);
125		list_del_init(&obj->list);
126	}
127
128	spin_unlock_irqrestore(&queue->lock, irqL);
129
130
131	return obj;
132}
133
134u32 rtw_init_cmd_priv(struct cmd_priv *pcmdpriv)
135{
136	u32	res;
137	res = _rtw_init_cmd_priv(pcmdpriv);
138	return res;
139}
140
141void rtw_free_cmd_priv(struct cmd_priv *pcmdpriv)
142{
143	RT_TRACE(_module_rtl871x_cmd_c_, _drv_info_, ("rtw_free_cmd_priv\n"));
144	_rtw_free_cmd_priv(pcmdpriv);
145}
146
147static int rtw_cmd_filter(struct cmd_priv *pcmdpriv, struct cmd_obj *cmd_obj)
148{
149	u8 bAllow = false; /* set to true to allow enqueuing cmd when hw_init_completed is false */
150
151	/* To decide allow or not */
152	if ((pcmdpriv->padapter->pwrctrlpriv.bHWPwrPindetect) &&
153	    (!pcmdpriv->padapter->registrypriv.usbss_enable)) {
154		if (cmd_obj->cmdcode == GEN_CMD_CODE(_Set_Drv_Extra)) {
155			struct drvextra_cmd_parm	*pdrvextra_cmd_parm = (struct drvextra_cmd_parm	*)cmd_obj->parmbuf;
156			if (pdrvextra_cmd_parm->ec_id == POWER_SAVING_CTRL_WK_CID)
157				bAllow = true;
158		}
159	}
160
161	if (cmd_obj->cmdcode == GEN_CMD_CODE(_SetChannelPlan))
162		bAllow = true;
163
164	if ((!pcmdpriv->padapter->hw_init_completed && !bAllow) ||
165	    !pcmdpriv->cmdthd_running)	/* com_thread not running */
166		return _FAIL;
167	return _SUCCESS;
168}
169
170u32 rtw_enqueue_cmd(struct cmd_priv *pcmdpriv, struct cmd_obj *cmd_obj)
171{
172	int res = _FAIL;
173	struct adapter *padapter = pcmdpriv->padapter;
174
175
176	if (cmd_obj == NULL)
177		goto exit;
178
179	cmd_obj->padapter = padapter;
180
181	res = rtw_cmd_filter(pcmdpriv, cmd_obj);
182	if (_FAIL == res) {
183		rtw_free_cmd_obj(cmd_obj);
184		goto exit;
185	}
186
187	res = _rtw_enqueue_cmd(&pcmdpriv->cmd_queue, cmd_obj);
188
189	if (res == _SUCCESS)
190		up(&pcmdpriv->cmd_queue_sema);
191
192exit:
193
194
195	return res;
196}
197
198struct cmd_obj	*rtw_dequeue_cmd(struct cmd_priv *pcmdpriv)
199{
200	struct cmd_obj *cmd_obj;
201
202
203	cmd_obj = _rtw_dequeue_cmd(&pcmdpriv->cmd_queue);
204
205	return cmd_obj;
206}
207
208void rtw_cmd_clr_isr(struct cmd_priv *pcmdpriv)
209{
210	pcmdpriv->cmd_done_cnt++;
211	/* up(&(pcmdpriv->cmd_done_sema)); */
212}
213
214void rtw_free_cmd_obj(struct cmd_obj *pcmd)
215{
216
217	if ((pcmd->cmdcode != _JoinBss_CMD_) && (pcmd->cmdcode != _CreateBss_CMD_)) {
218		/* free parmbuf in cmd_obj */
219		kfree(pcmd->parmbuf);
220	}
221
222	if (pcmd->rsp != NULL) {
223		if (pcmd->rspsz != 0) {
224			/* free rsp in cmd_obj */
225			kfree(pcmd->rsp);
226		}
227	}
228
229	/* free cmd_obj */
230	kfree(pcmd);
231
232}
233
234int rtw_cmd_thread(void *context)
235{
236	u8 ret;
237	struct cmd_obj *pcmd;
238	u8 *pcmdbuf;
239	u8 (*cmd_hdl)(struct adapter *padapter, u8 *pbuf);
240	void (*pcmd_callback)(struct adapter *dev, struct cmd_obj *pcmd);
241	struct adapter *padapter = (struct adapter *)context;
242	struct cmd_priv *pcmdpriv = &(padapter->cmdpriv);
243
244	allow_signal(SIGTERM);
245
246	pcmdbuf = pcmdpriv->cmd_buf;
247
248	pcmdpriv->cmdthd_running = true;
249	up(&pcmdpriv->terminate_cmdthread_sema);
250
251	RT_TRACE(_module_rtl871x_cmd_c_, _drv_info_, ("start r871x rtw_cmd_thread !!!!\n"));
252
253	while (1) {
254		if (_rtw_down_sema(&pcmdpriv->cmd_queue_sema) == _FAIL)
255			break;
256
257		if (padapter->bDriverStopped ||
258		    padapter->bSurpriseRemoved) {
259			DBG_88E("%s: DriverStopped(%d) SurpriseRemoved(%d) break at line %d\n",
260				__func__, padapter->bDriverStopped, padapter->bSurpriseRemoved, __LINE__);
261			break;
262		}
263_next:
264		if (padapter->bDriverStopped ||
265		    padapter->bSurpriseRemoved) {
266			DBG_88E("%s: DriverStopped(%d) SurpriseRemoved(%d) break at line %d\n",
267				__func__, padapter->bDriverStopped, padapter->bSurpriseRemoved, __LINE__);
268			break;
269		}
270
271		pcmd = rtw_dequeue_cmd(pcmdpriv);
272		if (!pcmd)
273			continue;
274
275		if (_FAIL == rtw_cmd_filter(pcmdpriv, pcmd)) {
276			pcmd->res = H2C_DROPPED;
277			goto post_process;
278		}
279
280		pcmdpriv->cmd_issued_cnt++;
281
282		pcmd->cmdsz = round_up(pcmd->cmdsz, 4);
283
284		memcpy(pcmdbuf, pcmd->parmbuf, pcmd->cmdsz);
285
286		if (pcmd->cmdcode < ARRAY_SIZE(wlancmds)) {
287			cmd_hdl = wlancmds[pcmd->cmdcode].h2cfuns;
288
289			if (cmd_hdl) {
290				ret = cmd_hdl(pcmd->padapter, pcmdbuf);
291				pcmd->res = ret;
292			}
293
294			pcmdpriv->cmd_seq++;
295		} else {
296			pcmd->res = H2C_PARAMETERS_ERROR;
297		}
298
299		cmd_hdl = NULL;
300
301post_process:
302
303		/* call callback function for post-processed */
304		if (pcmd->cmdcode < ARRAY_SIZE(rtw_cmd_callback)) {
305			pcmd_callback = rtw_cmd_callback[pcmd->cmdcode].callback;
306			if (pcmd_callback == NULL) {
307				RT_TRACE(_module_rtl871x_cmd_c_, _drv_info_, ("mlme_cmd_hdl(): pcmd_callback = 0x%p, cmdcode = 0x%x\n", pcmd_callback, pcmd->cmdcode));
308				rtw_free_cmd_obj(pcmd);
309			} else {
310				/* todo: !!! fill rsp_buf to pcmd->rsp if (pcmd->rsp!= NULL) */
311				pcmd_callback(pcmd->padapter, pcmd);/* need conider that free cmd_obj in rtw_cmd_callback */
312			}
313		} else {
314			RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_, ("%s: cmdcode = 0x%x callback not defined!\n", __func__, pcmd->cmdcode));
315			rtw_free_cmd_obj(pcmd);
316		}
317
318		if (signal_pending(current))
319			flush_signals(current);
320
321		goto _next;
322	}
323	pcmdpriv->cmdthd_running = false;
324
325	/*  free all cmd_obj resources */
326	do {
327		pcmd = rtw_dequeue_cmd(pcmdpriv);
328		if (pcmd == NULL)
329			break;
330
331		/* DBG_88E("%s: leaving... drop cmdcode:%u\n", __func__, pcmd->cmdcode); */
332
333		rtw_free_cmd_obj(pcmd);
334	} while (1);
335
336	up(&pcmdpriv->terminate_cmdthread_sema);
337
338
339	complete_and_exit(NULL, 0);
340}
341
342u8 rtw_setstandby_cmd(struct adapter *padapter, uint action)
343{
344	struct cmd_obj *ph2c;
345	struct usb_suspend_parm *psetusbsuspend;
346	struct cmd_priv	*pcmdpriv = &padapter->cmdpriv;
347
348	u8 ret = _SUCCESS;
349
350
351	ph2c = kzalloc(sizeof(struct cmd_obj), GFP_KERNEL);
352	if (ph2c == NULL) {
353		ret = _FAIL;
354		goto exit;
355	}
356
357	psetusbsuspend = kzalloc(sizeof(struct usb_suspend_parm), GFP_KERNEL);
358	if (psetusbsuspend == NULL) {
359		kfree(ph2c);
360		ret = _FAIL;
361		goto exit;
362	}
363
364	psetusbsuspend->action = action;
365
366	init_h2fwcmd_w_parm_no_rsp(ph2c, psetusbsuspend, GEN_CMD_CODE(_SetUsbSuspend));
367
368	ret = rtw_enqueue_cmd(pcmdpriv, ph2c);
369
370exit:
371
372
373	return ret;
374}
375
376/*
377rtw_sitesurvey_cmd(~)
378	### NOTE:#### (!!!!)
379	MUST TAKE CARE THAT BEFORE CALLING THIS FUNC, YOU SHOULD HAVE LOCKED pmlmepriv->lock
380*/
381u8 rtw_sitesurvey_cmd(struct adapter  *padapter, struct ndis_802_11_ssid *ssid, int ssid_num,
382	struct rtw_ieee80211_channel *ch, int ch_num)
383{
384	u8 res = _FAIL;
385	struct cmd_obj		*ph2c;
386	struct sitesurvey_parm	*psurveyPara;
387	struct cmd_priv		*pcmdpriv = &padapter->cmdpriv;
388	struct mlme_priv	*pmlmepriv = &padapter->mlmepriv;
389
390	if (check_fwstate(pmlmepriv, _FW_LINKED) == true)
391		rtw_lps_ctrl_wk_cmd(padapter, LPS_CTRL_SCAN, 1);
392
393	ph2c = kzalloc(sizeof(struct cmd_obj), GFP_KERNEL);
394	if (ph2c == NULL)
395		return _FAIL;
396
397	psurveyPara = kzalloc(sizeof(struct sitesurvey_parm), GFP_KERNEL);
398	if (psurveyPara == NULL) {
399		kfree(ph2c);
400		return _FAIL;
401	}
402
403	rtw_free_network_queue(padapter, false);
404
405	RT_TRACE(_module_rtl871x_cmd_c_, _drv_info_, ("%s: flush network queue\n", __func__));
406
407	init_h2fwcmd_w_parm_no_rsp(ph2c, psurveyPara, GEN_CMD_CODE(_SiteSurvey));
408
409	/* psurveyPara->bsslimit = 48; */
410	psurveyPara->scan_mode = pmlmepriv->scan_mode;
411
412	/* prepare ssid list */
413	if (ssid) {
414		int i;
415		for (i = 0; i < ssid_num && i < RTW_SSID_SCAN_AMOUNT; i++) {
416			if (ssid[i].SsidLength) {
417				memcpy(&psurveyPara->ssid[i], &ssid[i], sizeof(struct ndis_802_11_ssid));
418				psurveyPara->ssid_num++;
419			}
420		}
421	}
422
423	/* prepare channel list */
424	if (ch) {
425		int i;
426		for (i = 0; i < ch_num && i < RTW_CHANNEL_SCAN_AMOUNT; i++) {
427			if (ch[i].hw_value && !(ch[i].flags & RTW_IEEE80211_CHAN_DISABLED)) {
428				memcpy(&psurveyPara->ch[i], &ch[i], sizeof(struct rtw_ieee80211_channel));
429				psurveyPara->ch_num++;
430			}
431		}
432	}
433
434	set_fwstate(pmlmepriv, _FW_UNDER_SURVEY);
435
436	res = rtw_enqueue_cmd(pcmdpriv, ph2c);
437
438	if (res == _SUCCESS) {
439		pmlmepriv->scan_start_time = jiffies;
440
441		_set_timer(&pmlmepriv->scan_to_timer, SCANNING_TIMEOUT);
442
443		rtw_led_control(padapter, LED_CTL_SITE_SURVEY);
444
445		pmlmepriv->scan_interval = SCAN_INTERVAL;/*  30*2 sec = 60sec */
446	} else {
447		_clr_fwstate_(pmlmepriv, _FW_UNDER_SURVEY);
448	}
449
450
451	return res;
452}
453
454u8 rtw_setdatarate_cmd(struct adapter *padapter, u8 *rateset)
455{
456	struct cmd_obj *ph2c;
457	struct setdatarate_parm *pbsetdataratepara;
458	struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
459	u8	res = _SUCCESS;
460
461
462	ph2c = kzalloc(sizeof(struct cmd_obj), GFP_KERNEL);
463	if (ph2c == NULL) {
464		res = _FAIL;
465		goto exit;
466	}
467
468	pbsetdataratepara = kzalloc(sizeof(struct setdatarate_parm), GFP_KERNEL);
469	if (pbsetdataratepara == NULL) {
470		kfree(ph2c);
471		res = _FAIL;
472		goto exit;
473	}
474
475	init_h2fwcmd_w_parm_no_rsp(ph2c, pbsetdataratepara, GEN_CMD_CODE(_SetDataRate));
476	pbsetdataratepara->mac_id = 5;
477	memcpy(pbsetdataratepara->datarates, rateset, NumRates);
478	res = rtw_enqueue_cmd(pcmdpriv, ph2c);
479exit:
480
481
482	return res;
483}
484
485/*
486unsigned char rtw_setphy_cmd(unsigned char  *adapter)
487
4881.  be called only after rtw_update_registrypriv_dev_network(~) or mp testing program
4892.  for AdHoc/Ap mode or mp mode?
490
491*/
492u8 rtw_setphy_cmd(struct adapter *padapter, u8 modem, u8 ch)
493{
494	struct cmd_obj *ph2c;
495	struct setphy_parm *psetphypara;
496	struct cmd_priv	*pcmdpriv = &padapter->cmdpriv;
497	u8	res = _SUCCESS;
498
499
500	ph2c = kzalloc(sizeof(struct cmd_obj), GFP_KERNEL);
501	if (ph2c == NULL) {
502		res = _FAIL;
503		goto exit;
504		}
505	psetphypara = kzalloc(sizeof(struct setphy_parm), GFP_KERNEL);
506
507	if (psetphypara == NULL) {
508		kfree(ph2c);
509		res = _FAIL;
510		goto exit;
511	}
512
513	init_h2fwcmd_w_parm_no_rsp(ph2c, psetphypara, _SetPhy_CMD_);
514
515	RT_TRACE(_module_rtl871x_cmd_c_, _drv_info_, ("CH =%d, modem =%d", ch, modem));
516
517	psetphypara->modem = modem;
518	psetphypara->rfchannel = ch;
519
520	res = rtw_enqueue_cmd(pcmdpriv, ph2c);
521exit:
522	return res;
523}
524
525u8 rtw_setbbreg_cmd(struct adapter *padapter, u8 offset, u8 val)
526{
527	struct cmd_obj *ph2c;
528	struct writeBB_parm *pwritebbparm;
529	struct cmd_priv	*pcmdpriv = &padapter->cmdpriv;
530	u8	res = _SUCCESS;
531
532	ph2c = kzalloc(sizeof(struct cmd_obj), GFP_KERNEL);
533	if (ph2c == NULL) {
534		res = _FAIL;
535		goto exit;
536		}
537	pwritebbparm = kzalloc(sizeof(struct writeBB_parm), GFP_KERNEL);
538
539	if (pwritebbparm == NULL) {
540		kfree(ph2c);
541		res = _FAIL;
542		goto exit;
543	}
544
545	init_h2fwcmd_w_parm_no_rsp(ph2c, pwritebbparm, GEN_CMD_CODE(_SetBBReg));
546
547	pwritebbparm->offset = offset;
548	pwritebbparm->value = val;
549
550	res = rtw_enqueue_cmd(pcmdpriv, ph2c);
551exit:
552	return res;
553}
554
555u8 rtw_getbbreg_cmd(struct adapter  *padapter, u8 offset, u8 *pval)
556{
557	struct cmd_obj *ph2c;
558	struct readBB_parm *prdbbparm;
559	struct cmd_priv	*pcmdpriv = &padapter->cmdpriv;
560	u8	res = _SUCCESS;
561
562	ph2c = kzalloc(sizeof(struct cmd_obj), GFP_KERNEL);
563	if (ph2c == NULL) {
564		res = _FAIL;
565		goto exit;
566		}
567	prdbbparm = kzalloc(sizeof(struct readBB_parm), GFP_KERNEL);
568
569	if (prdbbparm == NULL) {
570		kfree(ph2c);
571		return _FAIL;
572	}
573
574	INIT_LIST_HEAD(&ph2c->list);
575	ph2c->cmdcode = GEN_CMD_CODE(_GetBBReg);
576	ph2c->parmbuf = (unsigned char *)prdbbparm;
577	ph2c->cmdsz =  sizeof(struct readBB_parm);
578	ph2c->rsp = pval;
579	ph2c->rspsz = sizeof(struct readBB_rsp);
580
581	prdbbparm->offset = offset;
582
583	res = rtw_enqueue_cmd(pcmdpriv, ph2c);
584exit:
585	return res;
586}
587
588u8 rtw_setrfreg_cmd(struct adapter  *padapter, u8 offset, u32 val)
589{
590	struct cmd_obj *ph2c;
591	struct writeRF_parm *pwriterfparm;
592	struct cmd_priv	*pcmdpriv = &padapter->cmdpriv;
593	u8	res = _SUCCESS;
594	ph2c = kzalloc(sizeof(struct cmd_obj), GFP_KERNEL);
595	if (ph2c == NULL) {
596		res = _FAIL;
597		goto exit;
598	}
599	pwriterfparm = kzalloc(sizeof(struct writeRF_parm), GFP_KERNEL);
600
601	if (pwriterfparm == NULL) {
602		kfree(ph2c);
603		res = _FAIL;
604		goto exit;
605	}
606
607	init_h2fwcmd_w_parm_no_rsp(ph2c, pwriterfparm, GEN_CMD_CODE(_SetRFReg));
608
609	pwriterfparm->offset = offset;
610	pwriterfparm->value = val;
611
612	res = rtw_enqueue_cmd(pcmdpriv, ph2c);
613exit:
614	return res;
615}
616
617u8 rtw_getrfreg_cmd(struct adapter  *padapter, u8 offset, u8 *pval)
618{
619	struct cmd_obj *ph2c;
620	struct readRF_parm *prdrfparm;
621	struct cmd_priv	*pcmdpriv = &padapter->cmdpriv;
622	u8	res = _SUCCESS;
623
624
625	ph2c = kzalloc(sizeof(struct cmd_obj), GFP_KERNEL);
626	if (ph2c == NULL) {
627		res = _FAIL;
628		goto exit;
629	}
630
631	prdrfparm = kzalloc(sizeof(struct readRF_parm), GFP_KERNEL);
632	if (prdrfparm == NULL) {
633		kfree(ph2c);
634		res = _FAIL;
635		goto exit;
636	}
637
638	INIT_LIST_HEAD(&ph2c->list);
639	ph2c->cmdcode = GEN_CMD_CODE(_GetRFReg);
640	ph2c->parmbuf = (unsigned char *)prdrfparm;
641	ph2c->cmdsz =  sizeof(struct readRF_parm);
642	ph2c->rsp = pval;
643	ph2c->rspsz = sizeof(struct readRF_rsp);
644
645	prdrfparm->offset = offset;
646
647	res = rtw_enqueue_cmd(pcmdpriv, ph2c);
648
649exit:
650
651
652	return res;
653}
654
655void rtw_getbbrfreg_cmdrsp_callback(struct adapter *padapter,  struct cmd_obj *pcmd)
656{
657
658	kfree(pcmd->parmbuf);
659	kfree(pcmd);
660
661}
662
663void rtw_readtssi_cmdrsp_callback(struct adapter *padapter,  struct cmd_obj *pcmd)
664{
665
666	kfree(pcmd->parmbuf);
667	kfree(pcmd);
668}
669
670u8 rtw_createbss_cmd(struct adapter  *padapter)
671{
672	struct cmd_obj *pcmd;
673	struct cmd_priv	*pcmdpriv = &padapter->cmdpriv;
674	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
675	struct wlan_bssid_ex *pdev_network = &padapter->registrypriv.dev_network;
676	u8	res = _SUCCESS;
677
678
679	rtw_led_control(padapter, LED_CTL_START_TO_LINK);
680
681	if (pmlmepriv->assoc_ssid.SsidLength == 0)
682		RT_TRACE(_module_rtl871x_cmd_c_, _drv_info_, (" createbss for Any SSid:%s\n", pmlmepriv->assoc_ssid.Ssid));
683	else
684		RT_TRACE(_module_rtl871x_cmd_c_, _drv_info_, (" createbss for SSid:%s\n", pmlmepriv->assoc_ssid.Ssid));
685
686	pcmd = kzalloc(sizeof(struct cmd_obj), GFP_KERNEL);
687	if (pcmd == NULL) {
688		res = _FAIL;
689		goto exit;
690	}
691
692	INIT_LIST_HEAD(&pcmd->list);
693	pcmd->cmdcode = _CreateBss_CMD_;
694	pcmd->parmbuf = (unsigned char *)pdev_network;
695	pcmd->cmdsz = get_wlan_bssid_ex_sz((struct wlan_bssid_ex *)pdev_network);
696	pcmd->rsp = NULL;
697	pcmd->rspsz = 0;
698	pdev_network->Length = pcmd->cmdsz;
699	res = rtw_enqueue_cmd(pcmdpriv, pcmd);
700exit:
701
702
703	return res;
704}
705
706u8 rtw_createbss_cmd_ex(struct adapter  *padapter, unsigned char *pbss, unsigned int sz)
707{
708	struct cmd_obj *pcmd;
709	struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
710	u8	res = _SUCCESS;
711
712
713	pcmd = kzalloc(sizeof(struct cmd_obj), GFP_KERNEL);
714	if (pcmd == NULL) {
715		res = _FAIL;
716		goto exit;
717	}
718
719	INIT_LIST_HEAD(&pcmd->list);
720	pcmd->cmdcode = GEN_CMD_CODE(_CreateBss);
721	pcmd->parmbuf = pbss;
722	pcmd->cmdsz =  sz;
723	pcmd->rsp = NULL;
724	pcmd->rspsz = 0;
725
726	res = rtw_enqueue_cmd(pcmdpriv, pcmd);
727
728exit:
729
730
731	return res;
732}
733
734u8 rtw_joinbss_cmd(struct adapter  *padapter, struct wlan_network *pnetwork)
735{
736	u8	res = _SUCCESS;
737	uint	t_len = 0;
738	struct wlan_bssid_ex		*psecnetwork;
739	struct cmd_obj		*pcmd;
740	struct cmd_priv		*pcmdpriv = &padapter->cmdpriv;
741	struct mlme_priv	*pmlmepriv = &padapter->mlmepriv;
742	struct qos_priv		*pqospriv = &pmlmepriv->qospriv;
743	struct security_priv	*psecuritypriv = &padapter->securitypriv;
744	struct registry_priv	*pregistrypriv = &padapter->registrypriv;
745	struct ht_priv		*phtpriv = &pmlmepriv->htpriv;
746	enum ndis_802_11_network_infra ndis_network_mode = pnetwork->network.InfrastructureMode;
747	struct mlme_ext_priv	*pmlmeext = &padapter->mlmeextpriv;
748	struct mlme_ext_info	*pmlmeinfo = &(pmlmeext->mlmext_info);
749
750
751	rtw_led_control(padapter, LED_CTL_START_TO_LINK);
752
753	if (pmlmepriv->assoc_ssid.SsidLength == 0)
754		RT_TRACE(_module_rtl871x_cmd_c_, _drv_info_, ("+Join cmd: Any SSid\n"));
755	else
756		RT_TRACE(_module_rtl871x_cmd_c_, _drv_notice_, ("+Join cmd: SSid =[%s]\n", pmlmepriv->assoc_ssid.Ssid));
757
758	pcmd = kzalloc(sizeof(struct cmd_obj), GFP_KERNEL);
759	if (pcmd == NULL) {
760		res = _FAIL;
761		RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_, ("rtw_joinbss_cmd: memory allocate for cmd_obj fail!!!\n"));
762		goto exit;
763	}
764	/* for IEs is fix buf size */
765	t_len = sizeof(struct wlan_bssid_ex);
766
767
768	/* for hidden ap to set fw_state here */
769	if (!check_fwstate(pmlmepriv, WIFI_STATION_STATE|WIFI_ADHOC_STATE)) {
770		switch (ndis_network_mode) {
771		case Ndis802_11IBSS:
772			set_fwstate(pmlmepriv, WIFI_ADHOC_STATE);
773			break;
774		case Ndis802_11Infrastructure:
775			set_fwstate(pmlmepriv, WIFI_STATION_STATE);
776			break;
777		case Ndis802_11APMode:
778		case Ndis802_11AutoUnknown:
779		case Ndis802_11InfrastructureMax:
780			break;
781		}
782	}
783
784	psecnetwork = (struct wlan_bssid_ex *)&psecuritypriv->sec_bss;
785	if (psecnetwork == NULL) {
786		if (pcmd != NULL)
787			kfree(pcmd);
788
789		res = _FAIL;
790
791		RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_, ("rtw_joinbss_cmd :psecnetwork == NULL!!!\n"));
792
793		goto exit;
794	}
795
796	memset(psecnetwork, 0, t_len);
797
798	memcpy(psecnetwork, &pnetwork->network, get_wlan_bssid_ex_sz(&pnetwork->network));
799
800	psecuritypriv->authenticator_ie[0] = (unsigned char)psecnetwork->IELength;
801
802	if ((psecnetwork->IELength-12) < (256-1))
803		memcpy(&psecuritypriv->authenticator_ie[1], &psecnetwork->IEs[12], psecnetwork->IELength-12);
804	else
805		memcpy(&psecuritypriv->authenticator_ie[1], &psecnetwork->IEs[12], (256-1));
806
807	psecnetwork->IELength = 0;
808	/*  Added by Albert 2009/02/18 */
809	/*  If the the driver wants to use the bssid to create the connection. */
810	/*  If not,  we have to copy the connecting AP's MAC address to it so that */
811	/*  the driver just has the bssid information for PMKIDList searching. */
812
813	if (!pmlmepriv->assoc_by_bssid)
814		memcpy(&pmlmepriv->assoc_bssid[0], &pnetwork->network.MacAddress[0], ETH_ALEN);
815
816	psecnetwork->IELength = rtw_restruct_sec_ie(padapter, &pnetwork->network.IEs[0], &psecnetwork->IEs[0], pnetwork->network.IELength);
817
818
819	pqospriv->qos_option = 0;
820
821	if (pregistrypriv->wmm_enable) {
822		u32 tmp_len;
823
824		tmp_len = rtw_restruct_wmm_ie(padapter, &pnetwork->network.IEs[0], &psecnetwork->IEs[0], pnetwork->network.IELength, psecnetwork->IELength);
825
826		if (psecnetwork->IELength != tmp_len) {
827			psecnetwork->IELength = tmp_len;
828			pqospriv->qos_option = 1; /* There is WMM IE in this corresp. beacon */
829		} else {
830			pqospriv->qos_option = 0;/* There is no WMM IE in this corresp. beacon */
831		}
832	}
833
834	phtpriv->ht_option = false;
835	if (pregistrypriv->ht_enable) {
836		/*
837		 * Added by Albert 2010/06/23
838		 * For the WEP mode, we will use the bg mode to do
839		 * the connection to avoid some IOT issue.
840		 * Especially for Realtek 8192u SoftAP.
841		 */
842		if ((padapter->securitypriv.dot11PrivacyAlgrthm != _WEP40_) &&
843		    (padapter->securitypriv.dot11PrivacyAlgrthm != _WEP104_) &&
844		    (padapter->securitypriv.dot11PrivacyAlgrthm != _TKIP_)) {
845			/* rtw_restructure_ht_ie */
846			rtw_restructure_ht_ie(padapter, &pnetwork->network.IEs[0], &psecnetwork->IEs[0],
847									pnetwork->network.IELength, &psecnetwork->IELength);
848		}
849	}
850
851	pmlmeinfo->assoc_AP_vendor = check_assoc_AP(pnetwork->network.IEs, pnetwork->network.IELength);
852
853	if (pmlmeinfo->assoc_AP_vendor == HT_IOT_PEER_TENDA)
854		padapter->pwrctrlpriv.smart_ps = 0;
855	else
856		padapter->pwrctrlpriv.smart_ps = padapter->registrypriv.smart_ps;
857
858	DBG_88E("%s: smart_ps =%d\n", __func__, padapter->pwrctrlpriv.smart_ps);
859
860	pcmd->cmdsz = get_wlan_bssid_ex_sz(psecnetwork);/* get cmdsz before endian conversion */
861
862	INIT_LIST_HEAD(&pcmd->list);
863	pcmd->cmdcode = _JoinBss_CMD_;/* GEN_CMD_CODE(_JoinBss) */
864	pcmd->parmbuf = (unsigned char *)psecnetwork;
865	pcmd->rsp = NULL;
866	pcmd->rspsz = 0;
867
868	res = rtw_enqueue_cmd(pcmdpriv, pcmd);
869
870exit:
871
872
873	return res;
874}
875
876u8 rtw_disassoc_cmd(struct adapter *padapter, u32 deauth_timeout_ms, bool enqueue) /* for sta_mode */
877{
878	struct cmd_obj *cmdobj = NULL;
879	struct disconnect_parm *param = NULL;
880	struct cmd_priv *cmdpriv = &padapter->cmdpriv;
881	u8 res = _SUCCESS;
882
883
884	RT_TRACE(_module_rtl871x_cmd_c_, _drv_notice_, ("+rtw_disassoc_cmd\n"));
885
886	/* prepare cmd parameter */
887	param = kzalloc(sizeof(*param), GFP_KERNEL);
888	if (param == NULL) {
889		res = _FAIL;
890		goto exit;
891	}
892	param->deauth_timeout_ms = deauth_timeout_ms;
893
894	if (enqueue) {
895		/* need enqueue, prepare cmd_obj and enqueue */
896		cmdobj = kzalloc(sizeof(*cmdobj), GFP_KERNEL);
897		if (cmdobj == NULL) {
898			res = _FAIL;
899			kfree(param);
900			goto exit;
901		}
902		init_h2fwcmd_w_parm_no_rsp(cmdobj, param, _DisConnect_CMD_);
903		res = rtw_enqueue_cmd(cmdpriv, cmdobj);
904	} else {
905		/* no need to enqueue, do the cmd hdl directly and free cmd parameter */
906		if (H2C_SUCCESS != disconnect_hdl(padapter, (u8 *)param))
907			res = _FAIL;
908		kfree(param);
909	}
910
911exit:
912
913
914	return res;
915}
916
917u8 rtw_setopmode_cmd(struct adapter  *padapter, enum ndis_802_11_network_infra networktype)
918{
919	struct	cmd_obj *ph2c;
920	struct	setopmode_parm *psetop;
921
922	struct	cmd_priv   *pcmdpriv = &padapter->cmdpriv;
923	u8	res = _SUCCESS;
924
925
926	ph2c = kzalloc(sizeof(struct cmd_obj), GFP_KERNEL);
927	if (ph2c == NULL) {
928		res = false;
929		goto exit;
930	}
931	psetop = kzalloc(sizeof(struct setopmode_parm), GFP_KERNEL);
932
933	if (psetop == NULL) {
934		kfree(ph2c);
935		res = false;
936		goto exit;
937	}
938
939	init_h2fwcmd_w_parm_no_rsp(ph2c, psetop, _SetOpMode_CMD_);
940	psetop->mode = (u8)networktype;
941
942	res = rtw_enqueue_cmd(pcmdpriv, ph2c);
943
944exit:
945
946
947	return res;
948}
949
950u8 rtw_setstakey_cmd(struct adapter *padapter, u8 *psta, u8 unicast_key)
951{
952	struct cmd_obj *ph2c;
953	struct set_stakey_parm *psetstakey_para;
954	struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
955	struct set_stakey_rsp *psetstakey_rsp = NULL;
956
957	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
958	struct security_priv *psecuritypriv = &padapter->securitypriv;
959	struct sta_info *sta = (struct sta_info *)psta;
960	u8	res = _SUCCESS;
961
962
963	ph2c = kzalloc(sizeof(struct cmd_obj), GFP_KERNEL);
964	if (ph2c == NULL) {
965		res = _FAIL;
966		goto exit;
967	}
968
969	psetstakey_para = kzalloc(sizeof(struct set_stakey_parm), GFP_KERNEL);
970	if (psetstakey_para == NULL) {
971		kfree(ph2c);
972		res = _FAIL;
973		goto exit;
974	}
975
976	psetstakey_rsp = kzalloc(sizeof(struct set_stakey_rsp), GFP_KERNEL);
977	if (psetstakey_rsp == NULL) {
978		kfree(ph2c);
979		kfree(psetstakey_para);
980		res = _FAIL;
981		goto exit;
982	}
983
984	init_h2fwcmd_w_parm_no_rsp(ph2c, psetstakey_para, _SetStaKey_CMD_);
985	ph2c->rsp = (u8 *)psetstakey_rsp;
986	ph2c->rspsz = sizeof(struct set_stakey_rsp);
987
988	ether_addr_copy(psetstakey_para->addr, sta->hwaddr);
989
990	if (check_fwstate(pmlmepriv, WIFI_STATION_STATE))
991		psetstakey_para->algorithm = (unsigned char) psecuritypriv->dot11PrivacyAlgrthm;
992	else
993		GET_ENCRY_ALGO(psecuritypriv, sta, psetstakey_para->algorithm, false);
994
995	if (unicast_key)
996		memcpy(&psetstakey_para->key, &sta->dot118021x_UncstKey, 16);
997	else
998		memcpy(&psetstakey_para->key, &psecuritypriv->dot118021XGrpKey[psecuritypriv->dot118021XGrpKeyid].skey, 16);
999
1000	/* jeff: set this because at least sw key is ready */
1001	padapter->securitypriv.busetkipkey = true;
1002
1003	res = rtw_enqueue_cmd(pcmdpriv, ph2c);
1004
1005exit:
1006
1007
1008	return res;
1009}
1010
1011u8 rtw_clearstakey_cmd(struct adapter *padapter, u8 *psta, u8 entry, u8 enqueue)
1012{
1013	struct cmd_obj *ph2c;
1014	struct set_stakey_parm	*psetstakey_para;
1015	struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
1016	struct set_stakey_rsp *psetstakey_rsp = NULL;
1017	struct sta_info *sta = (struct sta_info *)psta;
1018	u8	res = _SUCCESS;
1019
1020
1021	if (!enqueue) {
1022		clear_cam_entry(padapter, entry);
1023	} else {
1024		ph2c = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC);
1025		if (ph2c == NULL) {
1026			res = _FAIL;
1027			goto exit;
1028		}
1029
1030		psetstakey_para = kzalloc(sizeof(struct set_stakey_parm), GFP_ATOMIC);
1031		if (psetstakey_para == NULL) {
1032			kfree(ph2c);
1033			res = _FAIL;
1034			goto exit;
1035		}
1036
1037		psetstakey_rsp = kzalloc(sizeof(struct set_stakey_rsp), GFP_ATOMIC);
1038		if (psetstakey_rsp == NULL) {
1039			kfree(ph2c);
1040			kfree(psetstakey_para);
1041			res = _FAIL;
1042			goto exit;
1043		}
1044
1045		init_h2fwcmd_w_parm_no_rsp(ph2c, psetstakey_para, _SetStaKey_CMD_);
1046		ph2c->rsp = (u8 *)psetstakey_rsp;
1047		ph2c->rspsz = sizeof(struct set_stakey_rsp);
1048
1049		ether_addr_copy(psetstakey_para->addr, sta->hwaddr);
1050
1051		psetstakey_para->algorithm = _NO_PRIVACY_;
1052
1053		psetstakey_para->id = entry;
1054
1055		res = rtw_enqueue_cmd(pcmdpriv, ph2c);
1056	}
1057exit:
1058
1059
1060	return res;
1061}
1062
1063u8 rtw_setrttbl_cmd(struct adapter  *padapter, struct setratable_parm *prate_table)
1064{
1065	struct cmd_obj *ph2c;
1066	struct setratable_parm *psetrttblparm;
1067	struct cmd_priv	*pcmdpriv = &padapter->cmdpriv;
1068	u8	res = _SUCCESS;
1069
1070	ph2c = kzalloc(sizeof(struct cmd_obj), GFP_KERNEL);
1071	if (ph2c == NULL) {
1072		res = _FAIL;
1073		goto exit;
1074	}
1075	psetrttblparm = kzalloc(sizeof(struct setratable_parm), GFP_KERNEL);
1076
1077	if (psetrttblparm == NULL) {
1078		kfree(ph2c);
1079		res = _FAIL;
1080		goto exit;
1081	}
1082
1083	init_h2fwcmd_w_parm_no_rsp(ph2c, psetrttblparm, GEN_CMD_CODE(_SetRaTable));
1084
1085	memcpy(psetrttblparm, prate_table, sizeof(struct setratable_parm));
1086
1087	res = rtw_enqueue_cmd(pcmdpriv, ph2c);
1088exit:
1089	return res;
1090}
1091
1092u8 rtw_setassocsta_cmd(struct adapter  *padapter, u8 *mac_addr)
1093{
1094	struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
1095	struct cmd_obj *ph2c;
1096	struct set_assocsta_parm *psetassocsta_para;
1097	struct set_stakey_rsp *psetassocsta_rsp = NULL;
1098
1099	u8	res = _SUCCESS;
1100
1101
1102	ph2c = kzalloc(sizeof(struct cmd_obj), GFP_KERNEL);
1103	if (ph2c == NULL) {
1104		res = _FAIL;
1105		goto exit;
1106	}
1107
1108	psetassocsta_para = kzalloc(sizeof(struct set_assocsta_parm), GFP_KERNEL);
1109	if (psetassocsta_para == NULL) {
1110		kfree(ph2c);
1111		res = _FAIL;
1112		goto exit;
1113	}
1114
1115	psetassocsta_rsp = kzalloc(sizeof(struct set_assocsta_rsp), GFP_KERNEL);
1116	if (psetassocsta_rsp == NULL) {
1117		kfree(ph2c);
1118		kfree(psetassocsta_para);
1119		return _FAIL;
1120	}
1121
1122	init_h2fwcmd_w_parm_no_rsp(ph2c, psetassocsta_para, _SetAssocSta_CMD_);
1123	ph2c->rsp = (u8 *)psetassocsta_rsp;
1124	ph2c->rspsz = sizeof(struct set_assocsta_rsp);
1125
1126	ether_addr_copy(psetassocsta_para->addr, mac_addr);
1127
1128	res = rtw_enqueue_cmd(pcmdpriv, ph2c);
1129
1130exit:
1131
1132
1133	return res;
1134}
1135
1136u8 rtw_addbareq_cmd(struct adapter *padapter, u8 tid, u8 *addr)
1137{
1138	struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
1139	struct cmd_obj *ph2c;
1140	struct addBaReq_parm *paddbareq_parm;
1141	u8	res = _SUCCESS;
1142
1143
1144	ph2c = kzalloc(sizeof(struct cmd_obj), GFP_KERNEL);
1145	if (ph2c == NULL) {
1146		res = _FAIL;
1147		goto exit;
1148	}
1149
1150	paddbareq_parm = kzalloc(sizeof(struct addBaReq_parm), GFP_KERNEL);
1151	if (paddbareq_parm == NULL) {
1152		kfree(ph2c);
1153		res = _FAIL;
1154		goto exit;
1155	}
1156
1157	paddbareq_parm->tid = tid;
1158	memcpy(paddbareq_parm->addr, addr, ETH_ALEN);
1159
1160	init_h2fwcmd_w_parm_no_rsp(ph2c, paddbareq_parm, GEN_CMD_CODE(_AddBAReq));
1161
1162	/* DBG_88E("rtw_addbareq_cmd, tid =%d\n", tid); */
1163
1164	/* rtw_enqueue_cmd(pcmdpriv, ph2c); */
1165	res = rtw_enqueue_cmd(pcmdpriv, ph2c);
1166
1167exit:
1168
1169
1170	return res;
1171}
1172
1173u8 rtw_dynamic_chk_wk_cmd(struct adapter *padapter)
1174{
1175	struct cmd_obj *ph2c;
1176	struct drvextra_cmd_parm *pdrvextra_cmd_parm;
1177	struct cmd_priv	*pcmdpriv = &padapter->cmdpriv;
1178	u8	res = _SUCCESS;
1179
1180
1181	ph2c = kzalloc(sizeof(struct cmd_obj), GFP_KERNEL);
1182	if (ph2c == NULL) {
1183		res = _FAIL;
1184		goto exit;
1185	}
1186
1187	pdrvextra_cmd_parm = kzalloc(sizeof(struct drvextra_cmd_parm), GFP_KERNEL);
1188	if (pdrvextra_cmd_parm == NULL) {
1189		kfree(ph2c);
1190		res = _FAIL;
1191		goto exit;
1192	}
1193
1194	pdrvextra_cmd_parm->ec_id = DYNAMIC_CHK_WK_CID;
1195	pdrvextra_cmd_parm->type_size = 0;
1196	pdrvextra_cmd_parm->pbuf = (u8 *)padapter;
1197
1198	init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, GEN_CMD_CODE(_Set_Drv_Extra));
1199
1200
1201	/* rtw_enqueue_cmd(pcmdpriv, ph2c); */
1202	res = rtw_enqueue_cmd(pcmdpriv, ph2c);
1203exit:
1204	return res;
1205}
1206
1207u8 rtw_set_ch_cmd(struct adapter *padapter, u8 ch, u8 bw, u8 ch_offset, u8 enqueue)
1208{
1209	struct cmd_obj *pcmdobj;
1210	struct set_ch_parm *set_ch_parm;
1211	struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
1212
1213	u8 res = _SUCCESS;
1214
1215
1216	DBG_88E(FUNC_NDEV_FMT" ch:%u, bw:%u, ch_offset:%u\n",
1217		FUNC_NDEV_ARG(padapter->pnetdev), ch, bw, ch_offset);
1218
1219	/* check input parameter */
1220
1221	/* prepare cmd parameter */
1222	set_ch_parm = kzalloc(sizeof(*set_ch_parm), GFP_KERNEL);
1223	if (set_ch_parm == NULL) {
1224		res = _FAIL;
1225		goto exit;
1226	}
1227	set_ch_parm->ch = ch;
1228	set_ch_parm->bw = bw;
1229	set_ch_parm->ch_offset = ch_offset;
1230
1231	if (enqueue) {
1232		/* need enqueue, prepare cmd_obj and enqueue */
1233		pcmdobj = kzalloc(sizeof(struct	cmd_obj), GFP_KERNEL);
1234		if (pcmdobj == NULL) {
1235			kfree(set_ch_parm);
1236			res = _FAIL;
1237			goto exit;
1238		}
1239
1240		init_h2fwcmd_w_parm_no_rsp(pcmdobj, set_ch_parm, GEN_CMD_CODE(_SetChannel));
1241		res = rtw_enqueue_cmd(pcmdpriv, pcmdobj);
1242	} else {
1243		/* no need to enqueue, do the cmd hdl directly and free cmd parameter */
1244		if (H2C_SUCCESS != set_ch_hdl(padapter, (u8 *)set_ch_parm))
1245			res = _FAIL;
1246
1247		kfree(set_ch_parm);
1248	}
1249
1250	/* do something based on res... */
1251
1252exit:
1253
1254	DBG_88E(FUNC_NDEV_FMT" res:%u\n", FUNC_NDEV_ARG(padapter->pnetdev), res);
1255
1256
1257	return res;
1258}
1259
1260u8 rtw_set_chplan_cmd(struct adapter *padapter, u8 chplan, u8 enqueue)
1261{
1262	struct	cmd_obj *pcmdobj;
1263	struct	SetChannelPlan_param *setChannelPlan_param;
1264	struct	cmd_priv   *pcmdpriv = &padapter->cmdpriv;
1265
1266	u8	res = _SUCCESS;
1267
1268
1269	RT_TRACE(_module_rtl871x_cmd_c_, _drv_notice_, ("+rtw_set_chplan_cmd\n"));
1270
1271	/* check input parameter */
1272	if (!rtw_is_channel_plan_valid(chplan)) {
1273		res = _FAIL;
1274		goto exit;
1275	}
1276
1277	/* prepare cmd parameter */
1278	setChannelPlan_param = kzalloc(sizeof(struct SetChannelPlan_param), GFP_KERNEL);
1279	if (setChannelPlan_param == NULL) {
1280		res = _FAIL;
1281		goto exit;
1282	}
1283	setChannelPlan_param->channel_plan = chplan;
1284
1285	if (enqueue) {
1286		/* need enqueue, prepare cmd_obj and enqueue */
1287		pcmdobj = kzalloc(sizeof(struct	cmd_obj), GFP_KERNEL);
1288		if (pcmdobj == NULL) {
1289			kfree(setChannelPlan_param);
1290			res = _FAIL;
1291			goto exit;
1292		}
1293
1294		init_h2fwcmd_w_parm_no_rsp(pcmdobj, setChannelPlan_param, GEN_CMD_CODE(_SetChannelPlan));
1295		res = rtw_enqueue_cmd(pcmdpriv, pcmdobj);
1296	} else {
1297		/* no need to enqueue, do the cmd hdl directly and free cmd parameter */
1298		if (H2C_SUCCESS != set_chplan_hdl(padapter, (unsigned char *)setChannelPlan_param))
1299			res = _FAIL;
1300
1301		kfree(setChannelPlan_param);
1302	}
1303
1304	/* do something based on res... */
1305	if (res == _SUCCESS)
1306		padapter->mlmepriv.ChannelPlan = chplan;
1307
1308exit:
1309
1310
1311	return res;
1312}
1313
1314u8 rtw_set_csa_cmd(struct adapter *padapter, u8 new_ch_no)
1315{
1316	struct	cmd_obj *pcmdobj;
1317	struct	SetChannelSwitch_param *setChannelSwitch_param;
1318	struct	cmd_priv   *pcmdpriv = &padapter->cmdpriv;
1319
1320	u8	res = _SUCCESS;
1321
1322
1323	RT_TRACE(_module_rtl871x_cmd_c_, _drv_notice_, ("+rtw_set_csa_cmd\n"));
1324
1325	pcmdobj = kzalloc(sizeof(struct	cmd_obj), GFP_KERNEL);
1326	if (pcmdobj == NULL) {
1327		res = _FAIL;
1328		goto exit;
1329	}
1330
1331	setChannelSwitch_param = kzalloc(sizeof(struct	SetChannelSwitch_param), GFP_KERNEL);
1332	if (setChannelSwitch_param == NULL) {
1333		kfree(pcmdobj);
1334		res = _FAIL;
1335		goto exit;
1336	}
1337
1338	setChannelSwitch_param->new_ch_no = new_ch_no;
1339
1340	init_h2fwcmd_w_parm_no_rsp(pcmdobj, setChannelSwitch_param, GEN_CMD_CODE(_SetChannelSwitch));
1341	res = rtw_enqueue_cmd(pcmdpriv, pcmdobj);
1342
1343exit:
1344
1345
1346	return res;
1347}
1348
1349u8 rtw_tdls_cmd(struct adapter *padapter, u8 *addr, u8 option)
1350{
1351	return _SUCCESS;
1352}
1353
1354static void traffic_status_watchdog(struct adapter *padapter)
1355{
1356	u8	bEnterPS;
1357	u8	bBusyTraffic = false, bTxBusyTraffic = false, bRxBusyTraffic = false;
1358	u8	bHigherBusyTraffic = false, bHigherBusyRxTraffic = false, bHigherBusyTxTraffic = false;
1359	struct mlme_priv		*pmlmepriv = &(padapter->mlmepriv);
1360
1361	/*  */
1362	/*  Determine if our traffic is busy now */
1363	/*  */
1364	if (check_fwstate(pmlmepriv, _FW_LINKED)) {
1365		if (pmlmepriv->LinkDetectInfo.NumRxOkInPeriod > 100 ||
1366		    pmlmepriv->LinkDetectInfo.NumTxOkInPeriod > 100) {
1367			bBusyTraffic = true;
1368
1369			if (pmlmepriv->LinkDetectInfo.NumRxOkInPeriod > pmlmepriv->LinkDetectInfo.NumTxOkInPeriod)
1370				bRxBusyTraffic = true;
1371			else
1372				bTxBusyTraffic = true;
1373		}
1374
1375		/*  Higher Tx/Rx data. */
1376		if (pmlmepriv->LinkDetectInfo.NumRxOkInPeriod > 4000 ||
1377		    pmlmepriv->LinkDetectInfo.NumTxOkInPeriod > 4000) {
1378			bHigherBusyTraffic = true;
1379
1380			if (pmlmepriv->LinkDetectInfo.NumRxOkInPeriod > pmlmepriv->LinkDetectInfo.NumTxOkInPeriod)
1381				bHigherBusyRxTraffic = true;
1382			else
1383				bHigherBusyTxTraffic = true;
1384		}
1385
1386		/*  check traffic for  powersaving. */
1387		if (((pmlmepriv->LinkDetectInfo.NumRxUnicastOkInPeriod + pmlmepriv->LinkDetectInfo.NumTxOkInPeriod) > 8) ||
1388		    (pmlmepriv->LinkDetectInfo.NumRxUnicastOkInPeriod > 2))
1389			bEnterPS = false;
1390		else
1391			bEnterPS = true;
1392
1393		/*  LeisurePS only work in infra mode. */
1394		if (bEnterPS)
1395			LPS_Enter(padapter);
1396		else
1397			LPS_Leave(padapter);
1398	} else {
1399		LPS_Leave(padapter);
1400	}
1401
1402	pmlmepriv->LinkDetectInfo.NumRxOkInPeriod = 0;
1403	pmlmepriv->LinkDetectInfo.NumTxOkInPeriod = 0;
1404	pmlmepriv->LinkDetectInfo.NumRxUnicastOkInPeriod = 0;
1405	pmlmepriv->LinkDetectInfo.bBusyTraffic = bBusyTraffic;
1406	pmlmepriv->LinkDetectInfo.bTxBusyTraffic = bTxBusyTraffic;
1407	pmlmepriv->LinkDetectInfo.bRxBusyTraffic = bRxBusyTraffic;
1408	pmlmepriv->LinkDetectInfo.bHigherBusyTraffic = bHigherBusyTraffic;
1409	pmlmepriv->LinkDetectInfo.bHigherBusyRxTraffic = bHigherBusyRxTraffic;
1410	pmlmepriv->LinkDetectInfo.bHigherBusyTxTraffic = bHigherBusyTxTraffic;
1411}
1412
1413static void dynamic_chk_wk_hdl(struct adapter *padapter, u8 *pbuf, int sz)
1414{
1415	struct mlme_priv *pmlmepriv;
1416
1417	padapter = (struct adapter *)pbuf;
1418	pmlmepriv = &(padapter->mlmepriv);
1419
1420#ifdef CONFIG_88EU_AP_MODE
1421	if (check_fwstate(pmlmepriv, WIFI_AP_STATE) == true)
1422		expire_timeout_chk(padapter);
1423#endif
1424
1425	linked_status_chk(padapter);
1426	traffic_status_watchdog(padapter);
1427
1428	rtw_hal_dm_watchdog(padapter);
1429}
1430
1431static void lps_ctrl_wk_hdl(struct adapter *padapter, u8 lps_ctrl_type)
1432{
1433	struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv;
1434	struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
1435	u8	mstatus;
1436
1437
1438	if ((check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) == true) ||
1439	    (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE) == true))
1440		return;
1441
1442	switch (lps_ctrl_type) {
1443	case LPS_CTRL_SCAN:
1444		if (check_fwstate(pmlmepriv, _FW_LINKED) == true) {
1445			/* connect */
1446			LPS_Leave(padapter);
1447		}
1448		break;
1449	case LPS_CTRL_JOINBSS:
1450		LPS_Leave(padapter);
1451		break;
1452	case LPS_CTRL_CONNECT:
1453		mstatus = 1;/* connect */
1454		/*  Reset LPS Setting */
1455		padapter->pwrctrlpriv.LpsIdleCount = 0;
1456		rtw_hal_set_hwreg(padapter, HW_VAR_H2C_FW_JOINBSSRPT, (u8 *)(&mstatus));
1457		break;
1458	case LPS_CTRL_DISCONNECT:
1459		mstatus = 0;/* disconnect */
1460		LPS_Leave(padapter);
1461		rtw_hal_set_hwreg(padapter, HW_VAR_H2C_FW_JOINBSSRPT, (u8 *)(&mstatus));
1462		break;
1463	case LPS_CTRL_SPECIAL_PACKET:
1464		/* DBG_88E("LPS_CTRL_SPECIAL_PACKET\n"); */
1465		pwrpriv->DelayLPSLastTimeStamp = jiffies;
1466		LPS_Leave(padapter);
1467		break;
1468	case LPS_CTRL_LEAVE:
1469		LPS_Leave(padapter);
1470		break;
1471	default:
1472		break;
1473	}
1474
1475}
1476
1477u8 rtw_lps_ctrl_wk_cmd(struct adapter *padapter, u8 lps_ctrl_type, u8 enqueue)
1478{
1479	struct cmd_obj	*ph2c;
1480	struct drvextra_cmd_parm	*pdrvextra_cmd_parm;
1481	struct cmd_priv	*pcmdpriv = &padapter->cmdpriv;
1482	/* struct pwrctrl_priv *pwrctrlpriv = &padapter->pwrctrlpriv; */
1483	u8	res = _SUCCESS;
1484
1485	if (enqueue) {
1486		ph2c = kzalloc(sizeof(struct cmd_obj), GFP_KERNEL);
1487		if (ph2c == NULL) {
1488			res = _FAIL;
1489			goto exit;
1490		}
1491
1492		pdrvextra_cmd_parm = kzalloc(sizeof(struct drvextra_cmd_parm), GFP_KERNEL);
1493		if (pdrvextra_cmd_parm == NULL) {
1494			kfree(ph2c);
1495			res = _FAIL;
1496			goto exit;
1497		}
1498
1499		pdrvextra_cmd_parm->ec_id = LPS_CTRL_WK_CID;
1500		pdrvextra_cmd_parm->type_size = lps_ctrl_type;
1501		pdrvextra_cmd_parm->pbuf = NULL;
1502
1503		init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, GEN_CMD_CODE(_Set_Drv_Extra));
1504
1505		res = rtw_enqueue_cmd(pcmdpriv, ph2c);
1506	} else {
1507		lps_ctrl_wk_hdl(padapter, lps_ctrl_type);
1508	}
1509
1510exit:
1511
1512
1513	return res;
1514}
1515
1516static void rpt_timer_setting_wk_hdl(struct adapter *padapter, u16 min_time)
1517{
1518	rtw_hal_set_hwreg(padapter, HW_VAR_RPT_TIMER_SETTING, (u8 *)(&min_time));
1519}
1520
1521u8 rtw_rpt_timer_cfg_cmd(struct adapter *padapter, u16 min_time)
1522{
1523	struct cmd_obj		*ph2c;
1524	struct drvextra_cmd_parm	*pdrvextra_cmd_parm;
1525	struct cmd_priv	*pcmdpriv = &padapter->cmdpriv;
1526
1527	u8	res = _SUCCESS;
1528
1529	ph2c = kzalloc(sizeof(struct cmd_obj), GFP_KERNEL);
1530	if (ph2c == NULL) {
1531		res = _FAIL;
1532		goto exit;
1533	}
1534
1535	pdrvextra_cmd_parm = kzalloc(sizeof(struct drvextra_cmd_parm), GFP_KERNEL);
1536	if (pdrvextra_cmd_parm == NULL) {
1537		kfree(ph2c);
1538		res = _FAIL;
1539		goto exit;
1540	}
1541
1542	pdrvextra_cmd_parm->ec_id = RTP_TIMER_CFG_WK_CID;
1543	pdrvextra_cmd_parm->type_size = min_time;
1544	pdrvextra_cmd_parm->pbuf = NULL;
1545	init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, GEN_CMD_CODE(_Set_Drv_Extra));
1546	res = rtw_enqueue_cmd(pcmdpriv, ph2c);
1547exit:
1548
1549
1550	return res;
1551}
1552
1553static void antenna_select_wk_hdl(struct adapter *padapter, u8 antenna)
1554{
1555	rtw_hal_set_hwreg(padapter, HW_VAR_ANTENNA_DIVERSITY_SELECT, (u8 *)(&antenna));
1556}
1557
1558u8 rtw_antenna_select_cmd(struct adapter *padapter, u8 antenna, u8 enqueue)
1559{
1560	struct cmd_obj		*ph2c;
1561	struct drvextra_cmd_parm	*pdrvextra_cmd_parm;
1562	struct cmd_priv	*pcmdpriv = &padapter->cmdpriv;
1563	u8	support_ant_div;
1564	u8	res = _SUCCESS;
1565
1566	rtw_hal_get_def_var(padapter, HAL_DEF_IS_SUPPORT_ANT_DIV, &support_ant_div);
1567	if (!support_ant_div)
1568		return res;
1569
1570	if (enqueue) {
1571		ph2c = kzalloc(sizeof(struct cmd_obj), GFP_KERNEL);
1572		if (ph2c == NULL) {
1573			res = _FAIL;
1574			goto exit;
1575		}
1576
1577		pdrvextra_cmd_parm = kzalloc(sizeof(struct drvextra_cmd_parm), GFP_KERNEL);
1578		if (pdrvextra_cmd_parm == NULL) {
1579			kfree(ph2c);
1580			res = _FAIL;
1581			goto exit;
1582		}
1583
1584		pdrvextra_cmd_parm->ec_id = ANT_SELECT_WK_CID;
1585		pdrvextra_cmd_parm->type_size = antenna;
1586		pdrvextra_cmd_parm->pbuf = NULL;
1587		init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, GEN_CMD_CODE(_Set_Drv_Extra));
1588
1589		res = rtw_enqueue_cmd(pcmdpriv, ph2c);
1590	} else {
1591		antenna_select_wk_hdl(padapter, antenna);
1592	}
1593exit:
1594
1595
1596	return res;
1597}
1598
1599static void power_saving_wk_hdl(struct adapter *padapter, u8 *pbuf, int sz)
1600{
1601	 rtw_ps_processor(padapter);
1602}
1603
1604u8 rtw_ps_cmd(struct adapter *padapter)
1605{
1606	struct cmd_obj		*ppscmd;
1607	struct drvextra_cmd_parm	*pdrvextra_cmd_parm;
1608	struct cmd_priv	*pcmdpriv = &padapter->cmdpriv;
1609
1610	u8	res = _SUCCESS;
1611
1612	ppscmd = kzalloc(sizeof(struct cmd_obj), GFP_KERNEL);
1613	if (ppscmd == NULL) {
1614		res = _FAIL;
1615		goto exit;
1616	}
1617
1618	pdrvextra_cmd_parm = kzalloc(sizeof(struct drvextra_cmd_parm), GFP_KERNEL);
1619	if (pdrvextra_cmd_parm == NULL) {
1620		kfree(ppscmd);
1621		res = _FAIL;
1622		goto exit;
1623	}
1624
1625	pdrvextra_cmd_parm->ec_id = POWER_SAVING_CTRL_WK_CID;
1626	pdrvextra_cmd_parm->pbuf = NULL;
1627	init_h2fwcmd_w_parm_no_rsp(ppscmd, pdrvextra_cmd_parm, GEN_CMD_CODE(_Set_Drv_Extra));
1628
1629	res = rtw_enqueue_cmd(pcmdpriv, ppscmd);
1630
1631exit:
1632
1633
1634	return res;
1635}
1636
1637#ifdef CONFIG_88EU_AP_MODE
1638
1639static void rtw_chk_hi_queue_hdl(struct adapter *padapter)
1640{
1641	int cnt = 0;
1642	struct sta_info *psta_bmc;
1643	struct sta_priv *pstapriv = &padapter->stapriv;
1644
1645	psta_bmc = rtw_get_bcmc_stainfo(padapter);
1646	if (!psta_bmc)
1647		return;
1648
1649	if (psta_bmc->sleepq_len == 0) {
1650		u8 val = 0;
1651
1652		/* while ((rtw_read32(padapter, 0x414)&0x00ffff00)!= 0) */
1653		/* while ((rtw_read32(padapter, 0x414)&0x0000ff00)!= 0) */
1654
1655		rtw_hal_get_hwreg(padapter, HW_VAR_CHK_HI_QUEUE_EMPTY, &val);
1656
1657		while (!val) {
1658			msleep(100);
1659
1660			cnt++;
1661
1662			if (cnt > 10)
1663				break;
1664
1665			rtw_hal_get_hwreg(padapter, HW_VAR_CHK_HI_QUEUE_EMPTY, &val);
1666		}
1667
1668		if (cnt <= 10) {
1669			pstapriv->tim_bitmap &= ~BIT(0);
1670			pstapriv->sta_dz_bitmap &= ~BIT(0);
1671
1672			update_beacon(padapter, _TIM_IE_, NULL, false);
1673		} else { /* re check again */
1674			rtw_chk_hi_queue_cmd(padapter);
1675		}
1676	}
1677}
1678
1679u8 rtw_chk_hi_queue_cmd(struct adapter *padapter)
1680{
1681	struct cmd_obj	*ph2c;
1682	struct drvextra_cmd_parm	*pdrvextra_cmd_parm;
1683	struct cmd_priv	*pcmdpriv = &padapter->cmdpriv;
1684	u8	res = _SUCCESS;
1685
1686	ph2c = kzalloc(sizeof(struct cmd_obj), GFP_KERNEL);
1687	if (ph2c == NULL) {
1688		res = _FAIL;
1689		goto exit;
1690	}
1691
1692	pdrvextra_cmd_parm = kzalloc(sizeof(struct drvextra_cmd_parm), GFP_KERNEL);
1693	if (pdrvextra_cmd_parm == NULL) {
1694		kfree(ph2c);
1695		res = _FAIL;
1696		goto exit;
1697	}
1698
1699	pdrvextra_cmd_parm->ec_id = CHECK_HIQ_WK_CID;
1700	pdrvextra_cmd_parm->type_size = 0;
1701	pdrvextra_cmd_parm->pbuf = NULL;
1702
1703	init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, GEN_CMD_CODE(_Set_Drv_Extra));
1704
1705	res = rtw_enqueue_cmd(pcmdpriv, ph2c);
1706exit:
1707	return res;
1708}
1709#endif
1710
1711u8 rtw_drvextra_cmd_hdl(struct adapter *padapter, unsigned char *pbuf)
1712{
1713	struct drvextra_cmd_parm *pdrvextra_cmd;
1714
1715	if (!pbuf)
1716		return H2C_PARAMETERS_ERROR;
1717
1718	pdrvextra_cmd = (struct drvextra_cmd_parm *)pbuf;
1719
1720	switch (pdrvextra_cmd->ec_id) {
1721	case DYNAMIC_CHK_WK_CID:
1722		dynamic_chk_wk_hdl(padapter, pdrvextra_cmd->pbuf, pdrvextra_cmd->type_size);
1723		break;
1724	case POWER_SAVING_CTRL_WK_CID:
1725		power_saving_wk_hdl(padapter, pdrvextra_cmd->pbuf, pdrvextra_cmd->type_size);
1726		break;
1727	case LPS_CTRL_WK_CID:
1728		lps_ctrl_wk_hdl(padapter, (u8)pdrvextra_cmd->type_size);
1729		break;
1730	case RTP_TIMER_CFG_WK_CID:
1731		rpt_timer_setting_wk_hdl(padapter, pdrvextra_cmd->type_size);
1732		break;
1733	case ANT_SELECT_WK_CID:
1734		antenna_select_wk_hdl(padapter, pdrvextra_cmd->type_size);
1735		break;
1736#ifdef CONFIG_88EU_AP_MODE
1737	case CHECK_HIQ_WK_CID:
1738		rtw_chk_hi_queue_hdl(padapter);
1739		break;
1740#endif /* CONFIG_88EU_AP_MODE */
1741	default:
1742		break;
1743	}
1744
1745	if (pdrvextra_cmd->pbuf && pdrvextra_cmd->type_size > 0)
1746		kfree(pdrvextra_cmd->pbuf);
1747
1748	return H2C_SUCCESS;
1749}
1750
1751void rtw_survey_cmd_callback(struct adapter *padapter,  struct cmd_obj *pcmd)
1752{
1753	struct	mlme_priv *pmlmepriv = &padapter->mlmepriv;
1754
1755
1756	if (pcmd->res == H2C_DROPPED) {
1757		/* TODO: cancel timer and do timeout handler directly... */
1758		/* need to make timeout handlerOS independent */
1759		_set_timer(&pmlmepriv->scan_to_timer, 1);
1760	} else if (pcmd->res != H2C_SUCCESS) {
1761		_set_timer(&pmlmepriv->scan_to_timer, 1);
1762		RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_, ("\n ********Error: MgntActrtw_set_802_11_bssid_LIST_SCAN Fail ************\n\n."));
1763	}
1764
1765	/*  free cmd */
1766	rtw_free_cmd_obj(pcmd);
1767
1768}
1769void rtw_disassoc_cmd_callback(struct adapter *padapter, struct cmd_obj *pcmd)
1770{
1771	struct	mlme_priv *pmlmepriv = &padapter->mlmepriv;
1772
1773
1774	if (pcmd->res != H2C_SUCCESS) {
1775		spin_lock_bh(&pmlmepriv->lock);
1776		set_fwstate(pmlmepriv, _FW_LINKED);
1777		spin_unlock_bh(&pmlmepriv->lock);
1778
1779		RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_, ("\n ***Error: disconnect_cmd_callback Fail ***\n."));
1780		return;
1781	}
1782
1783	/*  free cmd */
1784	rtw_free_cmd_obj(pcmd);
1785}
1786
1787void rtw_joinbss_cmd_callback(struct adapter *padapter,  struct cmd_obj *pcmd)
1788{
1789	struct	mlme_priv *pmlmepriv = &padapter->mlmepriv;
1790
1791
1792	if (pcmd->res == H2C_DROPPED) {
1793		/* TODO: cancel timer and do timeout handler directly... */
1794		/* need to make timeout handlerOS independent */
1795		_set_timer(&pmlmepriv->assoc_timer, 1);
1796	} else if (pcmd->res != H2C_SUCCESS) {
1797		RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_, ("********Error:rtw_select_and_join_from_scanned_queue Wait Sema  Fail ************\n"));
1798		_set_timer(&pmlmepriv->assoc_timer, 1);
1799	}
1800
1801	rtw_free_cmd_obj(pcmd);
1802
1803}
1804
1805void rtw_createbss_cmd_callback(struct adapter *padapter, struct cmd_obj *pcmd)
1806{
1807	struct sta_info *psta = NULL;
1808	struct wlan_network *pwlan = NULL;
1809	struct	mlme_priv *pmlmepriv = &padapter->mlmepriv;
1810	struct wlan_bssid_ex *pnetwork = (struct wlan_bssid_ex *)pcmd->parmbuf;
1811	struct wlan_network *tgt_network = &(pmlmepriv->cur_network);
1812
1813
1814	if (pcmd->res != H2C_SUCCESS) {
1815		RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_, ("\n ********Error: rtw_createbss_cmd_callback  Fail ************\n\n."));
1816		_set_timer(&pmlmepriv->assoc_timer, 1);
1817	}
1818
1819	del_timer_sync(&pmlmepriv->assoc_timer);
1820
1821	spin_lock_bh(&pmlmepriv->lock);
1822
1823	if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) {
1824		psta = rtw_get_stainfo(&padapter->stapriv, pnetwork->MacAddress);
1825		if (!psta) {
1826			psta = rtw_alloc_stainfo(&padapter->stapriv, pnetwork->MacAddress);
1827			if (psta == NULL) {
1828				RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_, ("\nCan't alloc sta_info when createbss_cmd_callback\n"));
1829				goto createbss_cmd_fail;
1830			}
1831		}
1832
1833		rtw_indicate_connect(padapter);
1834	} else {
1835		pwlan = _rtw_alloc_network(pmlmepriv);
1836		spin_lock_bh(&(pmlmepriv->scanned_queue.lock));
1837		if (pwlan == NULL) {
1838			pwlan = rtw_get_oldest_wlan_network(&pmlmepriv->scanned_queue);
1839			if (pwlan == NULL) {
1840				RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_, ("\n Error:  can't get pwlan in rtw_joinbss_event_callback\n"));
1841				spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
1842				goto createbss_cmd_fail;
1843			}
1844			pwlan->last_scanned = jiffies;
1845		} else {
1846			list_add_tail(&(pwlan->list), &pmlmepriv->scanned_queue.queue);
1847		}
1848
1849		pnetwork->Length = get_wlan_bssid_ex_sz(pnetwork);
1850		memcpy(&(pwlan->network), pnetwork, pnetwork->Length);
1851
1852		memcpy(&tgt_network->network, pnetwork, (get_wlan_bssid_ex_sz(pnetwork)));
1853
1854		_clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING);
1855
1856		spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
1857		/*  we will set _FW_LINKED when there is one more sat to join us (rtw_stassoc_event_callback) */
1858	}
1859
1860createbss_cmd_fail:
1861
1862	spin_unlock_bh(&pmlmepriv->lock);
1863
1864	rtw_free_cmd_obj(pcmd);
1865
1866}
1867
1868void rtw_setstaKey_cmdrsp_callback(struct adapter *padapter,  struct cmd_obj *pcmd)
1869{
1870	struct sta_priv *pstapriv = &padapter->stapriv;
1871	struct set_stakey_rsp *psetstakey_rsp = (struct set_stakey_rsp *)(pcmd->rsp);
1872	struct sta_info *psta = rtw_get_stainfo(pstapriv, psetstakey_rsp->addr);
1873
1874
1875	if (psta == NULL) {
1876		RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_, ("\nERROR: rtw_setstaKey_cmdrsp_callback => can't get sta_info\n\n"));
1877		goto exit;
1878	}
1879exit:
1880	rtw_free_cmd_obj(pcmd);
1881}
1882
1883void rtw_setassocsta_cmdrsp_callback(struct adapter *padapter,  struct cmd_obj *pcmd)
1884{
1885	struct sta_priv *pstapriv = &padapter->stapriv;
1886	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1887	struct set_assocsta_parm *passocsta_parm = (struct set_assocsta_parm *)(pcmd->parmbuf);
1888	struct set_assocsta_rsp *passocsta_rsp = (struct set_assocsta_rsp *)(pcmd->rsp);
1889	struct sta_info *psta = rtw_get_stainfo(pstapriv, passocsta_parm->addr);
1890
1891
1892	if (psta == NULL) {
1893		RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_, ("\nERROR: setassocsta_cmdrsp_callbac => can't get sta_info\n\n"));
1894		goto exit;
1895	}
1896
1897	psta->aid = passocsta_rsp->cam_id;
1898	psta->mac_id = passocsta_rsp->cam_id;
1899
1900	spin_lock_bh(&pmlmepriv->lock);
1901
1902	if ((check_fwstate(pmlmepriv, WIFI_MP_STATE) == true) && (check_fwstate(pmlmepriv, _FW_UNDER_LINKING) == true))
1903		_clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING);
1904
1905	set_fwstate(pmlmepriv, _FW_LINKED);
1906	spin_unlock_bh(&pmlmepriv->lock);
1907
1908exit:
1909	rtw_free_cmd_obj(pcmd);
1910
1911}
1912