• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 <mlme_osdep.h>
21 #include <rtl8723a_cmd.h>
22 #include <rtw_sreset.h>
23 
24 static struct cmd_hdl wlancmds[] = {
25 	GEN_DRV_CMD_HANDLER(0, NULL) /*0*/
26 	GEN_DRV_CMD_HANDLER(0, NULL)
27 	GEN_DRV_CMD_HANDLER(0, NULL)
28 	GEN_DRV_CMD_HANDLER(0, NULL)
29 	GEN_DRV_CMD_HANDLER(0, NULL)
30 	GEN_DRV_CMD_HANDLER(0, NULL)
31 	GEN_MLME_EXT_HANDLER(0, NULL)
32 	GEN_MLME_EXT_HANDLER(0, NULL)
33 	GEN_MLME_EXT_HANDLER(0, NULL)
34 	GEN_MLME_EXT_HANDLER(0, NULL)
35 	GEN_MLME_EXT_HANDLER(0, NULL) /*10*/
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(sizeof (struct wlan_bssid_ex), join_cmd_hdl23a) /*14*/
40 	GEN_MLME_EXT_HANDLER(sizeof (struct disconnect_parm), disconnect_hdl23a)
41 	GEN_MLME_EXT_HANDLER(sizeof (struct wlan_bssid_ex), createbss_hdl23a)
42 	GEN_MLME_EXT_HANDLER(sizeof (struct setopmode_parm), setopmode_hdl23a)
43 	GEN_MLME_EXT_HANDLER(sizeof (struct sitesurvey_parm), sitesurvey_cmd_hdl23a) /*18*/
44 	GEN_MLME_EXT_HANDLER(sizeof (struct setauth_parm), setauth_hdl23a)
45 	GEN_MLME_EXT_HANDLER(sizeof (struct setkey_parm), setkey_hdl23a) /*20*/
46 	GEN_MLME_EXT_HANDLER(sizeof (struct set_stakey_parm), set_stakey_hdl23a)
47 	GEN_MLME_EXT_HANDLER(sizeof (struct set_assocsta_parm), NULL)
48 	GEN_MLME_EXT_HANDLER(sizeof (struct del_assocsta_parm), NULL)
49 	GEN_MLME_EXT_HANDLER(sizeof (struct setstapwrstate_parm), NULL)
50 	GEN_MLME_EXT_HANDLER(sizeof (struct setbasicrate_parm), NULL)
51 	GEN_MLME_EXT_HANDLER(sizeof (struct getbasicrate_parm), NULL)
52 	GEN_MLME_EXT_HANDLER(sizeof (struct setdatarate_parm), NULL)
53 	GEN_MLME_EXT_HANDLER(sizeof (struct getdatarate_parm), NULL)
54 	GEN_MLME_EXT_HANDLER(sizeof (struct setphyinfo_parm), NULL)
55 	GEN_MLME_EXT_HANDLER(sizeof (struct getphyinfo_parm), NULL)  /*30*/
56 	GEN_MLME_EXT_HANDLER(sizeof (struct setphy_parm), NULL)
57 	GEN_MLME_EXT_HANDLER(sizeof (struct getphy_parm), NULL)
58 	GEN_MLME_EXT_HANDLER(0, NULL)
59 	GEN_MLME_EXT_HANDLER(0, NULL)
60 	GEN_MLME_EXT_HANDLER(0, 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)	/*40*/
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)
70 	GEN_MLME_EXT_HANDLER(sizeof(struct addBaReq_parm), add_ba_hdl23a)
71 	GEN_MLME_EXT_HANDLER(sizeof(struct set_ch_parm), set_ch_hdl23a) /* 46 */
72 	GEN_MLME_EXT_HANDLER(0, NULL)
73 	GEN_MLME_EXT_HANDLER(0, NULL)
74 	GEN_MLME_EXT_HANDLER(0, NULL)
75 	GEN_MLME_EXT_HANDLER(0, NULL) /*50*/
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)
80 	GEN_MLME_EXT_HANDLER(sizeof(struct Tx_Beacon_param), tx_beacon_hdl23a) /*55*/
81 
82 	GEN_MLME_EXT_HANDLER(0, mlme_evt_hdl23a) /*56*/
83 	GEN_MLME_EXT_HANDLER(0, rtw_drvextra_cmd_hdl23a) /*57*/
84 
85 	GEN_MLME_EXT_HANDLER(0, h2c_msg_hdl23a) /*58*/
86 	GEN_MLME_EXT_HANDLER(sizeof(struct SetChannelPlan_param), set_chplan_hdl23a) /*59*/
87 	GEN_MLME_EXT_HANDLER(sizeof(struct LedBlink_param), led_blink_hdl23a) /*60*/
88 
89 	GEN_MLME_EXT_HANDLER(sizeof(struct SetChannelSwitch_param), set_csa_hdl23a) /*61*/
90 	GEN_MLME_EXT_HANDLER(sizeof(struct TDLSoption_param), tdls_hdl23a) /*62*/
91 };
92 
93 struct _cmd_callback	rtw_cmd_callback[] = {
94 	{GEN_CMD_CODE(_Read_MACREG), NULL}, /*0*/
95 	{GEN_CMD_CODE(_Write_MACREG), NULL},
96 	{GEN_CMD_CODE(_Read_BBREG), &rtw_getbbrfreg_cmdrsp_callback23a},
97 	{GEN_CMD_CODE(_Write_BBREG), NULL},
98 	{GEN_CMD_CODE(_Read_RFREG), &rtw_getbbrfreg_cmdrsp_callback23a},
99 	{GEN_CMD_CODE(_Write_RFREG), NULL}, /*5*/
100 	{GEN_CMD_CODE(_Read_EEPROM), NULL},
101 	{GEN_CMD_CODE(_Write_EEPROM), NULL},
102 	{GEN_CMD_CODE(_Read_EFUSE), NULL},
103 	{GEN_CMD_CODE(_Write_EFUSE), NULL},
104 
105 	{GEN_CMD_CODE(_Read_CAM),	NULL},	/*10*/
106 	{GEN_CMD_CODE(_Write_CAM),	 NULL},
107 	{GEN_CMD_CODE(_setBCNITV), NULL},
108 	{GEN_CMD_CODE(_setMBIDCFG), NULL},
109 	{GEN_CMD_CODE(_JoinBss), &rtw_joinbss_cmd23a_callback},  /*14*/
110 	{GEN_CMD_CODE(_DisConnect), &rtw_disassoc_cmd23a_callback}, /*15*/
111 	{GEN_CMD_CODE(_CreateBss), &rtw_createbss_cmd23a_callback},
112 	{GEN_CMD_CODE(_SetOpMode), NULL},
113 	{GEN_CMD_CODE(_SiteSurvey), &rtw_survey_cmd_callback23a}, /*18*/
114 	{GEN_CMD_CODE(_SetAuth), NULL},
115 
116 	{GEN_CMD_CODE(_SetKey), NULL},	/*20*/
117 	{GEN_CMD_CODE(_SetStaKey), &rtw_setstaKey_cmdrsp_callback23a},
118 	{GEN_CMD_CODE(_SetAssocSta), &rtw_setassocsta_cmdrsp_callback23a},
119 	{GEN_CMD_CODE(_DelAssocSta), NULL},
120 	{GEN_CMD_CODE(_SetStaPwrState), NULL},
121 	{GEN_CMD_CODE(_SetBasicRate), NULL}, /*25*/
122 	{GEN_CMD_CODE(_GetBasicRate), NULL},
123 	{GEN_CMD_CODE(_SetDataRate), NULL},
124 	{GEN_CMD_CODE(_GetDataRate), NULL},
125 	{GEN_CMD_CODE(_SetPhyInfo), NULL},
126 
127 	{GEN_CMD_CODE(_GetPhyInfo), NULL}, /*30*/
128 	{GEN_CMD_CODE(_SetPhy), NULL},
129 	{GEN_CMD_CODE(_GetPhy), NULL},
130 	{GEN_CMD_CODE(_readRssi), NULL},
131 	{GEN_CMD_CODE(_readGain), NULL},
132 	{GEN_CMD_CODE(_SetAtim), NULL}, /*35*/
133 	{GEN_CMD_CODE(_SetPwrMode), NULL},
134 	{GEN_CMD_CODE(_JoinbssRpt), NULL},
135 	{GEN_CMD_CODE(_SetRaTable), NULL},
136 	{GEN_CMD_CODE(_GetRaTable), NULL},
137 
138 	{GEN_CMD_CODE(_GetCCXReport), NULL}, /*40*/
139 	{GEN_CMD_CODE(_GetDTMReport),	NULL},
140 	{GEN_CMD_CODE(_GetTXRateStatistics), NULL},
141 	{GEN_CMD_CODE(_SetUsbSuspend), NULL},
142 	{GEN_CMD_CODE(_SetH2cLbk), NULL},
143 	{GEN_CMD_CODE(_AddBAReq), NULL}, /*45*/
144 	{GEN_CMD_CODE(_SetChannel), NULL},		/*46*/
145 	{GEN_CMD_CODE(_SetTxPower), NULL},
146 	{GEN_CMD_CODE(_SwitchAntenna), NULL},
147 	{GEN_CMD_CODE(_SetCrystalCap), NULL},
148 	{GEN_CMD_CODE(_SetSingleCarrierTx), NULL},	/*50*/
149 
150 	{GEN_CMD_CODE(_SetSingleToneTx), NULL}, /*51*/
151 	{GEN_CMD_CODE(_SetCarrierSuppressionTx), NULL},
152 	{GEN_CMD_CODE(_SetContinuousTx), NULL},
153 	{GEN_CMD_CODE(_SwitchBandwidth), NULL},		/*54*/
154 	{GEN_CMD_CODE(_TX_Beacon), NULL},/*55*/
155 
156 	{GEN_CMD_CODE(_Set_MLME_EVT), NULL},/*56*/
157 	{GEN_CMD_CODE(_Set_Drv_Extra), NULL},/*57*/
158 	{GEN_CMD_CODE(_Set_H2C_MSG), NULL},/*58*/
159 	{GEN_CMD_CODE(_SetChannelPlan), NULL},/*59*/
160 	{GEN_CMD_CODE(_LedBlink), NULL},/*60*/
161 
162 	{GEN_CMD_CODE(_SetChannelSwitch), NULL},/*61*/
163 	{GEN_CMD_CODE(_TDLS), NULL},/*62*/
164 };
165 
166 /*
167 Caller and the rtw_cmd_thread23a can protect cmd_q by spin_lock.
168 No irqsave is necessary.
169 */
170 
rtw_init_cmd_priv23a(struct cmd_priv * pcmdpriv)171 int rtw_init_cmd_priv23a(struct cmd_priv *pcmdpriv)
172 {
173 	int res = _SUCCESS;
174 
175 	pcmdpriv->cmd_issued_cnt = 0;
176 	pcmdpriv->cmd_done_cnt = 0;
177 	pcmdpriv->rsp_cnt = 0;
178 
179 	pcmdpriv->wq = alloc_workqueue("rtl8723au_cmd", 0, 1);
180 	if (!pcmdpriv->wq)
181 		res = _FAIL;
182 
183 	return res;
184 }
185 
186 /* forward definition */
187 
188 static void rtw_irq_work(struct work_struct *work);
189 
rtw_init_evt_priv23a(struct evt_priv * pevtpriv)190 u32 rtw_init_evt_priv23a(struct evt_priv *pevtpriv)
191 {
192 	pevtpriv->wq = alloc_workqueue("rtl8723au_evt", 0, 1);
193 
194 	INIT_WORK(&pevtpriv->irq_wk, rtw_irq_work);
195 
196 	return _SUCCESS;
197 }
198 
rtw_free_evt_priv23a(struct evt_priv * pevtpriv)199 void rtw_free_evt_priv23a(struct evt_priv *pevtpriv)
200 {
201 	cancel_work_sync(&pevtpriv->irq_wk);
202 }
203 
rtw_cmd_filter(struct cmd_priv * pcmdpriv,struct cmd_obj * cmd_obj)204 static int rtw_cmd_filter(struct cmd_priv *pcmdpriv, struct cmd_obj *cmd_obj)
205 {
206 	/* set to true to allow enqueuing cmd when hw_init_completed is false */
207 	u8 bAllow = false;
208 
209 	if (cmd_obj->cmdcode == GEN_CMD_CODE(_SetChannelPlan))
210 		bAllow = true;
211 
212 	if (pcmdpriv->padapter->hw_init_completed == false && bAllow == false)
213 		return _FAIL;
214 	return _SUCCESS;
215 }
216 
217 static void rtw_cmd_work(struct work_struct *work);
218 
rtw_enqueue_cmd23a(struct cmd_priv * pcmdpriv,struct cmd_obj * cmd_obj)219 int rtw_enqueue_cmd23a(struct cmd_priv *pcmdpriv, struct cmd_obj *cmd_obj)
220 {
221 	int res = _FAIL;
222 
223 	if (!cmd_obj)
224 		goto exit;
225 
226 	cmd_obj->padapter = pcmdpriv->padapter;
227 
228 	res = rtw_cmd_filter(pcmdpriv, cmd_obj);
229 	if (res == _FAIL) {
230 		rtw_free_cmd_obj23a(cmd_obj);
231 		goto exit;
232 	}
233 
234 	INIT_WORK(&cmd_obj->work, rtw_cmd_work);
235 
236 	res = queue_work(pcmdpriv->wq, &cmd_obj->work);
237 
238 	if (!res) {
239 		printk(KERN_ERR "%s: Call to queue_work() failed\n", __func__);
240 		res = _FAIL;
241 	} else
242 		res = _SUCCESS;
243 exit:
244 
245 	return res;
246 }
247 
rtw_cmd_clr_isr23a(struct cmd_priv * pcmdpriv)248 void rtw_cmd_clr_isr23a(struct	cmd_priv *pcmdpriv)
249 {
250 	pcmdpriv->cmd_done_cnt++;
251 }
252 
rtw_free_cmd_obj23a(struct cmd_obj * pcmd)253 void rtw_free_cmd_obj23a(struct cmd_obj *pcmd)
254 {
255 
256 	if (pcmd->cmdcode != _JoinBss_CMD_ &&
257 	    pcmd->cmdcode != _CreateBss_CMD_) {
258 		/* free parmbuf in cmd_obj */
259 		kfree(pcmd->parmbuf);
260 	}
261 
262 	if (pcmd->rsp) {
263 		if (pcmd->rspsz != 0) {
264 			/* free rsp in cmd_obj */
265 			kfree(pcmd->rsp);
266 		}
267 	}
268 
269 	kfree(pcmd);
270 }
271 
rtw_cmd_work(struct work_struct * work)272 static void rtw_cmd_work(struct work_struct *work)
273 {
274 	int (*cmd_hdl)(struct rtw_adapter *padapter, const u8 *pbuf);
275 	void (*pcmd_callback)(struct rtw_adapter *dev, struct cmd_obj *pcmd);
276 	struct cmd_priv *pcmdpriv;
277 	struct cmd_obj *pcmd = container_of(work, struct cmd_obj, work);
278 
279 	pcmdpriv = &pcmd->padapter->cmdpriv;
280 
281 	if (rtw_cmd_filter(pcmdpriv, pcmd) == _FAIL) {
282 		pcmd->res = H2C_DROPPED;
283 		goto post_process;
284 	}
285 
286 	pcmdpriv->cmd_issued_cnt++;
287 
288 	pcmd->cmdsz = ALIGN(pcmd->cmdsz, 4);
289 
290 	if (pcmd->cmdcode < (sizeof(wlancmds)/sizeof(struct cmd_hdl))) {
291 		cmd_hdl = wlancmds[pcmd->cmdcode].h2cfuns;
292 
293 		if (cmd_hdl)
294 			pcmd->res = cmd_hdl(pcmd->padapter, pcmd->parmbuf);
295 		else
296 			pcmd->res = H2C_DROPPED;
297 	} else
298 		pcmd->res = H2C_PARAMETERS_ERROR;
299 
300 post_process:
301 	/* call callback function for post-processed */
302 	if (pcmd->cmdcode < (sizeof(rtw_cmd_callback) /
303 			     sizeof(struct _cmd_callback))) {
304 		pcmd_callback =	rtw_cmd_callback[pcmd->cmdcode].callback;
305 		if (!pcmd_callback) {
306 			RT_TRACE(_module_rtl871x_cmd_c_, _drv_info_,
307 				 ("mlme_cmd_hdl(): pcmd_callback = 0x%p, "
308 				  "cmdcode = 0x%x\n",
309 				  pcmd_callback, pcmd->cmdcode));
310 			rtw_free_cmd_obj23a(pcmd);
311 		} else {
312 			/* need consider that free cmd_obj in
313 			   rtw_cmd_callback */
314 			pcmd_callback(pcmd->padapter, pcmd);
315 		}
316 	} else {
317 		RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_,
318 			 ("%s: cmdcode = 0x%x callback not defined!\n",
319 			  __func__, pcmd->cmdcode));
320 		rtw_free_cmd_obj23a(pcmd);
321 	}
322 }
323 
324 
rtw_sitesurvey_cmd23a(struct rtw_adapter * padapter,struct cfg80211_ssid * ssid,int ssid_num,struct rtw_ieee80211_channel * ch,int ch_num)325 int rtw_sitesurvey_cmd23a(struct rtw_adapter *padapter,
326 			  struct cfg80211_ssid *ssid, int ssid_num,
327 			  struct rtw_ieee80211_channel *ch, int ch_num)
328 {
329 	int res = _FAIL;
330 	struct cmd_obj *ph2c;
331 	struct sitesurvey_parm *psurveyPara;
332 	struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
333 	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
334 
335 	if (check_fwstate(pmlmepriv, _FW_LINKED))
336 		rtw_lps_ctrl_wk_cmd23a(padapter, LPS_CTRL_SCAN, 1);
337 
338 	ph2c = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC);
339 	if (!ph2c)
340 		return _FAIL;
341 
342 	psurveyPara = kzalloc(sizeof(struct sitesurvey_parm), GFP_ATOMIC);
343 	if (!psurveyPara) {
344 		kfree(ph2c);
345 		return _FAIL;
346 	}
347 
348 	rtw_free_network_queue23a(padapter);
349 
350 	RT_TRACE(_module_rtl871x_cmd_c_, _drv_info_,
351 		 ("%s: flush network queue\n", __func__));
352 
353 	init_h2fwcmd_w_parm_no_rsp(ph2c, psurveyPara,
354 				   GEN_CMD_CODE(_SiteSurvey));
355 
356 	/* psurveyPara->bsslimit = 48; */
357 	psurveyPara->scan_mode = pmlmepriv->scan_mode;
358 
359 	/* prepare ssid list */
360 	if (ssid) {
361 		int i;
362 		for (i = 0; i < ssid_num && i < RTW_SSID_SCAN_AMOUNT; i++) {
363 			if (ssid[i].ssid_len) {
364 				memcpy(&psurveyPara->ssid[i], &ssid[i],
365 				       sizeof(struct cfg80211_ssid));
366 				psurveyPara->ssid_num++;
367 			}
368 		}
369 	}
370 
371 	/* prepare channel list */
372 	if (ch) {
373 		int i;
374 		for (i = 0; i < ch_num && i < RTW_CHANNEL_SCAN_AMOUNT; i++) {
375 			if (ch[i].hw_value &&
376 			    !(ch[i].flags & IEEE80211_CHAN_DISABLED)) {
377 				memcpy(&psurveyPara->ch[i], &ch[i],
378 				       sizeof(struct rtw_ieee80211_channel));
379 				psurveyPara->ch_num++;
380 			}
381 		}
382 	}
383 
384 	set_fwstate(pmlmepriv, _FW_UNDER_SURVEY);
385 
386 	res = rtw_enqueue_cmd23a(pcmdpriv, ph2c);
387 
388 	if (res == _SUCCESS) {
389 		mod_timer(&pmlmepriv->scan_to_timer, jiffies +
390 			  msecs_to_jiffies(SCANNING_TIMEOUT));
391 
392 		rtw_led_control(padapter, LED_CTL_SITE_SURVEY);
393 
394 		pmlmepriv->scan_interval = SCAN_INTERVAL;/*  30*2 sec = 60sec */
395 	} else
396 		_clr_fwstate_(pmlmepriv, _FW_UNDER_SURVEY);
397 
398 	return res;
399 }
400 
rtw_getbbrfreg_cmdrsp_callback23a(struct rtw_adapter * padapter,struct cmd_obj * pcmd)401 void rtw_getbbrfreg_cmdrsp_callback23a(struct rtw_adapter *padapter,
402 				       struct cmd_obj *pcmd)
403 {
404 	kfree(pcmd->parmbuf);
405 	kfree(pcmd);
406 }
407 
rtw_createbss_cmd23a(struct rtw_adapter * padapter)408 int rtw_createbss_cmd23a(struct rtw_adapter  *padapter)
409 {
410 	struct cmd_obj *pcmd;
411 	struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
412 	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
413 	struct wlan_bssid_ex *pdev_network;
414 	u8 res = _SUCCESS;
415 
416 	pdev_network = &padapter->registrypriv.dev_network;
417 
418 	rtw_led_control(padapter, LED_CTL_START_TO_LINK);
419 
420 	if (pmlmepriv->assoc_ssid.ssid_len == 0) {
421 		RT_TRACE(_module_rtl871x_cmd_c_, _drv_info_,
422 			 (" createbss for Any SSid:%s\n",
423 			  pmlmepriv->assoc_ssid.ssid));
424 	} else {
425 		RT_TRACE(_module_rtl871x_cmd_c_, _drv_info_,
426 			 (" createbss for SSid:%s\n",
427 			  pmlmepriv->assoc_ssid.ssid));
428 	}
429 
430 	pcmd = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC);
431 	if (!pcmd) {
432 		res = _FAIL;
433 		goto exit;
434 	}
435 
436 	pcmd->cmdcode = _CreateBss_CMD_;
437 	pcmd->parmbuf = (unsigned char *)pdev_network;
438 	pcmd->cmdsz = get_wlan_bssid_ex_sz(pdev_network);
439 	pcmd->rsp = NULL;
440 	pcmd->rspsz = 0;
441 
442 	pdev_network->Length = pcmd->cmdsz;
443 
444 	res = rtw_enqueue_cmd23a(pcmdpriv, pcmd);
445 
446 exit:
447 
448 	return res;
449 }
450 
rtw_joinbss_cmd23a(struct rtw_adapter * padapter,struct wlan_network * pnetwork)451 int rtw_joinbss_cmd23a(struct rtw_adapter *padapter,
452 		       struct wlan_network *pnetwork)
453 {
454 	int res = _SUCCESS;
455 	struct wlan_bssid_ex *psecnetwork;
456 	struct cmd_obj *pcmd;
457 	struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
458 	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
459 	struct security_priv *psecuritypriv = &padapter->securitypriv;
460 	struct registry_priv *pregistrypriv = &padapter->registrypriv;
461 	struct ht_priv *phtpriv = &pmlmepriv->htpriv;
462 	enum nl80211_iftype ifmode;
463 	struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
464 	struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
465 
466 	ifmode = pnetwork->network.ifmode;
467 
468 	rtw_led_control(padapter, LED_CTL_START_TO_LINK);
469 
470 	if (pmlmepriv->assoc_ssid.ssid_len == 0) {
471 		RT_TRACE(_module_rtl871x_cmd_c_, _drv_info_,
472 			 ("+Join cmd: Any SSid\n"));
473 	} else {
474 		RT_TRACE(_module_rtl871x_cmd_c_, _drv_notice_,
475 			 ("+Join cmd: SSid =[%s]\n",
476 			  pmlmepriv->assoc_ssid.ssid));
477 	}
478 
479 	pcmd = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC);
480 	if (!pcmd) {
481 		res = _FAIL;
482 		RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_,
483 			 ("rtw_joinbss_cmd23a: memory allocate for cmd_obj "
484 			  "fail!!!\n"));
485 		goto exit;
486 	}
487 
488 	/* for hidden ap to set fw_state here */
489 	if (!check_fwstate(pmlmepriv, WIFI_STATION_STATE|WIFI_ADHOC_STATE)) {
490 		switch (ifmode) {
491 		case NL80211_IFTYPE_ADHOC:
492 			set_fwstate(pmlmepriv, WIFI_ADHOC_STATE);
493 			break;
494 		case NL80211_IFTYPE_P2P_CLIENT:
495 		case NL80211_IFTYPE_STATION:
496 			set_fwstate(pmlmepriv, WIFI_STATION_STATE);
497 			break;
498 		default:
499 			break;
500 		}
501 	}
502 
503 	psecnetwork = &psecuritypriv->sec_bss;
504 	if (!psecnetwork) {
505 		kfree(pcmd);
506 		res = _FAIL;
507 
508 		RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_,
509 			 ("rtw_joinbss_cmd23a :psecnetwork == NULL!!!\n"));
510 
511 		goto exit;
512 	}
513 
514 	memset(psecnetwork, 0, sizeof(struct wlan_bssid_ex));
515 
516 	memcpy(psecnetwork, &pnetwork->network,
517 	       get_wlan_bssid_ex_sz(&pnetwork->network));
518 
519 	psecnetwork->IELength = 0;
520 	/*  Added by Albert 2009/02/18 */
521 	/*  If the the driver wants to use the bssid to create the
522 	 *  connection. If not,  we have to copy the connecting AP's
523 	 *  MAC address to it so that the driver just has the bssid
524 	 *  information for PMKIDList searching. */
525 
526 	if (pmlmepriv->assoc_by_bssid == false)
527 		ether_addr_copy(&pmlmepriv->assoc_bssid[0],
528 				&pnetwork->network.MacAddress[0]);
529 
530 	psecnetwork->IELength =
531 		rtw_restruct_sec_ie23a(padapter, &pnetwork->network.IEs[0],
532 				       &psecnetwork->IEs[0],
533 				       pnetwork->network.IELength);
534 
535 	pmlmepriv->qos_option = 0;
536 
537 	if (pregistrypriv->wmm_enable) {
538 		u32 tmp_len;
539 
540 		tmp_len = rtw_restruct_wmm_ie23a(padapter,
541 						 &pnetwork->network.IEs[0],
542 						 &psecnetwork->IEs[0],
543 						 pnetwork->network.IELength,
544 						 psecnetwork->IELength);
545 
546 		if (psecnetwork->IELength != tmp_len) {
547 			psecnetwork->IELength = tmp_len;
548 			/* There is WMM IE in this corresp. beacon */
549 			pmlmepriv->qos_option = 1;
550 		} else {
551 			/* There is no WMM IE in this corresp. beacon */
552 			pmlmepriv->qos_option = 0;
553 		}
554 	}
555 
556 	phtpriv->ht_option = false;
557 	if (pregistrypriv->ht_enable) {
558 		u32 algo = padapter->securitypriv.dot11PrivacyAlgrthm;
559 		/*	Added by Albert 2010/06/23 */
560 		/*	For the WEP mode, we will use the bg mode to do
561 			the connection to avoid some IOT issue. */
562 		/*	Especially for Realtek 8192u SoftAP. */
563 		if (algo != WLAN_CIPHER_SUITE_WEP40 &&
564 		    algo != WLAN_CIPHER_SUITE_WEP104 &&
565 		    algo != WLAN_CIPHER_SUITE_TKIP) {
566 			/* rtw_restructure_ht_ie23a */
567 			rtw_restructure_ht_ie23a(padapter,
568 						 &pnetwork->network.IEs[0],
569 						 &psecnetwork->IEs[0],
570 						 pnetwork->network.IELength,
571 						 &psecnetwork->IELength);
572 		}
573 	}
574 
575 	pmlmeinfo->assoc_AP_vendor =
576 		check_assoc_AP23a(pnetwork->network.IEs,
577 				  pnetwork->network.IELength);
578 
579 	if (pmlmeinfo->assoc_AP_vendor == HT_IOT_PEER_TENDA)
580 		padapter->pwrctrlpriv.smart_ps = 0;
581 	else
582 		padapter->pwrctrlpriv.smart_ps =
583 			padapter->registrypriv.smart_ps;
584 
585 	DBG_8723A("%s: smart_ps =%d\n", __func__,
586 		  padapter->pwrctrlpriv.smart_ps);
587 
588 	/* get cmdsz before endian conversion */
589 	pcmd->cmdsz = get_wlan_bssid_ex_sz(psecnetwork);
590 
591 	pcmd->cmdcode = _JoinBss_CMD_;/* GEN_CMD_CODE(_JoinBss) */
592 	pcmd->parmbuf = (unsigned char *)psecnetwork;
593 	pcmd->rsp = NULL;
594 	pcmd->rspsz = 0;
595 
596 	res = rtw_enqueue_cmd23a(pcmdpriv, pcmd);
597 exit:
598 
599 	return res;
600 }
601 
rtw_disassoc_cmd23a(struct rtw_adapter * padapter,u32 deauth_timeout_ms,bool enqueue)602 int rtw_disassoc_cmd23a(struct rtw_adapter*padapter, u32 deauth_timeout_ms,
603 			bool enqueue)
604 {
605 	struct cmd_obj *cmdobj = NULL;
606 	struct disconnect_parm *param = NULL;
607 	struct cmd_priv *cmdpriv = &padapter->cmdpriv;
608 	int res = _SUCCESS;
609 
610 	RT_TRACE(_module_rtl871x_cmd_c_, _drv_notice_,
611 		 ("+rtw_disassoc_cmd23a\n"));
612 
613 	/* prepare cmd parameter */
614 	param = kzalloc(sizeof(*param), GFP_ATOMIC);
615 	if (param == NULL) {
616 		res = _FAIL;
617 		goto exit;
618 	}
619 	param->deauth_timeout_ms = deauth_timeout_ms;
620 
621 	if (enqueue) {
622 		/* need enqueue, prepare cmd_obj and enqueue */
623 		cmdobj = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC);
624 		if (!cmdobj) {
625 			res = _FAIL;
626 			kfree(param);
627 			goto exit;
628 		}
629 		init_h2fwcmd_w_parm_no_rsp(cmdobj, param, _DisConnect_CMD_);
630 		res = rtw_enqueue_cmd23a(cmdpriv, cmdobj);
631 	} else {
632 		/* no need to enqueue, do the cmd hdl directly and
633 		   free cmd parameter */
634 		if (H2C_SUCCESS != disconnect_hdl23a(padapter, (u8 *)param))
635 			res = _FAIL;
636 		kfree(param);
637 	}
638 
639 exit:
640 	return res;
641 }
642 
rtw_setopmode_cmd23a(struct rtw_adapter * padapter,enum nl80211_iftype ifmode)643 int rtw_setopmode_cmd23a(struct rtw_adapter *padapter,
644 			 enum nl80211_iftype ifmode)
645 {
646 	struct	cmd_obj *ph2c;
647 	struct	setopmode_parm *psetop;
648 	struct	cmd_priv   *pcmdpriv = &padapter->cmdpriv;
649 	int res = _SUCCESS;
650 
651 	ph2c = kzalloc(sizeof(struct cmd_obj), GFP_KERNEL);
652 	if (!ph2c) {
653 		res = false;
654 		goto exit;
655 	}
656 	psetop = kzalloc(sizeof(struct setopmode_parm), GFP_KERNEL);
657 
658 	if (!psetop) {
659 		kfree(ph2c);
660 		res = false;
661 		goto exit;
662 	}
663 
664 	init_h2fwcmd_w_parm_no_rsp(ph2c, psetop, _SetOpMode_CMD_);
665 	psetop->mode = ifmode;
666 
667 	res = rtw_enqueue_cmd23a(pcmdpriv, ph2c);
668 exit:
669 	return res;
670 }
671 
rtw_setstakey_cmd23a(struct rtw_adapter * padapter,u8 * psta,u8 unicast_key)672 int rtw_setstakey_cmd23a(struct rtw_adapter *padapter, u8 *psta, u8 unicast_key)
673 {
674 	struct cmd_obj *ph2c;
675 	struct set_stakey_parm *psetstakey_para;
676 	struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
677 	struct set_stakey_rsp *psetstakey_rsp = NULL;
678 	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
679 	struct security_priv *psecuritypriv = &padapter->securitypriv;
680 	struct sta_info *sta = (struct sta_info *)psta;
681 	int res = _SUCCESS;
682 
683 	ph2c = kzalloc(sizeof(struct cmd_obj), GFP_KERNEL);
684 	if (!ph2c) {
685 		res = _FAIL;
686 		goto exit;
687 	}
688 
689 	psetstakey_para = kzalloc(sizeof(struct set_stakey_parm), GFP_KERNEL);
690 	if (!psetstakey_para) {
691 		kfree(ph2c);
692 		res = _FAIL;
693 		goto exit;
694 	}
695 
696 	psetstakey_rsp = kzalloc(sizeof(struct set_stakey_rsp), GFP_KERNEL);
697 	if (!psetstakey_rsp) {
698 		kfree(ph2c);
699 		kfree(psetstakey_para);
700 		res = _FAIL;
701 		goto exit;
702 	}
703 
704 	init_h2fwcmd_w_parm_no_rsp(ph2c, psetstakey_para, _SetStaKey_CMD_);
705 	ph2c->rsp = (u8 *) psetstakey_rsp;
706 	ph2c->rspsz = sizeof(struct set_stakey_rsp);
707 
708 	ether_addr_copy(psetstakey_para->addr, sta->hwaddr);
709 
710 	if (check_fwstate(pmlmepriv, WIFI_STATION_STATE)) {
711 		psetstakey_para->algorithm =
712 			(unsigned char)psecuritypriv->dot11PrivacyAlgrthm;
713 	} else {
714 		GET_ENCRY_ALGO(psecuritypriv, sta, psetstakey_para->algorithm,
715 			       false);
716 	}
717 
718 	if (unicast_key == true) {
719 		memcpy(&psetstakey_para->key, &sta->dot118021x_UncstKey, 16);
720 	} else {
721 		int idx = psecuritypriv->dot118021XGrpKeyid;
722 		memcpy(&psetstakey_para->key,
723 		       &psecuritypriv->dot118021XGrpKey[idx].skey, 16);
724 	}
725 
726 	/* jeff: set this because at least sw key is ready */
727 	padapter->securitypriv.busetkipkey = 1;
728 
729 	res = rtw_enqueue_cmd23a(pcmdpriv, ph2c);
730 
731 exit:
732 
733 	return res;
734 }
735 
rtw_clearstakey_cmd23a(struct rtw_adapter * padapter,u8 * psta,u8 entry,u8 enqueue)736 int rtw_clearstakey_cmd23a(struct rtw_adapter *padapter, u8 *psta, u8 entry,
737 			   u8 enqueue)
738 {
739 	struct cmd_obj *ph2c;
740 	struct set_stakey_parm *psetstakey_para;
741 	struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
742 	struct set_stakey_rsp *psetstakey_rsp = NULL;
743 	struct sta_info *sta = (struct sta_info *)psta;
744 	int res = _SUCCESS;
745 
746 	if (!enqueue) {
747 		clear_cam_entry23a(padapter, entry);
748 	} else {
749 		ph2c = kzalloc(sizeof(struct cmd_obj), GFP_KERNEL);
750 		if (!ph2c) {
751 			res = _FAIL;
752 			goto exit;
753 		}
754 
755 		psetstakey_para = kzalloc(sizeof(struct set_stakey_parm),
756 					  GFP_KERNEL);
757 		if (!psetstakey_para) {
758 			kfree(ph2c);
759 			res = _FAIL;
760 			goto exit;
761 		}
762 
763 		psetstakey_rsp = kzalloc(sizeof(struct set_stakey_rsp),
764 					 GFP_KERNEL);
765 		if (!psetstakey_rsp) {
766 			kfree(ph2c);
767 			kfree(psetstakey_para);
768 			res = _FAIL;
769 			goto exit;
770 		}
771 
772 		init_h2fwcmd_w_parm_no_rsp(ph2c, psetstakey_para,
773 					   _SetStaKey_CMD_);
774 		ph2c->rsp = (u8 *) psetstakey_rsp;
775 		ph2c->rspsz = sizeof(struct set_stakey_rsp);
776 
777 		ether_addr_copy(psetstakey_para->addr, sta->hwaddr);
778 
779 		psetstakey_para->algorithm = 0;
780 
781 		psetstakey_para->id = entry;
782 
783 		res = rtw_enqueue_cmd23a(pcmdpriv, ph2c);
784 	}
785 exit:
786 	return res;
787 }
788 
rtw_addbareq_cmd23a(struct rtw_adapter * padapter,u8 tid,u8 * addr)789 int rtw_addbareq_cmd23a(struct rtw_adapter*padapter, u8 tid, u8 *addr)
790 {
791 	struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
792 	struct cmd_obj *ph2c;
793 	struct addBaReq_parm *paddbareq_parm;
794 	int res = _SUCCESS;
795 
796 	if (tid >= MAXTID) {
797 		res = _FAIL;
798 		goto exit;
799 	}
800 
801 	ph2c = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC);
802 	if (!ph2c) {
803 		res = _FAIL;
804 		goto exit;
805 	}
806 
807 	paddbareq_parm = kzalloc(sizeof(struct addBaReq_parm), GFP_ATOMIC);
808 	if (!paddbareq_parm) {
809 		kfree(ph2c);
810 		res = _FAIL;
811 		goto exit;
812 	}
813 
814 	paddbareq_parm->tid = tid;
815 	ether_addr_copy(paddbareq_parm->addr, addr);
816 
817 	init_h2fwcmd_w_parm_no_rsp(ph2c, paddbareq_parm,
818 				   GEN_CMD_CODE(_AddBAReq));
819 
820 	res = rtw_enqueue_cmd23a(pcmdpriv, ph2c);
821 exit:
822 	return res;
823 }
824 
rtw_dynamic_chk_wk_cmd23a(struct rtw_adapter * padapter)825 int rtw_dynamic_chk_wk_cmd23a(struct rtw_adapter*padapter)
826 {
827 	struct cmd_obj *ph2c;
828 	struct drvextra_cmd_parm *pdrvextra_cmd_parm;
829 	struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
830 	int res = _SUCCESS;
831 
832 	ph2c = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC);
833 	if (!ph2c) {
834 		res = _FAIL;
835 		goto exit;
836 	}
837 
838 	pdrvextra_cmd_parm = kzalloc(sizeof(*pdrvextra_cmd_parm), GFP_ATOMIC);
839 	if (!pdrvextra_cmd_parm) {
840 		kfree(ph2c);
841 		res = _FAIL;
842 		goto exit;
843 	}
844 
845 	pdrvextra_cmd_parm->ec_id = DYNAMIC_CHK_WK_CID;
846 	pdrvextra_cmd_parm->type_size = 0;
847 	pdrvextra_cmd_parm->pbuf = (u8 *)padapter;
848 
849 	init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm,
850 				   GEN_CMD_CODE(_Set_Drv_Extra));
851 
852 	res = rtw_enqueue_cmd23a(pcmdpriv, ph2c);
853 exit:
854 
855 	return res;
856 }
857 
858 /*
859  * This is only ever called from on_action_spct23a_ch_switch () which isn't
860  * called from anywhere itself
861  */
rtw_set_ch_cmd23a(struct rtw_adapter * padapter,u8 ch,u8 bw,u8 ch_offset,u8 enqueue)862 int rtw_set_ch_cmd23a(struct rtw_adapter*padapter, u8 ch, u8 bw, u8 ch_offset,
863 		      u8 enqueue)
864 {
865 	struct cmd_obj *pcmdobj;
866 	struct set_ch_parm *set_ch_parm;
867 	struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
868 	int res = _SUCCESS;
869 
870 	DBG_8723A("%s(%s): ch:%u, bw:%u, ch_offset:%u\n", __func__,
871 		  padapter->pnetdev->name, ch, bw, ch_offset);
872 
873 	/* check input parameter */
874 
875 	/* prepare cmd parameter */
876 	set_ch_parm = kzalloc(sizeof(*set_ch_parm), GFP_KERNEL);
877 	if (!set_ch_parm) {
878 		res = _FAIL;
879 		goto exit;
880 	}
881 	set_ch_parm->ch = ch;
882 	set_ch_parm->bw = bw;
883 	set_ch_parm->ch_offset = ch_offset;
884 
885 	if (enqueue) {
886 		/* need enqueue, prepare cmd_obj and enqueue */
887 		pcmdobj = kzalloc(sizeof(struct cmd_obj), GFP_KERNEL);
888 		if (!pcmdobj) {
889 			kfree(set_ch_parm);
890 			res = _FAIL;
891 			goto exit;
892 		}
893 
894 		init_h2fwcmd_w_parm_no_rsp(pcmdobj, set_ch_parm,
895 					   GEN_CMD_CODE(_SetChannel));
896 		res = rtw_enqueue_cmd23a(pcmdpriv, pcmdobj);
897 	} else {
898 		/* no need to enqueue, do the cmd hdl directly and
899 		   free cmd parameter */
900 		if (H2C_SUCCESS != set_ch_hdl23a(padapter, (u8 *)set_ch_parm))
901 			res = _FAIL;
902 
903 		kfree(set_ch_parm);
904 	}
905 
906 	/* do something based on res... */
907 exit:
908 
909 	DBG_8723A("%s(%s): res:%u\n", __func__, padapter->pnetdev->name, res);
910 
911 	return res;
912 }
913 
traffic_status_watchdog(struct rtw_adapter * padapter)914 static void traffic_status_watchdog(struct rtw_adapter *padapter)
915 {
916 	u8 bEnterPS;
917 	u8 bBusyTraffic = false, bTxBusyTraffic = false, bRxBusyTraffic = false;
918 	u8 bHigherBusyTraffic = false, bHigherBusyRxTraffic = false;
919 	u8 bHigherBusyTxTraffic = false;
920 	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
921 	int BusyThreshold = 100;
922 	/*  */
923 	/*  Determine if our traffic is busy now */
924 	/*  */
925 	if (check_fwstate(pmlmepriv, _FW_LINKED)) {
926 		if (rtl8723a_BT_coexist(padapter))
927 			BusyThreshold = 50;
928 		else if (pmlmepriv->LinkDetectInfo.bBusyTraffic)
929 			BusyThreshold = 75;
930 		/*  if we raise bBusyTraffic in last watchdog, using
931 		    lower threshold. */
932 		if (pmlmepriv->LinkDetectInfo.NumRxOkInPeriod > BusyThreshold ||
933 		    pmlmepriv->LinkDetectInfo.NumTxOkInPeriod > BusyThreshold) {
934 			bBusyTraffic = true;
935 
936 			if (pmlmepriv->LinkDetectInfo.NumRxOkInPeriod >
937 			    pmlmepriv->LinkDetectInfo.NumTxOkInPeriod)
938 				bRxBusyTraffic = true;
939 			else
940 				bTxBusyTraffic = true;
941 		}
942 
943 		/*  Higher Tx/Rx data. */
944 		if (pmlmepriv->LinkDetectInfo.NumRxOkInPeriod > 4000 ||
945 		    pmlmepriv->LinkDetectInfo.NumTxOkInPeriod > 4000) {
946 			bHigherBusyTraffic = true;
947 
948 			if (pmlmepriv->LinkDetectInfo.NumRxOkInPeriod >
949 			    pmlmepriv->LinkDetectInfo.NumTxOkInPeriod)
950 				bHigherBusyRxTraffic = true;
951 			else
952 				bHigherBusyTxTraffic = true;
953 		}
954 
955 		if (!rtl8723a_BT_coexist(padapter) ||
956 		    !rtl8723a_BT_using_antenna_1(padapter)) {
957 		/*  check traffic for  powersaving. */
958 			if (((pmlmepriv->LinkDetectInfo.NumRxUnicastOkInPeriod +
959 			      pmlmepriv->LinkDetectInfo.NumTxOkInPeriod) > 8) ||
960 			    pmlmepriv->LinkDetectInfo.NumRxUnicastOkInPeriod >2)
961 				bEnterPS = false;
962 			else
963 				bEnterPS = true;
964 
965 			/*  LeisurePS only work in infra mode. */
966 			if (bEnterPS)
967 				LPS_Enter23a(padapter);
968 			else
969 				LPS_Leave23a(padapter);
970 		}
971 	} else
972 		LPS_Leave23a(padapter);
973 
974 	pmlmepriv->LinkDetectInfo.NumRxOkInPeriod = 0;
975 	pmlmepriv->LinkDetectInfo.NumTxOkInPeriod = 0;
976 	pmlmepriv->LinkDetectInfo.NumRxUnicastOkInPeriod = 0;
977 	pmlmepriv->LinkDetectInfo.bBusyTraffic = bBusyTraffic;
978 	pmlmepriv->LinkDetectInfo.bTxBusyTraffic = bTxBusyTraffic;
979 	pmlmepriv->LinkDetectInfo.bRxBusyTraffic = bRxBusyTraffic;
980 	pmlmepriv->LinkDetectInfo.bHigherBusyTraffic = bHigherBusyTraffic;
981 	pmlmepriv->LinkDetectInfo.bHigherBusyRxTraffic = bHigherBusyRxTraffic;
982 	pmlmepriv->LinkDetectInfo.bHigherBusyTxTraffic = bHigherBusyTxTraffic;
983 }
984 
dynamic_chk_wk_hdl(struct rtw_adapter * padapter,u8 * pbuf,int sz)985 static void dynamic_chk_wk_hdl(struct rtw_adapter *padapter, u8 *pbuf, int sz)
986 {
987 	struct mlme_priv *pmlmepriv;
988 
989 	padapter = (struct rtw_adapter *)pbuf;
990 	pmlmepriv = &padapter->mlmepriv;
991 
992 #ifdef CONFIG_8723AU_AP_MODE
993 	if (check_fwstate(pmlmepriv, WIFI_AP_STATE))
994 		expire_timeout_chk23a(padapter);
995 #endif
996 
997 	rtl8723a_sreset_xmit_status_check(padapter);
998 
999 	linked_status_chk23a(padapter);
1000 	traffic_status_watchdog(padapter);
1001 
1002 	rtl8723a_HalDmWatchDog(padapter);
1003 
1004 	/*  */
1005 	/*  BT-Coexist */
1006 	/*  */
1007 	rtl8723a_BT_do_coexist(padapter);
1008 }
1009 
lps_ctrl_wk_hdl(struct rtw_adapter * padapter,u8 lps_ctrl_type)1010 static void lps_ctrl_wk_hdl(struct rtw_adapter *padapter, u8 lps_ctrl_type)
1011 {
1012 	struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv;
1013 	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1014 	u8 mstatus;
1015 
1016 	if (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) ||
1017 	    check_fwstate(pmlmepriv, WIFI_ADHOC_STATE))
1018 		return;
1019 
1020 	switch (lps_ctrl_type)
1021 	{
1022 		case LPS_CTRL_SCAN:
1023 			rtl8723a_BT_wifiscan_notify(padapter, true);
1024 			if (!rtl8723a_BT_using_antenna_1(padapter)) {
1025 				if (check_fwstate(pmlmepriv, _FW_LINKED))
1026 					LPS_Leave23a(padapter);
1027 			}
1028 			break;
1029 		case LPS_CTRL_JOINBSS:
1030 			LPS_Leave23a(padapter);
1031 			break;
1032 		case LPS_CTRL_CONNECT:
1033 			mstatus = 1;/* connect */
1034 			/*  Reset LPS Setting */
1035 			padapter->pwrctrlpriv.LpsIdleCount = 0;
1036 			rtl8723a_set_FwJoinBssReport_cmd(padapter, 1);
1037 			rtl8723a_BT_mediastatus_notify(padapter, mstatus);
1038 			break;
1039 		case LPS_CTRL_DISCONNECT:
1040 			mstatus = 0;/* disconnect */
1041 			rtl8723a_BT_mediastatus_notify(padapter, mstatus);
1042 			if (!rtl8723a_BT_using_antenna_1(padapter))
1043 				LPS_Leave23a(padapter);
1044 			rtl8723a_set_FwJoinBssReport_cmd(padapter, 0);
1045 			break;
1046 		case LPS_CTRL_SPECIAL_PACKET:
1047 			pwrpriv->DelayLPSLastTimeStamp = jiffies;
1048 			rtl8723a_BT_specialpacket_notify(padapter);
1049 			if (!rtl8723a_BT_using_antenna_1(padapter))
1050 				LPS_Leave23a(padapter);
1051 			break;
1052 		case LPS_CTRL_LEAVE:
1053 			rtl8723a_BT_lps_leave(padapter);
1054 			if (!rtl8723a_BT_using_antenna_1(padapter))
1055 				LPS_Leave23a(padapter);
1056 			break;
1057 
1058 		default:
1059 			break;
1060 	}
1061 }
1062 
rtw_lps_ctrl_wk_cmd23a(struct rtw_adapter * padapter,u8 lps_ctrl_type,u8 enqueue)1063 int rtw_lps_ctrl_wk_cmd23a(struct rtw_adapter *padapter,
1064 			   u8 lps_ctrl_type, u8 enqueue)
1065 {
1066 	struct cmd_obj *ph2c;
1067 	struct drvextra_cmd_parm *pdrvextra_cmd_parm;
1068 	struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
1069 	int res = _SUCCESS;
1070 
1071 	if (enqueue) {
1072 		ph2c = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC);
1073 		if (!ph2c) {
1074 			res = _FAIL;
1075 			goto exit;
1076 		}
1077 
1078 		pdrvextra_cmd_parm = kzalloc(sizeof(struct drvextra_cmd_parm),
1079 					     GFP_ATOMIC);
1080 		if (!pdrvextra_cmd_parm) {
1081 			kfree(ph2c);
1082 			res = _FAIL;
1083 			goto exit;
1084 		}
1085 
1086 		pdrvextra_cmd_parm->ec_id = LPS_CTRL_WK_CID;
1087 		pdrvextra_cmd_parm->type_size = lps_ctrl_type;
1088 		pdrvextra_cmd_parm->pbuf = NULL;
1089 
1090 		init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm,
1091 					   GEN_CMD_CODE(_Set_Drv_Extra));
1092 
1093 		res = rtw_enqueue_cmd23a(pcmdpriv, ph2c);
1094 	} else
1095 		lps_ctrl_wk_hdl(padapter, lps_ctrl_type);
1096 exit:
1097 
1098 	return res;
1099 }
1100 
rtw_ps_cmd23a(struct rtw_adapter * padapter)1101 int rtw_ps_cmd23a(struct rtw_adapter*padapter)
1102 {
1103 	struct cmd_obj *ppscmd;
1104 	struct drvextra_cmd_parm *pdrvextra_cmd_parm;
1105 	struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
1106 	int res = _SUCCESS;
1107 
1108 	ppscmd = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC);
1109 	if (!ppscmd) {
1110 		res = _FAIL;
1111 		goto exit;
1112 	}
1113 
1114 	pdrvextra_cmd_parm = kzalloc(sizeof(struct drvextra_cmd_parm),
1115 				     GFP_ATOMIC);
1116 	if (!pdrvextra_cmd_parm) {
1117 		kfree(ppscmd);
1118 		res = _FAIL;
1119 		goto exit;
1120 	}
1121 
1122 	pdrvextra_cmd_parm->ec_id = POWER_SAVING_CTRL_WK_CID;
1123 	pdrvextra_cmd_parm->pbuf = NULL;
1124 	init_h2fwcmd_w_parm_no_rsp(ppscmd, pdrvextra_cmd_parm,
1125 				   GEN_CMD_CODE(_Set_Drv_Extra));
1126 
1127 	res = rtw_enqueue_cmd23a(pcmdpriv, ppscmd);
1128 exit:
1129 
1130 	return res;
1131 }
1132 
1133 #ifdef CONFIG_8723AU_AP_MODE
1134 
rtw_chk_hi_queue_hdl(struct rtw_adapter * padapter)1135 static void rtw_chk_hi_queue_hdl(struct rtw_adapter *padapter)
1136 {
1137 	int cnt = 0;
1138 	struct sta_info *psta_bmc;
1139 	struct sta_priv *pstapriv = &padapter->stapriv;
1140 
1141 	psta_bmc = rtw_get_bcmc_stainfo23a(padapter);
1142 	if (!psta_bmc)
1143 		return;
1144 
1145 	if (psta_bmc->sleepq_len == 0) {
1146 		bool val;
1147 
1148 		val = rtl8723a_chk_hi_queue_empty(padapter);
1149 
1150 		while (val == false) {
1151 			msleep(100);
1152 
1153 			cnt++;
1154 
1155 			if (cnt>10)
1156 				break;
1157 
1158 			val = rtl8723a_chk_hi_queue_empty(padapter);
1159 		}
1160 
1161 		if (cnt <= 10) {
1162 			pstapriv->tim_bitmap &= ~BIT(0);
1163 			pstapriv->sta_dz_bitmap &= ~BIT(0);
1164 
1165 			update_beacon23a(padapter, WLAN_EID_TIM, NULL, false);
1166 		} else /* re check again */
1167 			rtw_chk_hi_queue_cmd23a(padapter);
1168 	}
1169 }
1170 
rtw_chk_hi_queue_cmd23a(struct rtw_adapter * padapter)1171 int rtw_chk_hi_queue_cmd23a(struct rtw_adapter*padapter)
1172 {
1173 	struct cmd_obj *ph2c;
1174 	struct drvextra_cmd_parm *pdrvextra_cmd_parm;
1175 	struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
1176 	int res = _SUCCESS;
1177 
1178 	ph2c = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC);
1179 	if (!ph2c) {
1180 		res = _FAIL;
1181 		goto exit;
1182 	}
1183 
1184 	pdrvextra_cmd_parm = kzalloc(sizeof(struct drvextra_cmd_parm),
1185 				     GFP_ATOMIC);
1186 	if (!pdrvextra_cmd_parm) {
1187 		kfree(ph2c);
1188 		res = _FAIL;
1189 		goto exit;
1190 	}
1191 
1192 	pdrvextra_cmd_parm->ec_id = CHECK_HIQ_WK_CID;
1193 	pdrvextra_cmd_parm->type_size = 0;
1194 	pdrvextra_cmd_parm->pbuf = NULL;
1195 
1196 	init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm,
1197 				   GEN_CMD_CODE(_Set_Drv_Extra));
1198 
1199 	res = rtw_enqueue_cmd23a(pcmdpriv, ph2c);
1200 exit:
1201 
1202 	return res;
1203 }
1204 #endif
1205 
rtw_c2h_wk_cmd23a(struct rtw_adapter * padapter,u8 * c2h_evt)1206 int rtw_c2h_wk_cmd23a(struct rtw_adapter *padapter, u8 *c2h_evt)
1207 {
1208 	struct cmd_obj *ph2c;
1209 	struct drvextra_cmd_parm *pdrvextra_cmd_parm;
1210 	struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
1211 	int res = _SUCCESS;
1212 
1213 	ph2c = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC);
1214 	if (!ph2c) {
1215 		res = _FAIL;
1216 		goto exit;
1217 	}
1218 
1219 	pdrvextra_cmd_parm = kzalloc(sizeof(struct drvextra_cmd_parm),
1220 				     GFP_ATOMIC);
1221 	if (!pdrvextra_cmd_parm) {
1222 		kfree(ph2c);
1223 		res = _FAIL;
1224 		goto exit;
1225 	}
1226 
1227 	pdrvextra_cmd_parm->ec_id = C2H_WK_CID;
1228 	pdrvextra_cmd_parm->type_size = c2h_evt?16:0;
1229 	pdrvextra_cmd_parm->pbuf = c2h_evt;
1230 
1231 	init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm,
1232 				   GEN_CMD_CODE(_Set_Drv_Extra));
1233 
1234 	res = rtw_enqueue_cmd23a(pcmdpriv, ph2c);
1235 
1236 exit:
1237 
1238 	return res;
1239 }
1240 
c2h_evt_hdl(struct rtw_adapter * adapter,struct c2h_evt_hdr * c2h_evt)1241 static int c2h_evt_hdl(struct rtw_adapter *adapter, struct c2h_evt_hdr *c2h_evt)
1242 {
1243 	int ret = _FAIL;
1244 	u8 buf[16];
1245 
1246 	if (!c2h_evt) {
1247 		/* No c2h event in cmd_obj, read c2h event before handling*/
1248 		if (c2h_evt_read23a(adapter, buf) == _SUCCESS) {
1249 			c2h_evt = (struct c2h_evt_hdr *)buf;
1250 
1251 			ret = c2h_handler_8723a(adapter, c2h_evt);
1252 		}
1253 	} else
1254 		ret = c2h_handler_8723a(adapter, c2h_evt);
1255 
1256 	return ret;
1257 }
1258 
rtw_irq_work(struct work_struct * work)1259 static void rtw_irq_work(struct work_struct *work)
1260 {
1261 	struct evt_priv *evtpriv;
1262 	struct rtw_adapter *adapter;
1263 
1264 	evtpriv = container_of(work, struct evt_priv, irq_wk);
1265 	adapter = container_of(evtpriv, struct rtw_adapter, evtpriv);
1266 
1267 	c2h_evt_clear23a(adapter);
1268 }
1269 
rtw_evt_work(struct work_struct * work)1270 void rtw_evt_work(struct work_struct *work)
1271 {
1272 	struct evt_work *ework;
1273 	struct rtw_adapter *adapter;
1274 
1275 	ework = container_of(work, struct evt_work, work);
1276 	adapter = ework->adapter;
1277 
1278 	c2h_evt_clear23a(adapter);
1279 
1280 	if (!c2h_evt_exist(&ework->u.c2h_evt)) {
1281 		kfree(ework);
1282 		return;
1283 	}
1284 
1285 	if (c2h_id_filter_ccx_8723a(ework->u.c2h_evt.id) == true) {
1286 		/* Handle CCX report here */
1287 		c2h_handler_8723a(adapter, &ework->u.c2h_evt);
1288 		kfree(ework);
1289 	} else {
1290 		/*
1291 		 * Enqueue into cmd_thread for others.
1292 		 * ework will be turned into a c2h_evt and freed once it
1293 		 * has been consumed.
1294 		 */
1295 		rtw_c2h_wk_cmd23a(adapter, (u8 *)&ework->u.c2h_evt);
1296 	}
1297 }
1298 
rtw_drvextra_cmd_hdl23a(struct rtw_adapter * padapter,const u8 * pbuf)1299 int rtw_drvextra_cmd_hdl23a(struct rtw_adapter *padapter, const u8 *pbuf)
1300 {
1301 	const struct drvextra_cmd_parm *pdrvextra_cmd;
1302 
1303 	if (!pbuf)
1304 		return H2C_PARAMETERS_ERROR;
1305 
1306 	pdrvextra_cmd = (struct drvextra_cmd_parm *)pbuf;
1307 
1308 	switch (pdrvextra_cmd->ec_id)
1309 	{
1310 	case DYNAMIC_CHK_WK_CID:
1311 		dynamic_chk_wk_hdl(padapter, pdrvextra_cmd->pbuf,
1312 				   pdrvextra_cmd->type_size);
1313 		break;
1314 	case POWER_SAVING_CTRL_WK_CID:
1315 		rtw_ps_processor23a(padapter);
1316 		break;
1317 	case LPS_CTRL_WK_CID:
1318 		lps_ctrl_wk_hdl(padapter, (u8)pdrvextra_cmd->type_size);
1319 		break;
1320 #ifdef CONFIG_8723AU_AP_MODE
1321 	case CHECK_HIQ_WK_CID:
1322 		rtw_chk_hi_queue_hdl(padapter);
1323 		break;
1324 #endif /* CONFIG_8723AU_AP_MODE */
1325 	case C2H_WK_CID:
1326 		c2h_evt_hdl(padapter,
1327 			    (struct c2h_evt_hdr *)pdrvextra_cmd->pbuf);
1328 		break;
1329 
1330 	default:
1331 		break;
1332 	}
1333 
1334 	if (pdrvextra_cmd->pbuf && (pdrvextra_cmd->type_size > 0)) {
1335 		kfree(pdrvextra_cmd->pbuf);
1336 		/*
1337 		 * No need to set pdrvextra_cmd->pbuf = NULL as we were
1338 		 * operating on a copy of the original pcmd->parmbuf
1339 		 * created in rtw_cmd_work().
1340 		 */
1341 	}
1342 
1343 	return H2C_SUCCESS;
1344 }
1345 
rtw_survey_cmd_callback23a(struct rtw_adapter * padapter,struct cmd_obj * pcmd)1346 void rtw_survey_cmd_callback23a(struct rtw_adapter *padapter,
1347 				struct cmd_obj *pcmd)
1348 {
1349 	struct	mlme_priv *pmlmepriv = &padapter->mlmepriv;
1350 
1351 	if (pcmd->res == H2C_DROPPED) {
1352 		/* TODO: cancel timer and do timeout handler directly... */
1353 		/* need to make timeout handlerOS independent */
1354 		mod_timer(&pmlmepriv->scan_to_timer,
1355 			  jiffies + msecs_to_jiffies(1));
1356 	} else if (pcmd->res != H2C_SUCCESS) {
1357 		mod_timer(&pmlmepriv->scan_to_timer,
1358 			  jiffies + msecs_to_jiffies(1));
1359 		RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_,
1360 			 ("\n ********Error: MgntActrtw_set_802_11_bssid23a_"
1361 			  "LIST_SCAN Fail ************\n\n."));
1362 	}
1363 
1364 	/*  free cmd */
1365 	rtw_free_cmd_obj23a(pcmd);
1366 }
1367 
rtw_disassoc_cmd23a_callback(struct rtw_adapter * padapter,struct cmd_obj * pcmd)1368 void rtw_disassoc_cmd23a_callback(struct rtw_adapter *padapter,
1369 				  struct cmd_obj *pcmd)
1370 {
1371 	struct	mlme_priv *pmlmepriv = &padapter->mlmepriv;
1372 
1373 	if (pcmd->res != H2C_SUCCESS) {
1374 		spin_lock_bh(&pmlmepriv->lock);
1375 		set_fwstate(pmlmepriv, _FW_LINKED);
1376 		spin_unlock_bh(&pmlmepriv->lock);
1377 		RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_,
1378 			 ("\n ***Error: disconnect_cmd_callback Fail ***\n."));
1379 		return;
1380 	}
1381 
1382 	/*  free cmd */
1383 	rtw_free_cmd_obj23a(pcmd);
1384 }
1385 
rtw_joinbss_cmd23a_callback(struct rtw_adapter * padapter,struct cmd_obj * pcmd)1386 void rtw_joinbss_cmd23a_callback(struct rtw_adapter *padapter,
1387 				 struct cmd_obj *pcmd)
1388 {
1389 	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1390 
1391 	if (pcmd->res == H2C_DROPPED) {
1392 		/* TODO: cancel timer and do timeout handler directly... */
1393 		/* need to make timeout handlerOS independent */
1394 		mod_timer(&pmlmepriv->assoc_timer,
1395 			  jiffies + msecs_to_jiffies(1));
1396 	} else if (pcmd->res != H2C_SUCCESS) {
1397 		RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_,
1398 			 ("********Error:rtw_select_and_join_from_scanned_"
1399 			  "queue Wait Sema  Fail ************\n"));
1400 		mod_timer(&pmlmepriv->assoc_timer,
1401 			  jiffies + msecs_to_jiffies(1));
1402 	}
1403 
1404 	rtw_free_cmd_obj23a(pcmd);
1405 }
1406 
rtw_createbss_cmd23a_callback(struct rtw_adapter * padapter,struct cmd_obj * pcmd)1407 void rtw_createbss_cmd23a_callback(struct rtw_adapter *padapter,
1408 				   struct cmd_obj *pcmd)
1409 {
1410 	struct sta_info *psta;
1411 	struct wlan_network *pwlan;
1412 	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1413 	struct wlan_bssid_ex *pnetwork = (struct wlan_bssid_ex *)pcmd->parmbuf;
1414 	struct wlan_network *tgt_network = &pmlmepriv->cur_network;
1415 
1416 	if (pcmd->res != H2C_SUCCESS) {
1417 		RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_,
1418 			 ("\n ********Error: rtw_createbss_cmd23a_callback  "
1419 			  "Fail ************\n\n."));
1420 		mod_timer(&pmlmepriv->assoc_timer,
1421 			  jiffies + msecs_to_jiffies(1));
1422 	}
1423 
1424 	del_timer_sync(&pmlmepriv->assoc_timer);
1425 
1426 	if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) {
1427 		psta = rtw_get_stainfo23a(&padapter->stapriv,
1428 					  pnetwork->MacAddress);
1429 		if (!psta) {
1430 			psta = rtw_alloc_stainfo23a(&padapter->stapriv,
1431 						    pnetwork->MacAddress,
1432 						    GFP_KERNEL);
1433 			if (!psta) {
1434 				RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_,
1435 					 ("\nCan't alloc sta_info when "
1436 					  "createbss_cmd_callback\n"));
1437 				goto createbss_cmd_fail ;
1438 			}
1439 		}
1440 
1441 		spin_lock_bh(&pmlmepriv->lock);
1442 		rtw_indicate_connect23a(padapter);
1443 		spin_unlock_bh(&pmlmepriv->lock);
1444 	} else {
1445 		pwlan = rtw_alloc_network(pmlmepriv, GFP_KERNEL);
1446 		spin_lock_bh(&pmlmepriv->scanned_queue.lock);
1447 		if (!pwlan) {
1448 			pwlan = rtw_get_oldest_wlan_network23a(&pmlmepriv->scanned_queue);
1449 			if (!pwlan) {
1450 				RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_,
1451 					 ("\n Error:  can't get pwlan in "
1452 					  "rtw23a_joinbss_event_cb\n"));
1453 				spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
1454 				goto createbss_cmd_fail;
1455 			}
1456 			pwlan->last_scanned = jiffies;
1457 		} else {
1458 			list_add_tail(&pwlan->list,
1459 				      &pmlmepriv->scanned_queue.queue);
1460 		}
1461 
1462 		pnetwork->Length = get_wlan_bssid_ex_sz(pnetwork);
1463 		memcpy(&pwlan->network, pnetwork, pnetwork->Length);
1464 		/* pwlan->fixed = true; */
1465 
1466 		/* list_add_tail(&pwlan->list,
1467 		   &pmlmepriv->scanned_queue.queue); */
1468 
1469 		/*  copy pdev_network information to
1470 		    pmlmepriv->cur_network */
1471 		memcpy(&tgt_network->network, pnetwork,
1472 		       get_wlan_bssid_ex_sz(pnetwork));
1473 
1474 		/*  reset DSConfig */
1475 
1476 		clr_fwstate(pmlmepriv, _FW_UNDER_LINKING);
1477 
1478 		spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
1479 		/*  we will set _FW_LINKED when there is one more sat to
1480 		    join us (rtw_stassoc_event_callback23a) */
1481 	}
1482 
1483 createbss_cmd_fail:
1484 
1485 	rtw_free_cmd_obj23a(pcmd);
1486 }
1487 
rtw_setstaKey_cmdrsp_callback23a(struct rtw_adapter * padapter,struct cmd_obj * pcmd)1488 void rtw_setstaKey_cmdrsp_callback23a(struct rtw_adapter *padapter,
1489 				      struct cmd_obj *pcmd)
1490 {
1491 	struct sta_priv *pstapriv;
1492 	struct set_stakey_rsp *psetstakey_rsp;
1493 	struct sta_info *psta;
1494 
1495 	pstapriv = &padapter->stapriv;
1496 	psetstakey_rsp = (struct set_stakey_rsp *) (pcmd->rsp);
1497 	psta = rtw_get_stainfo23a(pstapriv, psetstakey_rsp->addr);
1498 
1499 	if (!psta) {
1500 		RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_,
1501 			 ("\nERROR: rtw_setstaKey_cmdrsp_callback23a => "
1502 			  "can't get sta_info\n\n"));
1503 		goto exit;
1504 	}
1505 
1506 exit:
1507 
1508 	rtw_free_cmd_obj23a(pcmd);
1509 }
1510 
rtw_setassocsta_cmdrsp_callback23a(struct rtw_adapter * padapter,struct cmd_obj * pcmd)1511 void rtw_setassocsta_cmdrsp_callback23a(struct rtw_adapter *padapter,
1512 					struct cmd_obj *pcmd)
1513 {
1514 	struct sta_priv *pstapriv = &padapter->stapriv;
1515 	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1516 	struct set_assocsta_parm *passocsta_parm;
1517 	struct set_assocsta_rsp *passocsta_rsp;
1518 	struct sta_info *psta;
1519 
1520 	passocsta_parm = (struct set_assocsta_parm *)(pcmd->parmbuf);
1521 	passocsta_rsp = (struct set_assocsta_rsp *) (pcmd->rsp);
1522 	psta = rtw_get_stainfo23a(pstapriv, passocsta_parm->addr);
1523 
1524 	if (psta == NULL) {
1525 		RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_,
1526 			 ("\nERROR: setassocsta_cmdrsp_callbac => can't "
1527 			  "get sta_info\n\n"));
1528 		goto exit;
1529 	}
1530 
1531 	psta->aid = psta->mac_id = passocsta_rsp->cam_id;
1532 
1533 	spin_lock_bh(&pmlmepriv->lock);
1534 
1535 	if (check_fwstate(pmlmepriv, WIFI_MP_STATE) &&
1536 	    check_fwstate(pmlmepriv, _FW_UNDER_LINKING))
1537 		_clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING);
1538 
1539 	set_fwstate(pmlmepriv, _FW_LINKED);
1540 	spin_unlock_bh(&pmlmepriv->lock);
1541 
1542 exit:
1543 	rtw_free_cmd_obj23a(pcmd);
1544 }
1545