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