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