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