1 // SPDX-License-Identifier: GPL-2.0
2 /* Copyright(c) 2007 - 2012 Realtek Corporation. */
3 
4 #define _RTW_CMD_C_
5 
6 #include "../include/osdep_service.h"
7 #include "../include/drv_types.h"
8 #include "../include/recv_osdep.h"
9 #include "../include/mlme_osdep.h"
10 #include "../include/rtw_br_ext.h"
11 #include "../include/rtw_mlme_ext.h"
12 #include "../include/rtl8188e_dm.h"
13 
14 /* Caller and the rtw_cmd_thread can protect cmd_q by spin_lock.
15  * No irqsave is necessary.
16  */
17 
18 static void c2h_wk_callback(struct work_struct *work);
19 
rtw_free_evt_priv(struct evt_priv * pevtpriv)20 void rtw_free_evt_priv(struct	evt_priv *pevtpriv)
21 {
22 	cancel_work_sync(&pevtpriv->c2h_wk);
23 	while (pevtpriv->c2h_wk_alive)
24 		msleep(10);
25 
26 	while (!rtw_cbuf_empty(pevtpriv->c2h_queue)) {
27 		void *c2h = rtw_cbuf_pop(pevtpriv->c2h_queue);
28 		if (c2h && c2h != (void *)pevtpriv)
29 			kfree(c2h);
30 	}
31 }
32 
33 /* Calling Context:
34  *
35  * rtw_enqueue_cmd can only be called between kernel thread,
36  * since only spin_lock is used.
37  *
38  * ISR/Call-Back functions can't call this sub-function.
39  */
40 
_rtw_enqueue_cmd(struct __queue * queue,struct cmd_obj * obj)41 static int _rtw_enqueue_cmd(struct __queue *queue, struct cmd_obj *obj)
42 {
43 	unsigned long flags;
44 
45 	if (!obj)
46 		goto exit;
47 
48 	spin_lock_irqsave(&queue->lock, flags);
49 
50 	list_add_tail(&obj->list, &queue->queue);
51 
52 	spin_unlock_irqrestore(&queue->lock, flags);
53 
54 exit:
55 
56 	return _SUCCESS;
57 }
58 
rtw_init_cmd_priv(struct cmd_priv * pcmdpriv)59 u32	rtw_init_cmd_priv(struct cmd_priv *pcmdpriv)
60 {
61 	u32 res = _SUCCESS;
62 
63 	init_completion(&pcmdpriv->enqueue_cmd);
64 	/* sema_init(&(pcmdpriv->cmd_done_sema), 0); */
65 	init_completion(&pcmdpriv->start_cmd_thread);
66 	init_completion(&pcmdpriv->stop_cmd_thread);
67 
68 	rtw_init_queue(&pcmdpriv->cmd_queue);
69 
70 	/* allocate DMA-able/Non-Page memory for cmd_buf and rsp_buf */
71 
72 	pcmdpriv->cmd_seq = 1;
73 
74 	pcmdpriv->cmd_allocated_buf = kzalloc(MAX_CMDSZ + CMDBUFF_ALIGN_SZ,
75 					      GFP_KERNEL);
76 
77 	if (!pcmdpriv->cmd_allocated_buf) {
78 		res = _FAIL;
79 		goto exit;
80 	}
81 
82 	pcmdpriv->cmd_buf = pcmdpriv->cmd_allocated_buf  +  CMDBUFF_ALIGN_SZ - ((size_t)(pcmdpriv->cmd_allocated_buf) & (CMDBUFF_ALIGN_SZ - 1));
83 
84 	pcmdpriv->rsp_allocated_buf = kzalloc(MAX_RSPSZ + 4, GFP_KERNEL);
85 
86 	if (!pcmdpriv->rsp_allocated_buf) {
87 		res = _FAIL;
88 		goto exit;
89 	}
90 
91 	pcmdpriv->rsp_buf = pcmdpriv->rsp_allocated_buf  +  4 - ((size_t)(pcmdpriv->rsp_allocated_buf) & 3);
92 
93 	pcmdpriv->cmd_done_cnt = 0;
94 	pcmdpriv->rsp_cnt = 0;
95 exit:
96 
97 	return res;
98 }
99 
rtw_init_evt_priv(struct evt_priv * pevtpriv)100 u32 rtw_init_evt_priv(struct evt_priv *pevtpriv)
101 {
102 	u32 res = _SUCCESS;
103 
104 	/* allocate DMA-able/Non-Page memory for cmd_buf and rsp_buf */
105 	atomic_set(&pevtpriv->event_seq, 0);
106 
107 	INIT_WORK(&pevtpriv->c2h_wk, c2h_wk_callback);
108 	pevtpriv->c2h_wk_alive = false;
109 	pevtpriv->c2h_queue = rtw_cbuf_alloc(C2H_QUEUE_MAX_LEN + 1);
110 	if (!pevtpriv->c2h_queue)
111 		res = _FAIL;
112 
113 	return res;
114 }
115 
rtw_free_cmd_priv(struct cmd_priv * pcmdpriv)116 void rtw_free_cmd_priv(struct	cmd_priv *pcmdpriv)
117 {
118 	if (pcmdpriv) {
119 		kfree(pcmdpriv->cmd_allocated_buf);
120 		kfree(pcmdpriv->rsp_allocated_buf);
121 	}
122 }
123 
rtw_cmd_filter(struct cmd_priv * pcmdpriv,struct cmd_obj * cmd_obj)124 static int rtw_cmd_filter(struct cmd_priv *pcmdpriv, struct cmd_obj *cmd_obj)
125 {
126 	u8 bAllow = false; /* set to true to allow enqueuing cmd when hw_init_completed is false */
127 
128 	if (cmd_obj->cmdcode == GEN_CMD_CODE(_SetChannelPlan))
129 		bAllow = true;
130 
131 	if ((!pcmdpriv->padapter->hw_init_completed && !bAllow) ||
132 	    !pcmdpriv->cmdthd_running)	/* com_thread not running */
133 		return _FAIL;
134 	return _SUCCESS;
135 }
136 
rtw_enqueue_cmd(struct cmd_priv * pcmdpriv,struct cmd_obj * cmd_obj)137 u32 rtw_enqueue_cmd(struct cmd_priv *pcmdpriv, struct cmd_obj *cmd_obj)
138 {
139 	int res = _FAIL;
140 	struct adapter *padapter = pcmdpriv->padapter;
141 
142 	if (!cmd_obj)
143 		goto exit;
144 
145 	cmd_obj->padapter = padapter;
146 
147 	res = rtw_cmd_filter(pcmdpriv, cmd_obj);
148 	if (res == _FAIL) {
149 		rtw_free_cmd_obj(cmd_obj);
150 		goto exit;
151 	}
152 
153 	res = _rtw_enqueue_cmd(&pcmdpriv->cmd_queue, cmd_obj);
154 
155 	if (res == _SUCCESS)
156 		complete(&pcmdpriv->enqueue_cmd);
157 
158 exit:
159 
160 	return res;
161 }
162 
rtw_dequeue_cmd(struct cmd_priv * pcmdpriv)163 struct	cmd_obj	*rtw_dequeue_cmd(struct cmd_priv *pcmdpriv)
164 {
165 	struct cmd_obj *obj;
166 	struct __queue *queue = &pcmdpriv->cmd_queue;
167 	unsigned long flags;
168 
169 	spin_lock_irqsave(&queue->lock, flags);
170 	if (list_empty(&queue->queue)) {
171 		obj = NULL;
172 	} else {
173 		obj = container_of((&queue->queue)->next, struct cmd_obj, list);
174 		list_del_init(&obj->list);
175 	}
176 
177 	spin_unlock_irqrestore(&queue->lock, flags);
178 
179 	return obj;
180 }
181 
rtw_free_cmd_obj(struct cmd_obj * pcmd)182 void rtw_free_cmd_obj(struct cmd_obj *pcmd)
183 {
184 
185 	if ((pcmd->cmdcode != _JoinBss_CMD_) && (pcmd->cmdcode != _CreateBss_CMD_)) {
186 		/* free parmbuf in cmd_obj */
187 		kfree(pcmd->parmbuf);
188 	}
189 
190 	if (pcmd->rsp) {
191 		if (pcmd->rspsz != 0) {
192 			/* free rsp in cmd_obj */
193 			kfree(pcmd->rsp);
194 		}
195 	}
196 
197 	/* free cmd_obj */
198 	kfree(pcmd);
199 
200 }
201 
rtw_cmd_thread(void * context)202 int rtw_cmd_thread(void *context)
203 {
204 	u8 ret;
205 	struct cmd_obj *pcmd;
206 	u8 *pcmdbuf;
207 	u8 (*cmd_hdl)(struct adapter *padapter, u8 *pbuf);
208 	void (*pcmd_callback)(struct adapter *dev, struct cmd_obj *pcmd);
209 	struct adapter *padapter = (struct adapter *)context;
210 	struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
211 
212 	pcmdbuf = pcmdpriv->cmd_buf;
213 
214 	pcmdpriv->cmdthd_running = true;
215 	complete(&pcmdpriv->start_cmd_thread);
216 
217 	while (1) {
218 		wait_for_completion(&pcmdpriv->enqueue_cmd);
219 
220 _next:
221 		if (padapter->bDriverStopped ||
222 		    padapter->bSurpriseRemoved)
223 			break;
224 
225 		pcmd = rtw_dequeue_cmd(pcmdpriv);
226 		if (!pcmd)
227 			continue;
228 
229 		if (rtw_cmd_filter(pcmdpriv, pcmd) == _FAIL) {
230 			pcmd->res = H2C_DROPPED;
231 			goto post_process;
232 		}
233 
234 		pcmd->cmdsz = round_up(pcmd->cmdsz, 4);
235 
236 		memcpy(pcmdbuf, pcmd->parmbuf, pcmd->cmdsz);
237 
238 		if (pcmd->cmdcode < ARRAY_SIZE(wlancmds)) {
239 			cmd_hdl = wlancmds[pcmd->cmdcode].h2cfuns;
240 
241 			if (cmd_hdl) {
242 				ret = cmd_hdl(pcmd->padapter, pcmdbuf);
243 				pcmd->res = ret;
244 			}
245 
246 			pcmdpriv->cmd_seq++;
247 		} else {
248 			pcmd->res = H2C_PARAMETERS_ERROR;
249 		}
250 
251 		cmd_hdl = NULL;
252 
253 post_process:
254 
255 		/* call callback function for post-processed */
256 		if (pcmd->cmdcode < ARRAY_SIZE(rtw_cmd_callback)) {
257 			pcmd_callback = rtw_cmd_callback[pcmd->cmdcode].callback;
258 			if (!pcmd_callback)
259 				rtw_free_cmd_obj(pcmd);
260 			else
261 				/* todo: !!! fill rsp_buf to pcmd->rsp if (pcmd->rsp!= NULL) */
262 				pcmd_callback(pcmd->padapter, pcmd);/* need consider that free cmd_obj in rtw_cmd_callback */
263 		} else {
264 			rtw_free_cmd_obj(pcmd);
265 		}
266 
267 		flush_signals_thread();
268 
269 		goto _next;
270 	}
271 	pcmdpriv->cmdthd_running = false;
272 
273 	/*  free all cmd_obj resources */
274 	do {
275 		pcmd = rtw_dequeue_cmd(pcmdpriv);
276 		if (!pcmd)
277 			break;
278 
279 		rtw_free_cmd_obj(pcmd);
280 	} while (1);
281 
282 	complete(&pcmdpriv->stop_cmd_thread);
283 
284 	return 0;
285 }
286 
287 /* rtw_sitesurvey_cmd(~)
288  *	### NOTE:#### (!!!!)
289  *	MUST TAKE CARE THAT BEFORE CALLING THIS FUNC, YOU SHOULD HAVE LOCKED pmlmepriv->lock
290  */
rtw_sitesurvey_cmd(struct adapter * padapter,struct ndis_802_11_ssid * ssid,int ssid_num,struct rtw_ieee80211_channel * ch,int ch_num)291 u8 rtw_sitesurvey_cmd(struct adapter  *padapter, struct ndis_802_11_ssid *ssid, int ssid_num,
292 	struct rtw_ieee80211_channel *ch, int ch_num)
293 {
294 	u8 res = _FAIL;
295 	struct cmd_obj		*ph2c;
296 	struct sitesurvey_parm	*psurveyPara;
297 	struct cmd_priv		*pcmdpriv = &padapter->cmdpriv;
298 	struct mlme_priv	*pmlmepriv = &padapter->mlmepriv;
299 
300 	if (check_fwstate(pmlmepriv, _FW_LINKED))
301 		rtw_lps_ctrl_wk_cmd(padapter, LPS_CTRL_SCAN, 1);
302 
303 	if (check_fwstate(pmlmepriv, _FW_LINKED))
304 		p2p_ps_wk_cmd(padapter, P2P_PS_SCAN, 1);
305 
306 	ph2c = kzalloc(sizeof(*ph2c), GFP_ATOMIC);
307 	if (!ph2c)
308 		return _FAIL;
309 
310 	psurveyPara = kzalloc(sizeof(*psurveyPara), GFP_ATOMIC);
311 	if (!psurveyPara) {
312 		kfree(ph2c);
313 		return _FAIL;
314 	}
315 
316 	rtw_free_network_queue(padapter, false);
317 
318 	init_h2fwcmd_w_parm_no_rsp(ph2c, psurveyPara, GEN_CMD_CODE(_SiteSurvey));
319 
320 	/* psurveyPara->bsslimit = 48; */
321 	psurveyPara->scan_mode = pmlmepriv->scan_mode;
322 
323 	/* prepare ssid list */
324 	if (ssid) {
325 		int i;
326 		for (i = 0; i < ssid_num && i < RTW_SSID_SCAN_AMOUNT; i++) {
327 			if (ssid[i].SsidLength) {
328 				memcpy(&psurveyPara->ssid[i], &ssid[i], sizeof(struct ndis_802_11_ssid));
329 				psurveyPara->ssid_num++;
330 			}
331 		}
332 	}
333 
334 	/* prepare channel list */
335 	if (ch) {
336 		int i;
337 		for (i = 0; i < ch_num && i < RTW_CHANNEL_SCAN_AMOUNT; i++) {
338 			if (ch[i].hw_value && !(ch[i].flags & RTW_IEEE80211_CHAN_DISABLED)) {
339 				memcpy(&psurveyPara->ch[i], &ch[i], sizeof(struct rtw_ieee80211_channel));
340 				psurveyPara->ch_num++;
341 			}
342 		}
343 	}
344 
345 	set_fwstate(pmlmepriv, _FW_UNDER_SURVEY);
346 
347 	res = rtw_enqueue_cmd(pcmdpriv, ph2c);
348 
349 	if (res == _SUCCESS) {
350 		pmlmepriv->scan_start_time = jiffies;
351 
352 		_set_timer(&pmlmepriv->scan_to_timer, SCANNING_TIMEOUT);
353 
354 		rtw_led_control(padapter, LED_CTL_SITE_SURVEY);
355 
356 		pmlmepriv->scan_interval = SCAN_INTERVAL;/*  30*2 sec = 60sec */
357 	} else {
358 		_clr_fwstate_(pmlmepriv, _FW_UNDER_SURVEY);
359 	}
360 
361 	return res;
362 }
363 
rtw_setdatarate_cmd(struct adapter * padapter,u8 * rateset)364 u8 rtw_setdatarate_cmd(struct adapter *padapter, u8 *rateset)
365 {
366 	struct cmd_obj *ph2c;
367 	struct setdatarate_parm *pbsetdataratepara;
368 	struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
369 	u8	res = _SUCCESS;
370 
371 	ph2c = kzalloc(sizeof(*ph2c), GFP_ATOMIC);
372 	if (!ph2c) {
373 		res = _FAIL;
374 		goto exit;
375 	}
376 
377 	pbsetdataratepara = kzalloc(sizeof(*pbsetdataratepara), GFP_ATOMIC);
378 	if (!pbsetdataratepara) {
379 		kfree(ph2c);
380 		res = _FAIL;
381 		goto exit;
382 	}
383 
384 	init_h2fwcmd_w_parm_no_rsp(ph2c, pbsetdataratepara, GEN_CMD_CODE(_SetDataRate));
385 	pbsetdataratepara->mac_id = 5;
386 	memcpy(pbsetdataratepara->datarates, rateset, NumRates);
387 	res = rtw_enqueue_cmd(pcmdpriv, ph2c);
388 exit:
389 
390 	return res;
391 }
392 
rtw_getbbrfreg_cmdrsp_callback(struct adapter * padapter,struct cmd_obj * pcmd)393 void rtw_getbbrfreg_cmdrsp_callback(struct adapter *padapter,  struct cmd_obj *pcmd)
394 {
395 
396 
397 	kfree(pcmd->parmbuf);
398 	kfree(pcmd);
399 }
400 
rtw_createbss_cmd(struct adapter * padapter)401 u8 rtw_createbss_cmd(struct adapter  *padapter)
402 {
403 	struct cmd_obj *pcmd;
404 	struct cmd_priv	*pcmdpriv = &padapter->cmdpriv;
405 	struct wlan_bssid_ex *pdev_network = &padapter->registrypriv.dev_network;
406 	u8	res = _SUCCESS;
407 
408 	rtw_led_control(padapter, LED_CTL_START_TO_LINK);
409 
410 	pcmd = kzalloc(sizeof(*pcmd), GFP_ATOMIC);
411 	if (!pcmd) {
412 		res = _FAIL;
413 		goto exit;
414 	}
415 
416 	INIT_LIST_HEAD(&pcmd->list);
417 	pcmd->cmdcode = _CreateBss_CMD_;
418 	pcmd->parmbuf = (unsigned char *)pdev_network;
419 	pcmd->cmdsz = get_wlan_bssid_ex_sz((struct wlan_bssid_ex *)pdev_network);
420 	pcmd->rsp = NULL;
421 	pcmd->rspsz = 0;
422 	pdev_network->Length = pcmd->cmdsz;
423 	res = rtw_enqueue_cmd(pcmdpriv, pcmd);
424 exit:
425 
426 	return res;
427 }
428 
rtw_joinbss_cmd(struct adapter * padapter,struct wlan_network * pnetwork)429 u8 rtw_joinbss_cmd(struct adapter  *padapter, struct wlan_network *pnetwork)
430 {
431 	u8	res = _SUCCESS;
432 	uint	t_len = 0;
433 	struct wlan_bssid_ex		*psecnetwork;
434 	struct cmd_obj		*pcmd;
435 	struct cmd_priv		*pcmdpriv = &padapter->cmdpriv;
436 	struct mlme_priv	*pmlmepriv = &padapter->mlmepriv;
437 	struct qos_priv		*pqospriv = &pmlmepriv->qospriv;
438 	struct security_priv	*psecuritypriv = &padapter->securitypriv;
439 	struct registry_priv	*pregistrypriv = &padapter->registrypriv;
440 	struct ht_priv		*phtpriv = &pmlmepriv->htpriv;
441 	enum ndis_802_11_network_infra ndis_network_mode = pnetwork->network.InfrastructureMode;
442 	struct mlme_ext_priv	*pmlmeext = &padapter->mlmeextpriv;
443 	struct mlme_ext_info	*pmlmeinfo = &pmlmeext->mlmext_info;
444 
445 	rtw_led_control(padapter, LED_CTL_START_TO_LINK);
446 
447 	pcmd = kzalloc(sizeof(*pcmd), GFP_ATOMIC);
448 	if (!pcmd) {
449 		res = _FAIL;
450 		goto exit;
451 	}
452 	/* for IEs is fix buf size */
453 	t_len = sizeof(struct wlan_bssid_ex);
454 
455 	/* for hidden ap to set fw_state here */
456 	if (!check_fwstate(pmlmepriv, WIFI_STATION_STATE | WIFI_ADHOC_STATE)) {
457 		switch (ndis_network_mode) {
458 		case Ndis802_11IBSS:
459 			set_fwstate(pmlmepriv, WIFI_ADHOC_STATE);
460 			break;
461 		case Ndis802_11Infrastructure:
462 			set_fwstate(pmlmepriv, WIFI_STATION_STATE);
463 			break;
464 		case Ndis802_11APMode:
465 		case Ndis802_11AutoUnknown:
466 		case Ndis802_11InfrastructureMax:
467 			break;
468 		}
469 	}
470 
471 	psecnetwork = (struct wlan_bssid_ex *)&psecuritypriv->sec_bss;
472 	if (!psecnetwork) {
473 		kfree(pcmd);
474 		res = _FAIL;
475 		goto exit;
476 	}
477 
478 	memset(psecnetwork, 0, t_len);
479 
480 	memcpy(psecnetwork, &pnetwork->network, get_wlan_bssid_ex_sz(&pnetwork->network));
481 
482 	psecuritypriv->authenticator_ie[0] = (unsigned char)psecnetwork->IELength;
483 
484 	if (psecnetwork->IELength - 12 < 255)
485 		memcpy(&psecuritypriv->authenticator_ie[1], &psecnetwork->IEs[12], psecnetwork->IELength - 12);
486 	else
487 		memcpy(&psecuritypriv->authenticator_ie[1], &psecnetwork->IEs[12], 255);
488 
489 	psecnetwork->IELength = 0;
490 	/*  Added by Albert 2009/02/18 */
491 	/*  If the driver wants to use the bssid to create the connection. */
492 	/*  If not,  we have to copy the connecting AP's MAC address to it so that */
493 	/*  the driver just has the bssid information for PMKIDList searching. */
494 
495 	if (!pmlmepriv->assoc_by_bssid)
496 		memcpy(&pmlmepriv->assoc_bssid[0], &pnetwork->network.MacAddress[0], ETH_ALEN);
497 
498 	psecnetwork->IELength = rtw_restruct_sec_ie(padapter, &pnetwork->network.IEs[0], &psecnetwork->IEs[0], pnetwork->network.IELength);
499 
500 	pqospriv->qos_option = 0;
501 
502 	if (pregistrypriv->wmm_enable) {
503 		u32 tmp_len;
504 
505 		tmp_len = rtw_restruct_wmm_ie(padapter, &pnetwork->network.IEs[0], &psecnetwork->IEs[0], pnetwork->network.IELength, psecnetwork->IELength);
506 
507 		if (psecnetwork->IELength != tmp_len) {
508 			psecnetwork->IELength = tmp_len;
509 			pqospriv->qos_option = 1; /* There is WMM IE in this corresp. beacon */
510 		} else {
511 			pqospriv->qos_option = 0;/* There is no WMM IE in this corresp. beacon */
512 		}
513 	}
514 
515 	phtpriv->ht_option = false;
516 	if (pregistrypriv->ht_enable) {
517 		/*	Added by Albert 2010/06/23 */
518 		/*	For the WEP mode, we will use the bg mode to do the connection to avoid some IOT issue. */
519 		/*	Especially for Realtek 8192u SoftAP. */
520 		if ((padapter->securitypriv.dot11PrivacyAlgrthm != _WEP40_) &&
521 		    (padapter->securitypriv.dot11PrivacyAlgrthm != _WEP104_) &&
522 		    (padapter->securitypriv.dot11PrivacyAlgrthm != _TKIP_)) {
523 			/* rtw_restructure_ht_ie */
524 			rtw_restructure_ht_ie(padapter, &pnetwork->network.IEs[0], &psecnetwork->IEs[0],
525 									pnetwork->network.IELength, &psecnetwork->IELength);
526 		}
527 	}
528 
529 	pmlmeinfo->assoc_AP_vendor = check_assoc_AP(pnetwork->network.IEs, pnetwork->network.IELength);
530 
531 	if (pmlmeinfo->assoc_AP_vendor == HT_IOT_PEER_TENDA)
532 		padapter->pwrctrlpriv.smart_ps = 0;
533 	else
534 		padapter->pwrctrlpriv.smart_ps = padapter->registrypriv.smart_ps;
535 
536 	pcmd->cmdsz = get_wlan_bssid_ex_sz(psecnetwork);/* get cmdsz before endian conversion */
537 
538 	INIT_LIST_HEAD(&pcmd->list);
539 	pcmd->cmdcode = _JoinBss_CMD_;/* GEN_CMD_CODE(_JoinBss) */
540 	pcmd->parmbuf = (unsigned char *)psecnetwork;
541 	pcmd->rsp = NULL;
542 	pcmd->rspsz = 0;
543 
544 	res = rtw_enqueue_cmd(pcmdpriv, pcmd);
545 
546 exit:
547 
548 	return res;
549 }
550 
rtw_disassoc_cmd(struct adapter * padapter,u32 deauth_timeout_ms,bool enqueue)551 u8 rtw_disassoc_cmd(struct adapter *padapter, u32 deauth_timeout_ms, bool enqueue) /* for sta_mode */
552 {
553 	struct cmd_obj *cmdobj = NULL;
554 	struct disconnect_parm *param = NULL;
555 	struct cmd_priv *cmdpriv = &padapter->cmdpriv;
556 	u8 res = _SUCCESS;
557 
558 	/* prepare cmd parameter */
559 	param = kzalloc(sizeof(*param), GFP_ATOMIC);
560 	if (!param) {
561 		res = _FAIL;
562 		goto exit;
563 	}
564 	param->deauth_timeout_ms = deauth_timeout_ms;
565 
566 	if (enqueue) {
567 		/* need enqueue, prepare cmd_obj and enqueue */
568 		cmdobj = kzalloc(sizeof(*cmdobj), GFP_ATOMIC);
569 		if (!cmdobj) {
570 			res = _FAIL;
571 			kfree(param);
572 			goto exit;
573 		}
574 		init_h2fwcmd_w_parm_no_rsp(cmdobj, param, _DisConnect_CMD_);
575 		res = rtw_enqueue_cmd(cmdpriv, cmdobj);
576 	} else {
577 		/* no need to enqueue, do the cmd hdl directly and free cmd parameter */
578 		if (disconnect_hdl(padapter, (u8 *)param) != H2C_SUCCESS)
579 			res = _FAIL;
580 		kfree(param);
581 	}
582 
583 exit:
584 
585 	return res;
586 }
587 
rtw_setopmode_cmd(struct adapter * padapter,enum ndis_802_11_network_infra networktype)588 u8 rtw_setopmode_cmd(struct adapter  *padapter, enum ndis_802_11_network_infra networktype)
589 {
590 	struct	cmd_obj *ph2c;
591 	struct	setopmode_parm *psetop;
592 
593 	struct	cmd_priv   *pcmdpriv = &padapter->cmdpriv;
594 	u8	res = _SUCCESS;
595 
596 	ph2c = kzalloc(sizeof(*ph2c), GFP_KERNEL);
597 	if (!ph2c) {
598 		res = false;
599 		goto exit;
600 	}
601 	psetop = kzalloc(sizeof(*psetop), GFP_KERNEL);
602 
603 	if (!psetop) {
604 		kfree(ph2c);
605 		res = false;
606 		goto exit;
607 	}
608 
609 	init_h2fwcmd_w_parm_no_rsp(ph2c, psetop, _SetOpMode_CMD_);
610 	psetop->mode = (u8)networktype;
611 
612 	res = rtw_enqueue_cmd(pcmdpriv, ph2c);
613 
614 exit:
615 
616 	return res;
617 }
618 
rtw_setstakey_cmd(struct adapter * padapter,u8 * psta,u8 unicast_key)619 u8 rtw_setstakey_cmd(struct adapter *padapter, u8 *psta, u8 unicast_key)
620 {
621 	struct cmd_obj *ph2c;
622 	struct set_stakey_parm *psetstakey_para;
623 	struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
624 	struct set_stakey_rsp *psetstakey_rsp = NULL;
625 
626 	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
627 	struct security_priv *psecuritypriv = &padapter->securitypriv;
628 	struct sta_info *sta = (struct sta_info *)psta;
629 	u8	res = _SUCCESS;
630 
631 	ph2c = kzalloc(sizeof(*ph2c), GFP_KERNEL);
632 	if (!ph2c) {
633 		res = _FAIL;
634 		goto exit;
635 	}
636 
637 	psetstakey_para = kzalloc(sizeof(*psetstakey_para), GFP_KERNEL);
638 	if (!psetstakey_para) {
639 		kfree(ph2c);
640 		res = _FAIL;
641 		goto exit;
642 	}
643 
644 	psetstakey_rsp = kzalloc(sizeof(*psetstakey_rsp), GFP_KERNEL);
645 	if (!psetstakey_rsp) {
646 		kfree(ph2c);
647 		kfree(psetstakey_para);
648 		res = _FAIL;
649 		goto exit;
650 	}
651 
652 	init_h2fwcmd_w_parm_no_rsp(ph2c, psetstakey_para, _SetStaKey_CMD_);
653 	ph2c->rsp = (u8 *)psetstakey_rsp;
654 	ph2c->rspsz = sizeof(struct set_stakey_rsp);
655 
656 	memcpy(psetstakey_para->addr, sta->hwaddr, ETH_ALEN);
657 
658 	if (check_fwstate(pmlmepriv, WIFI_STATION_STATE))
659 		psetstakey_para->algorithm = (unsigned char)psecuritypriv->dot11PrivacyAlgrthm;
660 	else
661 		GET_ENCRY_ALGO(psecuritypriv, sta, psetstakey_para->algorithm, false);
662 
663 	if (unicast_key)
664 		memcpy(&psetstakey_para->key, &sta->dot118021x_UncstKey, 16);
665 	else
666 		memcpy(&psetstakey_para->key, &psecuritypriv->dot118021XGrpKey[psecuritypriv->dot118021XGrpKeyid].skey, 16);
667 
668 	/* jeff: set this because at least sw key is ready */
669 	padapter->securitypriv.busetkipkey = true;
670 
671 	res = rtw_enqueue_cmd(pcmdpriv, ph2c);
672 
673 exit:
674 
675 	return res;
676 }
677 
rtw_clearstakey_cmd(struct adapter * padapter,u8 * psta,u8 entry,u8 enqueue)678 u8 rtw_clearstakey_cmd(struct adapter *padapter, u8 *psta, u8 entry, u8 enqueue)
679 {
680 	struct cmd_obj *ph2c;
681 	struct set_stakey_parm	*psetstakey_para;
682 	struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
683 	struct set_stakey_rsp *psetstakey_rsp = NULL;
684 	struct sta_info *sta = (struct sta_info *)psta;
685 	u8	res = _SUCCESS;
686 
687 	if (!enqueue) {
688 		clear_cam_entry(padapter, entry);
689 	} else {
690 		ph2c = kzalloc(sizeof(*ph2c), GFP_ATOMIC);
691 		if (!ph2c) {
692 			res = _FAIL;
693 			goto exit;
694 		}
695 
696 		psetstakey_para = kzalloc(sizeof(*psetstakey_para),
697 					  GFP_ATOMIC);
698 		if (!psetstakey_para) {
699 			kfree(ph2c);
700 			res = _FAIL;
701 			goto exit;
702 		}
703 
704 		psetstakey_rsp = kzalloc(sizeof(*psetstakey_rsp),
705 					 GFP_ATOMIC);
706 		if (!psetstakey_rsp) {
707 			kfree(ph2c);
708 			kfree(psetstakey_para);
709 			res = _FAIL;
710 			goto exit;
711 		}
712 
713 		init_h2fwcmd_w_parm_no_rsp(ph2c, psetstakey_para, _SetStaKey_CMD_);
714 		ph2c->rsp = (u8 *)psetstakey_rsp;
715 		ph2c->rspsz = sizeof(struct set_stakey_rsp);
716 
717 		memcpy(psetstakey_para->addr, sta->hwaddr, ETH_ALEN);
718 
719 		psetstakey_para->algorithm = _NO_PRIVACY_;
720 
721 		psetstakey_para->id = entry;
722 
723 		res = rtw_enqueue_cmd(pcmdpriv, ph2c);
724 	}
725 exit:
726 
727 	return res;
728 }
729 
rtw_addbareq_cmd(struct adapter * padapter,u8 tid,u8 * addr)730 u8 rtw_addbareq_cmd(struct adapter *padapter, u8 tid, u8 *addr)
731 {
732 	struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
733 	struct cmd_obj *ph2c;
734 	struct addBaReq_parm *paddbareq_parm;
735 	u8	res = _SUCCESS;
736 
737 	ph2c = kzalloc(sizeof(*ph2c), GFP_ATOMIC);
738 	if (!ph2c) {
739 		res = _FAIL;
740 		goto exit;
741 	}
742 
743 	paddbareq_parm = kzalloc(sizeof(*paddbareq_parm), GFP_ATOMIC);
744 	if (!paddbareq_parm) {
745 		kfree(ph2c);
746 		res = _FAIL;
747 		goto exit;
748 	}
749 
750 	paddbareq_parm->tid = tid;
751 	memcpy(paddbareq_parm->addr, addr, ETH_ALEN);
752 
753 	init_h2fwcmd_w_parm_no_rsp(ph2c, paddbareq_parm, GEN_CMD_CODE(_AddBAReq));
754 
755 	/* rtw_enqueue_cmd(pcmdpriv, ph2c); */
756 	res = rtw_enqueue_cmd(pcmdpriv, ph2c);
757 
758 exit:
759 
760 	return res;
761 }
762 
rtw_dynamic_chk_wk_cmd(struct adapter * padapter)763 u8 rtw_dynamic_chk_wk_cmd(struct adapter *padapter)
764 {
765 	struct cmd_obj *ph2c;
766 	struct drvextra_cmd_parm *pdrvextra_cmd_parm;
767 	struct cmd_priv	*pcmdpriv = &padapter->cmdpriv;
768 	u8	res = _SUCCESS;
769 
770 	ph2c = kzalloc(sizeof(*ph2c), GFP_ATOMIC);
771 	if (!ph2c) {
772 		res = _FAIL;
773 		goto exit;
774 	}
775 
776 	pdrvextra_cmd_parm = kzalloc(sizeof(*pdrvextra_cmd_parm), GFP_ATOMIC);
777 	if (!pdrvextra_cmd_parm) {
778 		kfree(ph2c);
779 		res = _FAIL;
780 		goto exit;
781 	}
782 
783 	pdrvextra_cmd_parm->ec_id = DYNAMIC_CHK_WK_CID;
784 	pdrvextra_cmd_parm->type_size = 0;
785 	pdrvextra_cmd_parm->pbuf = (u8 *)padapter;
786 
787 	init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, GEN_CMD_CODE(_Set_Drv_Extra));
788 
789 	/* rtw_enqueue_cmd(pcmdpriv, ph2c); */
790 	res = rtw_enqueue_cmd(pcmdpriv, ph2c);
791 exit:
792 
793 	return res;
794 }
795 
rtw_set_chplan_cmd(struct adapter * padapter,u8 chplan)796 u8 rtw_set_chplan_cmd(struct adapter *padapter, u8 chplan)
797 {
798 	struct	cmd_obj *pcmdobj;
799 	struct	SetChannelPlan_param *setChannelPlan_param;
800 	struct	cmd_priv   *pcmdpriv = &padapter->cmdpriv;
801 
802 	u8	res = _SUCCESS;
803 
804 	/* check input parameter */
805 	if (!rtw_is_channel_plan_valid(chplan)) {
806 		res = _FAIL;
807 		goto exit;
808 	}
809 
810 	/* prepare cmd parameter */
811 	setChannelPlan_param = kzalloc(sizeof(*setChannelPlan_param),
812 				       GFP_KERNEL);
813 	if (!setChannelPlan_param) {
814 		res = _FAIL;
815 		goto exit;
816 	}
817 	setChannelPlan_param->channel_plan = chplan;
818 
819 	/* need enqueue, prepare cmd_obj and enqueue */
820 	pcmdobj = kzalloc(sizeof(*pcmdobj), GFP_KERNEL);
821 	if (!pcmdobj) {
822 		kfree(setChannelPlan_param);
823 		res = _FAIL;
824 		goto exit;
825 	}
826 
827 	init_h2fwcmd_w_parm_no_rsp(pcmdobj, setChannelPlan_param, GEN_CMD_CODE(_SetChannelPlan));
828 	res = rtw_enqueue_cmd(pcmdpriv, pcmdobj);
829 
830 	/* do something based on res... */
831 	if (res == _SUCCESS)
832 		padapter->mlmepriv.ChannelPlan = chplan;
833 
834 exit:
835 
836 	return res;
837 }
838 
traffic_status_watchdog(struct adapter * padapter)839 static void traffic_status_watchdog(struct adapter *padapter)
840 {
841 	u8	bEnterPS;
842 	u8	bBusyTraffic = false, bTxBusyTraffic = false, bRxBusyTraffic = false;
843 	u8	bHigherBusyTraffic = false, bHigherBusyRxTraffic = false, bHigherBusyTxTraffic = false;
844 	struct mlme_priv		*pmlmepriv = &padapter->mlmepriv;
845 
846 	/*  */
847 	/*  Determine if our traffic is busy now */
848 	/*  */
849 	if (check_fwstate(pmlmepriv, _FW_LINKED)) {
850 		if (pmlmepriv->LinkDetectInfo.NumRxOkInPeriod > 100 ||
851 		    pmlmepriv->LinkDetectInfo.NumTxOkInPeriod > 100) {
852 			bBusyTraffic = true;
853 
854 			if (pmlmepriv->LinkDetectInfo.NumRxOkInPeriod > pmlmepriv->LinkDetectInfo.NumTxOkInPeriod)
855 				bRxBusyTraffic = true;
856 			else
857 				bTxBusyTraffic = true;
858 		}
859 
860 		/*  Higher Tx/Rx data. */
861 		if (pmlmepriv->LinkDetectInfo.NumRxOkInPeriod > 4000 ||
862 		    pmlmepriv->LinkDetectInfo.NumTxOkInPeriod > 4000) {
863 			bHigherBusyTraffic = true;
864 
865 			if (pmlmepriv->LinkDetectInfo.NumRxOkInPeriod > pmlmepriv->LinkDetectInfo.NumTxOkInPeriod)
866 				bHigherBusyRxTraffic = true;
867 			else
868 				bHigherBusyTxTraffic = true;
869 		}
870 
871 		/*  check traffic for  powersaving. */
872 		if (((pmlmepriv->LinkDetectInfo.NumRxUnicastOkInPeriod + pmlmepriv->LinkDetectInfo.NumTxOkInPeriod) > 8) ||
873 		    (pmlmepriv->LinkDetectInfo.NumRxUnicastOkInPeriod > 2))
874 			bEnterPS = false;
875 		else
876 			bEnterPS = true;
877 
878 		/*  LeisurePS only work in infra mode. */
879 		if (bEnterPS)
880 			LPS_Enter(padapter);
881 		else
882 			LPS_Leave(padapter);
883 	} else {
884 		LPS_Leave(padapter);
885 	}
886 
887 	pmlmepriv->LinkDetectInfo.NumRxOkInPeriod = 0;
888 	pmlmepriv->LinkDetectInfo.NumTxOkInPeriod = 0;
889 	pmlmepriv->LinkDetectInfo.NumRxUnicastOkInPeriod = 0;
890 	pmlmepriv->LinkDetectInfo.bBusyTraffic = bBusyTraffic;
891 	pmlmepriv->LinkDetectInfo.bTxBusyTraffic = bTxBusyTraffic;
892 	pmlmepriv->LinkDetectInfo.bRxBusyTraffic = bRxBusyTraffic;
893 	pmlmepriv->LinkDetectInfo.bHigherBusyTraffic = bHigherBusyTraffic;
894 	pmlmepriv->LinkDetectInfo.bHigherBusyRxTraffic = bHigherBusyRxTraffic;
895 	pmlmepriv->LinkDetectInfo.bHigherBusyTxTraffic = bHigherBusyTxTraffic;
896 }
897 
rtl8188e_sreset_xmit_status_check(struct adapter * padapter)898 static void rtl8188e_sreset_xmit_status_check(struct adapter *padapter)
899 {
900 	u32 txdma_status;
901 	int res;
902 
903 	res = rtw_read32(padapter, REG_TXDMA_STATUS, &txdma_status);
904 	if (res)
905 		return;
906 
907 	if (txdma_status != 0x00)
908 		rtw_write32(padapter, REG_TXDMA_STATUS, txdma_status);
909 	/* total xmit irp = 4 */
910 }
911 
dynamic_chk_wk_hdl(struct adapter * padapter,u8 * pbuf)912 static void dynamic_chk_wk_hdl(struct adapter *padapter, u8 *pbuf)
913 {
914 	struct mlme_priv *pmlmepriv;
915 
916 	padapter = (struct adapter *)pbuf;
917 	pmlmepriv = &padapter->mlmepriv;
918 
919 	if (check_fwstate(pmlmepriv, WIFI_AP_STATE))
920 		expire_timeout_chk(padapter);
921 
922 	rtl8188e_sreset_xmit_status_check(padapter);
923 
924 	linked_status_chk(padapter);
925 	traffic_status_watchdog(padapter);
926 
927 	rtl8188e_HalDmWatchDog(padapter);
928 }
929 
lps_ctrl_wk_hdl(struct adapter * padapter,u8 lps_ctrl_type)930 static void lps_ctrl_wk_hdl(struct adapter *padapter, u8 lps_ctrl_type)
931 {
932 	struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv;
933 	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
934 	u8	mstatus;
935 
936 	if (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) ||
937 	    check_fwstate(pmlmepriv, WIFI_ADHOC_STATE))
938 		return;
939 
940 	switch (lps_ctrl_type) {
941 	case LPS_CTRL_SCAN:
942 		if (check_fwstate(pmlmepriv, _FW_LINKED)) {
943 			/* connect */
944 			LPS_Leave(padapter);
945 		}
946 		break;
947 	case LPS_CTRL_JOINBSS:
948 		LPS_Leave(padapter);
949 		break;
950 	case LPS_CTRL_CONNECT:
951 		mstatus = 1;/* connect */
952 		/*  Reset LPS Setting */
953 		padapter->pwrctrlpriv.LpsIdleCount = 0;
954 		rtl8188e_set_FwJoinBssReport_cmd(padapter, mstatus);
955 		break;
956 	case LPS_CTRL_DISCONNECT:
957 		mstatus = 0;/* disconnect */
958 		LPS_Leave(padapter);
959 		rtl8188e_set_FwJoinBssReport_cmd(padapter, mstatus);
960 		break;
961 	case LPS_CTRL_SPECIAL_PACKET:
962 		pwrpriv->DelayLPSLastTimeStamp = jiffies;
963 		LPS_Leave(padapter);
964 		break;
965 	case LPS_CTRL_LEAVE:
966 		LPS_Leave(padapter);
967 		break;
968 	default:
969 		break;
970 	}
971 
972 }
973 
rtw_lps_ctrl_wk_cmd(struct adapter * padapter,u8 lps_ctrl_type,u8 enqueue)974 u8 rtw_lps_ctrl_wk_cmd(struct adapter *padapter, u8 lps_ctrl_type, u8 enqueue)
975 {
976 	struct cmd_obj	*ph2c;
977 	struct drvextra_cmd_parm	*pdrvextra_cmd_parm;
978 	struct cmd_priv	*pcmdpriv = &padapter->cmdpriv;
979 	/* struct pwrctrl_priv *pwrctrlpriv = &padapter->pwrctrlpriv; */
980 	u8	res = _SUCCESS;
981 
982 	/* if (!pwrctrlpriv->bLeisurePs) */
983 	/*	return res; */
984 
985 	if (enqueue) {
986 		ph2c = kzalloc(sizeof(*ph2c), GFP_ATOMIC);
987 		if (!ph2c) {
988 			res = _FAIL;
989 			goto exit;
990 		}
991 
992 		pdrvextra_cmd_parm = kzalloc(sizeof(*pdrvextra_cmd_parm),
993 					     GFP_ATOMIC);
994 		if (!pdrvextra_cmd_parm) {
995 			kfree(ph2c);
996 			res = _FAIL;
997 			goto exit;
998 		}
999 
1000 		pdrvextra_cmd_parm->ec_id = LPS_CTRL_WK_CID;
1001 		pdrvextra_cmd_parm->type_size = lps_ctrl_type;
1002 		pdrvextra_cmd_parm->pbuf = NULL;
1003 
1004 		init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, GEN_CMD_CODE(_Set_Drv_Extra));
1005 
1006 		res = rtw_enqueue_cmd(pcmdpriv, ph2c);
1007 	} else {
1008 		lps_ctrl_wk_hdl(padapter, lps_ctrl_type);
1009 	}
1010 
1011 exit:
1012 
1013 	return res;
1014 }
1015 
rpt_timer_setting_wk_hdl(struct adapter * padapter,u16 min_time)1016 static void rpt_timer_setting_wk_hdl(struct adapter *padapter, u16 min_time)
1017 {
1018 	struct hal_data_8188e *haldata = &padapter->haldata;
1019 	struct odm_dm_struct *odmpriv = &haldata->odmpriv;
1020 
1021 	ODM_RA_Set_TxRPT_Time(odmpriv, min_time);
1022 }
1023 
rtw_rpt_timer_cfg_cmd(struct adapter * padapter,u16 min_time)1024 u8 rtw_rpt_timer_cfg_cmd(struct adapter *padapter, u16 min_time)
1025 {
1026 	struct cmd_obj		*ph2c;
1027 	struct drvextra_cmd_parm	*pdrvextra_cmd_parm;
1028 	struct cmd_priv	*pcmdpriv = &padapter->cmdpriv;
1029 
1030 	u8	res = _SUCCESS;
1031 
1032 	ph2c = kzalloc(sizeof(*ph2c), GFP_ATOMIC);
1033 	if (!ph2c) {
1034 		res = _FAIL;
1035 		goto exit;
1036 	}
1037 
1038 	pdrvextra_cmd_parm = kzalloc(sizeof(*pdrvextra_cmd_parm),
1039 				     GFP_ATOMIC);
1040 	if (!pdrvextra_cmd_parm) {
1041 		kfree(ph2c);
1042 		res = _FAIL;
1043 		goto exit;
1044 	}
1045 
1046 	pdrvextra_cmd_parm->ec_id = RTP_TIMER_CFG_WK_CID;
1047 	pdrvextra_cmd_parm->type_size = min_time;
1048 	pdrvextra_cmd_parm->pbuf = NULL;
1049 	init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, GEN_CMD_CODE(_Set_Drv_Extra));
1050 	res = rtw_enqueue_cmd(pcmdpriv, ph2c);
1051 exit:
1052 
1053 	return res;
1054 }
1055 
antenna_select_wk_hdl(struct adapter * padapter,u8 antenna)1056 static void antenna_select_wk_hdl(struct adapter *padapter, u8 antenna)
1057 {
1058 	struct hal_data_8188e *haldata = &padapter->haldata;
1059 
1060 	/* switch current antenna to optimum antenna */
1061 	if (haldata->CurAntenna != antenna) {
1062 		ODM_UpdateRxIdleAnt_88E(&haldata->odmpriv, antenna == 2 ? MAIN_ANT : AUX_ANT);
1063 		haldata->CurAntenna = antenna;
1064 	}
1065 }
1066 
rtw_antenna_diversity(struct adapter * adapter)1067 static bool rtw_antenna_diversity(struct adapter *adapter)
1068 {
1069 	struct hal_data_8188e *haldata = &adapter->haldata;
1070 
1071 	return haldata->AntDivCfg != 0;
1072 }
1073 
rtw_antenna_select_cmd(struct adapter * padapter,u8 antenna,u8 enqueue)1074 u8 rtw_antenna_select_cmd(struct adapter *padapter, u8 antenna, u8 enqueue)
1075 {
1076 	struct cmd_obj		*ph2c;
1077 	struct drvextra_cmd_parm	*pdrvextra_cmd_parm;
1078 	struct cmd_priv	*pcmdpriv = &padapter->cmdpriv;
1079 	u8	res = _SUCCESS;
1080 
1081 	if (!rtw_antenna_diversity(padapter))
1082 		return res;
1083 
1084 	if (enqueue) {
1085 		ph2c = kzalloc(sizeof(*ph2c), GFP_KERNEL);
1086 		if (!ph2c) {
1087 			res = _FAIL;
1088 			goto exit;
1089 		}
1090 
1091 		pdrvextra_cmd_parm = kzalloc(sizeof(*pdrvextra_cmd_parm),
1092 					     GFP_KERNEL);
1093 		if (!pdrvextra_cmd_parm) {
1094 			kfree(ph2c);
1095 			res = _FAIL;
1096 			goto exit;
1097 		}
1098 
1099 		pdrvextra_cmd_parm->ec_id = ANT_SELECT_WK_CID;
1100 		pdrvextra_cmd_parm->type_size = antenna;
1101 		pdrvextra_cmd_parm->pbuf = NULL;
1102 		init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, GEN_CMD_CODE(_Set_Drv_Extra));
1103 
1104 		res = rtw_enqueue_cmd(pcmdpriv, ph2c);
1105 	} else {
1106 		antenna_select_wk_hdl(padapter, antenna);
1107 	}
1108 exit:
1109 
1110 	return res;
1111 }
1112 
p2p_protocol_wk_cmd(struct adapter * padapter,int intCmdType)1113 u8 p2p_protocol_wk_cmd(struct adapter *padapter, int intCmdType)
1114 {
1115 	struct cmd_obj	*ph2c;
1116 	struct drvextra_cmd_parm	*pdrvextra_cmd_parm;
1117 	struct wifidirect_info	*pwdinfo = &padapter->wdinfo;
1118 	struct cmd_priv	*pcmdpriv = &padapter->cmdpriv;
1119 	u8	res = _SUCCESS;
1120 
1121 	if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE))
1122 		return res;
1123 
1124 	ph2c = kzalloc(sizeof(*ph2c), GFP_ATOMIC);
1125 	if (!ph2c) {
1126 		res = _FAIL;
1127 		goto exit;
1128 	}
1129 
1130 	pdrvextra_cmd_parm = kzalloc(sizeof(*pdrvextra_cmd_parm), GFP_ATOMIC);
1131 	if (!pdrvextra_cmd_parm) {
1132 		kfree(ph2c);
1133 		res = _FAIL;
1134 		goto exit;
1135 	}
1136 
1137 	pdrvextra_cmd_parm->ec_id = P2P_PROTO_WK_CID;
1138 	pdrvextra_cmd_parm->type_size = intCmdType;	/*	As the command type. */
1139 	pdrvextra_cmd_parm->pbuf = NULL;		/*	Must be NULL here */
1140 
1141 	init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, GEN_CMD_CODE(_Set_Drv_Extra));
1142 
1143 	res = rtw_enqueue_cmd(pcmdpriv, ph2c);
1144 
1145 exit:
1146 
1147 	return res;
1148 }
1149 
rtw_ps_cmd(struct adapter * padapter)1150 u8 rtw_ps_cmd(struct adapter *padapter)
1151 {
1152 	struct cmd_obj		*ppscmd;
1153 	struct drvextra_cmd_parm	*pdrvextra_cmd_parm;
1154 	struct cmd_priv	*pcmdpriv = &padapter->cmdpriv;
1155 
1156 	u8	res = _SUCCESS;
1157 
1158 	ppscmd = kzalloc(sizeof(*ppscmd), GFP_ATOMIC);
1159 	if (!ppscmd) {
1160 		res = _FAIL;
1161 		goto exit;
1162 	}
1163 
1164 	pdrvextra_cmd_parm = kzalloc(sizeof(*pdrvextra_cmd_parm), GFP_ATOMIC);
1165 	if (!pdrvextra_cmd_parm) {
1166 		kfree(ppscmd);
1167 		res = _FAIL;
1168 		goto exit;
1169 	}
1170 
1171 	pdrvextra_cmd_parm->ec_id = POWER_SAVING_CTRL_WK_CID;
1172 	pdrvextra_cmd_parm->pbuf = NULL;
1173 	init_h2fwcmd_w_parm_no_rsp(ppscmd, pdrvextra_cmd_parm, GEN_CMD_CODE(_Set_Drv_Extra));
1174 
1175 	res = rtw_enqueue_cmd(pcmdpriv, ppscmd);
1176 
1177 exit:
1178 
1179 	return res;
1180 }
1181 
rtw_is_hi_queue_empty(struct adapter * adapter)1182 static bool rtw_is_hi_queue_empty(struct adapter *adapter)
1183 {
1184 	int res;
1185 	u32 reg;
1186 
1187 	res = rtw_read32(adapter, REG_HGQ_INFORMATION, &reg);
1188 	if (res)
1189 		return false;
1190 
1191 	return (reg & 0x0000ff00) == 0;
1192 }
1193 
rtw_chk_hi_queue_hdl(struct adapter * padapter)1194 static void rtw_chk_hi_queue_hdl(struct adapter *padapter)
1195 {
1196 	int cnt = 0;
1197 	struct sta_info *psta_bmc;
1198 	struct sta_priv *pstapriv = &padapter->stapriv;
1199 
1200 	psta_bmc = rtw_get_bcmc_stainfo(padapter);
1201 	if (!psta_bmc)
1202 		return;
1203 
1204 	if (psta_bmc->sleepq_len == 0) {
1205 		bool val = rtw_is_hi_queue_empty(padapter);
1206 
1207 		while (!val) {
1208 			msleep(100);
1209 
1210 			cnt++;
1211 
1212 			if (cnt > 10)
1213 				break;
1214 
1215 			val = rtw_is_hi_queue_empty(padapter);
1216 		}
1217 
1218 		if (cnt <= 10) {
1219 			pstapriv->tim_bitmap &= ~BIT(0);
1220 			pstapriv->sta_dz_bitmap &= ~BIT(0);
1221 
1222 			update_beacon(padapter, _TIM_IE_, NULL, false);
1223 		} else { /* re check again */
1224 			rtw_chk_hi_queue_cmd(padapter);
1225 		}
1226 	}
1227 }
1228 
rtw_chk_hi_queue_cmd(struct adapter * padapter)1229 u8 rtw_chk_hi_queue_cmd(struct adapter *padapter)
1230 {
1231 	struct cmd_obj	*ph2c;
1232 	struct drvextra_cmd_parm	*pdrvextra_cmd_parm;
1233 	struct cmd_priv	*pcmdpriv = &padapter->cmdpriv;
1234 	u8	res = _SUCCESS;
1235 
1236 	ph2c = kzalloc(sizeof(*ph2c), GFP_ATOMIC);
1237 	if (!ph2c) {
1238 		res = _FAIL;
1239 		goto exit;
1240 	}
1241 
1242 	pdrvextra_cmd_parm = kzalloc(sizeof(*pdrvextra_cmd_parm), GFP_ATOMIC);
1243 	if (!pdrvextra_cmd_parm) {
1244 		kfree(ph2c);
1245 		res = _FAIL;
1246 		goto exit;
1247 	}
1248 
1249 	pdrvextra_cmd_parm->ec_id = CHECK_HIQ_WK_CID;
1250 	pdrvextra_cmd_parm->type_size = 0;
1251 	pdrvextra_cmd_parm->pbuf = NULL;
1252 
1253 	init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, GEN_CMD_CODE(_Set_Drv_Extra));
1254 
1255 	res = rtw_enqueue_cmd(pcmdpriv, ph2c);
1256 exit:
1257 	return res;
1258 }
1259 
rtw_c2h_wk_cmd(struct adapter * padapter,u8 * c2h_evt)1260 u8 rtw_c2h_wk_cmd(struct adapter *padapter, u8 *c2h_evt)
1261 {
1262 	struct cmd_obj *ph2c;
1263 	struct drvextra_cmd_parm *pdrvextra_cmd_parm;
1264 	struct cmd_priv	*pcmdpriv = &padapter->cmdpriv;
1265 	u8	res = _SUCCESS;
1266 
1267 	ph2c = kzalloc(sizeof(*ph2c), GFP_ATOMIC);
1268 	if (!ph2c) {
1269 		res = _FAIL;
1270 		goto exit;
1271 	}
1272 
1273 	pdrvextra_cmd_parm = kzalloc(sizeof(*pdrvextra_cmd_parm), GFP_ATOMIC);
1274 	if (!pdrvextra_cmd_parm) {
1275 		kfree(ph2c);
1276 		res = _FAIL;
1277 		goto exit;
1278 	}
1279 
1280 	pdrvextra_cmd_parm->ec_id = C2H_WK_CID;
1281 	pdrvextra_cmd_parm->type_size = c2h_evt ? 16 : 0;
1282 	pdrvextra_cmd_parm->pbuf = c2h_evt;
1283 
1284 	init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, GEN_CMD_CODE(_Set_Drv_Extra));
1285 
1286 	res = rtw_enqueue_cmd(pcmdpriv, ph2c);
1287 
1288 exit:
1289 
1290 	return res;
1291 }
1292 
c2h_evt_hdl(struct adapter * adapter,struct c2h_evt_hdr * c2h_evt,c2h_id_filter filter)1293 static void c2h_evt_hdl(struct adapter *adapter, struct c2h_evt_hdr *c2h_evt, c2h_id_filter filter)
1294 {
1295 	u8 buf[16];
1296 
1297 	if (!c2h_evt)
1298 		c2h_evt_read(adapter, buf);
1299 }
1300 
c2h_wk_callback(struct work_struct * work)1301 static void c2h_wk_callback(struct work_struct *work)
1302 {
1303 	struct evt_priv *evtpriv = container_of(work, struct evt_priv, c2h_wk);
1304 	struct adapter *adapter = container_of(evtpriv, struct adapter, evtpriv);
1305 	struct c2h_evt_hdr *c2h_evt;
1306 
1307 	evtpriv->c2h_wk_alive = true;
1308 
1309 	while (!rtw_cbuf_empty(evtpriv->c2h_queue)) {
1310 		c2h_evt = (struct c2h_evt_hdr *)rtw_cbuf_pop(evtpriv->c2h_queue);
1311 		if (c2h_evt) {
1312 			/* This C2H event is read, clear it */
1313 			rtw_write8(adapter, REG_C2HEVT_CLEAR, C2H_EVT_HOST_CLOSE);
1314 		} else {
1315 			c2h_evt = kmalloc(16, GFP_KERNEL);
1316 			if (c2h_evt) {
1317 				/* This C2H event is not read, read & clear now */
1318 				if (c2h_evt_read(adapter, (u8 *)c2h_evt) != _SUCCESS) {
1319 					kfree(c2h_evt);
1320 					continue;
1321 				}
1322 			} else {
1323 				return;
1324 			}
1325 		}
1326 
1327 		/* Special pointer to trigger c2h_evt_clear only */
1328 		if ((void *)c2h_evt == (void *)evtpriv)
1329 			continue;
1330 
1331 		if (!c2h_evt_exist(c2h_evt)) {
1332 			kfree(c2h_evt);
1333 			continue;
1334 		}
1335 
1336 		/* Enqueue into cmd_thread for others */
1337 		rtw_c2h_wk_cmd(adapter, (u8 *)c2h_evt);
1338 	}
1339 
1340 	evtpriv->c2h_wk_alive = false;
1341 }
1342 
rtw_drvextra_cmd_hdl(struct adapter * padapter,unsigned char * pbuf)1343 u8 rtw_drvextra_cmd_hdl(struct adapter *padapter, unsigned char *pbuf)
1344 {
1345 	struct drvextra_cmd_parm *pdrvextra_cmd;
1346 
1347 	if (!pbuf)
1348 		return H2C_PARAMETERS_ERROR;
1349 
1350 	pdrvextra_cmd = (struct drvextra_cmd_parm *)pbuf;
1351 
1352 	switch (pdrvextra_cmd->ec_id) {
1353 	case DYNAMIC_CHK_WK_CID:
1354 		dynamic_chk_wk_hdl(padapter, pdrvextra_cmd->pbuf);
1355 		break;
1356 	case POWER_SAVING_CTRL_WK_CID:
1357 		rtw_ps_processor(padapter);
1358 		break;
1359 	case LPS_CTRL_WK_CID:
1360 		lps_ctrl_wk_hdl(padapter, (u8)pdrvextra_cmd->type_size);
1361 		break;
1362 	case RTP_TIMER_CFG_WK_CID:
1363 		rpt_timer_setting_wk_hdl(padapter, pdrvextra_cmd->type_size);
1364 		break;
1365 	case ANT_SELECT_WK_CID:
1366 		antenna_select_wk_hdl(padapter, pdrvextra_cmd->type_size);
1367 		break;
1368 	case P2P_PS_WK_CID:
1369 		p2p_ps_wk_hdl(padapter, pdrvextra_cmd->type_size);
1370 		break;
1371 	case P2P_PROTO_WK_CID:
1372 		/*	Commented by Albert 2011/07/01 */
1373 		/*	I used the type_size as the type command */
1374 		p2p_protocol_wk_hdl(padapter, pdrvextra_cmd->type_size);
1375 		break;
1376 	case CHECK_HIQ_WK_CID:
1377 		rtw_chk_hi_queue_hdl(padapter);
1378 		break;
1379 	case C2H_WK_CID:
1380 		c2h_evt_hdl(padapter, (struct c2h_evt_hdr *)pdrvextra_cmd->pbuf, NULL);
1381 		break;
1382 	default:
1383 		break;
1384 	}
1385 
1386 	if (pdrvextra_cmd->pbuf && pdrvextra_cmd->type_size > 0)
1387 		kfree(pdrvextra_cmd->pbuf);
1388 
1389 	return H2C_SUCCESS;
1390 }
1391 
rtw_survey_cmd_callback(struct adapter * padapter,struct cmd_obj * pcmd)1392 void rtw_survey_cmd_callback(struct adapter *padapter,  struct cmd_obj *pcmd)
1393 {
1394 	struct	mlme_priv *pmlmepriv = &padapter->mlmepriv;
1395 
1396 	if (pcmd->res != H2C_SUCCESS) {
1397 		/* TODO: cancel timer and do timeout handler directly... */
1398 		_set_timer(&pmlmepriv->scan_to_timer, 1);
1399 	}
1400 
1401 	/*  free cmd */
1402 	rtw_free_cmd_obj(pcmd);
1403 
1404 }
1405 
rtw_disassoc_cmd_callback(struct adapter * padapter,struct cmd_obj * pcmd)1406 void rtw_disassoc_cmd_callback(struct adapter *padapter, struct cmd_obj *pcmd)
1407 {
1408 	struct	mlme_priv *pmlmepriv = &padapter->mlmepriv;
1409 
1410 	if (pcmd->res != H2C_SUCCESS) {
1411 		spin_lock_bh(&pmlmepriv->lock);
1412 		set_fwstate(pmlmepriv, _FW_LINKED);
1413 		spin_unlock_bh(&pmlmepriv->lock);
1414 
1415 		return;
1416 	}
1417 
1418 	/* clear bridge database */
1419 	nat25_db_cleanup(padapter);
1420 
1421 	/*  free cmd */
1422 	rtw_free_cmd_obj(pcmd);
1423 }
1424 
rtw_joinbss_cmd_callback(struct adapter * padapter,struct cmd_obj * pcmd)1425 void rtw_joinbss_cmd_callback(struct adapter *padapter,  struct cmd_obj *pcmd)
1426 {
1427 	struct	mlme_priv *pmlmepriv = &padapter->mlmepriv;
1428 
1429 	if (pcmd->res != H2C_SUCCESS) {
1430 		/* TODO: cancel timer and do timeout handler directly... */
1431 		_set_timer(&pmlmepriv->assoc_timer, 1);
1432 	}
1433 
1434 	rtw_free_cmd_obj(pcmd);
1435 }
1436 
rtw_createbss_cmd_callback(struct adapter * padapter,struct cmd_obj * pcmd)1437 void rtw_createbss_cmd_callback(struct adapter *padapter, struct cmd_obj *pcmd)
1438 {
1439 	struct sta_info *psta = NULL;
1440 	struct wlan_network *pwlan = NULL;
1441 	struct	mlme_priv *pmlmepriv = &padapter->mlmepriv;
1442 	struct wlan_bssid_ex *pnetwork = (struct wlan_bssid_ex *)pcmd->parmbuf;
1443 	struct wlan_network *tgt_network = &pmlmepriv->cur_network;
1444 
1445 	if (pcmd->res != H2C_SUCCESS)
1446 		_set_timer(&pmlmepriv->assoc_timer, 1);
1447 
1448 	del_timer_sync(&pmlmepriv->assoc_timer);
1449 
1450 	spin_lock_bh(&pmlmepriv->lock);
1451 
1452 	if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) {
1453 		psta = rtw_get_stainfo(&padapter->stapriv, pnetwork->MacAddress);
1454 		if (!psta) {
1455 			psta = rtw_alloc_stainfo(&padapter->stapriv, pnetwork->MacAddress);
1456 			if (!psta)
1457 				goto createbss_cmd_fail;
1458 		}
1459 
1460 		rtw_indicate_connect(padapter);
1461 	} else {
1462 
1463 		pwlan = rtw_alloc_network(pmlmepriv);
1464 		spin_lock_bh(&pmlmepriv->scanned_queue.lock);
1465 		if (!pwlan) {
1466 			pwlan = rtw_get_oldest_wlan_network(&pmlmepriv->scanned_queue);
1467 			if (!pwlan) {
1468 				spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
1469 				goto createbss_cmd_fail;
1470 			}
1471 			pwlan->last_scanned = jiffies;
1472 		} else {
1473 			list_add_tail(&pwlan->list, &pmlmepriv->scanned_queue.queue);
1474 		}
1475 
1476 		pnetwork->Length = get_wlan_bssid_ex_sz(pnetwork);
1477 		memcpy(&pwlan->network, pnetwork, pnetwork->Length);
1478 
1479 		memcpy(&tgt_network->network, pnetwork, (get_wlan_bssid_ex_sz(pnetwork)));
1480 
1481 		_clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING);
1482 
1483 		spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
1484 		/*  we will set _FW_LINKED when there is one more sat to join us (rtw_stassoc_event_callback) */
1485 	}
1486 
1487 createbss_cmd_fail:
1488 
1489 	spin_unlock_bh(&pmlmepriv->lock);
1490 
1491 	rtw_free_cmd_obj(pcmd);
1492 
1493 }
1494 
rtw_setstaKey_cmdrsp_callback(struct adapter * padapter,struct cmd_obj * pcmd)1495 void rtw_setstaKey_cmdrsp_callback(struct adapter *padapter,  struct cmd_obj *pcmd)
1496 {
1497 	struct sta_priv *pstapriv = &padapter->stapriv;
1498 	struct set_stakey_rsp *psetstakey_rsp = (struct set_stakey_rsp *)(pcmd->rsp);
1499 	struct sta_info *psta = rtw_get_stainfo(pstapriv, psetstakey_rsp->addr);
1500 
1501 	if (!psta)
1502 		goto exit;
1503 exit:
1504 	rtw_free_cmd_obj(pcmd);
1505 
1506 }
1507 
rtw_setassocsta_cmdrsp_callback(struct adapter * padapter,struct cmd_obj * pcmd)1508 void rtw_setassocsta_cmdrsp_callback(struct adapter *padapter,  struct cmd_obj *pcmd)
1509 {
1510 	struct sta_priv *pstapriv = &padapter->stapriv;
1511 	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1512 	struct set_assocsta_parm *passocsta_parm = (struct set_assocsta_parm *)(pcmd->parmbuf);
1513 	struct set_assocsta_rsp *passocsta_rsp = (struct set_assocsta_rsp *)(pcmd->rsp);
1514 	struct sta_info *psta = rtw_get_stainfo(pstapriv, passocsta_parm->addr);
1515 
1516 	if (!psta)
1517 		goto exit;
1518 
1519 	psta->aid = passocsta_rsp->cam_id;
1520 	psta->mac_id = passocsta_rsp->cam_id;
1521 
1522 	spin_lock_bh(&pmlmepriv->lock);
1523 
1524 	if (check_fwstate(pmlmepriv, WIFI_MP_STATE) && check_fwstate(pmlmepriv, _FW_UNDER_LINKING))
1525 		_clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING);
1526 
1527 	set_fwstate(pmlmepriv, _FW_LINKED);
1528 	spin_unlock_bh(&pmlmepriv->lock);
1529 
1530 exit:
1531 	rtw_free_cmd_obj(pcmd);
1532 
1533 }
1534