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