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