1 // SPDX-License-Identifier: GPL-2.0
2 /******************************************************************************
3  *
4  * Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved.
5  *
6  ******************************************************************************/
7 #define _RTW_CMD_C_
8 
9 #include <osdep_service.h>
10 #include <drv_types.h>
11 #include <recv_osdep.h>
12 #include <mlme_osdep.h>
13 #include <rtw_mlme_ext.h>
14 
15 /*
16  * Caller and the rtw_cmd_thread can protect cmd_q by spin_lock.
17  * No irqsave is necessary.
18  */
19 
rtw_init_cmd_priv(struct cmd_priv * pcmdpriv)20 int rtw_init_cmd_priv(struct cmd_priv *pcmdpriv)
21 {
22 	init_completion(&pcmdpriv->cmd_queue_comp);
23 	init_completion(&pcmdpriv->terminate_cmdthread_comp);
24 
25 	_rtw_init_queue(&pcmdpriv->cmd_queue);
26 	return _SUCCESS;
27 }
28 
29 /*
30  * Calling Context:
31  *
32  * rtw_enqueue_cmd can only be called between kernel thread,
33  * since only spin_lock is used.
34  *
35  * ISR/Call-Back functions can't call this sub-function.
36  */
37 
_rtw_enqueue_cmd(struct __queue * queue,struct cmd_obj * obj)38 static int _rtw_enqueue_cmd(struct __queue *queue, struct cmd_obj *obj)
39 {
40 	unsigned long irqL;
41 
42 	if (!obj)
43 		goto exit;
44 
45 	spin_lock_irqsave(&queue->lock, irqL);
46 
47 	list_add_tail(&obj->list, &queue->queue);
48 
49 	spin_unlock_irqrestore(&queue->lock, irqL);
50 
51 exit:
52 
53 	return _SUCCESS;
54 }
55 
rtw_dequeue_cmd(struct __queue * queue)56 struct cmd_obj *rtw_dequeue_cmd(struct __queue *queue)
57 {
58 	unsigned long irqL;
59 	struct cmd_obj *obj;
60 
61 	spin_lock_irqsave(&queue->lock, irqL);
62 	obj = list_first_entry_or_null(&queue->queue, struct cmd_obj, list);
63 	if (obj)
64 		list_del_init(&obj->list);
65 	spin_unlock_irqrestore(&queue->lock, irqL);
66 
67 	return obj;
68 }
69 
rtw_cmd_filter(struct cmd_priv * pcmdpriv,struct cmd_obj * cmd_obj)70 static int rtw_cmd_filter(struct cmd_priv *pcmdpriv, struct cmd_obj *cmd_obj)
71 {
72 	u8 bAllow = false; /* set to true to allow enqueuing cmd when hw_init_completed is false */
73 
74 	/* To decide allow or not */
75 	if ((pcmdpriv->padapter->pwrctrlpriv.bHWPwrPindetect) &&
76 	    (!pcmdpriv->padapter->registrypriv.usbss_enable)) {
77 		if (cmd_obj->cmdcode == _Set_Drv_Extra_CMD_) {
78 			struct drvextra_cmd_parm	*pdrvextra_cmd_parm = (struct drvextra_cmd_parm	*)cmd_obj->parmbuf;
79 
80 			if (pdrvextra_cmd_parm->ec_id == POWER_SAVING_CTRL_WK_CID)
81 				bAllow = true;
82 		}
83 	}
84 
85 	if (cmd_obj->cmdcode == _SetChannelPlan_CMD_)
86 		bAllow = true;
87 
88 	if ((!pcmdpriv->padapter->hw_init_completed && !bAllow) ||
89 	    !pcmdpriv->cmdthd_running)	/* com_thread not running */
90 		return _FAIL;
91 	return _SUCCESS;
92 }
93 
rtw_enqueue_cmd(struct cmd_priv * pcmdpriv,struct cmd_obj * cmd_obj)94 u32 rtw_enqueue_cmd(struct cmd_priv *pcmdpriv, struct cmd_obj *cmd_obj)
95 {
96 	int res = _FAIL;
97 	struct adapter *padapter = pcmdpriv->padapter;
98 
99 	if (!cmd_obj)
100 		goto exit;
101 
102 	cmd_obj->padapter = padapter;
103 
104 	res = rtw_cmd_filter(pcmdpriv, cmd_obj);
105 	if (res == _FAIL) {
106 		rtw_free_cmd_obj(cmd_obj);
107 		goto exit;
108 	}
109 
110 	res = _rtw_enqueue_cmd(&pcmdpriv->cmd_queue, cmd_obj);
111 
112 	if (res == _SUCCESS)
113 		complete(&pcmdpriv->cmd_queue_comp);
114 
115 exit:
116 
117 	return res;
118 }
119 
rtw_free_cmd_obj(struct cmd_obj * pcmd)120 void rtw_free_cmd_obj(struct cmd_obj *pcmd)
121 {
122 	if ((pcmd->cmdcode != _JoinBss_CMD_) && (pcmd->cmdcode != _CreateBss_CMD_)) {
123 		/* free parmbuf in cmd_obj */
124 		kfree(pcmd->parmbuf);
125 	}
126 
127 	if (pcmd->rsp) {
128 		if (pcmd->rspsz != 0) {
129 			/* free rsp in cmd_obj */
130 			kfree(pcmd->rsp);
131 		}
132 	}
133 
134 	/* free cmd_obj */
135 	kfree(pcmd);
136 }
137 
rtw_cmd_thread(void * context)138 int rtw_cmd_thread(void *context)
139 {
140 	u8 ret;
141 	struct cmd_obj *pcmd;
142 	u8 (*cmd_hdl)(struct adapter *padapter, u8 *pbuf);
143 	void (*pcmd_callback)(struct adapter *dev, struct cmd_obj *pcmd);
144 	struct adapter *padapter = context;
145 	struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
146 
147 	allow_signal(SIGTERM);
148 
149 	pcmdpriv->cmdthd_running = true;
150 	complete(&pcmdpriv->terminate_cmdthread_comp);
151 
152 	RT_TRACE(_module_rtl871x_cmd_c_, _drv_info_,
153 		 ("start r871x %s !!!!\n", __func__));
154 
155 	while (1) {
156 		if (wait_for_completion_interruptible(&pcmdpriv->cmd_queue_comp))
157 			break;
158 
159 		if (padapter->bDriverStopped ||
160 		    padapter->bSurpriseRemoved) {
161 			DBG_88E("%s: DriverStopped(%d) SurpriseRemoved(%d) break at line %d\n",
162 				__func__, padapter->bDriverStopped, padapter->bSurpriseRemoved, __LINE__);
163 			break;
164 		}
165 _next:
166 		if (padapter->bDriverStopped ||
167 		    padapter->bSurpriseRemoved) {
168 			DBG_88E("%s: DriverStopped(%d) SurpriseRemoved(%d) break at line %d\n",
169 				__func__, padapter->bDriverStopped, padapter->bSurpriseRemoved, __LINE__);
170 			break;
171 		}
172 
173 		pcmd = rtw_dequeue_cmd(&pcmdpriv->cmd_queue);
174 		if (!pcmd)
175 			continue;
176 
177 		if (rtw_cmd_filter(pcmdpriv, pcmd) == _FAIL) {
178 			pcmd->res = H2C_DROPPED;
179 		} else {
180 			if (pcmd->cmdcode < ARRAY_SIZE(wlancmds)) {
181 				cmd_hdl = wlancmds[pcmd->cmdcode].h2cfuns;
182 
183 				if (cmd_hdl) {
184 					ret = cmd_hdl(pcmd->padapter, pcmd->parmbuf);
185 					pcmd->res = ret;
186 				}
187 			} else {
188 				pcmd->res = H2C_PARAMETERS_ERROR;
189 			}
190 
191 			cmd_hdl = NULL;
192 		}
193 
194 		/* call callback function for post-processed */
195 		if (pcmd->cmdcode < ARRAY_SIZE(rtw_cmd_callback)) {
196 			pcmd_callback = rtw_cmd_callback[pcmd->cmdcode].callback;
197 			if (!pcmd_callback) {
198 				RT_TRACE(_module_rtl871x_cmd_c_, _drv_info_, ("mlme_cmd_hdl(): pcmd_callback = 0x%p, cmdcode = 0x%x\n", pcmd_callback, pcmd->cmdcode));
199 				rtw_free_cmd_obj(pcmd);
200 			} else {
201 				/* todo: !!! fill rsp_buf to pcmd->rsp if (pcmd->rsp!= NULL) */
202 				pcmd_callback(pcmd->padapter, pcmd);/* need conider that free cmd_obj in rtw_cmd_callback */
203 			}
204 		} else {
205 			RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_, ("%s: cmdcode = 0x%x callback not defined!\n", __func__, pcmd->cmdcode));
206 			rtw_free_cmd_obj(pcmd);
207 		}
208 
209 		if (signal_pending(current))
210 			flush_signals(current);
211 
212 		goto _next;
213 	}
214 	pcmdpriv->cmdthd_running = false;
215 
216 	/*  free all cmd_obj resources */
217 	while ((pcmd = rtw_dequeue_cmd(&pcmdpriv->cmd_queue)))
218 		rtw_free_cmd_obj(pcmd);
219 
220 	complete(&pcmdpriv->terminate_cmdthread_comp);
221 
222 	complete_and_exit(NULL, 0);
223 }
224 
225 /*
226  * rtw_sitesurvey_cmd(~)
227  * ### NOTE:#### (!!!!)
228  * MUST TAKE CARE THAT BEFORE CALLING THIS FUNC, YOU SHOULD HAVE
229  * LOCKED pmlmepriv->lock
230  */
rtw_sitesurvey_cmd(struct adapter * padapter,struct ndis_802_11_ssid * ssid,int ssid_num,struct rtw_ieee80211_channel * ch,int ch_num)231 u8 rtw_sitesurvey_cmd(struct adapter  *padapter, struct ndis_802_11_ssid *ssid, int ssid_num,
232 	struct rtw_ieee80211_channel *ch, int ch_num)
233 {
234 	u8 res = _FAIL;
235 	struct cmd_obj		*ph2c;
236 	struct sitesurvey_parm	*psurveyPara;
237 	struct cmd_priv		*pcmdpriv = &padapter->cmdpriv;
238 	struct mlme_priv	*pmlmepriv = &padapter->mlmepriv;
239 
240 	if (check_fwstate(pmlmepriv, _FW_LINKED))
241 		rtw_lps_ctrl_wk_cmd(padapter, LPS_CTRL_SCAN, 1);
242 
243 	ph2c = kzalloc(sizeof(*ph2c), GFP_ATOMIC);
244 	if (!ph2c)
245 		return _FAIL;
246 
247 	psurveyPara = kzalloc(sizeof(*psurveyPara), GFP_ATOMIC);
248 	if (!psurveyPara) {
249 		kfree(ph2c);
250 		return _FAIL;
251 	}
252 
253 	rtw_free_network_queue(padapter, false);
254 
255 	RT_TRACE(_module_rtl871x_cmd_c_, _drv_info_, ("%s: flush network queue\n", __func__));
256 
257 	init_h2fwcmd_w_parm_no_rsp(ph2c, psurveyPara, _SiteSurvey_CMD_);
258 
259 	psurveyPara->scan_mode = pmlmepriv->scan_mode;
260 
261 	/* prepare ssid list */
262 	if (ssid) {
263 		int i;
264 
265 		for (i = 0; i < ssid_num && i < RTW_SSID_SCAN_AMOUNT; i++) {
266 			if (ssid[i].ssid_length) {
267 				memcpy(&psurveyPara->ssid[i], &ssid[i], sizeof(struct ndis_802_11_ssid));
268 				psurveyPara->ssid_num++;
269 			}
270 		}
271 	}
272 
273 	/* prepare channel list */
274 	if (ch) {
275 		int i;
276 
277 		for (i = 0; i < ch_num && i < RTW_CHANNEL_SCAN_AMOUNT; i++) {
278 			if (ch[i].hw_value && !(ch[i].flags & RTW_IEEE80211_CHAN_DISABLED)) {
279 				memcpy(&psurveyPara->ch[i], &ch[i], sizeof(struct rtw_ieee80211_channel));
280 				psurveyPara->ch_num++;
281 			}
282 		}
283 	}
284 
285 	set_fwstate(pmlmepriv, _FW_UNDER_SURVEY);
286 
287 	res = rtw_enqueue_cmd(pcmdpriv, ph2c);
288 
289 	if (res == _SUCCESS) {
290 		mod_timer(&pmlmepriv->scan_to_timer,
291 			  jiffies + msecs_to_jiffies(SCANNING_TIMEOUT));
292 
293 		led_control_8188eu(padapter, LED_CTL_SITE_SURVEY);
294 
295 		pmlmepriv->scan_interval = SCAN_INTERVAL;/*  30*2 sec = 60sec */
296 	} else {
297 		_clr_fwstate_(pmlmepriv, _FW_UNDER_SURVEY);
298 	}
299 
300 	return res;
301 }
302 
rtw_readtssi_cmdrsp_callback(struct adapter * padapter,struct cmd_obj * pcmd)303 void rtw_readtssi_cmdrsp_callback(struct adapter *padapter,  struct cmd_obj *pcmd)
304 {
305 	kfree(pcmd->parmbuf);
306 	kfree(pcmd);
307 }
308 
rtw_createbss_cmd(struct adapter * padapter)309 u8 rtw_createbss_cmd(struct adapter  *padapter)
310 {
311 	struct cmd_obj *pcmd;
312 	struct cmd_priv	*pcmdpriv = &padapter->cmdpriv;
313 	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
314 	struct wlan_bssid_ex *pdev_network = &padapter->registrypriv.dev_network;
315 	u8	res = _SUCCESS;
316 
317 	led_control_8188eu(padapter, LED_CTL_START_TO_LINK);
318 
319 	if (pmlmepriv->assoc_ssid.ssid_length == 0)
320 		RT_TRACE(_module_rtl871x_cmd_c_, _drv_info_, (" createbss for Any SSid:%s\n", pmlmepriv->assoc_ssid.ssid));
321 	else
322 		RT_TRACE(_module_rtl871x_cmd_c_, _drv_info_, (" createbss for SSid:%s\n", pmlmepriv->assoc_ssid.ssid));
323 
324 	pcmd = kzalloc(sizeof(*pcmd), GFP_ATOMIC);
325 	if (!pcmd) {
326 		res = _FAIL;
327 		goto exit;
328 	}
329 
330 	INIT_LIST_HEAD(&pcmd->list);
331 	pcmd->cmdcode = _CreateBss_CMD_;
332 	pcmd->parmbuf = (unsigned char *)pdev_network;
333 	pcmd->cmdsz = get_wlan_bssid_ex_sz((struct wlan_bssid_ex *)pdev_network);
334 	pcmd->rsp = NULL;
335 	pcmd->rspsz = 0;
336 	pdev_network->Length = pcmd->cmdsz;
337 	res = rtw_enqueue_cmd(pcmdpriv, pcmd);
338 exit:
339 
340 	return res;
341 }
342 
rtw_joinbss_cmd(struct adapter * padapter,struct wlan_network * pnetwork)343 u8 rtw_joinbss_cmd(struct adapter  *padapter, struct wlan_network *pnetwork)
344 {
345 	u8	res = _SUCCESS;
346 	uint	t_len = 0;
347 	struct wlan_bssid_ex		*psecnetwork;
348 	struct cmd_obj		*pcmd;
349 	struct cmd_priv		*pcmdpriv = &padapter->cmdpriv;
350 	struct mlme_priv	*pmlmepriv = &padapter->mlmepriv;
351 	struct qos_priv		*pqospriv = &pmlmepriv->qospriv;
352 	struct security_priv	*psecuritypriv = &padapter->securitypriv;
353 	struct registry_priv	*pregistrypriv = &padapter->registrypriv;
354 	struct ht_priv		*phtpriv = &pmlmepriv->htpriv;
355 	enum ndis_802_11_network_infra ndis_network_mode = pnetwork->network.InfrastructureMode;
356 	struct mlme_ext_priv	*pmlmeext = &padapter->mlmeextpriv;
357 	struct mlme_ext_info	*pmlmeinfo = &pmlmeext->mlmext_info;
358 
359 	led_control_8188eu(padapter, LED_CTL_START_TO_LINK);
360 
361 	if (pmlmepriv->assoc_ssid.ssid_length == 0)
362 		RT_TRACE(_module_rtl871x_cmd_c_, _drv_info_, ("+Join cmd: Any SSid\n"));
363 	else
364 		RT_TRACE(_module_rtl871x_cmd_c_, _drv_notice_, ("+Join cmd: SSid =[%s]\n", pmlmepriv->assoc_ssid.ssid));
365 
366 	pcmd = kzalloc(sizeof(*pcmd), GFP_ATOMIC);
367 	if (!pcmd) {
368 		res = _FAIL;
369 		goto exit;
370 	}
371 	/* for ies is fix buf size */
372 	t_len = sizeof(struct wlan_bssid_ex);
373 
374 	/* for hidden ap to set fw_state here */
375 	if (!check_fwstate(pmlmepriv, WIFI_STATION_STATE | WIFI_ADHOC_STATE)) {
376 		switch (ndis_network_mode) {
377 		case Ndis802_11IBSS:
378 			set_fwstate(pmlmepriv, WIFI_ADHOC_STATE);
379 			break;
380 		case Ndis802_11Infrastructure:
381 			set_fwstate(pmlmepriv, WIFI_STATION_STATE);
382 			break;
383 		case Ndis802_11APMode:
384 		case Ndis802_11AutoUnknown:
385 		case Ndis802_11InfrastructureMax:
386 			break;
387 		}
388 	}
389 
390 	psecnetwork = (struct wlan_bssid_ex *)&psecuritypriv->sec_bss;
391 	if (!psecnetwork) {
392 		kfree(pcmd);
393 
394 		res = _FAIL;
395 
396 		RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_,
397 			 ("%s :psecnetwork == NULL!!!\n", __func__));
398 
399 		goto exit;
400 	}
401 
402 	memset(psecnetwork, 0, t_len);
403 
404 	memcpy(psecnetwork, &pnetwork->network, get_wlan_bssid_ex_sz(&pnetwork->network));
405 
406 	psecuritypriv->authenticator_ie[0] = (unsigned char)psecnetwork->ie_length;
407 
408 	if (psecnetwork->ie_length - 12 < 255)
409 		memcpy(&psecuritypriv->authenticator_ie[1], &psecnetwork->ies[12], psecnetwork->ie_length - 12);
410 	else
411 		memcpy(&psecuritypriv->authenticator_ie[1], &psecnetwork->ies[12], 255);
412 
413 	psecnetwork->ie_length = 0;
414 	/*  Added by Albert 2009/02/18 */
415 	/*  If the driver wants to use the bssid to create the connection. */
416 	/*  If not,  we have to copy the connecting AP's MAC address to it so that */
417 	/*  the driver just has the bssid information for PMKIDList searching. */
418 
419 	if (!pmlmepriv->assoc_by_bssid)
420 		memcpy(&pmlmepriv->assoc_bssid[0], &pnetwork->network.MacAddress[0], ETH_ALEN);
421 
422 	psecnetwork->ie_length = rtw_restruct_sec_ie(padapter, &pnetwork->network.ies[0], &psecnetwork->ies[0], pnetwork->network.ie_length);
423 
424 	pqospriv->qos_option = 0;
425 
426 	if (pregistrypriv->wmm_enable) {
427 		u32 tmp_len;
428 
429 		tmp_len = rtw_restruct_wmm_ie(padapter, &pnetwork->network.ies[0], &psecnetwork->ies[0], pnetwork->network.ie_length, psecnetwork->ie_length);
430 
431 		if (psecnetwork->ie_length != tmp_len) {
432 			psecnetwork->ie_length = tmp_len;
433 			pqospriv->qos_option = 1; /* There is WMM IE in this corresp. beacon */
434 		} else {
435 			pqospriv->qos_option = 0;/* There is no WMM IE in this corresp. beacon */
436 		}
437 	}
438 
439 	phtpriv->ht_option = false;
440 	if (pregistrypriv->ht_enable) {
441 		/*
442 		 * Added by Albert 2010/06/23
443 		 * For the WEP mode, we will use the bg mode to do
444 		 * the connection to avoid some IOT issue.
445 		 * Especially for Realtek 8192u SoftAP.
446 		 */
447 		if ((padapter->securitypriv.dot11PrivacyAlgrthm != _WEP40_) &&
448 		    (padapter->securitypriv.dot11PrivacyAlgrthm != _WEP104_) &&
449 		    (padapter->securitypriv.dot11PrivacyAlgrthm != _TKIP_)) {
450 			/* rtw_restructure_ht_ie */
451 			rtw_restructure_ht_ie(padapter, &pnetwork->network.ies[0], &psecnetwork->ies[0],
452 									pnetwork->network.ie_length, &psecnetwork->ie_length);
453 		}
454 	}
455 
456 	pmlmeinfo->assoc_AP_vendor = check_assoc_AP(pnetwork->network.ies, pnetwork->network.ie_length);
457 
458 	if (pmlmeinfo->assoc_AP_vendor == HT_IOT_PEER_TENDA)
459 		padapter->pwrctrlpriv.smart_ps = 0;
460 	else
461 		padapter->pwrctrlpriv.smart_ps = padapter->registrypriv.smart_ps;
462 
463 	DBG_88E("%s: smart_ps =%d\n", __func__, padapter->pwrctrlpriv.smart_ps);
464 
465 	pcmd->cmdsz = get_wlan_bssid_ex_sz(psecnetwork);/* get cmdsz before endian conversion */
466 
467 	INIT_LIST_HEAD(&pcmd->list);
468 	pcmd->cmdcode = _JoinBss_CMD_;
469 	pcmd->parmbuf = (unsigned char *)psecnetwork;
470 	pcmd->rsp = NULL;
471 	pcmd->rspsz = 0;
472 
473 	res = rtw_enqueue_cmd(pcmdpriv, pcmd);
474 
475 exit:
476 
477 	return res;
478 }
479 
rtw_disassoc_cmd(struct adapter * padapter,u32 deauth_timeout_ms,bool enqueue)480 u8 rtw_disassoc_cmd(struct adapter *padapter, u32 deauth_timeout_ms, bool enqueue) /* for sta_mode */
481 {
482 	struct cmd_obj *cmdobj = NULL;
483 	struct disconnect_parm *param = NULL;
484 	struct cmd_priv *cmdpriv = &padapter->cmdpriv;
485 	u8 res = _SUCCESS;
486 
487 	RT_TRACE(_module_rtl871x_cmd_c_, _drv_notice_, ("+%s\n", __func__));
488 
489 	/* prepare cmd parameter */
490 	param = kzalloc(sizeof(*param), GFP_ATOMIC);
491 	if (!param) {
492 		res = _FAIL;
493 		goto exit;
494 	}
495 	param->deauth_timeout_ms = deauth_timeout_ms;
496 
497 	if (enqueue) {
498 		/* need enqueue, prepare cmd_obj and enqueue */
499 		cmdobj = kzalloc(sizeof(*cmdobj), GFP_ATOMIC);
500 		if (!cmdobj) {
501 			res = _FAIL;
502 			kfree(param);
503 			goto exit;
504 		}
505 		init_h2fwcmd_w_parm_no_rsp(cmdobj, param, _DisConnect_CMD_);
506 		res = rtw_enqueue_cmd(cmdpriv, cmdobj);
507 	} else {
508 		/* no need to enqueue, do the cmd hdl directly and free cmd parameter */
509 		if (disconnect_hdl(padapter, (u8 *)param) != H2C_SUCCESS)
510 			res = _FAIL;
511 		kfree(param);
512 	}
513 
514 exit:
515 
516 	return res;
517 }
518 
rtw_setopmode_cmd(struct adapter * padapter,enum ndis_802_11_network_infra networktype)519 u8 rtw_setopmode_cmd(struct adapter  *padapter, enum ndis_802_11_network_infra networktype)
520 {
521 	struct	cmd_obj *ph2c;
522 	struct	setopmode_parm *psetop;
523 
524 	struct	cmd_priv   *pcmdpriv = &padapter->cmdpriv;
525 
526 	ph2c = kzalloc(sizeof(*ph2c), GFP_KERNEL);
527 	psetop = kzalloc(sizeof(*psetop), GFP_KERNEL);
528 	if (!ph2c || !psetop) {
529 		kfree(ph2c);
530 		kfree(psetop);
531 		return false;
532 	}
533 
534 	init_h2fwcmd_w_parm_no_rsp(ph2c, psetop, _SetOpMode_CMD_);
535 	psetop->mode = (u8)networktype;
536 
537 	return rtw_enqueue_cmd(pcmdpriv, ph2c);
538 }
539 
rtw_setstakey_cmd(struct adapter * padapter,u8 * psta,u8 unicast_key)540 u8 rtw_setstakey_cmd(struct adapter *padapter, u8 *psta, u8 unicast_key)
541 {
542 	struct cmd_obj *ph2c;
543 	struct set_stakey_parm *psetstakey_para;
544 	struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
545 	struct set_stakey_rsp *psetstakey_rsp = NULL;
546 
547 	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
548 	struct security_priv *psecuritypriv = &padapter->securitypriv;
549 	struct sta_info *sta = (struct sta_info *)psta;
550 
551 	ph2c = kzalloc(sizeof(*ph2c), GFP_KERNEL);
552 	psetstakey_para = kzalloc(sizeof(*psetstakey_para), GFP_KERNEL);
553 	psetstakey_rsp = kzalloc(sizeof(*psetstakey_rsp), GFP_KERNEL);
554 
555 	if (!ph2c || !psetstakey_para || !psetstakey_rsp) {
556 		kfree(ph2c);
557 		kfree(psetstakey_para);
558 		kfree(psetstakey_rsp);
559 		return _FAIL;
560 	}
561 
562 	init_h2fwcmd_w_parm_no_rsp(ph2c, psetstakey_para, _SetStaKey_CMD_);
563 	ph2c->rsp = (u8 *)psetstakey_rsp;
564 	ph2c->rspsz = sizeof(struct set_stakey_rsp);
565 
566 	ether_addr_copy(psetstakey_para->addr, sta->hwaddr);
567 
568 	if (check_fwstate(pmlmepriv, WIFI_STATION_STATE))
569 		psetstakey_para->algorithm = (unsigned char)psecuritypriv->dot11PrivacyAlgrthm;
570 	else
571 		GET_ENCRY_ALGO(psecuritypriv, sta, psetstakey_para->algorithm, false);
572 
573 	if (unicast_key)
574 		memcpy(&psetstakey_para->key, &sta->dot118021x_UncstKey, 16);
575 	else
576 		memcpy(&psetstakey_para->key, &psecuritypriv->dot118021XGrpKey[psecuritypriv->dot118021XGrpKeyid].skey, 16);
577 
578 	/* jeff: set this because at least sw key is ready */
579 	padapter->securitypriv.busetkipkey = true;
580 
581 	return rtw_enqueue_cmd(pcmdpriv, ph2c);
582 }
583 
rtw_clearstakey_cmd(struct adapter * padapter,u8 * psta,u8 entry,u8 enqueue)584 u8 rtw_clearstakey_cmd(struct adapter *padapter, u8 *psta, u8 entry, u8 enqueue)
585 {
586 	struct cmd_obj *ph2c;
587 	struct set_stakey_parm	*psetstakey_para;
588 	struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
589 	struct set_stakey_rsp *psetstakey_rsp = NULL;
590 	struct sta_info *sta = (struct sta_info *)psta;
591 	u8	res = _SUCCESS;
592 
593 	if (!enqueue) {
594 		clear_cam_entry(padapter, entry);
595 	} else {
596 		ph2c = kzalloc(sizeof(*ph2c), GFP_ATOMIC);
597 		if (!ph2c) {
598 			res = _FAIL;
599 			goto exit;
600 		}
601 
602 		psetstakey_para = kzalloc(sizeof(*psetstakey_para), GFP_ATOMIC);
603 		if (!psetstakey_para) {
604 			kfree(ph2c);
605 			res = _FAIL;
606 			goto exit;
607 		}
608 
609 		psetstakey_rsp = kzalloc(sizeof(*psetstakey_rsp), GFP_ATOMIC);
610 		if (!psetstakey_rsp) {
611 			kfree(ph2c);
612 			kfree(psetstakey_para);
613 			res = _FAIL;
614 			goto exit;
615 		}
616 
617 		init_h2fwcmd_w_parm_no_rsp(ph2c, psetstakey_para, _SetStaKey_CMD_);
618 		ph2c->rsp = (u8 *)psetstakey_rsp;
619 		ph2c->rspsz = sizeof(struct set_stakey_rsp);
620 
621 		ether_addr_copy(psetstakey_para->addr, sta->hwaddr);
622 
623 		psetstakey_para->algorithm = _NO_PRIVACY_;
624 
625 		psetstakey_para->id = entry;
626 
627 		res = rtw_enqueue_cmd(pcmdpriv, ph2c);
628 	}
629 exit:
630 
631 	return res;
632 }
633 
rtw_addbareq_cmd(struct adapter * padapter,u8 tid,u8 * addr)634 u8 rtw_addbareq_cmd(struct adapter *padapter, u8 tid, u8 *addr)
635 {
636 	struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
637 	struct cmd_obj *ph2c;
638 	struct addBaReq_parm *paddbareq_parm;
639 	u8	res = _SUCCESS;
640 
641 	ph2c = kzalloc(sizeof(*ph2c), GFP_ATOMIC);
642 	if (!ph2c) {
643 		res = _FAIL;
644 		goto exit;
645 	}
646 
647 	paddbareq_parm = kzalloc(sizeof(*paddbareq_parm), GFP_ATOMIC);
648 	if (!paddbareq_parm) {
649 		kfree(ph2c);
650 		res = _FAIL;
651 		goto exit;
652 	}
653 
654 	paddbareq_parm->tid = tid;
655 	memcpy(paddbareq_parm->addr, addr, ETH_ALEN);
656 
657 	init_h2fwcmd_w_parm_no_rsp(ph2c, paddbareq_parm, _AddBAReq_CMD_);
658 
659 	res = rtw_enqueue_cmd(pcmdpriv, ph2c);
660 
661 exit:
662 
663 	return res;
664 }
665 
rtw_dynamic_chk_wk_cmd(struct adapter * padapter)666 u8 rtw_dynamic_chk_wk_cmd(struct adapter *padapter)
667 {
668 	struct cmd_obj *ph2c;
669 	struct drvextra_cmd_parm *pdrvextra_cmd_parm;
670 	struct cmd_priv	*pcmdpriv = &padapter->cmdpriv;
671 	u8	res = _SUCCESS;
672 
673 	ph2c = kzalloc(sizeof(*ph2c), GFP_ATOMIC);
674 	if (!ph2c) {
675 		res = _FAIL;
676 		goto exit;
677 	}
678 
679 	pdrvextra_cmd_parm = kzalloc(sizeof(*pdrvextra_cmd_parm), GFP_ATOMIC);
680 	if (!pdrvextra_cmd_parm) {
681 		kfree(ph2c);
682 		res = _FAIL;
683 		goto exit;
684 	}
685 
686 	pdrvextra_cmd_parm->ec_id = DYNAMIC_CHK_WK_CID;
687 	pdrvextra_cmd_parm->type_size = 0;
688 	pdrvextra_cmd_parm->pbuf = (u8 *)padapter;
689 
690 	init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, _Set_Drv_Extra_CMD_);
691 
692 	res = rtw_enqueue_cmd(pcmdpriv, ph2c);
693 exit:
694 	return res;
695 }
696 
rtw_set_chplan_cmd(struct adapter * padapter,u8 chplan,u8 enqueue)697 u8 rtw_set_chplan_cmd(struct adapter *padapter, u8 chplan, u8 enqueue)
698 {
699 	struct	cmd_obj *pcmdobj;
700 	struct	SetChannelPlan_param *setChannelPlan_param;
701 	struct	cmd_priv   *pcmdpriv = &padapter->cmdpriv;
702 
703 	u8	res = _SUCCESS;
704 
705 	RT_TRACE(_module_rtl871x_cmd_c_, _drv_notice_, ("+%s\n", __func__));
706 
707 	/* check input parameter */
708 	if (!rtw_is_channel_plan_valid(chplan)) {
709 		res = _FAIL;
710 		goto exit;
711 	}
712 
713 	/* prepare cmd parameter */
714 	setChannelPlan_param = kzalloc(sizeof(*setChannelPlan_param), GFP_KERNEL);
715 	if (!setChannelPlan_param) {
716 		res = _FAIL;
717 		goto exit;
718 	}
719 	setChannelPlan_param->channel_plan = chplan;
720 
721 	if (enqueue) {
722 		/* need enqueue, prepare cmd_obj and enqueue */
723 		pcmdobj = kzalloc(sizeof(*pcmdobj), GFP_KERNEL);
724 		if (!pcmdobj) {
725 			kfree(setChannelPlan_param);
726 			res = _FAIL;
727 			goto exit;
728 		}
729 
730 		init_h2fwcmd_w_parm_no_rsp(pcmdobj, setChannelPlan_param, _SetChannelPlan_CMD_);
731 		res = rtw_enqueue_cmd(pcmdpriv, pcmdobj);
732 	} else {
733 		/* no need to enqueue, do the cmd hdl directly and free cmd parameter */
734 		if (set_chplan_hdl(padapter, (unsigned char *)setChannelPlan_param) != H2C_SUCCESS)
735 			res = _FAIL;
736 
737 		kfree(setChannelPlan_param);
738 	}
739 
740 	if (res == _SUCCESS)
741 		padapter->mlmepriv.ChannelPlan = chplan;
742 
743 exit:
744 
745 	return res;
746 }
747 
traffic_status_watchdog(struct adapter * padapter)748 static void traffic_status_watchdog(struct adapter *padapter)
749 {
750 	u8	bEnterPS;
751 	u8	bBusyTraffic = false, bTxBusyTraffic = false, bRxBusyTraffic = false;
752 	u8	bHigherBusyTraffic = false, bHigherBusyRxTraffic = false, bHigherBusyTxTraffic = false;
753 	struct mlme_priv		*pmlmepriv = &padapter->mlmepriv;
754 
755 	/*  */
756 	/*  Determine if our traffic is busy now */
757 	/*  */
758 	if (check_fwstate(pmlmepriv, _FW_LINKED)) {
759 		if (pmlmepriv->LinkDetectInfo.NumRxOkInPeriod > 100 ||
760 		    pmlmepriv->LinkDetectInfo.NumTxOkInPeriod > 100) {
761 			bBusyTraffic = true;
762 
763 			if (pmlmepriv->LinkDetectInfo.NumRxOkInPeriod > pmlmepriv->LinkDetectInfo.NumTxOkInPeriod)
764 				bRxBusyTraffic = true;
765 			else
766 				bTxBusyTraffic = true;
767 		}
768 
769 		/*  Higher Tx/Rx data. */
770 		if (pmlmepriv->LinkDetectInfo.NumRxOkInPeriod > 4000 ||
771 		    pmlmepriv->LinkDetectInfo.NumTxOkInPeriod > 4000) {
772 			bHigherBusyTraffic = true;
773 
774 			if (pmlmepriv->LinkDetectInfo.NumRxOkInPeriod > pmlmepriv->LinkDetectInfo.NumTxOkInPeriod)
775 				bHigherBusyRxTraffic = true;
776 			else
777 				bHigherBusyTxTraffic = true;
778 		}
779 
780 		/*  check traffic for  powersaving. */
781 		if (((pmlmepriv->LinkDetectInfo.NumRxUnicastOkInPeriod + pmlmepriv->LinkDetectInfo.NumTxOkInPeriod) > 8) ||
782 		    (pmlmepriv->LinkDetectInfo.NumRxUnicastOkInPeriod > 2))
783 			bEnterPS = false;
784 		else
785 			bEnterPS = true;
786 
787 		/*  LeisurePS only work in infra mode. */
788 		if (bEnterPS)
789 			LPS_Enter(padapter);
790 		else
791 			LPS_Leave(padapter);
792 	} else {
793 		LPS_Leave(padapter);
794 	}
795 
796 	pmlmepriv->LinkDetectInfo.NumRxOkInPeriod = 0;
797 	pmlmepriv->LinkDetectInfo.NumTxOkInPeriod = 0;
798 	pmlmepriv->LinkDetectInfo.NumRxUnicastOkInPeriod = 0;
799 	pmlmepriv->LinkDetectInfo.bBusyTraffic = bBusyTraffic;
800 	pmlmepriv->LinkDetectInfo.bTxBusyTraffic = bTxBusyTraffic;
801 	pmlmepriv->LinkDetectInfo.bRxBusyTraffic = bRxBusyTraffic;
802 	pmlmepriv->LinkDetectInfo.bHigherBusyTraffic = bHigherBusyTraffic;
803 	pmlmepriv->LinkDetectInfo.bHigherBusyRxTraffic = bHigherBusyRxTraffic;
804 	pmlmepriv->LinkDetectInfo.bHigherBusyTxTraffic = bHigherBusyTxTraffic;
805 }
806 
dynamic_chk_wk_hdl(struct adapter * padapter,u8 * pbuf,int sz)807 static void dynamic_chk_wk_hdl(struct adapter *padapter, u8 *pbuf, int sz)
808 {
809 	struct mlme_priv *pmlmepriv;
810 
811 	padapter = (struct adapter *)pbuf;
812 	pmlmepriv = &padapter->mlmepriv;
813 
814 #ifdef CONFIG_88EU_AP_MODE
815 	if (check_fwstate(pmlmepriv, WIFI_AP_STATE))
816 		expire_timeout_chk(padapter);
817 #endif
818 
819 	linked_status_chk(padapter);
820 	traffic_status_watchdog(padapter);
821 
822 	rtw_hal_dm_watchdog(padapter);
823 }
824 
lps_ctrl_wk_hdl(struct adapter * padapter,u8 lps_ctrl_type)825 static void lps_ctrl_wk_hdl(struct adapter *padapter, u8 lps_ctrl_type)
826 {
827 	struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv;
828 	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
829 	u8	mstatus;
830 
831 	if (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) ||
832 	    check_fwstate(pmlmepriv, WIFI_ADHOC_STATE))
833 		return;
834 
835 	switch (lps_ctrl_type) {
836 	case LPS_CTRL_SCAN:
837 		if (check_fwstate(pmlmepriv, _FW_LINKED)) {
838 			/* connect */
839 			LPS_Leave(padapter);
840 		}
841 		break;
842 	case LPS_CTRL_JOINBSS:
843 		LPS_Leave(padapter);
844 		break;
845 	case LPS_CTRL_CONNECT:
846 		mstatus = 1;/* connect */
847 		/*  Reset LPS Setting */
848 		padapter->pwrctrlpriv.LpsIdleCount = 0;
849 		rtw_hal_set_hwreg(padapter, HW_VAR_H2C_FW_JOINBSSRPT, (u8 *)(&mstatus));
850 		break;
851 	case LPS_CTRL_DISCONNECT:
852 		mstatus = 0;/* disconnect */
853 		LPS_Leave(padapter);
854 		rtw_hal_set_hwreg(padapter, HW_VAR_H2C_FW_JOINBSSRPT, (u8 *)(&mstatus));
855 		break;
856 	case LPS_CTRL_SPECIAL_PACKET:
857 		pwrpriv->DelayLPSLastTimeStamp = jiffies;
858 		LPS_Leave(padapter);
859 		break;
860 	case LPS_CTRL_LEAVE:
861 		LPS_Leave(padapter);
862 		break;
863 	default:
864 		break;
865 	}
866 }
867 
rtw_lps_ctrl_wk_cmd(struct adapter * padapter,u8 lps_ctrl_type,u8 enqueue)868 u8 rtw_lps_ctrl_wk_cmd(struct adapter *padapter, u8 lps_ctrl_type, u8 enqueue)
869 {
870 	struct cmd_obj	*ph2c;
871 	struct drvextra_cmd_parm	*pdrvextra_cmd_parm;
872 	struct cmd_priv	*pcmdpriv = &padapter->cmdpriv;
873 	u8	res = _SUCCESS;
874 
875 	if (enqueue) {
876 		ph2c = kzalloc(sizeof(*ph2c), GFP_ATOMIC);
877 		if (!ph2c) {
878 			res = _FAIL;
879 			goto exit;
880 		}
881 
882 		pdrvextra_cmd_parm = kzalloc(sizeof(*pdrvextra_cmd_parm), GFP_ATOMIC);
883 		if (!pdrvextra_cmd_parm) {
884 			kfree(ph2c);
885 			res = _FAIL;
886 			goto exit;
887 		}
888 
889 		pdrvextra_cmd_parm->ec_id = LPS_CTRL_WK_CID;
890 		pdrvextra_cmd_parm->type_size = lps_ctrl_type;
891 		pdrvextra_cmd_parm->pbuf = NULL;
892 
893 		init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, _Set_Drv_Extra_CMD_);
894 
895 		res = rtw_enqueue_cmd(pcmdpriv, ph2c);
896 	} else {
897 		lps_ctrl_wk_hdl(padapter, lps_ctrl_type);
898 	}
899 
900 exit:
901 
902 	return res;
903 }
904 
rpt_timer_setting_wk_hdl(struct adapter * padapter,u16 min_time)905 static void rpt_timer_setting_wk_hdl(struct adapter *padapter, u16 min_time)
906 {
907 	rtw_hal_set_hwreg(padapter, HW_VAR_RPT_TIMER_SETTING, (u8 *)(&min_time));
908 }
909 
rtw_rpt_timer_cfg_cmd(struct adapter * padapter,u16 min_time)910 u8 rtw_rpt_timer_cfg_cmd(struct adapter *padapter, u16 min_time)
911 {
912 	struct cmd_obj		*ph2c;
913 	struct drvextra_cmd_parm	*pdrvextra_cmd_parm;
914 	struct cmd_priv	*pcmdpriv = &padapter->cmdpriv;
915 
916 	u8	res = _SUCCESS;
917 
918 	ph2c = kzalloc(sizeof(*ph2c), GFP_ATOMIC);
919 	if (!ph2c) {
920 		res = _FAIL;
921 		goto exit;
922 	}
923 
924 	pdrvextra_cmd_parm = kzalloc(sizeof(*pdrvextra_cmd_parm), GFP_ATOMIC);
925 	if (!pdrvextra_cmd_parm) {
926 		kfree(ph2c);
927 		res = _FAIL;
928 		goto exit;
929 	}
930 
931 	pdrvextra_cmd_parm->ec_id = RTP_TIMER_CFG_WK_CID;
932 	pdrvextra_cmd_parm->type_size = min_time;
933 	pdrvextra_cmd_parm->pbuf = NULL;
934 	init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, _Set_Drv_Extra_CMD_);
935 	res = rtw_enqueue_cmd(pcmdpriv, ph2c);
936 exit:
937 
938 	return res;
939 }
940 
antenna_select_wk_hdl(struct adapter * padapter,u8 antenna)941 static void antenna_select_wk_hdl(struct adapter *padapter, u8 antenna)
942 {
943 	rtw_hal_set_hwreg(padapter, HW_VAR_ANTENNA_DIVERSITY_SELECT, (u8 *)(&antenna));
944 }
945 
rtw_antenna_select_cmd(struct adapter * padapter,u8 antenna,u8 enqueue)946 u8 rtw_antenna_select_cmd(struct adapter *padapter, u8 antenna, u8 enqueue)
947 {
948 	struct cmd_obj		*ph2c;
949 	struct drvextra_cmd_parm	*pdrvextra_cmd_parm;
950 	struct cmd_priv	*pcmdpriv = &padapter->cmdpriv;
951 	u8	support_ant_div;
952 	u8	res = _SUCCESS;
953 
954 	rtw_hal_get_def_var(padapter, HAL_DEF_IS_SUPPORT_ANT_DIV, &support_ant_div);
955 	if (!support_ant_div)
956 		return res;
957 
958 	if (enqueue) {
959 		ph2c = kzalloc(sizeof(*ph2c), GFP_KERNEL);
960 		if (!ph2c) {
961 			res = _FAIL;
962 			goto exit;
963 		}
964 
965 		pdrvextra_cmd_parm = kzalloc(sizeof(*pdrvextra_cmd_parm), GFP_KERNEL);
966 		if (!pdrvextra_cmd_parm) {
967 			kfree(ph2c);
968 			res = _FAIL;
969 			goto exit;
970 		}
971 
972 		pdrvextra_cmd_parm->ec_id = ANT_SELECT_WK_CID;
973 		pdrvextra_cmd_parm->type_size = antenna;
974 		pdrvextra_cmd_parm->pbuf = NULL;
975 		init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, _Set_Drv_Extra_CMD_);
976 
977 		res = rtw_enqueue_cmd(pcmdpriv, ph2c);
978 	} else {
979 		antenna_select_wk_hdl(padapter, antenna);
980 	}
981 exit:
982 
983 	return res;
984 }
985 
rtw_ps_cmd(struct adapter * padapter)986 u8 rtw_ps_cmd(struct adapter *padapter)
987 {
988 	struct cmd_obj		*ppscmd;
989 	struct drvextra_cmd_parm	*pdrvextra_cmd_parm;
990 	struct cmd_priv	*pcmdpriv = &padapter->cmdpriv;
991 
992 	ppscmd = kzalloc(sizeof(*ppscmd), GFP_ATOMIC);
993 	pdrvextra_cmd_parm = kzalloc(sizeof(*pdrvextra_cmd_parm), GFP_ATOMIC);
994 	if (!ppscmd || !pdrvextra_cmd_parm) {
995 		kfree(ppscmd);
996 		kfree(pdrvextra_cmd_parm);
997 		return _FAIL;
998 	}
999 
1000 	pdrvextra_cmd_parm->ec_id = POWER_SAVING_CTRL_WK_CID;
1001 	pdrvextra_cmd_parm->pbuf = NULL;
1002 	init_h2fwcmd_w_parm_no_rsp(ppscmd, pdrvextra_cmd_parm, _Set_Drv_Extra_CMD_);
1003 
1004 	return rtw_enqueue_cmd(pcmdpriv, ppscmd);
1005 }
1006 
1007 #ifdef CONFIG_88EU_AP_MODE
1008 
rtw_chk_hi_queue_hdl(struct adapter * padapter)1009 static void rtw_chk_hi_queue_hdl(struct adapter *padapter)
1010 {
1011 	int cnt = 0;
1012 	struct sta_info *psta_bmc;
1013 	struct sta_priv *pstapriv = &padapter->stapriv;
1014 
1015 	psta_bmc = rtw_get_bcmc_stainfo(padapter);
1016 	if (!psta_bmc)
1017 		return;
1018 
1019 	if (psta_bmc->sleepq_len == 0) {
1020 		u8 val = 0;
1021 
1022 		rtw_hal_get_hwreg(padapter, HW_VAR_CHK_HI_QUEUE_EMPTY, &val);
1023 
1024 		while (!val) {
1025 			msleep(100);
1026 
1027 			cnt++;
1028 
1029 			if (cnt > 10)
1030 				break;
1031 
1032 			rtw_hal_get_hwreg(padapter, HW_VAR_CHK_HI_QUEUE_EMPTY, &val);
1033 		}
1034 
1035 		if (cnt <= 10) {
1036 			pstapriv->tim_bitmap &= ~BIT(0);
1037 			pstapriv->sta_dz_bitmap &= ~BIT(0);
1038 
1039 			update_beacon(padapter, _TIM_IE_, NULL, false);
1040 		} else { /* re check again */
1041 			rtw_chk_hi_queue_cmd(padapter);
1042 		}
1043 	}
1044 }
1045 
rtw_chk_hi_queue_cmd(struct adapter * padapter)1046 u8 rtw_chk_hi_queue_cmd(struct adapter *padapter)
1047 {
1048 	struct cmd_obj	*ph2c;
1049 	struct drvextra_cmd_parm	*pdrvextra_cmd_parm;
1050 	struct cmd_priv	*pcmdpriv = &padapter->cmdpriv;
1051 	u8	res = _SUCCESS;
1052 
1053 	ph2c = kzalloc(sizeof(*ph2c), GFP_ATOMIC);
1054 	if (!ph2c) {
1055 		res = _FAIL;
1056 		goto exit;
1057 	}
1058 
1059 	pdrvextra_cmd_parm = kzalloc(sizeof(*pdrvextra_cmd_parm), GFP_ATOMIC);
1060 	if (!pdrvextra_cmd_parm) {
1061 		kfree(ph2c);
1062 		res = _FAIL;
1063 		goto exit;
1064 	}
1065 
1066 	pdrvextra_cmd_parm->ec_id = CHECK_HIQ_WK_CID;
1067 	pdrvextra_cmd_parm->type_size = 0;
1068 	pdrvextra_cmd_parm->pbuf = NULL;
1069 
1070 	init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, _Set_Drv_Extra_CMD_);
1071 
1072 	res = rtw_enqueue_cmd(pcmdpriv, ph2c);
1073 exit:
1074 	return res;
1075 }
1076 #endif
1077 
rtw_drvextra_cmd_hdl(struct adapter * padapter,unsigned char * pbuf)1078 u8 rtw_drvextra_cmd_hdl(struct adapter *padapter, unsigned char *pbuf)
1079 {
1080 	struct drvextra_cmd_parm *pdrvextra_cmd;
1081 
1082 	if (!pbuf)
1083 		return H2C_PARAMETERS_ERROR;
1084 
1085 	pdrvextra_cmd = (struct drvextra_cmd_parm *)pbuf;
1086 
1087 	switch (pdrvextra_cmd->ec_id) {
1088 	case DYNAMIC_CHK_WK_CID:
1089 		dynamic_chk_wk_hdl(padapter, pdrvextra_cmd->pbuf, pdrvextra_cmd->type_size);
1090 		break;
1091 	case POWER_SAVING_CTRL_WK_CID:
1092 		rtw_ps_processor(padapter);
1093 		break;
1094 	case LPS_CTRL_WK_CID:
1095 		lps_ctrl_wk_hdl(padapter, (u8)pdrvextra_cmd->type_size);
1096 		break;
1097 	case RTP_TIMER_CFG_WK_CID:
1098 		rpt_timer_setting_wk_hdl(padapter, pdrvextra_cmd->type_size);
1099 		break;
1100 	case ANT_SELECT_WK_CID:
1101 		antenna_select_wk_hdl(padapter, pdrvextra_cmd->type_size);
1102 		break;
1103 #ifdef CONFIG_88EU_AP_MODE
1104 	case CHECK_HIQ_WK_CID:
1105 		rtw_chk_hi_queue_hdl(padapter);
1106 		break;
1107 #endif /* CONFIG_88EU_AP_MODE */
1108 	default:
1109 		break;
1110 	}
1111 
1112 	if (pdrvextra_cmd->pbuf && pdrvextra_cmd->type_size > 0)
1113 		kfree(pdrvextra_cmd->pbuf);
1114 
1115 	return H2C_SUCCESS;
1116 }
1117 
rtw_survey_cmd_callback(struct adapter * padapter,struct cmd_obj * pcmd)1118 void rtw_survey_cmd_callback(struct adapter *padapter,  struct cmd_obj *pcmd)
1119 {
1120 	struct	mlme_priv *pmlmepriv = &padapter->mlmepriv;
1121 
1122 	if (pcmd->res == H2C_DROPPED) {
1123 		/* TODO: cancel timer and do timeout handler directly... */
1124 		/* need to make timeout handlerOS independent */
1125 		mod_timer(&pmlmepriv->scan_to_timer,
1126 			  jiffies + msecs_to_jiffies(1));
1127 	} else if (pcmd->res != H2C_SUCCESS) {
1128 		mod_timer(&pmlmepriv->scan_to_timer,
1129 			  jiffies + msecs_to_jiffies(1));
1130 		RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_, ("\n ********Error: MgntActrtw_set_802_11_bssid_LIST_SCAN Fail ************\n\n."));
1131 	}
1132 
1133 	/*  free cmd */
1134 	rtw_free_cmd_obj(pcmd);
1135 }
1136 
rtw_disassoc_cmd_callback(struct adapter * padapter,struct cmd_obj * pcmd)1137 void rtw_disassoc_cmd_callback(struct adapter *padapter, struct cmd_obj *pcmd)
1138 {
1139 	struct	mlme_priv *pmlmepriv = &padapter->mlmepriv;
1140 
1141 	if (pcmd->res != H2C_SUCCESS) {
1142 		spin_lock_bh(&pmlmepriv->lock);
1143 		set_fwstate(pmlmepriv, _FW_LINKED);
1144 		spin_unlock_bh(&pmlmepriv->lock);
1145 
1146 		RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_, ("\n ***Error: disconnect_cmd_callback Fail ***\n."));
1147 		return;
1148 	}
1149 
1150 	/*  free cmd */
1151 	rtw_free_cmd_obj(pcmd);
1152 }
1153 
rtw_joinbss_cmd_callback(struct adapter * padapter,struct cmd_obj * pcmd)1154 void rtw_joinbss_cmd_callback(struct adapter *padapter,  struct cmd_obj *pcmd)
1155 {
1156 	struct	mlme_priv *pmlmepriv = &padapter->mlmepriv;
1157 
1158 	if (pcmd->res == H2C_DROPPED) {
1159 		/* TODO: cancel timer and do timeout handler directly... */
1160 		/* need to make timeout handlerOS independent */
1161 		mod_timer(&pmlmepriv->assoc_timer,
1162 			  jiffies + msecs_to_jiffies(1));
1163 	} else if (pcmd->res != H2C_SUCCESS) {
1164 		RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_, ("********Error:rtw_select_and_join_from_scanned_queue Wait Sema  Fail ************\n"));
1165 		mod_timer(&pmlmepriv->assoc_timer,
1166 			  jiffies + msecs_to_jiffies(1));
1167 	}
1168 
1169 	rtw_free_cmd_obj(pcmd);
1170 }
1171 
rtw_createbss_cmd_callback(struct adapter * padapter,struct cmd_obj * pcmd)1172 void rtw_createbss_cmd_callback(struct adapter *padapter, struct cmd_obj *pcmd)
1173 {
1174 	struct sta_info *psta = NULL;
1175 	struct wlan_network *pwlan = NULL;
1176 	struct	mlme_priv *pmlmepriv = &padapter->mlmepriv;
1177 	struct wlan_bssid_ex *pnetwork = (struct wlan_bssid_ex *)pcmd->parmbuf;
1178 	struct wlan_network *tgt_network = &pmlmepriv->cur_network;
1179 
1180 	if (pcmd->res != H2C_SUCCESS) {
1181 		RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_,
1182 			 ("\n **** Error: %s  Fail ****\n\n.", __func__));
1183 		mod_timer(&pmlmepriv->assoc_timer,
1184 			  jiffies + msecs_to_jiffies(1));
1185 	}
1186 
1187 	del_timer_sync(&pmlmepriv->assoc_timer);
1188 
1189 	spin_lock_bh(&pmlmepriv->lock);
1190 
1191 	if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) {
1192 		psta = rtw_get_stainfo(&padapter->stapriv, pnetwork->MacAddress);
1193 		if (!psta) {
1194 			psta = rtw_alloc_stainfo(&padapter->stapriv, pnetwork->MacAddress);
1195 			if (!psta) {
1196 				RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_, ("\nCan't alloc sta_info when createbss_cmd_callback\n"));
1197 				goto createbss_cmd_fail;
1198 			}
1199 		}
1200 
1201 		rtw_indicate_connect(padapter);
1202 	} else {
1203 		pwlan = rtw_alloc_network(pmlmepriv);
1204 		spin_lock_bh(&pmlmepriv->scanned_queue.lock);
1205 		if (!pwlan) {
1206 			pwlan = rtw_get_oldest_wlan_network(&pmlmepriv->scanned_queue);
1207 			if (!pwlan) {
1208 				RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_, ("\n Error:  can't get pwlan in rtw_joinbss_event_callback\n"));
1209 				spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
1210 				goto createbss_cmd_fail;
1211 			}
1212 			pwlan->last_scanned = jiffies;
1213 		} else {
1214 			list_add_tail(&pwlan->list,
1215 				      &pmlmepriv->scanned_queue.queue);
1216 		}
1217 
1218 		pnetwork->Length = get_wlan_bssid_ex_sz(pnetwork);
1219 		memcpy(&pwlan->network, pnetwork, pnetwork->Length);
1220 
1221 		memcpy(&tgt_network->network, pnetwork, (get_wlan_bssid_ex_sz(pnetwork)));
1222 
1223 		_clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING);
1224 
1225 		spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
1226 		/*  we will set _FW_LINKED when there is one more sat to
1227 		 *  join us (rtw_stassoc_event_callback)
1228 		 */
1229 	}
1230 
1231 createbss_cmd_fail:
1232 
1233 	spin_unlock_bh(&pmlmepriv->lock);
1234 
1235 	rtw_free_cmd_obj(pcmd);
1236 }
1237 
rtw_setstaKey_cmdrsp_callback(struct adapter * padapter,struct cmd_obj * pcmd)1238 void rtw_setstaKey_cmdrsp_callback(struct adapter *padapter,  struct cmd_obj *pcmd)
1239 {
1240 	struct sta_priv *pstapriv = &padapter->stapriv;
1241 	struct set_stakey_rsp *psetstakey_rsp = (struct set_stakey_rsp *)(pcmd->rsp);
1242 	struct sta_info *psta = rtw_get_stainfo(pstapriv, psetstakey_rsp->addr);
1243 
1244 	if (!psta) {
1245 		RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_, ("\nERROR: %s => can't get sta_info\n\n", __func__));
1246 		goto exit;
1247 	}
1248 exit:
1249 	rtw_free_cmd_obj(pcmd);
1250 }
1251 
rtw_setassocsta_cmdrsp_callback(struct adapter * padapter,struct cmd_obj * pcmd)1252 void rtw_setassocsta_cmdrsp_callback(struct adapter *padapter,  struct cmd_obj *pcmd)
1253 {
1254 	struct sta_priv *pstapriv = &padapter->stapriv;
1255 	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1256 	struct set_assocsta_parm *passocsta_parm = (struct set_assocsta_parm *)(pcmd->parmbuf);
1257 	struct set_assocsta_rsp *passocsta_rsp = (struct set_assocsta_rsp *)(pcmd->rsp);
1258 	struct sta_info *psta = rtw_get_stainfo(pstapriv, passocsta_parm->addr);
1259 
1260 	if (!psta) {
1261 		RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_, ("\nERROR: %s => can't get sta_info\n\n", __func__));
1262 		goto exit;
1263 	}
1264 
1265 	psta->aid = passocsta_rsp->cam_id;
1266 	psta->mac_id = passocsta_rsp->cam_id;
1267 
1268 	spin_lock_bh(&pmlmepriv->lock);
1269 
1270 	set_fwstate(pmlmepriv, _FW_LINKED);
1271 	spin_unlock_bh(&pmlmepriv->lock);
1272 
1273 exit:
1274 	rtw_free_cmd_obj(pcmd);
1275 }
1276