rtw_cmd.c revision c17416ef707312429aafcdc4597db73906f3572e
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			rtw_hal_set_hwreg23a(padapter, HW_VAR_H2C_FW_JOINBSSRPT,
1273					     (u8 *)&mstatus);
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			rtw_hal_set_hwreg23a(padapter, HW_VAR_H2C_FW_JOINBSSRPT,
1288					     (u8 *)&mstatus);
1289			break;
1290		case LPS_CTRL_SPECIAL_PACKET:
1291			pwrpriv->DelayLPSLastTimeStamp = jiffies;
1292#ifdef CONFIG_8723AU_BT_COEXIST
1293			BT_SpecialPacketNotify(padapter);
1294			if (BT_1Ant(padapter) == false)
1295#endif
1296			{
1297				LPS_Leave23a(padapter);
1298			}
1299			break;
1300		case LPS_CTRL_LEAVE:
1301#ifdef CONFIG_8723AU_BT_COEXIST
1302			BT_LpsLeave(padapter);
1303			if (BT_1Ant(padapter) == false)
1304#endif
1305			{
1306				LPS_Leave23a(padapter);
1307			}
1308			break;
1309
1310		default:
1311			break;
1312	}
1313}
1314
1315u8 rtw_lps_ctrl_wk_cmd23a(struct rtw_adapter *padapter,
1316			  u8 lps_ctrl_type, u8 enqueue)
1317{
1318	struct cmd_obj *ph2c;
1319	struct drvextra_cmd_parm *pdrvextra_cmd_parm;
1320	struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
1321	u8 res = _SUCCESS;
1322
1323	if (enqueue) {
1324		ph2c = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC);
1325		if (!ph2c) {
1326			res = _FAIL;
1327			goto exit;
1328		}
1329
1330		pdrvextra_cmd_parm = kzalloc(sizeof(struct drvextra_cmd_parm),
1331					     GFP_ATOMIC);
1332		if (!pdrvextra_cmd_parm) {
1333			kfree(ph2c);
1334			res = _FAIL;
1335			goto exit;
1336		}
1337
1338		pdrvextra_cmd_parm->ec_id = LPS_CTRL_WK_CID;
1339		pdrvextra_cmd_parm->type_size = lps_ctrl_type;
1340		pdrvextra_cmd_parm->pbuf = NULL;
1341
1342		init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm,
1343					   GEN_CMD_CODE(_Set_Drv_Extra));
1344
1345		res = rtw_enqueue_cmd23a(pcmdpriv, ph2c);
1346	} else
1347		lps_ctrl_wk_hdl(padapter, lps_ctrl_type);
1348exit:
1349
1350	return res;
1351}
1352
1353static void power_saving_wk_hdl(struct rtw_adapter *padapter, u8 *pbuf, int sz)
1354{
1355	 rtw_ps_processor23a(padapter);
1356}
1357
1358#ifdef CONFIG_8723AU_P2P
1359u8 p2p_protocol_wk_cmd23a(struct rtw_adapter*padapter, int intCmdType)
1360{
1361	struct cmd_obj *ph2c;
1362	struct drvextra_cmd_parm *pdrvextra_cmd_parm;
1363	struct wifidirect_info *pwdinfo = &padapter->wdinfo;
1364	struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
1365	u8 res = _SUCCESS;
1366
1367	if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE))
1368	{
1369		return res;
1370	}
1371
1372	ph2c = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC);
1373	if (!ph2c) {
1374		res = _FAIL;
1375		goto exit;
1376	}
1377
1378	pdrvextra_cmd_parm = kzalloc(sizeof(struct drvextra_cmd_parm),
1379				     GFP_ATOMIC);
1380	if (!pdrvextra_cmd_parm) {
1381		kfree(ph2c);
1382		res = _FAIL;
1383		goto exit;
1384	}
1385
1386	pdrvextra_cmd_parm->ec_id = P2P_PROTO_WK_CID;
1387	pdrvextra_cmd_parm->type_size = intCmdType; /* As the command tppe. */
1388	pdrvextra_cmd_parm->pbuf = NULL;	    /* Must be NULL here */
1389
1390	init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm,
1391				   GEN_CMD_CODE(_Set_Drv_Extra));
1392
1393	res = rtw_enqueue_cmd23a(pcmdpriv, ph2c);
1394exit:
1395
1396	return res;
1397}
1398#endif /* CONFIG_8723AU_P2P */
1399
1400u8 rtw_ps_cmd23a(struct rtw_adapter*padapter)
1401{
1402	struct cmd_obj *ppscmd;
1403	struct drvextra_cmd_parm *pdrvextra_cmd_parm;
1404	struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
1405
1406	u8 res = _SUCCESS;
1407
1408	ppscmd = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC);
1409	if (!ppscmd) {
1410		res = _FAIL;
1411		goto exit;
1412	}
1413
1414	pdrvextra_cmd_parm = kzalloc(sizeof(struct drvextra_cmd_parm),
1415				     GFP_ATOMIC);
1416	if (!pdrvextra_cmd_parm) {
1417		kfree(ppscmd);
1418		res = _FAIL;
1419		goto exit;
1420	}
1421
1422	pdrvextra_cmd_parm->ec_id = POWER_SAVING_CTRL_WK_CID;
1423	pdrvextra_cmd_parm->pbuf = NULL;
1424	init_h2fwcmd_w_parm_no_rsp(ppscmd, pdrvextra_cmd_parm,
1425				   GEN_CMD_CODE(_Set_Drv_Extra));
1426
1427	res = rtw_enqueue_cmd23a(pcmdpriv, ppscmd);
1428exit:
1429
1430	return res;
1431}
1432
1433#ifdef CONFIG_8723AU_AP_MODE
1434
1435static void rtw_chk_hi_queue_hdl(struct rtw_adapter *padapter)
1436{
1437	int cnt = 0;
1438	struct sta_info *psta_bmc;
1439	struct sta_priv *pstapriv = &padapter->stapriv;
1440
1441	psta_bmc = rtw_get_bcmc_stainfo23a(padapter);
1442	if (!psta_bmc)
1443		return;
1444
1445	if (psta_bmc->sleepq_len == 0) {
1446		u8 val = 0;
1447
1448		rtw23a_hal_get_hwreg(padapter, HW_VAR_CHK_HI_QUEUE_EMPTY, &val);
1449
1450		while(val == false) {
1451			msleep(100);
1452
1453			cnt++;
1454
1455			if (cnt>10)
1456				break;
1457
1458			rtw23a_hal_get_hwreg(padapter,
1459					     HW_VAR_CHK_HI_QUEUE_EMPTY, &val);
1460		}
1461
1462		if (cnt <= 10) {
1463			pstapriv->tim_bitmap &= ~BIT(0);
1464			pstapriv->sta_dz_bitmap &= ~BIT(0);
1465
1466			update_beacon23a(padapter, _TIM_IE_, NULL, false);
1467		} else /* re check again */
1468			rtw_chk_hi_queue_cmd23a(padapter);
1469	}
1470}
1471
1472u8 rtw_chk_hi_queue_cmd23a(struct rtw_adapter*padapter)
1473{
1474	struct cmd_obj *ph2c;
1475	struct drvextra_cmd_parm *pdrvextra_cmd_parm;
1476	struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
1477	u8 res = _SUCCESS;
1478
1479	ph2c = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC);
1480	if (!ph2c) {
1481		res = _FAIL;
1482		goto exit;
1483	}
1484
1485	pdrvextra_cmd_parm = kzalloc(sizeof(struct drvextra_cmd_parm),
1486				     GFP_ATOMIC);
1487	if (!pdrvextra_cmd_parm) {
1488		kfree(ph2c);
1489		res = _FAIL;
1490		goto exit;
1491	}
1492
1493	pdrvextra_cmd_parm->ec_id = CHECK_HIQ_WK_CID;
1494	pdrvextra_cmd_parm->type_size = 0;
1495	pdrvextra_cmd_parm->pbuf = NULL;
1496
1497	init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm,
1498				   GEN_CMD_CODE(_Set_Drv_Extra));
1499
1500	res = rtw_enqueue_cmd23a(pcmdpriv, ph2c);
1501exit:
1502
1503	return res;
1504}
1505#endif
1506
1507u8 rtw_c2h_wk_cmd23a(struct rtw_adapter *padapter, u8 *c2h_evt)
1508{
1509	struct cmd_obj *ph2c;
1510	struct drvextra_cmd_parm *pdrvextra_cmd_parm;
1511	struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
1512	u8 res = _SUCCESS;
1513
1514	ph2c = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC);
1515	if (!ph2c) {
1516		res = _FAIL;
1517		goto exit;
1518	}
1519
1520	pdrvextra_cmd_parm = kzalloc(sizeof(struct drvextra_cmd_parm),
1521				     GFP_ATOMIC);
1522	if (!pdrvextra_cmd_parm) {
1523		kfree(ph2c);
1524		res = _FAIL;
1525		goto exit;
1526	}
1527
1528	pdrvextra_cmd_parm->ec_id = C2H_WK_CID;
1529	pdrvextra_cmd_parm->type_size = c2h_evt?16:0;
1530	pdrvextra_cmd_parm->pbuf = c2h_evt;
1531
1532	init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm,
1533				   GEN_CMD_CODE(_Set_Drv_Extra));
1534
1535	res = rtw_enqueue_cmd23a(pcmdpriv, ph2c);
1536
1537exit:
1538
1539	return res;
1540}
1541
1542s32 c2h_evt_hdl(struct rtw_adapter *adapter, struct c2h_evt_hdr *c2h_evt,
1543		c2h_id_filter filter)
1544{
1545	s32 ret = _FAIL;
1546	u8 buf[16];
1547
1548	if (!c2h_evt) {
1549		/* No c2h event in cmd_obj, read c2h event before handling*/
1550		if (c2h_evt_read23a(adapter, buf) == _SUCCESS) {
1551			c2h_evt = (struct c2h_evt_hdr *)buf;
1552
1553			if (filter && filter(c2h_evt->id) == false)
1554				goto exit;
1555
1556			ret = rtw_hal_c2h_handler23a(adapter, c2h_evt);
1557		}
1558	} else {
1559
1560		if (filter && filter(c2h_evt->id) == false)
1561			goto exit;
1562
1563		ret = rtw_hal_c2h_handler23a(adapter, c2h_evt);
1564	}
1565exit:
1566	return ret;
1567}
1568
1569static void c2h_wk_callback(struct work_struct *work)
1570{
1571	struct evt_priv *evtpriv;
1572	struct rtw_adapter *adapter;
1573	struct c2h_evt_hdr *c2h_evt;
1574	c2h_id_filter ccx_id_filter;
1575
1576	evtpriv = container_of(work, struct evt_priv, c2h_wk);
1577	adapter = container_of(evtpriv, struct rtw_adapter, evtpriv);
1578	ccx_id_filter = rtw_hal_c2h_id_filter_ccx23a(adapter);
1579
1580	evtpriv->c2h_wk_alive = true;
1581
1582	while (!rtw_cbuf_empty23a(evtpriv->c2h_queue)) {
1583		c2h_evt = (struct c2h_evt_hdr *)
1584			rtw_cbuf_pop23a(evtpriv->c2h_queue);
1585		if (c2h_evt) {
1586			/* This C2H event is read, clear it */
1587			c2h_evt_clear23a(adapter);
1588		} else if ((c2h_evt = (struct c2h_evt_hdr *)
1589			    kmalloc(16, GFP_ATOMIC))) {
1590			/* This C2H event is not read, read & clear now */
1591			if (c2h_evt_read23a(adapter, (u8*)c2h_evt) != _SUCCESS)
1592				continue;
1593		}
1594
1595		/* Special pointer to trigger c2h_evt_clear23a only */
1596		if ((void *)c2h_evt == (void *)evtpriv)
1597			continue;
1598
1599		if (!c2h_evt_exist(c2h_evt)) {
1600			kfree(c2h_evt);
1601			continue;
1602		}
1603
1604		if (ccx_id_filter(c2h_evt->id) == true) {
1605			/* Handle CCX report here */
1606			rtw_hal_c2h_handler23a(adapter, c2h_evt);
1607			kfree(c2h_evt);
1608		} else {
1609			/* Enqueue into cmd_thread for others */
1610			rtw_c2h_wk_cmd23a(adapter, (u8 *)c2h_evt);
1611		}
1612	}
1613
1614	evtpriv->c2h_wk_alive = false;
1615}
1616
1617u8 rtw_drvextra_cmd_hdl23a(struct rtw_adapter *padapter, unsigned char *pbuf)
1618{
1619	struct drvextra_cmd_parm *pdrvextra_cmd;
1620
1621	if (!pbuf)
1622		return H2C_PARAMETERS_ERROR;
1623
1624	pdrvextra_cmd = (struct drvextra_cmd_parm *)pbuf;
1625
1626	switch (pdrvextra_cmd->ec_id)
1627	{
1628	case DYNAMIC_CHK_WK_CID:
1629		dynamic_chk_wk_hdl(padapter, pdrvextra_cmd->pbuf,
1630				   pdrvextra_cmd->type_size);
1631		break;
1632	case POWER_SAVING_CTRL_WK_CID:
1633		power_saving_wk_hdl(padapter, pdrvextra_cmd->pbuf,
1634				    pdrvextra_cmd->type_size);
1635		break;
1636	case LPS_CTRL_WK_CID:
1637		lps_ctrl_wk_hdl(padapter, (u8)pdrvextra_cmd->type_size);
1638		break;
1639#ifdef CONFIG_8723AU_P2P
1640	case P2P_PS_WK_CID:
1641		p2p_ps_wk_hdl23a(padapter, pdrvextra_cmd->type_size);
1642		break;
1643	case P2P_PROTO_WK_CID:
1644		/*	Commented by Albert 2011/07/01 */
1645		/*	I used the type_size as the type command */
1646		p2p_protocol_wk_hdl23a(padapter, pdrvextra_cmd->type_size);
1647		break;
1648#endif /*  CONFIG_8723AU_P2P */
1649#ifdef CONFIG_8723AU_AP_MODE
1650	case CHECK_HIQ_WK_CID:
1651		rtw_chk_hi_queue_hdl(padapter);
1652		break;
1653#endif /* CONFIG_8723AU_AP_MODE */
1654	case C2H_WK_CID:
1655		c2h_evt_hdl(padapter,
1656			    (struct c2h_evt_hdr *)pdrvextra_cmd->pbuf, NULL);
1657		break;
1658
1659	default:
1660		break;
1661	}
1662
1663	if (pdrvextra_cmd->pbuf && (pdrvextra_cmd->type_size > 0)) {
1664		kfree(pdrvextra_cmd->pbuf);
1665		pdrvextra_cmd->pbuf = NULL;
1666	}
1667
1668	return H2C_SUCCESS;
1669}
1670
1671void rtw_survey_cmd_callback23a(struct rtw_adapter *padapter,
1672			     struct cmd_obj *pcmd)
1673{
1674	struct	mlme_priv *pmlmepriv = &padapter->mlmepriv;
1675
1676	if (pcmd->res == H2C_DROPPED) {
1677		/* TODO: cancel timer and do timeout handler directly... */
1678		/* need to make timeout handlerOS independent */
1679		mod_timer(&pmlmepriv->scan_to_timer,
1680			  jiffies + msecs_to_jiffies(1));
1681	} else if (pcmd->res != H2C_SUCCESS) {
1682		mod_timer(&pmlmepriv->scan_to_timer,
1683			  jiffies + msecs_to_jiffies(1));
1684		RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_,
1685			 ("\n ********Error: MgntActrtw_set_802_11_bssid23a_"
1686			  "LIST_SCAN Fail ************\n\n."));
1687	}
1688
1689	/*  free cmd */
1690	rtw_free_cmd_obj23a(pcmd);
1691}
1692
1693void rtw_disassoc_cmd23a_callback(struct rtw_adapter *padapter,
1694				  struct cmd_obj *pcmd)
1695{
1696	struct	mlme_priv *pmlmepriv = &padapter->mlmepriv;
1697
1698	if (pcmd->res != H2C_SUCCESS) {
1699		spin_lock_bh(&pmlmepriv->lock);
1700		set_fwstate(pmlmepriv, _FW_LINKED);
1701		spin_unlock_bh(&pmlmepriv->lock);
1702		RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_,
1703			 ("\n ***Error: disconnect_cmd_callback Fail ***\n."));
1704		return;
1705	}
1706
1707	/*  free cmd */
1708	rtw_free_cmd_obj23a(pcmd);
1709}
1710
1711void rtw_joinbss_cmd23a_callback(struct rtw_adapter *padapter,
1712				 struct cmd_obj *pcmd)
1713{
1714	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1715
1716	if (pcmd->res == H2C_DROPPED) {
1717		/* TODO: cancel timer and do timeout handler directly... */
1718		/* need to make timeout handlerOS independent */
1719		mod_timer(&pmlmepriv->assoc_timer,
1720			  jiffies + msecs_to_jiffies(1));
1721	} else if (pcmd->res != H2C_SUCCESS) {
1722		RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_,
1723			 ("********Error:rtw_select_and_join_from_scanned_"
1724			  "queue Wait Sema  Fail ************\n"));
1725		mod_timer(&pmlmepriv->assoc_timer,
1726			  jiffies + msecs_to_jiffies(1));
1727	}
1728
1729	rtw_free_cmd_obj23a(pcmd);
1730}
1731
1732void rtw_createbss_cmd23a_callback(struct rtw_adapter *padapter,
1733				   struct cmd_obj *pcmd)
1734{
1735	struct sta_info *psta;
1736	struct wlan_network *pwlan;
1737	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1738	struct wlan_bssid_ex *pnetwork = (struct wlan_bssid_ex *)pcmd->parmbuf;
1739	struct wlan_network *tgt_network = &pmlmepriv->cur_network;
1740
1741	if (pcmd->res != H2C_SUCCESS) {
1742		RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_,
1743			 ("\n ********Error: rtw_createbss_cmd23a_callback  "
1744			  "Fail ************\n\n."));
1745		mod_timer(&pmlmepriv->assoc_timer,
1746			  jiffies + msecs_to_jiffies(1));
1747	}
1748
1749	del_timer_sync(&pmlmepriv->assoc_timer);
1750
1751	spin_lock_bh(&pmlmepriv->lock);
1752
1753	if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) {
1754		psta = rtw_get_stainfo23a(&padapter->stapriv,
1755					  pnetwork->MacAddress);
1756		if (!psta) {
1757			psta = rtw_alloc_stainfo23a(&padapter->stapriv,
1758						 pnetwork->MacAddress);
1759			if (!psta) {
1760				RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_,
1761					 ("\nCan't alloc sta_info when "
1762					  "createbss_cmd_callback\n"));
1763				goto createbss_cmd_fail ;
1764			}
1765		}
1766
1767		rtw_indicate_connect23a(padapter);
1768	} else {
1769		pwlan = rtw_alloc_network(pmlmepriv);
1770		spin_lock_bh(&pmlmepriv->scanned_queue.lock);
1771		if (!pwlan) {
1772			pwlan = rtw_get_oldest_wlan_network23a(&pmlmepriv->scanned_queue);
1773			if (!pwlan) {
1774				RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_,
1775					 ("\n Error:  can't get pwlan in "
1776					  "rtw23a_joinbss_event_cb\n"));
1777				spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
1778				goto createbss_cmd_fail;
1779			}
1780			pwlan->last_scanned = jiffies;
1781		} else {
1782			list_add_tail(&pwlan->list,
1783				      &pmlmepriv->scanned_queue.queue);
1784		}
1785
1786		pnetwork->Length = get_wlan_bssid_ex_sz(pnetwork);
1787		memcpy(&pwlan->network, pnetwork, pnetwork->Length);
1788		/* pwlan->fixed = true; */
1789
1790		/* list_add_tail(&pwlan->list,
1791		   &pmlmepriv->scanned_queue.queue); */
1792
1793		/*  copy pdev_network information to
1794		    pmlmepriv->cur_network */
1795		memcpy(&tgt_network->network, pnetwork,
1796		       get_wlan_bssid_ex_sz(pnetwork));
1797
1798		/*  reset DSConfig */
1799
1800		_clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING);
1801
1802		spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
1803		/*  we will set _FW_LINKED when there is one more sat to
1804		    join us (rtw_stassoc_event_callback23a) */
1805	}
1806
1807createbss_cmd_fail:
1808
1809	spin_unlock_bh(&pmlmepriv->lock);
1810
1811	rtw_free_cmd_obj23a(pcmd);
1812}
1813
1814void rtw_setstaKey_cmdrsp_callback23a(struct rtw_adapter *padapter,
1815				      struct cmd_obj *pcmd)
1816{
1817	struct sta_priv *pstapriv;
1818	struct set_stakey_rsp *psetstakey_rsp;
1819	struct sta_info *psta;
1820
1821	pstapriv = &padapter->stapriv;
1822	psetstakey_rsp = (struct set_stakey_rsp*) (pcmd->rsp);
1823	psta = rtw_get_stainfo23a(pstapriv, psetstakey_rsp->addr);
1824
1825	if (!psta) {
1826		RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_,
1827			 ("\nERROR: rtw_setstaKey_cmdrsp_callback23a => "
1828			  "can't get sta_info\n\n"));
1829		goto exit;
1830	}
1831
1832exit:
1833
1834	rtw_free_cmd_obj23a(pcmd);
1835}
1836
1837void rtw_setassocsta_cmdrsp_callback23a(struct rtw_adapter *padapter,
1838					struct cmd_obj *pcmd)
1839{
1840	struct sta_priv *pstapriv = &padapter->stapriv;
1841	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1842	struct set_assocsta_parm* passocsta_parm;
1843	struct set_assocsta_rsp* passocsta_rsp;
1844	struct sta_info *psta;
1845
1846	passocsta_parm = (struct set_assocsta_parm *)(pcmd->parmbuf);
1847	passocsta_rsp = (struct set_assocsta_rsp*) (pcmd->rsp);
1848	psta = rtw_get_stainfo23a(pstapriv, passocsta_parm->addr);
1849
1850	if (psta == NULL) {
1851		RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_,
1852			 ("\nERROR: setassocsta_cmdrsp_callbac => can't "
1853			  "get sta_info\n\n"));
1854		goto exit;
1855	}
1856
1857	psta->aid = psta->mac_id = passocsta_rsp->cam_id;
1858
1859	spin_lock_bh(&pmlmepriv->lock);
1860
1861	if ((check_fwstate(pmlmepriv, WIFI_MP_STATE) == true) &&
1862	    (check_fwstate(pmlmepriv, _FW_UNDER_LINKING) == true))
1863		_clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING);
1864
1865	set_fwstate(pmlmepriv, _FW_LINKED);
1866	spin_unlock_bh(&pmlmepriv->lock);
1867
1868exit:
1869	rtw_free_cmd_obj23a(pcmd);
1870}
1871
1872void rtw_getrttbl_cmd_cmdrsp_callback(struct rtw_adapter *padapter,
1873				      struct cmd_obj *pcmd)
1874{
1875	rtw_free_cmd_obj23a(pcmd);
1876}
1877