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