1 // SPDX-License-Identifier: GPL-2.0
2 /* Copyright(c) 2007 - 2012 Realtek Corporation. */
3 
4 #define _RTW_CMD_C_
5 
6 #include "../include/osdep_service.h"
7 #include "../include/drv_types.h"
8 #include "../include/recv_osdep.h"
9 #include "../include/mlme_osdep.h"
10 #include "../include/rtw_br_ext.h"
11 #include "../include/rtw_mlme_ext.h"
12 
13 /*
14 Caller and the rtw_cmd_thread can protect cmd_q by spin_lock.
15 No irqsave is necessary.
16 */
17 
_rtw_init_cmd_priv(struct cmd_priv * pcmdpriv)18 static int _rtw_init_cmd_priv(struct cmd_priv *pcmdpriv)
19 {
20 	int res = _SUCCESS;
21 
22 	sema_init(&pcmdpriv->cmd_queue_sema, 0);
23 	/* sema_init(&(pcmdpriv->cmd_done_sema), 0); */
24 	sema_init(&pcmdpriv->terminate_cmdthread_sema, 0);
25 
26 	_rtw_init_queue(&pcmdpriv->cmd_queue);
27 
28 	/* allocate DMA-able/Non-Page memory for cmd_buf and rsp_buf */
29 
30 	pcmdpriv->cmd_seq = 1;
31 
32 	pcmdpriv->cmd_allocated_buf = kzalloc(MAX_CMDSZ + CMDBUFF_ALIGN_SZ,
33 					      GFP_KERNEL);
34 
35 	if (!pcmdpriv->cmd_allocated_buf) {
36 		res = _FAIL;
37 		goto exit;
38 	}
39 
40 	pcmdpriv->cmd_buf = pcmdpriv->cmd_allocated_buf  +  CMDBUFF_ALIGN_SZ - ((size_t)(pcmdpriv->cmd_allocated_buf) & (CMDBUFF_ALIGN_SZ - 1));
41 
42 	pcmdpriv->rsp_allocated_buf = kzalloc(MAX_RSPSZ + 4, GFP_KERNEL);
43 
44 	if (!pcmdpriv->rsp_allocated_buf) {
45 		res = _FAIL;
46 		goto exit;
47 	}
48 
49 	pcmdpriv->rsp_buf = pcmdpriv->rsp_allocated_buf  +  4 - ((size_t)(pcmdpriv->rsp_allocated_buf) & 3);
50 
51 	pcmdpriv->cmd_issued_cnt = 0;
52 	pcmdpriv->cmd_done_cnt = 0;
53 	pcmdpriv->rsp_cnt = 0;
54 exit:
55 
56 	return res;
57 }
58 
59 static void c2h_wk_callback(struct work_struct *work);
60 
_rtw_init_evt_priv(struct evt_priv * pevtpriv)61 static int _rtw_init_evt_priv(struct evt_priv *pevtpriv)
62 {
63 	int res = _SUCCESS;
64 
65 	/* allocate DMA-able/Non-Page memory for cmd_buf and rsp_buf */
66 	atomic_set(&pevtpriv->event_seq, 0);
67 	pevtpriv->evt_done_cnt = 0;
68 
69 	_init_workitem(&pevtpriv->c2h_wk, c2h_wk_callback, NULL);
70 	pevtpriv->c2h_wk_alive = false;
71 	pevtpriv->c2h_queue = rtw_cbuf_alloc(C2H_QUEUE_MAX_LEN + 1);
72 
73 	return res;
74 }
75 
rtw_free_evt_priv(struct evt_priv * pevtpriv)76 void rtw_free_evt_priv(struct	evt_priv *pevtpriv)
77 {
78 	_cancel_workitem_sync(&pevtpriv->c2h_wk);
79 	while (pevtpriv->c2h_wk_alive)
80 		msleep(10);
81 
82 	while (!rtw_cbuf_empty(pevtpriv->c2h_queue)) {
83 		void *c2h = rtw_cbuf_pop(pevtpriv->c2h_queue);
84 		if (c2h && c2h != (void *)pevtpriv)
85 			kfree(c2h);
86 	}
87 }
88 
_rtw_free_cmd_priv(struct cmd_priv * pcmdpriv)89 static void _rtw_free_cmd_priv(struct cmd_priv *pcmdpriv)
90 {
91 	if (pcmdpriv) {
92 		kfree(pcmdpriv->cmd_allocated_buf);
93 		kfree(pcmdpriv->rsp_allocated_buf);
94 	}
95 }
96 
97 /*
98 Calling Context:
99 
100 rtw_enqueue_cmd can only be called between kernel thread,
101 since only spin_lock is used.
102 
103 ISR/Call-Back functions can't call this sub-function.
104 
105 */
106 
_rtw_enqueue_cmd(struct __queue * queue,struct cmd_obj * obj)107 static int _rtw_enqueue_cmd(struct __queue *queue, struct cmd_obj *obj)
108 {
109 	unsigned long flags;
110 
111 	if (!obj)
112 		goto exit;
113 
114 	spin_lock_irqsave(&queue->lock, flags);
115 
116 	list_add_tail(&obj->list, &queue->queue);
117 
118 	spin_unlock_irqrestore(&queue->lock, flags);
119 
120 exit:
121 
122 	return _SUCCESS;
123 }
124 
_rtw_dequeue_cmd(struct __queue * queue)125 static struct cmd_obj *_rtw_dequeue_cmd(struct __queue *queue)
126 {
127 	struct cmd_obj *obj;
128 	unsigned long flags;
129 
130 	spin_lock_irqsave(&queue->lock, flags);
131 	if (list_empty(&queue->queue)) {
132 		obj = NULL;
133 	} else {
134 		obj = container_of((&queue->queue)->next, struct cmd_obj, list);
135 		rtw_list_delete(&obj->list);
136 	}
137 
138 	spin_unlock_irqrestore(&queue->lock, flags);
139 
140 	return obj;
141 }
142 
rtw_init_cmd_priv(struct cmd_priv * pcmdpriv)143 u32	rtw_init_cmd_priv(struct cmd_priv *pcmdpriv)
144 {
145 	u32	res;
146 
147 	res = _rtw_init_cmd_priv(pcmdpriv);
148 
149 	return res;
150 }
151 
rtw_init_evt_priv(struct evt_priv * pevtpriv)152 u32 rtw_init_evt_priv(struct evt_priv *pevtpriv)
153 {
154 	int	res;
155 
156 	res = _rtw_init_evt_priv(pevtpriv);
157 
158 	return res;
159 }
160 
rtw_free_cmd_priv(struct cmd_priv * pcmdpriv)161 void rtw_free_cmd_priv(struct	cmd_priv *pcmdpriv)
162 {
163 	_rtw_free_cmd_priv(pcmdpriv);
164 }
165 
rtw_cmd_filter(struct cmd_priv * pcmdpriv,struct cmd_obj * cmd_obj)166 static int rtw_cmd_filter(struct cmd_priv *pcmdpriv, struct cmd_obj *cmd_obj)
167 {
168 	u8 bAllow = false; /* set to true to allow enqueuing cmd when hw_init_completed is false */
169 
170 	/* To decide allow or not */
171 	if ((pcmdpriv->padapter->pwrctrlpriv.bHWPwrPindetect) &&
172 	    (!pcmdpriv->padapter->registrypriv.usbss_enable)) {
173 		if (cmd_obj->cmdcode == GEN_CMD_CODE(_Set_Drv_Extra)) {
174 			struct drvextra_cmd_parm	*pdrvextra_cmd_parm = (struct drvextra_cmd_parm	*)cmd_obj->parmbuf;
175 			if (pdrvextra_cmd_parm->ec_id == POWER_SAVING_CTRL_WK_CID)
176 				bAllow = true;
177 		}
178 	}
179 
180 	if (cmd_obj->cmdcode == GEN_CMD_CODE(_SetChannelPlan))
181 		bAllow = true;
182 
183 	if ((!pcmdpriv->padapter->hw_init_completed && !bAllow) ||
184 	    !pcmdpriv->cmdthd_running)	/* com_thread not running */
185 		return _FAIL;
186 	return _SUCCESS;
187 }
188 
rtw_enqueue_cmd(struct cmd_priv * pcmdpriv,struct cmd_obj * cmd_obj)189 u32 rtw_enqueue_cmd(struct cmd_priv *pcmdpriv, struct cmd_obj *cmd_obj)
190 {
191 	int res = _FAIL;
192 	struct adapter *padapter = pcmdpriv->padapter;
193 
194 	if (!cmd_obj)
195 		goto exit;
196 
197 	cmd_obj->padapter = padapter;
198 
199 	res = rtw_cmd_filter(pcmdpriv, cmd_obj);
200 	if (_FAIL == res) {
201 		rtw_free_cmd_obj(cmd_obj);
202 		goto exit;
203 	}
204 
205 	res = _rtw_enqueue_cmd(&pcmdpriv->cmd_queue, cmd_obj);
206 
207 	if (res == _SUCCESS)
208 		up(&pcmdpriv->cmd_queue_sema);
209 
210 exit:
211 
212 	return res;
213 }
214 
rtw_dequeue_cmd(struct cmd_priv * pcmdpriv)215 struct	cmd_obj	*rtw_dequeue_cmd(struct cmd_priv *pcmdpriv)
216 {
217 	struct cmd_obj *cmd_obj;
218 
219 	cmd_obj = _rtw_dequeue_cmd(&pcmdpriv->cmd_queue);
220 
221 	return cmd_obj;
222 }
223 
rtw_cmd_clr_isr(struct cmd_priv * pcmdpriv)224 void rtw_cmd_clr_isr(struct	cmd_priv *pcmdpriv)
225 {
226 
227 	pcmdpriv->cmd_done_cnt++;
228 	/* up(&(pcmdpriv->cmd_done_sema)); */
229 
230 }
231 
rtw_free_cmd_obj(struct cmd_obj * pcmd)232 void rtw_free_cmd_obj(struct cmd_obj *pcmd)
233 {
234 
235 	if ((pcmd->cmdcode != _JoinBss_CMD_) && (pcmd->cmdcode != _CreateBss_CMD_)) {
236 		/* free parmbuf in cmd_obj */
237 		kfree(pcmd->parmbuf);
238 	}
239 
240 	if (pcmd->rsp) {
241 		if (pcmd->rspsz != 0) {
242 			/* free rsp in cmd_obj */
243 			kfree(pcmd->rsp);
244 		}
245 	}
246 
247 	/* free cmd_obj */
248 	kfree(pcmd);
249 
250 }
251 
rtw_cmd_thread(void * context)252 int rtw_cmd_thread(void *context)
253 {
254 	u8 ret;
255 	struct cmd_obj *pcmd;
256 	u8 *pcmdbuf;
257 	u8 (*cmd_hdl)(struct adapter *padapter, u8 *pbuf);
258 	void (*pcmd_callback)(struct adapter *dev, struct cmd_obj *pcmd);
259 	struct adapter *padapter = (struct adapter *)context;
260 	struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
261 
262 	thread_enter("RTW_CMD_THREAD");
263 
264 	pcmdbuf = pcmdpriv->cmd_buf;
265 
266 	pcmdpriv->cmdthd_running = true;
267 	up(&pcmdpriv->terminate_cmdthread_sema);
268 
269 	while (1) {
270 		if (_rtw_down_sema(&pcmdpriv->cmd_queue_sema) == _FAIL)
271 			break;
272 
273 		if (padapter->bDriverStopped ||
274 		    padapter->bSurpriseRemoved) {
275 			DBG_88E("%s: DriverStopped(%d) SurpriseRemoved(%d) break at line %d\n",
276 				__func__, padapter->bDriverStopped, padapter->bSurpriseRemoved, __LINE__);
277 			break;
278 		}
279 _next:
280 		if (padapter->bDriverStopped ||
281 		    padapter->bSurpriseRemoved) {
282 			DBG_88E("%s: DriverStopped(%d) SurpriseRemoved(%d) break at line %d\n",
283 				__func__, padapter->bDriverStopped, padapter->bSurpriseRemoved, __LINE__);
284 			break;
285 		}
286 
287 		pcmd = rtw_dequeue_cmd(pcmdpriv);
288 		if (!pcmd)
289 			continue;
290 
291 		if (_FAIL == rtw_cmd_filter(pcmdpriv, pcmd)) {
292 			pcmd->res = H2C_DROPPED;
293 			goto post_process;
294 		}
295 
296 		pcmdpriv->cmd_issued_cnt++;
297 
298 		pcmd->cmdsz = _RND4((pcmd->cmdsz));/* _RND4 */
299 
300 		memcpy(pcmdbuf, pcmd->parmbuf, pcmd->cmdsz);
301 
302 		if (pcmd->cmdcode < ARRAY_SIZE(wlancmds)) {
303 			cmd_hdl = wlancmds[pcmd->cmdcode].h2cfuns;
304 
305 			if (cmd_hdl) {
306 				ret = cmd_hdl(pcmd->padapter, pcmdbuf);
307 				pcmd->res = ret;
308 			}
309 
310 			pcmdpriv->cmd_seq++;
311 		} else {
312 			pcmd->res = H2C_PARAMETERS_ERROR;
313 		}
314 
315 		cmd_hdl = NULL;
316 
317 post_process:
318 
319 		/* call callback function for post-processed */
320 		if (pcmd->cmdcode < ARRAY_SIZE(rtw_cmd_callback)) {
321 			pcmd_callback = rtw_cmd_callback[pcmd->cmdcode].callback;
322 			if (!pcmd_callback)
323 				rtw_free_cmd_obj(pcmd);
324 			else
325 				/* todo: !!! fill rsp_buf to pcmd->rsp if (pcmd->rsp!= NULL) */
326 				pcmd_callback(pcmd->padapter, pcmd);/* need conider that free cmd_obj in rtw_cmd_callback */
327 		} else {
328 			rtw_free_cmd_obj(pcmd);
329 		}
330 
331 		flush_signals_thread();
332 
333 		goto _next;
334 	}
335 	pcmdpriv->cmdthd_running = false;
336 
337 	/*  free all cmd_obj resources */
338 	do {
339 		pcmd = rtw_dequeue_cmd(pcmdpriv);
340 		if (!pcmd)
341 			break;
342 
343 		/* DBG_88E("%s: leaving... drop cmdcode:%u\n", __func__, pcmd->cmdcode); */
344 
345 		rtw_free_cmd_obj(pcmd);
346 	} while (1);
347 
348 	up(&pcmdpriv->terminate_cmdthread_sema);
349 
350 	thread_exit();
351 }
352 
rtw_setstandby_cmd(struct adapter * padapter,uint action)353 u8 rtw_setstandby_cmd(struct adapter *padapter, uint action)
354 {
355 	struct cmd_obj *ph2c;
356 	struct usb_suspend_parm *psetusbsuspend;
357 	struct cmd_priv	*pcmdpriv = &padapter->cmdpriv;
358 
359 	u8 ret = _SUCCESS;
360 
361 	ph2c = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC);
362 	if (!ph2c) {
363 		ret = _FAIL;
364 		goto exit;
365 	}
366 
367 	psetusbsuspend = kzalloc(sizeof(struct usb_suspend_parm), GFP_ATOMIC);
368 	if (!psetusbsuspend) {
369 		kfree(ph2c);
370 		ret = _FAIL;
371 		goto exit;
372 	}
373 
374 	psetusbsuspend->action = action;
375 
376 	init_h2fwcmd_w_parm_no_rsp(ph2c, psetusbsuspend, GEN_CMD_CODE(_SetUsbSuspend));
377 
378 	ret = rtw_enqueue_cmd(pcmdpriv, ph2c);
379 
380 exit:
381 
382 	return ret;
383 }
384 
385 /*
386 rtw_sitesurvey_cmd(~)
387 	### NOTE:#### (!!!!)
388 	MUST TAKE CARE THAT BEFORE CALLING THIS FUNC, YOU SHOULD HAVE LOCKED pmlmepriv->lock
389 */
rtw_sitesurvey_cmd(struct adapter * padapter,struct ndis_802_11_ssid * ssid,int ssid_num,struct rtw_ieee80211_channel * ch,int ch_num)390 u8 rtw_sitesurvey_cmd(struct adapter  *padapter, struct ndis_802_11_ssid *ssid, int ssid_num,
391 	struct rtw_ieee80211_channel *ch, int ch_num)
392 {
393 	u8 res = _FAIL;
394 	struct cmd_obj		*ph2c;
395 	struct sitesurvey_parm	*psurveyPara;
396 	struct cmd_priv		*pcmdpriv = &padapter->cmdpriv;
397 	struct mlme_priv	*pmlmepriv = &padapter->mlmepriv;
398 
399 	if (check_fwstate(pmlmepriv, _FW_LINKED)) {
400 		rtw_lps_ctrl_wk_cmd(padapter, LPS_CTRL_SCAN, 1);
401 	}
402 
403 	if (check_fwstate(pmlmepriv, _FW_LINKED)) {
404 		p2p_ps_wk_cmd(padapter, P2P_PS_SCAN, 1);
405 	}
406 
407 	ph2c = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC);
408 	if (!ph2c)
409 		return _FAIL;
410 
411 	psurveyPara = kzalloc(sizeof(struct sitesurvey_parm), GFP_ATOMIC);
412 	if (!psurveyPara) {
413 		kfree(ph2c);
414 		return _FAIL;
415 	}
416 
417 	rtw_free_network_queue(padapter, false);
418 
419 	init_h2fwcmd_w_parm_no_rsp(ph2c, psurveyPara, GEN_CMD_CODE(_SiteSurvey));
420 
421 	/* psurveyPara->bsslimit = 48; */
422 	psurveyPara->scan_mode = pmlmepriv->scan_mode;
423 
424 	/* prepare ssid list */
425 	if (ssid) {
426 		int i;
427 		for (i = 0; i < ssid_num && i < RTW_SSID_SCAN_AMOUNT; i++) {
428 			if (ssid[i].SsidLength) {
429 				memcpy(&psurveyPara->ssid[i], &ssid[i], sizeof(struct ndis_802_11_ssid));
430 				psurveyPara->ssid_num++;
431 			}
432 		}
433 	}
434 
435 	/* prepare channel list */
436 	if (ch) {
437 		int i;
438 		for (i = 0; i < ch_num && i < RTW_CHANNEL_SCAN_AMOUNT; i++) {
439 			if (ch[i].hw_value && !(ch[i].flags & RTW_IEEE80211_CHAN_DISABLED)) {
440 				memcpy(&psurveyPara->ch[i], &ch[i], sizeof(struct rtw_ieee80211_channel));
441 				psurveyPara->ch_num++;
442 			}
443 		}
444 	}
445 
446 	set_fwstate(pmlmepriv, _FW_UNDER_SURVEY);
447 
448 	res = rtw_enqueue_cmd(pcmdpriv, ph2c);
449 
450 	if (res == _SUCCESS) {
451 		pmlmepriv->scan_start_time = jiffies;
452 
453 		_set_timer(&pmlmepriv->scan_to_timer, SCANNING_TIMEOUT);
454 
455 		rtw_led_control(padapter, LED_CTL_SITE_SURVEY);
456 
457 		pmlmepriv->scan_interval = SCAN_INTERVAL;/*  30*2 sec = 60sec */
458 	} else {
459 		_clr_fwstate_(pmlmepriv, _FW_UNDER_SURVEY);
460 	}
461 
462 	return res;
463 }
464 
rtw_setdatarate_cmd(struct adapter * padapter,u8 * rateset)465 u8 rtw_setdatarate_cmd(struct adapter *padapter, u8 *rateset)
466 {
467 	struct cmd_obj *ph2c;
468 	struct setdatarate_parm *pbsetdataratepara;
469 	struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
470 	u8	res = _SUCCESS;
471 
472 	ph2c = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC);
473 	if (!ph2c) {
474 		res = _FAIL;
475 		goto exit;
476 	}
477 
478 	pbsetdataratepara = kzalloc(sizeof(struct setdatarate_parm), GFP_ATOMIC);
479 	if (!pbsetdataratepara) {
480 		kfree(ph2c);
481 		res = _FAIL;
482 		goto exit;
483 	}
484 
485 	init_h2fwcmd_w_parm_no_rsp(ph2c, pbsetdataratepara, GEN_CMD_CODE(_SetDataRate));
486 	pbsetdataratepara->mac_id = 5;
487 	memcpy(pbsetdataratepara->datarates, rateset, NumRates);
488 	res = rtw_enqueue_cmd(pcmdpriv, ph2c);
489 exit:
490 
491 	return res;
492 }
493 
rtw_setbasicrate_cmd(struct adapter * padapter,u8 * rateset)494 u8 rtw_setbasicrate_cmd(struct adapter *padapter, u8 *rateset)
495 {
496 	struct cmd_obj *ph2c;
497 	struct setbasicrate_parm *pssetbasicratepara;
498 	struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
499 	u8	res = _SUCCESS;
500 
501 	ph2c = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC);
502 	if (!ph2c) {
503 		res = _FAIL;
504 		goto exit;
505 	}
506 	pssetbasicratepara = kzalloc(sizeof(struct setbasicrate_parm), GFP_ATOMIC);
507 
508 	if (!pssetbasicratepara) {
509 		kfree(ph2c);
510 		res = _FAIL;
511 		goto exit;
512 	}
513 
514 	init_h2fwcmd_w_parm_no_rsp(ph2c, pssetbasicratepara, _SetBasicRate_CMD_);
515 
516 	memcpy(pssetbasicratepara->basicrates, rateset, NumRates);
517 
518 	res = rtw_enqueue_cmd(pcmdpriv, ph2c);
519 exit:
520 
521 	return res;
522 }
523 
524 /*
525 unsigned char rtw_setphy_cmd(unsigned char  *adapter)
526 
527 1.  be called only after rtw_update_registrypriv_dev_network(~) or mp testing program
528 2.  for AdHoc/Ap mode or mp mode?
529 
530 */
rtw_setphy_cmd(struct adapter * padapter,u8 modem,u8 ch)531 u8 rtw_setphy_cmd(struct adapter *padapter, u8 modem, u8 ch)
532 {
533 	struct cmd_obj *ph2c;
534 	struct setphy_parm *psetphypara;
535 	struct cmd_priv	*pcmdpriv = &padapter->cmdpriv;
536 	u8	res = _SUCCESS;
537 
538 	ph2c = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC);
539 	if (!ph2c) {
540 		res = _FAIL;
541 		goto exit;
542 		}
543 	psetphypara = kzalloc(sizeof(struct setphy_parm), GFP_ATOMIC);
544 
545 	if (!psetphypara) {
546 		kfree(ph2c);
547 		res = _FAIL;
548 		goto exit;
549 	}
550 
551 	init_h2fwcmd_w_parm_no_rsp(ph2c, psetphypara, _SetPhy_CMD_);
552 
553 	psetphypara->modem = modem;
554 	psetphypara->rfchannel = ch;
555 
556 	res = rtw_enqueue_cmd(pcmdpriv, ph2c);
557 exit:
558 
559 	return res;
560 }
561 
rtw_setbbreg_cmd(struct adapter * padapter,u8 offset,u8 val)562 u8 rtw_setbbreg_cmd(struct adapter *padapter, u8 offset, u8 val)
563 {
564 	struct cmd_obj *ph2c;
565 	struct writeBB_parm *pwritebbparm;
566 	struct cmd_priv	*pcmdpriv = &padapter->cmdpriv;
567 	u8	res = _SUCCESS;
568 
569 	ph2c = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC);
570 	if (!ph2c) {
571 		res = _FAIL;
572 		goto exit;
573 		}
574 	pwritebbparm = kzalloc(sizeof(struct writeBB_parm), GFP_ATOMIC);
575 
576 	if (!pwritebbparm) {
577 		kfree(ph2c);
578 		res = _FAIL;
579 		goto exit;
580 	}
581 
582 	init_h2fwcmd_w_parm_no_rsp(ph2c, pwritebbparm, GEN_CMD_CODE(_SetBBReg));
583 
584 	pwritebbparm->offset = offset;
585 	pwritebbparm->value = val;
586 
587 	res = rtw_enqueue_cmd(pcmdpriv, ph2c);
588 exit:
589 
590 	return res;
591 }
592 
rtw_getbbreg_cmd(struct adapter * padapter,u8 offset,u8 * pval)593 u8 rtw_getbbreg_cmd(struct adapter  *padapter, u8 offset, u8 *pval)
594 {
595 	struct cmd_obj *ph2c;
596 	struct readBB_parm *prdbbparm;
597 	struct cmd_priv	*pcmdpriv = &padapter->cmdpriv;
598 	u8	res = _SUCCESS;
599 
600 	ph2c = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC);
601 	if (!ph2c) {
602 		res = _FAIL;
603 		goto exit;
604 		}
605 	prdbbparm = kzalloc(sizeof(struct readBB_parm), GFP_ATOMIC);
606 
607 	if (!prdbbparm) {
608 		kfree(ph2c);
609 		return _FAIL;
610 	}
611 
612 	INIT_LIST_HEAD(&ph2c->list);
613 	ph2c->cmdcode = GEN_CMD_CODE(_GetBBReg);
614 	ph2c->parmbuf = (unsigned char *)prdbbparm;
615 	ph2c->cmdsz =  sizeof(struct readBB_parm);
616 	ph2c->rsp = pval;
617 	ph2c->rspsz = sizeof(struct readBB_rsp);
618 
619 	prdbbparm->offset = offset;
620 
621 	res = rtw_enqueue_cmd(pcmdpriv, ph2c);
622 exit:
623 
624 	return res;
625 }
626 
rtw_setrfreg_cmd(struct adapter * padapter,u8 offset,u32 val)627 u8 rtw_setrfreg_cmd(struct adapter  *padapter, u8 offset, u32 val)
628 {
629 	struct cmd_obj *ph2c;
630 	struct writeRF_parm *pwriterfparm;
631 	struct cmd_priv	*pcmdpriv = &padapter->cmdpriv;
632 	u8	res = _SUCCESS;
633 
634 	ph2c = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC);
635 	if (!ph2c) {
636 		res = _FAIL;
637 		goto exit;
638 	}
639 	pwriterfparm = kzalloc(sizeof(struct writeRF_parm), GFP_ATOMIC);
640 
641 	if (!pwriterfparm) {
642 		kfree(ph2c);
643 		res = _FAIL;
644 		goto exit;
645 	}
646 
647 	init_h2fwcmd_w_parm_no_rsp(ph2c, pwriterfparm, GEN_CMD_CODE(_SetRFReg));
648 
649 	pwriterfparm->offset = offset;
650 	pwriterfparm->value = val;
651 
652 	res = rtw_enqueue_cmd(pcmdpriv, ph2c);
653 exit:
654 
655 	return res;
656 }
657 
rtw_getrfreg_cmd(struct adapter * padapter,u8 offset,u8 * pval)658 u8 rtw_getrfreg_cmd(struct adapter  *padapter, u8 offset, u8 *pval)
659 {
660 	struct cmd_obj *ph2c;
661 	struct readRF_parm *prdrfparm;
662 	struct cmd_priv	*pcmdpriv = &padapter->cmdpriv;
663 	u8	res = _SUCCESS;
664 
665 	ph2c = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC);
666 	if (!ph2c) {
667 		res = _FAIL;
668 		goto exit;
669 	}
670 
671 	prdrfparm = kzalloc(sizeof(struct readRF_parm), GFP_ATOMIC);
672 	if (!prdrfparm) {
673 		kfree(ph2c);
674 		res = _FAIL;
675 		goto exit;
676 	}
677 
678 	INIT_LIST_HEAD(&ph2c->list);
679 	ph2c->cmdcode = GEN_CMD_CODE(_GetRFReg);
680 	ph2c->parmbuf = (unsigned char *)prdrfparm;
681 	ph2c->cmdsz =  sizeof(struct readRF_parm);
682 	ph2c->rsp = pval;
683 	ph2c->rspsz = sizeof(struct readRF_rsp);
684 
685 	prdrfparm->offset = offset;
686 
687 	res = rtw_enqueue_cmd(pcmdpriv, ph2c);
688 
689 exit:
690 
691 	return res;
692 }
693 
rtw_getbbrfreg_cmdrsp_callback(struct adapter * padapter,struct cmd_obj * pcmd)694 void rtw_getbbrfreg_cmdrsp_callback(struct adapter *padapter,  struct cmd_obj *pcmd)
695 {
696 
697 
698 	kfree(pcmd->parmbuf);
699 	kfree(pcmd);
700 
701 	if (padapter->registrypriv.mp_mode == 1)
702 		padapter->mppriv.workparam.bcompleted = true;
703 
704 }
705 
rtw_readtssi_cmdrsp_callback(struct adapter * padapter,struct cmd_obj * pcmd)706 void rtw_readtssi_cmdrsp_callback(struct adapter *padapter,  struct cmd_obj *pcmd)
707 {
708 
709 
710 	kfree(pcmd->parmbuf);
711 	kfree(pcmd);
712 
713 	if (padapter->registrypriv.mp_mode == 1)
714 		padapter->mppriv.workparam.bcompleted = true;
715 
716 }
717 
rtw_createbss_cmd(struct adapter * padapter)718 u8 rtw_createbss_cmd(struct adapter  *padapter)
719 {
720 	struct cmd_obj *pcmd;
721 	struct cmd_priv	*pcmdpriv = &padapter->cmdpriv;
722 	struct wlan_bssid_ex *pdev_network = &padapter->registrypriv.dev_network;
723 	u8	res = _SUCCESS;
724 
725 	rtw_led_control(padapter, LED_CTL_START_TO_LINK);
726 
727 	pcmd = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC);
728 	if (!pcmd) {
729 		res = _FAIL;
730 		goto exit;
731 	}
732 
733 	INIT_LIST_HEAD(&pcmd->list);
734 	pcmd->cmdcode = _CreateBss_CMD_;
735 	pcmd->parmbuf = (unsigned char *)pdev_network;
736 	pcmd->cmdsz = get_wlan_bssid_ex_sz((struct wlan_bssid_ex *)pdev_network);
737 	pcmd->rsp = NULL;
738 	pcmd->rspsz = 0;
739 	pdev_network->Length = pcmd->cmdsz;
740 	res = rtw_enqueue_cmd(pcmdpriv, pcmd);
741 exit:
742 
743 	return res;
744 }
745 
rtw_createbss_cmd_ex(struct adapter * padapter,unsigned char * pbss,unsigned int sz)746 u8 rtw_createbss_cmd_ex(struct adapter  *padapter, unsigned char *pbss, unsigned int sz)
747 {
748 	struct cmd_obj *pcmd;
749 	struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
750 	u8	res = _SUCCESS;
751 
752 	pcmd = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC);
753 	if (!pcmd) {
754 		res = _FAIL;
755 		goto exit;
756 	}
757 
758 	INIT_LIST_HEAD(&pcmd->list);
759 	pcmd->cmdcode = GEN_CMD_CODE(_CreateBss);
760 	pcmd->parmbuf = pbss;
761 	pcmd->cmdsz =  sz;
762 	pcmd->rsp = NULL;
763 	pcmd->rspsz = 0;
764 
765 	res = rtw_enqueue_cmd(pcmdpriv, pcmd);
766 
767 exit:
768 
769 	return res;
770 }
771 
rtw_joinbss_cmd(struct adapter * padapter,struct wlan_network * pnetwork)772 u8 rtw_joinbss_cmd(struct adapter  *padapter, struct wlan_network *pnetwork)
773 {
774 	u8	res = _SUCCESS;
775 	uint	t_len = 0;
776 	struct wlan_bssid_ex		*psecnetwork;
777 	struct cmd_obj		*pcmd;
778 	struct cmd_priv		*pcmdpriv = &padapter->cmdpriv;
779 	struct mlme_priv	*pmlmepriv = &padapter->mlmepriv;
780 	struct qos_priv		*pqospriv = &pmlmepriv->qospriv;
781 	struct security_priv	*psecuritypriv = &padapter->securitypriv;
782 	struct registry_priv	*pregistrypriv = &padapter->registrypriv;
783 	struct ht_priv		*phtpriv = &pmlmepriv->htpriv;
784 	enum ndis_802_11_network_infra ndis_network_mode = pnetwork->network.InfrastructureMode;
785 	struct mlme_ext_priv	*pmlmeext = &padapter->mlmeextpriv;
786 	struct mlme_ext_info	*pmlmeinfo = &pmlmeext->mlmext_info;
787 
788 	rtw_led_control(padapter, LED_CTL_START_TO_LINK);
789 
790 	pcmd = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC);
791 	if (!pcmd) {
792 		res = _FAIL;
793 		goto exit;
794 	}
795 	/* for IEs is fix buf size */
796 	t_len = sizeof(struct wlan_bssid_ex);
797 
798 	/* for hidden ap to set fw_state here */
799 	if (!check_fwstate(pmlmepriv, WIFI_STATION_STATE | WIFI_ADHOC_STATE)) {
800 		switch (ndis_network_mode) {
801 		case Ndis802_11IBSS:
802 			set_fwstate(pmlmepriv, WIFI_ADHOC_STATE);
803 			break;
804 		case Ndis802_11Infrastructure:
805 			set_fwstate(pmlmepriv, WIFI_STATION_STATE);
806 			break;
807 		case Ndis802_11APMode:
808 		case Ndis802_11AutoUnknown:
809 		case Ndis802_11InfrastructureMax:
810 			break;
811 		}
812 	}
813 
814 	psecnetwork = (struct wlan_bssid_ex *)&psecuritypriv->sec_bss;
815 	if (!psecnetwork) {
816 		kfree(pcmd);
817 		res = _FAIL;
818 		goto exit;
819 	}
820 
821 	memset(psecnetwork, 0, t_len);
822 
823 	memcpy(psecnetwork, &pnetwork->network, get_wlan_bssid_ex_sz(&pnetwork->network));
824 
825 	psecuritypriv->authenticator_ie[0] = (unsigned char)psecnetwork->IELength;
826 
827 	if (psecnetwork->IELength - 12 < 255) {
828 		memcpy(&psecuritypriv->authenticator_ie[1], &psecnetwork->IEs[12], psecnetwork->IELength - 12);
829 	} else {
830 		memcpy(&psecuritypriv->authenticator_ie[1], &psecnetwork->IEs[12], 255);
831 	}
832 
833 	psecnetwork->IELength = 0;
834 	/*  Added by Albert 2009/02/18 */
835 	/*  If the the driver wants to use the bssid to create the connection. */
836 	/*  If not,  we have to copy the connecting AP's MAC address to it so that */
837 	/*  the driver just has the bssid information for PMKIDList searching. */
838 
839 	if (!pmlmepriv->assoc_by_bssid)
840 		memcpy(&pmlmepriv->assoc_bssid[0], &pnetwork->network.MacAddress[0], ETH_ALEN);
841 
842 	psecnetwork->IELength = rtw_restruct_sec_ie(padapter, &pnetwork->network.IEs[0], &psecnetwork->IEs[0], pnetwork->network.IELength);
843 
844 	pqospriv->qos_option = 0;
845 
846 	if (pregistrypriv->wmm_enable) {
847 		u32 tmp_len;
848 
849 		tmp_len = rtw_restruct_wmm_ie(padapter, &pnetwork->network.IEs[0], &psecnetwork->IEs[0], pnetwork->network.IELength, psecnetwork->IELength);
850 
851 		if (psecnetwork->IELength != tmp_len) {
852 			psecnetwork->IELength = tmp_len;
853 			pqospriv->qos_option = 1; /* There is WMM IE in this corresp. beacon */
854 		} else {
855 			pqospriv->qos_option = 0;/* There is no WMM IE in this corresp. beacon */
856 		}
857 	}
858 
859 	phtpriv->ht_option = false;
860 	if (pregistrypriv->ht_enable) {
861 		/* 	Added by Albert 2010/06/23 */
862 		/* 	For the WEP mode, we will use the bg mode to do the connection to avoid some IOT issue. */
863 		/* 	Especially for Realtek 8192u SoftAP. */
864 		if ((padapter->securitypriv.dot11PrivacyAlgrthm != _WEP40_) &&
865 		    (padapter->securitypriv.dot11PrivacyAlgrthm != _WEP104_) &&
866 		    (padapter->securitypriv.dot11PrivacyAlgrthm != _TKIP_)) {
867 			/* rtw_restructure_ht_ie */
868 			rtw_restructure_ht_ie(padapter, &pnetwork->network.IEs[0], &psecnetwork->IEs[0],
869 									pnetwork->network.IELength, &psecnetwork->IELength);
870 		}
871 	}
872 
873 	pmlmeinfo->assoc_AP_vendor = check_assoc_AP(pnetwork->network.IEs, pnetwork->network.IELength);
874 
875 	if (pmlmeinfo->assoc_AP_vendor == HT_IOT_PEER_TENDA)
876 		padapter->pwrctrlpriv.smart_ps = 0;
877 	else
878 		padapter->pwrctrlpriv.smart_ps = padapter->registrypriv.smart_ps;
879 
880 	DBG_88E("%s: smart_ps =%d\n", __func__, padapter->pwrctrlpriv.smart_ps);
881 
882 	pcmd->cmdsz = get_wlan_bssid_ex_sz(psecnetwork);/* get cmdsz before endian conversion */
883 
884 	INIT_LIST_HEAD(&pcmd->list);
885 	pcmd->cmdcode = _JoinBss_CMD_;/* GEN_CMD_CODE(_JoinBss) */
886 	pcmd->parmbuf = (unsigned char *)psecnetwork;
887 	pcmd->rsp = NULL;
888 	pcmd->rspsz = 0;
889 
890 	res = rtw_enqueue_cmd(pcmdpriv, pcmd);
891 
892 exit:
893 
894 	return res;
895 }
896 
rtw_disassoc_cmd(struct adapter * padapter,u32 deauth_timeout_ms,bool enqueue)897 u8 rtw_disassoc_cmd(struct adapter *padapter, u32 deauth_timeout_ms, bool enqueue) /* for sta_mode */
898 {
899 	struct cmd_obj *cmdobj = NULL;
900 	struct disconnect_parm *param = NULL;
901 	struct cmd_priv *cmdpriv = &padapter->cmdpriv;
902 	u8 res = _SUCCESS;
903 
904 	/* prepare cmd parameter */
905 	param = kzalloc(sizeof(*param), GFP_ATOMIC);
906 	if (!param) {
907 		res = _FAIL;
908 		goto exit;
909 	}
910 	param->deauth_timeout_ms = deauth_timeout_ms;
911 
912 	if (enqueue) {
913 		/* need enqueue, prepare cmd_obj and enqueue */
914 		cmdobj = kzalloc(sizeof(*cmdobj), GFP_ATOMIC);
915 		if (!cmdobj) {
916 			res = _FAIL;
917 			kfree(param);
918 			goto exit;
919 		}
920 		init_h2fwcmd_w_parm_no_rsp(cmdobj, param, _DisConnect_CMD_);
921 		res = rtw_enqueue_cmd(cmdpriv, cmdobj);
922 	} else {
923 		/* no need to enqueue, do the cmd hdl directly and free cmd parameter */
924 		if (H2C_SUCCESS != disconnect_hdl(padapter, (u8 *)param))
925 			res = _FAIL;
926 		kfree(param);
927 	}
928 
929 exit:
930 
931 	return res;
932 }
933 
rtw_setopmode_cmd(struct adapter * padapter,enum ndis_802_11_network_infra networktype)934 u8 rtw_setopmode_cmd(struct adapter  *padapter, enum ndis_802_11_network_infra networktype)
935 {
936 	struct	cmd_obj *ph2c;
937 	struct	setopmode_parm *psetop;
938 
939 	struct	cmd_priv   *pcmdpriv = &padapter->cmdpriv;
940 	u8	res = _SUCCESS;
941 
942 	ph2c = kzalloc(sizeof(struct cmd_obj), GFP_KERNEL);
943 	if (!ph2c) {
944 		res = false;
945 		goto exit;
946 	}
947 	psetop = kzalloc(sizeof(struct setopmode_parm), GFP_KERNEL);
948 
949 	if (!psetop) {
950 		kfree(ph2c);
951 		res = false;
952 		goto exit;
953 	}
954 
955 	init_h2fwcmd_w_parm_no_rsp(ph2c, psetop, _SetOpMode_CMD_);
956 	psetop->mode = (u8)networktype;
957 
958 	res = rtw_enqueue_cmd(pcmdpriv, ph2c);
959 
960 exit:
961 
962 	return res;
963 }
964 
rtw_setstakey_cmd(struct adapter * padapter,u8 * psta,u8 unicast_key)965 u8 rtw_setstakey_cmd(struct adapter *padapter, u8 *psta, u8 unicast_key)
966 {
967 	struct cmd_obj *ph2c;
968 	struct set_stakey_parm *psetstakey_para;
969 	struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
970 	struct set_stakey_rsp *psetstakey_rsp = NULL;
971 
972 	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
973 	struct security_priv *psecuritypriv = &padapter->securitypriv;
974 	struct sta_info *sta = (struct sta_info *)psta;
975 	u8	res = _SUCCESS;
976 
977 	ph2c = kzalloc(sizeof(struct cmd_obj), GFP_KERNEL);
978 	if (!ph2c) {
979 		res = _FAIL;
980 		goto exit;
981 	}
982 
983 	psetstakey_para = kzalloc(sizeof(struct set_stakey_parm), GFP_KERNEL);
984 	if (!psetstakey_para) {
985 		kfree(ph2c);
986 		res = _FAIL;
987 		goto exit;
988 	}
989 
990 	psetstakey_rsp = kzalloc(sizeof(struct set_stakey_rsp), GFP_KERNEL);
991 	if (!psetstakey_rsp) {
992 		kfree(ph2c);
993 		kfree(psetstakey_para);
994 		res = _FAIL;
995 		goto exit;
996 	}
997 
998 	init_h2fwcmd_w_parm_no_rsp(ph2c, psetstakey_para, _SetStaKey_CMD_);
999 	ph2c->rsp = (u8 *)psetstakey_rsp;
1000 	ph2c->rspsz = sizeof(struct set_stakey_rsp);
1001 
1002 	memcpy(psetstakey_para->addr, sta->hwaddr, ETH_ALEN);
1003 
1004 	if (check_fwstate(pmlmepriv, WIFI_STATION_STATE))
1005 		psetstakey_para->algorithm = (unsigned char)psecuritypriv->dot11PrivacyAlgrthm;
1006 	else
1007 		GET_ENCRY_ALGO(psecuritypriv, sta, psetstakey_para->algorithm, false);
1008 
1009 	if (unicast_key)
1010 		memcpy(&psetstakey_para->key, &sta->dot118021x_UncstKey, 16);
1011 	else
1012 		memcpy(&psetstakey_para->key, &psecuritypriv->dot118021XGrpKey[psecuritypriv->dot118021XGrpKeyid].skey, 16);
1013 
1014 	/* jeff: set this because at least sw key is ready */
1015 	padapter->securitypriv.busetkipkey = true;
1016 
1017 	res = rtw_enqueue_cmd(pcmdpriv, ph2c);
1018 
1019 exit:
1020 
1021 	return res;
1022 }
1023 
rtw_clearstakey_cmd(struct adapter * padapter,u8 * psta,u8 entry,u8 enqueue)1024 u8 rtw_clearstakey_cmd(struct adapter *padapter, u8 *psta, u8 entry, u8 enqueue)
1025 {
1026 	struct cmd_obj *ph2c;
1027 	struct set_stakey_parm	*psetstakey_para;
1028 	struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
1029 	struct set_stakey_rsp *psetstakey_rsp = NULL;
1030 	struct sta_info *sta = (struct sta_info *)psta;
1031 	u8	res = _SUCCESS;
1032 
1033 	if (!enqueue) {
1034 		clear_cam_entry(padapter, entry);
1035 	} else {
1036 		ph2c = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC);
1037 		if (!ph2c) {
1038 			res = _FAIL;
1039 			goto exit;
1040 		}
1041 
1042 		psetstakey_para = kzalloc(sizeof(struct set_stakey_parm),
1043 					  GFP_ATOMIC);
1044 		if (!psetstakey_para) {
1045 			kfree(ph2c);
1046 			res = _FAIL;
1047 			goto exit;
1048 		}
1049 
1050 		psetstakey_rsp = kzalloc(sizeof(struct set_stakey_rsp),
1051 					 GFP_ATOMIC);
1052 		if (!psetstakey_rsp) {
1053 			kfree(ph2c);
1054 			kfree(psetstakey_para);
1055 			res = _FAIL;
1056 			goto exit;
1057 		}
1058 
1059 		init_h2fwcmd_w_parm_no_rsp(ph2c, psetstakey_para, _SetStaKey_CMD_);
1060 		ph2c->rsp = (u8 *)psetstakey_rsp;
1061 		ph2c->rspsz = sizeof(struct set_stakey_rsp);
1062 
1063 		memcpy(psetstakey_para->addr, sta->hwaddr, ETH_ALEN);
1064 
1065 		psetstakey_para->algorithm = _NO_PRIVACY_;
1066 
1067 		psetstakey_para->id = entry;
1068 
1069 		res = rtw_enqueue_cmd(pcmdpriv, ph2c);
1070 	}
1071 exit:
1072 
1073 	return res;
1074 }
1075 
rtw_setrttbl_cmd(struct adapter * padapter,struct setratable_parm * prate_table)1076 u8 rtw_setrttbl_cmd(struct adapter  *padapter, struct setratable_parm *prate_table)
1077 {
1078 	struct cmd_obj *ph2c;
1079 	struct setratable_parm *psetrttblparm;
1080 	struct cmd_priv	*pcmdpriv = &padapter->cmdpriv;
1081 	u8	res = _SUCCESS;
1082 
1083 	ph2c = kzalloc(sizeof(struct cmd_obj), GFP_KERNEL);
1084 	if (!ph2c) {
1085 		res = _FAIL;
1086 		goto exit;
1087 	}
1088 	psetrttblparm = kzalloc(sizeof(struct setratable_parm), GFP_KERNEL);
1089 
1090 	if (!psetrttblparm) {
1091 		kfree(ph2c);
1092 		res = _FAIL;
1093 		goto exit;
1094 	}
1095 
1096 	init_h2fwcmd_w_parm_no_rsp(ph2c, psetrttblparm, GEN_CMD_CODE(_SetRaTable));
1097 
1098 	memcpy(psetrttblparm, prate_table, sizeof(struct setratable_parm));
1099 
1100 	res = rtw_enqueue_cmd(pcmdpriv, ph2c);
1101 exit:
1102 
1103 	return res;
1104 }
1105 
rtw_getrttbl_cmd(struct adapter * padapter,struct getratable_rsp * pval)1106 u8 rtw_getrttbl_cmd(struct adapter  *padapter, struct getratable_rsp *pval)
1107 {
1108 	struct cmd_obj *ph2c;
1109 	struct getratable_parm *pgetrttblparm;
1110 	struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
1111 	u8	res = _SUCCESS;
1112 
1113 	ph2c = kzalloc(sizeof(struct cmd_obj), GFP_KERNEL);
1114 	if (!ph2c) {
1115 		res = _FAIL;
1116 		goto exit;
1117 	}
1118 	pgetrttblparm = kzalloc(sizeof(struct getratable_parm), GFP_KERNEL);
1119 
1120 	if (!pgetrttblparm) {
1121 		kfree(ph2c);
1122 		res = _FAIL;
1123 		goto exit;
1124 	}
1125 
1126 /* 	init_h2fwcmd_w_parm_no_rsp(ph2c, psetrttblparm, GEN_CMD_CODE(_SetRaTable)); */
1127 
1128 	INIT_LIST_HEAD(&ph2c->list);
1129 	ph2c->cmdcode = GEN_CMD_CODE(_GetRaTable);
1130 	ph2c->parmbuf = (unsigned char *)pgetrttblparm;
1131 	ph2c->cmdsz =  sizeof(struct getratable_parm);
1132 	ph2c->rsp = (u8 *)pval;
1133 	ph2c->rspsz = sizeof(struct getratable_rsp);
1134 
1135 	pgetrttblparm->rsvd = 0x0;
1136 
1137 	res = rtw_enqueue_cmd(pcmdpriv, ph2c);
1138 exit:
1139 
1140 	return res;
1141 }
1142 
rtw_setassocsta_cmd(struct adapter * padapter,u8 * mac_addr)1143 u8 rtw_setassocsta_cmd(struct adapter  *padapter, u8 *mac_addr)
1144 {
1145 	struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
1146 	struct cmd_obj *ph2c;
1147 	struct set_assocsta_parm *psetassocsta_para;
1148 	struct set_stakey_rsp *psetassocsta_rsp = NULL;
1149 
1150 	u8	res = _SUCCESS;
1151 
1152 	ph2c = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC);
1153 	if (!ph2c) {
1154 		res = _FAIL;
1155 		goto exit;
1156 	}
1157 
1158 	psetassocsta_para = kzalloc(sizeof(struct set_assocsta_parm), GFP_ATOMIC);
1159 	if (!psetassocsta_para) {
1160 		kfree(ph2c);
1161 		res = _FAIL;
1162 		goto exit;
1163 	}
1164 
1165 	psetassocsta_rsp = kzalloc(sizeof(struct set_assocsta_rsp), GFP_ATOMIC);
1166 	if (!psetassocsta_rsp) {
1167 		kfree(ph2c);
1168 		kfree(psetassocsta_para);
1169 		return _FAIL;
1170 	}
1171 
1172 	init_h2fwcmd_w_parm_no_rsp(ph2c, psetassocsta_para, _SetAssocSta_CMD_);
1173 	ph2c->rsp = (u8 *)psetassocsta_rsp;
1174 	ph2c->rspsz = sizeof(struct set_assocsta_rsp);
1175 
1176 	memcpy(psetassocsta_para->addr, mac_addr, ETH_ALEN);
1177 
1178 	res = rtw_enqueue_cmd(pcmdpriv, ph2c);
1179 
1180 exit:
1181 
1182 	return res;
1183  }
1184 
rtw_addbareq_cmd(struct adapter * padapter,u8 tid,u8 * addr)1185 u8 rtw_addbareq_cmd(struct adapter *padapter, u8 tid, u8 *addr)
1186 {
1187 	struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
1188 	struct cmd_obj *ph2c;
1189 	struct addBaReq_parm *paddbareq_parm;
1190 	u8	res = _SUCCESS;
1191 
1192 	ph2c = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC);
1193 	if (!ph2c) {
1194 		res = _FAIL;
1195 		goto exit;
1196 	}
1197 
1198 	paddbareq_parm = kzalloc(sizeof(struct addBaReq_parm), GFP_ATOMIC);
1199 	if (!paddbareq_parm) {
1200 		kfree(ph2c);
1201 		res = _FAIL;
1202 		goto exit;
1203 	}
1204 
1205 	paddbareq_parm->tid = tid;
1206 	memcpy(paddbareq_parm->addr, addr, ETH_ALEN);
1207 
1208 	init_h2fwcmd_w_parm_no_rsp(ph2c, paddbareq_parm, GEN_CMD_CODE(_AddBAReq));
1209 
1210 	/* DBG_88E("rtw_addbareq_cmd, tid =%d\n", tid); */
1211 
1212 	/* rtw_enqueue_cmd(pcmdpriv, ph2c); */
1213 	res = rtw_enqueue_cmd(pcmdpriv, ph2c);
1214 
1215 exit:
1216 
1217 	return res;
1218 }
1219 
rtw_dynamic_chk_wk_cmd(struct adapter * padapter)1220 u8 rtw_dynamic_chk_wk_cmd(struct adapter *padapter)
1221 {
1222 	struct cmd_obj *ph2c;
1223 	struct drvextra_cmd_parm *pdrvextra_cmd_parm;
1224 	struct cmd_priv	*pcmdpriv = &padapter->cmdpriv;
1225 	u8	res = _SUCCESS;
1226 
1227 	ph2c = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC);
1228 	if (!ph2c) {
1229 		res = _FAIL;
1230 		goto exit;
1231 	}
1232 
1233 	pdrvextra_cmd_parm = kzalloc(sizeof(struct drvextra_cmd_parm), GFP_ATOMIC);
1234 	if (!pdrvextra_cmd_parm) {
1235 		kfree(ph2c);
1236 		res = _FAIL;
1237 		goto exit;
1238 	}
1239 
1240 	pdrvextra_cmd_parm->ec_id = DYNAMIC_CHK_WK_CID;
1241 	pdrvextra_cmd_parm->type_size = 0;
1242 	pdrvextra_cmd_parm->pbuf = (u8 *)padapter;
1243 
1244 	init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, GEN_CMD_CODE(_Set_Drv_Extra));
1245 
1246 	/* rtw_enqueue_cmd(pcmdpriv, ph2c); */
1247 	res = rtw_enqueue_cmd(pcmdpriv, ph2c);
1248 exit:
1249 
1250 	return res;
1251 }
1252 
rtw_set_ch_cmd(struct adapter * padapter,u8 ch,u8 bw,u8 ch_offset,u8 enqueue)1253 u8 rtw_set_ch_cmd(struct adapter *padapter, u8 ch, u8 bw, u8 ch_offset, u8 enqueue)
1254 {
1255 	struct cmd_obj *pcmdobj;
1256 	struct set_ch_parm *set_ch_parm;
1257 	struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
1258 
1259 	u8 res = _SUCCESS;
1260 
1261 	DBG_88E(FUNC_NDEV_FMT" ch:%u, bw:%u, ch_offset:%u\n",
1262 		FUNC_NDEV_ARG(padapter->pnetdev), ch, bw, ch_offset);
1263 
1264 	/* check input parameter */
1265 
1266 	/* prepare cmd parameter */
1267 	set_ch_parm = kzalloc(sizeof(*set_ch_parm), GFP_ATOMIC);
1268 	if (!set_ch_parm) {
1269 		res = _FAIL;
1270 		goto exit;
1271 	}
1272 	set_ch_parm->ch = ch;
1273 	set_ch_parm->bw = bw;
1274 	set_ch_parm->ch_offset = ch_offset;
1275 
1276 	if (enqueue) {
1277 		/* need enqueue, prepare cmd_obj and enqueue */
1278 		pcmdobj = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC);
1279 		if (!pcmdobj) {
1280 			kfree(set_ch_parm);
1281 			res = _FAIL;
1282 			goto exit;
1283 		}
1284 
1285 		init_h2fwcmd_w_parm_no_rsp(pcmdobj, set_ch_parm, GEN_CMD_CODE(_SetChannel));
1286 		res = rtw_enqueue_cmd(pcmdpriv, pcmdobj);
1287 	} else {
1288 		/* no need to enqueue, do the cmd hdl directly and free cmd parameter */
1289 		if (H2C_SUCCESS != set_ch_hdl(padapter, (u8 *)set_ch_parm))
1290 			res = _FAIL;
1291 
1292 		kfree(set_ch_parm);
1293 	}
1294 
1295 	/* do something based on res... */
1296 
1297 exit:
1298 
1299 	DBG_88E(FUNC_NDEV_FMT" res:%u\n", FUNC_NDEV_ARG(padapter->pnetdev), res);
1300 
1301 	return res;
1302 }
1303 
rtw_set_chplan_cmd(struct adapter * padapter,u8 chplan,u8 enqueue)1304 u8 rtw_set_chplan_cmd(struct adapter *padapter, u8 chplan, u8 enqueue)
1305 {
1306 	struct	cmd_obj *pcmdobj;
1307 	struct	SetChannelPlan_param *setChannelPlan_param;
1308 	struct	cmd_priv   *pcmdpriv = &padapter->cmdpriv;
1309 
1310 	u8	res = _SUCCESS;
1311 
1312 	/* check input parameter */
1313 	if (!rtw_is_channel_plan_valid(chplan)) {
1314 		res = _FAIL;
1315 		goto exit;
1316 	}
1317 
1318 	/* prepare cmd parameter */
1319 	setChannelPlan_param = kzalloc(sizeof(struct SetChannelPlan_param),
1320 				       GFP_KERNEL);
1321 	if (!setChannelPlan_param) {
1322 		res = _FAIL;
1323 		goto exit;
1324 	}
1325 	setChannelPlan_param->channel_plan = chplan;
1326 
1327 	if (enqueue) {
1328 		/* need enqueue, prepare cmd_obj and enqueue */
1329 		pcmdobj = kzalloc(sizeof(struct	cmd_obj), GFP_KERNEL);
1330 		if (!pcmdobj) {
1331 			kfree(setChannelPlan_param);
1332 			res = _FAIL;
1333 			goto exit;
1334 		}
1335 
1336 		init_h2fwcmd_w_parm_no_rsp(pcmdobj, setChannelPlan_param, GEN_CMD_CODE(_SetChannelPlan));
1337 		res = rtw_enqueue_cmd(pcmdpriv, pcmdobj);
1338 	} else {
1339 		/* no need to enqueue, do the cmd hdl directly and free cmd parameter */
1340 		if (H2C_SUCCESS != set_chplan_hdl(padapter, (unsigned char *)setChannelPlan_param))
1341 			res = _FAIL;
1342 
1343 		kfree(setChannelPlan_param);
1344 	}
1345 
1346 	/* do something based on res... */
1347 	if (res == _SUCCESS)
1348 		padapter->mlmepriv.ChannelPlan = chplan;
1349 
1350 exit:
1351 
1352 	return res;
1353 }
1354 
rtw_led_blink_cmd(struct adapter * padapter,struct LED_871x * pLed)1355 u8 rtw_led_blink_cmd(struct adapter *padapter, struct LED_871x *pLed)
1356 {
1357 	struct	cmd_obj *pcmdobj;
1358 	struct	LedBlink_param *ledBlink_param;
1359 	struct	cmd_priv   *pcmdpriv = &padapter->cmdpriv;
1360 
1361 	u8	res = _SUCCESS;
1362 
1363 	pcmdobj = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC);
1364 	if (!pcmdobj) {
1365 		res = _FAIL;
1366 		goto exit;
1367 	}
1368 
1369 	ledBlink_param = kzalloc(sizeof(struct LedBlink_param), GFP_ATOMIC);
1370 	if (!ledBlink_param) {
1371 		kfree(pcmdobj);
1372 		res = _FAIL;
1373 		goto exit;
1374 	}
1375 
1376 	ledBlink_param->pLed = pLed;
1377 
1378 	init_h2fwcmd_w_parm_no_rsp(pcmdobj, ledBlink_param, GEN_CMD_CODE(_LedBlink));
1379 	res = rtw_enqueue_cmd(pcmdpriv, pcmdobj);
1380 
1381 exit:
1382 
1383 	return res;
1384 }
1385 
rtw_set_csa_cmd(struct adapter * padapter,u8 new_ch_no)1386 u8 rtw_set_csa_cmd(struct adapter *padapter, u8 new_ch_no)
1387 {
1388 	struct	cmd_obj *pcmdobj;
1389 	struct	SetChannelSwitch_param *setChannelSwitch_param;
1390 	struct	cmd_priv   *pcmdpriv = &padapter->cmdpriv;
1391 
1392 	u8	res = _SUCCESS;
1393 
1394 	pcmdobj = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC);
1395 	if (!pcmdobj) {
1396 		res = _FAIL;
1397 		goto exit;
1398 	}
1399 
1400 	setChannelSwitch_param = kzalloc(sizeof(struct	SetChannelSwitch_param),
1401 					 GFP_ATOMIC);
1402 	if (!setChannelSwitch_param) {
1403 		kfree(pcmdobj);
1404 		res = _FAIL;
1405 		goto exit;
1406 	}
1407 
1408 	setChannelSwitch_param->new_ch_no = new_ch_no;
1409 
1410 	init_h2fwcmd_w_parm_no_rsp(pcmdobj, setChannelSwitch_param, GEN_CMD_CODE(_SetChannelSwitch));
1411 	res = rtw_enqueue_cmd(pcmdpriv, pcmdobj);
1412 
1413 exit:
1414 
1415 	return res;
1416 }
1417 
rtw_tdls_cmd(struct adapter * padapter,u8 * addr,u8 option)1418 u8 rtw_tdls_cmd(struct adapter *padapter, u8 *addr, u8 option)
1419 {
1420 	return _SUCCESS;
1421 }
1422 
traffic_status_watchdog(struct adapter * padapter)1423 static void traffic_status_watchdog(struct adapter *padapter)
1424 {
1425 	u8	bEnterPS;
1426 	u8	bBusyTraffic = false, bTxBusyTraffic = false, bRxBusyTraffic = false;
1427 	u8	bHigherBusyTraffic = false, bHigherBusyRxTraffic = false, bHigherBusyTxTraffic = false;
1428 	struct mlme_priv		*pmlmepriv = &padapter->mlmepriv;
1429 
1430 	/*  */
1431 	/*  Determine if our traffic is busy now */
1432 	/*  */
1433 	if (check_fwstate(pmlmepriv, _FW_LINKED)) {
1434 		if (pmlmepriv->LinkDetectInfo.NumRxOkInPeriod > 100 ||
1435 		    pmlmepriv->LinkDetectInfo.NumTxOkInPeriod > 100) {
1436 			bBusyTraffic = true;
1437 
1438 			if (pmlmepriv->LinkDetectInfo.NumRxOkInPeriod > pmlmepriv->LinkDetectInfo.NumTxOkInPeriod)
1439 				bRxBusyTraffic = true;
1440 			else
1441 				bTxBusyTraffic = true;
1442 		}
1443 
1444 		/*  Higher Tx/Rx data. */
1445 		if (pmlmepriv->LinkDetectInfo.NumRxOkInPeriod > 4000 ||
1446 		    pmlmepriv->LinkDetectInfo.NumTxOkInPeriod > 4000) {
1447 			bHigherBusyTraffic = true;
1448 
1449 			if (pmlmepriv->LinkDetectInfo.NumRxOkInPeriod > pmlmepriv->LinkDetectInfo.NumTxOkInPeriod)
1450 				bHigherBusyRxTraffic = true;
1451 			else
1452 				bHigherBusyTxTraffic = true;
1453 		}
1454 
1455 		/*  check traffic for  powersaving. */
1456 		if (((pmlmepriv->LinkDetectInfo.NumRxUnicastOkInPeriod + pmlmepriv->LinkDetectInfo.NumTxOkInPeriod) > 8) ||
1457 		    (pmlmepriv->LinkDetectInfo.NumRxUnicastOkInPeriod > 2))
1458 			bEnterPS = false;
1459 		else
1460 			bEnterPS = true;
1461 
1462 		/*  LeisurePS only work in infra mode. */
1463 		if (bEnterPS)
1464 			LPS_Enter(padapter);
1465 		else
1466 			LPS_Leave(padapter);
1467 	} else {
1468 		LPS_Leave(padapter);
1469 	}
1470 
1471 	pmlmepriv->LinkDetectInfo.NumRxOkInPeriod = 0;
1472 	pmlmepriv->LinkDetectInfo.NumTxOkInPeriod = 0;
1473 	pmlmepriv->LinkDetectInfo.NumRxUnicastOkInPeriod = 0;
1474 	pmlmepriv->LinkDetectInfo.bBusyTraffic = bBusyTraffic;
1475 	pmlmepriv->LinkDetectInfo.bTxBusyTraffic = bTxBusyTraffic;
1476 	pmlmepriv->LinkDetectInfo.bRxBusyTraffic = bRxBusyTraffic;
1477 	pmlmepriv->LinkDetectInfo.bHigherBusyTraffic = bHigherBusyTraffic;
1478 	pmlmepriv->LinkDetectInfo.bHigherBusyRxTraffic = bHigherBusyRxTraffic;
1479 	pmlmepriv->LinkDetectInfo.bHigherBusyTxTraffic = bHigherBusyTxTraffic;
1480 }
1481 
dynamic_chk_wk_hdl(struct adapter * padapter,u8 * pbuf,int sz)1482 static void dynamic_chk_wk_hdl(struct adapter *padapter, u8 *pbuf, int sz)
1483 {
1484 	struct mlme_priv *pmlmepriv;
1485 
1486 	padapter = (struct adapter *)pbuf;
1487 	pmlmepriv = &padapter->mlmepriv;
1488 
1489 #ifdef CONFIG_88EU_AP_MODE
1490 	if (check_fwstate(pmlmepriv, WIFI_AP_STATE))
1491 		expire_timeout_chk(padapter);
1492 #endif
1493 
1494 	rtw_hal_sreset_xmit_status_check(padapter);
1495 
1496 	linked_status_chk(padapter);
1497 	traffic_status_watchdog(padapter);
1498 
1499 	rtw_hal_dm_watchdog(padapter);
1500 }
1501 
lps_ctrl_wk_hdl(struct adapter * padapter,u8 lps_ctrl_type)1502 static void lps_ctrl_wk_hdl(struct adapter *padapter, u8 lps_ctrl_type)
1503 {
1504 	struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv;
1505 	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1506 	u8	mstatus;
1507 
1508 	if (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) ||
1509 	    check_fwstate(pmlmepriv, WIFI_ADHOC_STATE))
1510 		return;
1511 
1512 	switch (lps_ctrl_type) {
1513 	case LPS_CTRL_SCAN:
1514 		if (check_fwstate(pmlmepriv, _FW_LINKED)) {
1515 			/* connect */
1516 			LPS_Leave(padapter);
1517 		}
1518 		break;
1519 	case LPS_CTRL_JOINBSS:
1520 		LPS_Leave(padapter);
1521 		break;
1522 	case LPS_CTRL_CONNECT:
1523 		mstatus = 1;/* connect */
1524 		/*  Reset LPS Setting */
1525 		padapter->pwrctrlpriv.LpsIdleCount = 0;
1526 		rtw_hal_set_hwreg(padapter, HW_VAR_H2C_FW_JOINBSSRPT, (u8 *)(&mstatus));
1527 		break;
1528 	case LPS_CTRL_DISCONNECT:
1529 		mstatus = 0;/* disconnect */
1530 		LPS_Leave(padapter);
1531 		rtw_hal_set_hwreg(padapter, HW_VAR_H2C_FW_JOINBSSRPT, (u8 *)(&mstatus));
1532 		break;
1533 	case LPS_CTRL_SPECIAL_PACKET:
1534 		/* DBG_88E("LPS_CTRL_SPECIAL_PACKET\n"); */
1535 		pwrpriv->DelayLPSLastTimeStamp = jiffies;
1536 		LPS_Leave(padapter);
1537 		break;
1538 	case LPS_CTRL_LEAVE:
1539 		LPS_Leave(padapter);
1540 		break;
1541 	default:
1542 		break;
1543 	}
1544 
1545 }
1546 
rtw_lps_ctrl_wk_cmd(struct adapter * padapter,u8 lps_ctrl_type,u8 enqueue)1547 u8 rtw_lps_ctrl_wk_cmd(struct adapter *padapter, u8 lps_ctrl_type, u8 enqueue)
1548 {
1549 	struct cmd_obj	*ph2c;
1550 	struct drvextra_cmd_parm	*pdrvextra_cmd_parm;
1551 	struct cmd_priv	*pcmdpriv = &padapter->cmdpriv;
1552 	/* struct pwrctrl_priv *pwrctrlpriv = &padapter->pwrctrlpriv; */
1553 	u8	res = _SUCCESS;
1554 
1555 	/* if (!pwrctrlpriv->bLeisurePs) */
1556 	/* 	return res; */
1557 
1558 	if (enqueue) {
1559 		ph2c = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC);
1560 		if (!ph2c) {
1561 			res = _FAIL;
1562 			goto exit;
1563 		}
1564 
1565 		pdrvextra_cmd_parm = kzalloc(sizeof(struct drvextra_cmd_parm),
1566 					     GFP_ATOMIC);
1567 		if (!pdrvextra_cmd_parm) {
1568 			kfree(ph2c);
1569 			res = _FAIL;
1570 			goto exit;
1571 		}
1572 
1573 		pdrvextra_cmd_parm->ec_id = LPS_CTRL_WK_CID;
1574 		pdrvextra_cmd_parm->type_size = lps_ctrl_type;
1575 		pdrvextra_cmd_parm->pbuf = NULL;
1576 
1577 		init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, GEN_CMD_CODE(_Set_Drv_Extra));
1578 
1579 		res = rtw_enqueue_cmd(pcmdpriv, ph2c);
1580 	} else {
1581 		lps_ctrl_wk_hdl(padapter, lps_ctrl_type);
1582 	}
1583 
1584 exit:
1585 
1586 	return res;
1587 }
1588 
rpt_timer_setting_wk_hdl(struct adapter * padapter,u16 min_time)1589 static void rpt_timer_setting_wk_hdl(struct adapter *padapter, u16 min_time)
1590 {
1591 	rtw_hal_set_hwreg(padapter, HW_VAR_RPT_TIMER_SETTING, (u8 *)(&min_time));
1592 }
1593 
rtw_rpt_timer_cfg_cmd(struct adapter * padapter,u16 min_time)1594 u8 rtw_rpt_timer_cfg_cmd(struct adapter *padapter, u16 min_time)
1595 {
1596 	struct cmd_obj		*ph2c;
1597 	struct drvextra_cmd_parm	*pdrvextra_cmd_parm;
1598 	struct cmd_priv	*pcmdpriv = &padapter->cmdpriv;
1599 
1600 	u8	res = _SUCCESS;
1601 
1602 	ph2c = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC);
1603 	if (!ph2c) {
1604 		res = _FAIL;
1605 		goto exit;
1606 	}
1607 
1608 	pdrvextra_cmd_parm = kzalloc(sizeof(struct drvextra_cmd_parm),
1609 				     GFP_ATOMIC);
1610 	if (!pdrvextra_cmd_parm) {
1611 		kfree(ph2c);
1612 		res = _FAIL;
1613 		goto exit;
1614 	}
1615 
1616 	pdrvextra_cmd_parm->ec_id = RTP_TIMER_CFG_WK_CID;
1617 	pdrvextra_cmd_parm->type_size = min_time;
1618 	pdrvextra_cmd_parm->pbuf = NULL;
1619 	init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, GEN_CMD_CODE(_Set_Drv_Extra));
1620 	res = rtw_enqueue_cmd(pcmdpriv, ph2c);
1621 exit:
1622 
1623 	return res;
1624 }
1625 
antenna_select_wk_hdl(struct adapter * padapter,u8 antenna)1626 static void antenna_select_wk_hdl(struct adapter *padapter, u8 antenna)
1627 {
1628 	rtw_hal_set_hwreg(padapter, HW_VAR_ANTENNA_DIVERSITY_SELECT, (u8 *)(&antenna));
1629 }
1630 
rtw_antenna_select_cmd(struct adapter * padapter,u8 antenna,u8 enqueue)1631 u8 rtw_antenna_select_cmd(struct adapter *padapter, u8 antenna, u8 enqueue)
1632 {
1633 	struct cmd_obj		*ph2c;
1634 	struct drvextra_cmd_parm	*pdrvextra_cmd_parm;
1635 	struct cmd_priv	*pcmdpriv = &padapter->cmdpriv;
1636 	u8	support_ant_div;
1637 	u8	res = _SUCCESS;
1638 
1639 	rtw_hal_get_def_var(padapter, HAL_DEF_IS_SUPPORT_ANT_DIV, &support_ant_div);
1640 	if (!support_ant_div)
1641 		return res;
1642 
1643 	if (enqueue) {
1644 		ph2c = kzalloc(sizeof(struct cmd_obj), GFP_KERNEL);
1645 		if (!ph2c) {
1646 			res = _FAIL;
1647 			goto exit;
1648 		}
1649 
1650 		pdrvextra_cmd_parm = kzalloc(sizeof(struct drvextra_cmd_parm),
1651 					     GFP_KERNEL);
1652 		if (!pdrvextra_cmd_parm) {
1653 			kfree(ph2c);
1654 			res = _FAIL;
1655 			goto exit;
1656 		}
1657 
1658 		pdrvextra_cmd_parm->ec_id = ANT_SELECT_WK_CID;
1659 		pdrvextra_cmd_parm->type_size = antenna;
1660 		pdrvextra_cmd_parm->pbuf = NULL;
1661 		init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, GEN_CMD_CODE(_Set_Drv_Extra));
1662 
1663 		res = rtw_enqueue_cmd(pcmdpriv, ph2c);
1664 	} else {
1665 		antenna_select_wk_hdl(padapter, antenna);
1666 	}
1667 exit:
1668 
1669 	return res;
1670 }
1671 
power_saving_wk_hdl(struct adapter * padapter,u8 * pbuf,int sz)1672 static void power_saving_wk_hdl(struct adapter *padapter, u8 *pbuf, int sz)
1673 {
1674 	 rtw_ps_processor(padapter);
1675 }
1676 
1677 #ifdef CONFIG_88EU_P2P
p2p_protocol_wk_cmd(struct adapter * padapter,int intCmdType)1678 u8 p2p_protocol_wk_cmd(struct adapter *padapter, int intCmdType)
1679 {
1680 	struct cmd_obj	*ph2c;
1681 	struct drvextra_cmd_parm	*pdrvextra_cmd_parm;
1682 	struct wifidirect_info	*pwdinfo = &padapter->wdinfo;
1683 	struct cmd_priv	*pcmdpriv = &padapter->cmdpriv;
1684 	u8	res = _SUCCESS;
1685 
1686 	if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE))
1687 		return res;
1688 
1689 	ph2c = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC);
1690 	if (!ph2c) {
1691 		res = _FAIL;
1692 		goto exit;
1693 	}
1694 
1695 	pdrvextra_cmd_parm = kzalloc(sizeof(struct drvextra_cmd_parm), GFP_ATOMIC);
1696 	if (!pdrvextra_cmd_parm) {
1697 		kfree(ph2c);
1698 		res = _FAIL;
1699 		goto exit;
1700 	}
1701 
1702 	pdrvextra_cmd_parm->ec_id = P2P_PROTO_WK_CID;
1703 	pdrvextra_cmd_parm->type_size = intCmdType;	/* 	As the command tppe. */
1704 	pdrvextra_cmd_parm->pbuf = NULL;		/* 	Must be NULL here */
1705 
1706 	init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, GEN_CMD_CODE(_Set_Drv_Extra));
1707 
1708 	res = rtw_enqueue_cmd(pcmdpriv, ph2c);
1709 
1710 exit:
1711 
1712 	return res;
1713 }
1714 #endif /* CONFIG_88EU_P2P */
1715 
rtw_ps_cmd(struct adapter * padapter)1716 u8 rtw_ps_cmd(struct adapter *padapter)
1717 {
1718 	struct cmd_obj		*ppscmd;
1719 	struct drvextra_cmd_parm	*pdrvextra_cmd_parm;
1720 	struct cmd_priv	*pcmdpriv = &padapter->cmdpriv;
1721 
1722 	u8	res = _SUCCESS;
1723 
1724 	ppscmd = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC);
1725 	if (!ppscmd) {
1726 		res = _FAIL;
1727 		goto exit;
1728 	}
1729 
1730 	pdrvextra_cmd_parm = kzalloc(sizeof(struct drvextra_cmd_parm), GFP_ATOMIC);
1731 	if (!pdrvextra_cmd_parm) {
1732 		kfree(ppscmd);
1733 		res = _FAIL;
1734 		goto exit;
1735 	}
1736 
1737 	pdrvextra_cmd_parm->ec_id = POWER_SAVING_CTRL_WK_CID;
1738 	pdrvextra_cmd_parm->pbuf = NULL;
1739 	init_h2fwcmd_w_parm_no_rsp(ppscmd, pdrvextra_cmd_parm, GEN_CMD_CODE(_Set_Drv_Extra));
1740 
1741 	res = rtw_enqueue_cmd(pcmdpriv, ppscmd);
1742 
1743 exit:
1744 
1745 	return res;
1746 }
1747 
1748 #ifdef CONFIG_88EU_AP_MODE
1749 
rtw_chk_hi_queue_hdl(struct adapter * padapter)1750 static void rtw_chk_hi_queue_hdl(struct adapter *padapter)
1751 {
1752 	int cnt = 0;
1753 	struct sta_info *psta_bmc;
1754 	struct sta_priv *pstapriv = &padapter->stapriv;
1755 
1756 	psta_bmc = rtw_get_bcmc_stainfo(padapter);
1757 	if (!psta_bmc)
1758 		return;
1759 
1760 	if (psta_bmc->sleepq_len == 0) {
1761 		u8 val = 0;
1762 
1763 		/* while ((rtw_read32(padapter, 0x414)&0x00ffff00)!= 0) */
1764 		/* while ((rtw_read32(padapter, 0x414)&0x0000ff00)!= 0) */
1765 
1766 		rtw_hal_get_hwreg(padapter, HW_VAR_CHK_HI_QUEUE_EMPTY, &val);
1767 
1768 		while (!val) {
1769 			msleep(100);
1770 
1771 			cnt++;
1772 
1773 			if (cnt > 10)
1774 				break;
1775 
1776 			rtw_hal_get_hwreg(padapter, HW_VAR_CHK_HI_QUEUE_EMPTY, &val);
1777 		}
1778 
1779 		if (cnt <= 10) {
1780 			pstapriv->tim_bitmap &= ~BIT(0);
1781 			pstapriv->sta_dz_bitmap &= ~BIT(0);
1782 
1783 			update_beacon(padapter, _TIM_IE_, NULL, false);
1784 		} else { /* re check again */
1785 			rtw_chk_hi_queue_cmd(padapter);
1786 		}
1787 	}
1788 }
1789 
rtw_chk_hi_queue_cmd(struct adapter * padapter)1790 u8 rtw_chk_hi_queue_cmd(struct adapter *padapter)
1791 {
1792 	struct cmd_obj	*ph2c;
1793 	struct drvextra_cmd_parm	*pdrvextra_cmd_parm;
1794 	struct cmd_priv	*pcmdpriv = &padapter->cmdpriv;
1795 	u8	res = _SUCCESS;
1796 
1797 	ph2c = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC);
1798 	if (!ph2c) {
1799 		res = _FAIL;
1800 		goto exit;
1801 	}
1802 
1803 	pdrvextra_cmd_parm = kzalloc(sizeof(struct drvextra_cmd_parm), GFP_ATOMIC);
1804 	if (!pdrvextra_cmd_parm) {
1805 		kfree(ph2c);
1806 		res = _FAIL;
1807 		goto exit;
1808 	}
1809 
1810 	pdrvextra_cmd_parm->ec_id = CHECK_HIQ_WK_CID;
1811 	pdrvextra_cmd_parm->type_size = 0;
1812 	pdrvextra_cmd_parm->pbuf = NULL;
1813 
1814 	init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, GEN_CMD_CODE(_Set_Drv_Extra));
1815 
1816 	res = rtw_enqueue_cmd(pcmdpriv, ph2c);
1817 exit:
1818 	return res;
1819 }
1820 #endif
1821 
rtw_c2h_wk_cmd(struct adapter * padapter,u8 * c2h_evt)1822 u8 rtw_c2h_wk_cmd(struct adapter *padapter, u8 *c2h_evt)
1823 {
1824 	struct cmd_obj *ph2c;
1825 	struct drvextra_cmd_parm *pdrvextra_cmd_parm;
1826 	struct cmd_priv	*pcmdpriv = &padapter->cmdpriv;
1827 	u8	res = _SUCCESS;
1828 
1829 	ph2c = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC);
1830 	if (!ph2c) {
1831 		res = _FAIL;
1832 		goto exit;
1833 	}
1834 
1835 	pdrvextra_cmd_parm = kzalloc(sizeof(struct drvextra_cmd_parm), GFP_ATOMIC);
1836 	if (!pdrvextra_cmd_parm) {
1837 		kfree(ph2c);
1838 		res = _FAIL;
1839 		goto exit;
1840 	}
1841 
1842 	pdrvextra_cmd_parm->ec_id = C2H_WK_CID;
1843 	pdrvextra_cmd_parm->type_size = c2h_evt ? 16 : 0;
1844 	pdrvextra_cmd_parm->pbuf = c2h_evt;
1845 
1846 	init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, GEN_CMD_CODE(_Set_Drv_Extra));
1847 
1848 	res = rtw_enqueue_cmd(pcmdpriv, ph2c);
1849 
1850 exit:
1851 
1852 	return res;
1853 }
1854 
c2h_evt_hdl(struct adapter * adapter,struct c2h_evt_hdr * c2h_evt,c2h_id_filter filter)1855 static s32 c2h_evt_hdl(struct adapter *adapter, struct c2h_evt_hdr *c2h_evt, c2h_id_filter filter)
1856 {
1857 	s32 ret = _FAIL;
1858 	u8 buf[16];
1859 
1860 	if (!c2h_evt) {
1861 		/* No c2h event in cmd_obj, read c2h event before handling*/
1862 		if (c2h_evt_read(adapter, buf) == _SUCCESS) {
1863 			c2h_evt = (struct c2h_evt_hdr *)buf;
1864 
1865 			if (filter && !filter(c2h_evt->id))
1866 				goto exit;
1867 
1868 			ret = rtw_hal_c2h_handler(adapter, c2h_evt);
1869 		}
1870 	} else {
1871 		if (filter && !filter(c2h_evt->id))
1872 			goto exit;
1873 
1874 		ret = rtw_hal_c2h_handler(adapter, c2h_evt);
1875 	}
1876 exit:
1877 	return ret;
1878 }
1879 
c2h_wk_callback(struct work_struct * work)1880 static void c2h_wk_callback(struct work_struct *work)
1881 {
1882 	struct evt_priv *evtpriv = container_of(work, struct evt_priv, c2h_wk);
1883 	struct adapter *adapter = container_of(evtpriv, struct adapter, evtpriv);
1884 	struct c2h_evt_hdr *c2h_evt;
1885 	c2h_id_filter ccx_id_filter = rtw_hal_c2h_id_filter_ccx(adapter);
1886 
1887 	evtpriv->c2h_wk_alive = true;
1888 
1889 	while (!rtw_cbuf_empty(evtpriv->c2h_queue)) {
1890 		if ((c2h_evt = (struct c2h_evt_hdr *)rtw_cbuf_pop(evtpriv->c2h_queue)) != NULL) {
1891 			/* This C2H event is read, clear it */
1892 			c2h_evt_clear(adapter);
1893 		} else {
1894 			c2h_evt = kmalloc(16, GFP_KERNEL);
1895 			if (c2h_evt) {
1896 				/* This C2H event is not read, read & clear now */
1897 				if (c2h_evt_read(adapter, (u8 *)c2h_evt) != _SUCCESS) {
1898 					kfree(c2h_evt);
1899 					continue;
1900 				}
1901 			} else {
1902 				return;
1903 			}
1904 		}
1905 
1906 		/* Special pointer to trigger c2h_evt_clear only */
1907 		if ((void *)c2h_evt == (void *)evtpriv)
1908 			continue;
1909 
1910 		if (!c2h_evt_exist(c2h_evt)) {
1911 			kfree(c2h_evt);
1912 			continue;
1913 		}
1914 
1915 		if (ccx_id_filter(c2h_evt->id)) {
1916 			/* Handle CCX report here */
1917 			rtw_hal_c2h_handler(adapter, c2h_evt);
1918 			kfree(c2h_evt);
1919 		} else {
1920 #ifdef CONFIG_88EU_P2P
1921 			/* Enqueue into cmd_thread for others */
1922 			rtw_c2h_wk_cmd(adapter, (u8 *)c2h_evt);
1923 #endif
1924 		}
1925 	}
1926 
1927 	evtpriv->c2h_wk_alive = false;
1928 }
1929 
rtw_drvextra_cmd_hdl(struct adapter * padapter,unsigned char * pbuf)1930 u8 rtw_drvextra_cmd_hdl(struct adapter *padapter, unsigned char *pbuf)
1931 {
1932 	struct drvextra_cmd_parm *pdrvextra_cmd;
1933 
1934 	if (!pbuf)
1935 		return H2C_PARAMETERS_ERROR;
1936 
1937 	pdrvextra_cmd = (struct drvextra_cmd_parm *)pbuf;
1938 
1939 	switch (pdrvextra_cmd->ec_id) {
1940 	case DYNAMIC_CHK_WK_CID:
1941 		dynamic_chk_wk_hdl(padapter, pdrvextra_cmd->pbuf, pdrvextra_cmd->type_size);
1942 		break;
1943 	case POWER_SAVING_CTRL_WK_CID:
1944 		power_saving_wk_hdl(padapter, pdrvextra_cmd->pbuf, pdrvextra_cmd->type_size);
1945 		break;
1946 	case LPS_CTRL_WK_CID:
1947 		lps_ctrl_wk_hdl(padapter, (u8)pdrvextra_cmd->type_size);
1948 		break;
1949 	case RTP_TIMER_CFG_WK_CID:
1950 		rpt_timer_setting_wk_hdl(padapter, pdrvextra_cmd->type_size);
1951 		break;
1952 	case ANT_SELECT_WK_CID:
1953 		antenna_select_wk_hdl(padapter, pdrvextra_cmd->type_size);
1954 		break;
1955 #ifdef CONFIG_88EU_P2P
1956 	case P2P_PS_WK_CID:
1957 		p2p_ps_wk_hdl(padapter, pdrvextra_cmd->type_size);
1958 		break;
1959 	case P2P_PROTO_WK_CID:
1960 		/* 	Commented by Albert 2011/07/01 */
1961 		/* 	I used the type_size as the type command */
1962 		p2p_protocol_wk_hdl(padapter, pdrvextra_cmd->type_size);
1963 		break;
1964 #endif
1965 #ifdef CONFIG_88EU_AP_MODE
1966 	case CHECK_HIQ_WK_CID:
1967 		rtw_chk_hi_queue_hdl(padapter);
1968 		break;
1969 #endif /* CONFIG_88EU_AP_MODE */
1970 	case C2H_WK_CID:
1971 		c2h_evt_hdl(padapter, (struct c2h_evt_hdr *)pdrvextra_cmd->pbuf, NULL);
1972 		break;
1973 	default:
1974 		break;
1975 	}
1976 
1977 	if (pdrvextra_cmd->pbuf && pdrvextra_cmd->type_size > 0)
1978 		kfree(pdrvextra_cmd->pbuf);
1979 
1980 	return H2C_SUCCESS;
1981 }
1982 
rtw_survey_cmd_callback(struct adapter * padapter,struct cmd_obj * pcmd)1983 void rtw_survey_cmd_callback(struct adapter *padapter,  struct cmd_obj *pcmd)
1984 {
1985 	struct	mlme_priv *pmlmepriv = &padapter->mlmepriv;
1986 
1987 	if (pcmd->res == H2C_DROPPED) {
1988 		/* TODO: cancel timer and do timeout handler directly... */
1989 		/* need to make timeout handlerOS independent */
1990 		_set_timer(&pmlmepriv->scan_to_timer, 1);
1991 		} else if (pcmd->res != H2C_SUCCESS) {
1992 		_set_timer(&pmlmepriv->scan_to_timer, 1);
1993 	}
1994 
1995 	/*  free cmd */
1996 	rtw_free_cmd_obj(pcmd);
1997 
1998 }
rtw_disassoc_cmd_callback(struct adapter * padapter,struct cmd_obj * pcmd)1999 void rtw_disassoc_cmd_callback(struct adapter *padapter, struct cmd_obj *pcmd)
2000 {
2001 	struct	mlme_priv *pmlmepriv = &padapter->mlmepriv;
2002 
2003 	if (pcmd->res != H2C_SUCCESS) {
2004 		spin_lock_bh(&pmlmepriv->lock);
2005 		set_fwstate(pmlmepriv, _FW_LINKED);
2006 		spin_unlock_bh(&pmlmepriv->lock);
2007 
2008 		return;
2009 	} else /* clear bridge database */
2010 		nat25_db_cleanup(padapter);
2011 
2012 	/*  free cmd */
2013 	rtw_free_cmd_obj(pcmd);
2014 }
2015 
rtw_joinbss_cmd_callback(struct adapter * padapter,struct cmd_obj * pcmd)2016 void rtw_joinbss_cmd_callback(struct adapter *padapter,  struct cmd_obj *pcmd)
2017 {
2018 	struct	mlme_priv *pmlmepriv = &padapter->mlmepriv;
2019 
2020 	if (pcmd->res == H2C_DROPPED) {
2021 		/* TODO: cancel timer and do timeout handler directly... */
2022 		/* need to make timeout handlerOS independent */
2023 		_set_timer(&pmlmepriv->assoc_timer, 1);
2024 	} else if (pcmd->res != H2C_SUCCESS) {
2025 		_set_timer(&pmlmepriv->assoc_timer, 1);
2026 	}
2027 
2028 	rtw_free_cmd_obj(pcmd);
2029 }
2030 
rtw_createbss_cmd_callback(struct adapter * padapter,struct cmd_obj * pcmd)2031 void rtw_createbss_cmd_callback(struct adapter *padapter, struct cmd_obj *pcmd)
2032 {
2033 	u8 timer_cancelled;
2034 	struct sta_info *psta = NULL;
2035 	struct wlan_network *pwlan = NULL;
2036 	struct	mlme_priv *pmlmepriv = &padapter->mlmepriv;
2037 	struct wlan_bssid_ex *pnetwork = (struct wlan_bssid_ex *)pcmd->parmbuf;
2038 	struct wlan_network *tgt_network = &pmlmepriv->cur_network;
2039 
2040 	if (pcmd->res != H2C_SUCCESS)
2041 		_set_timer(&pmlmepriv->assoc_timer, 1);
2042 
2043 	_cancel_timer(&pmlmepriv->assoc_timer, &timer_cancelled);
2044 
2045 	spin_lock_bh(&pmlmepriv->lock);
2046 
2047 	if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) {
2048 		psta = rtw_get_stainfo(&padapter->stapriv, pnetwork->MacAddress);
2049 		if (!psta) {
2050 			psta = rtw_alloc_stainfo(&padapter->stapriv, pnetwork->MacAddress);
2051 			if (!psta)
2052 				goto createbss_cmd_fail;
2053 		}
2054 
2055 		rtw_indicate_connect(padapter);
2056 	} else {
2057 
2058 		pwlan = _rtw_alloc_network(pmlmepriv);
2059 		spin_lock_bh(&pmlmepriv->scanned_queue.lock);
2060 		if (!pwlan) {
2061 			pwlan = rtw_get_oldest_wlan_network(&pmlmepriv->scanned_queue);
2062 			if (!pwlan) {
2063 				spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
2064 				goto createbss_cmd_fail;
2065 			}
2066 			pwlan->last_scanned = jiffies;
2067 		} else {
2068 			list_add_tail(&pwlan->list, &pmlmepriv->scanned_queue.queue);
2069 		}
2070 
2071 		pnetwork->Length = get_wlan_bssid_ex_sz(pnetwork);
2072 		memcpy(&pwlan->network, pnetwork, pnetwork->Length);
2073 
2074 		memcpy(&tgt_network->network, pnetwork, (get_wlan_bssid_ex_sz(pnetwork)));
2075 
2076 		_clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING);
2077 
2078 		spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
2079 		/*  we will set _FW_LINKED when there is one more sat to join us (rtw_stassoc_event_callback) */
2080 	}
2081 
2082 createbss_cmd_fail:
2083 
2084 	spin_unlock_bh(&pmlmepriv->lock);
2085 
2086 	rtw_free_cmd_obj(pcmd);
2087 
2088 }
2089 
rtw_setstaKey_cmdrsp_callback(struct adapter * padapter,struct cmd_obj * pcmd)2090 void rtw_setstaKey_cmdrsp_callback(struct adapter *padapter,  struct cmd_obj *pcmd)
2091 {
2092 	struct sta_priv *pstapriv = &padapter->stapriv;
2093 	struct set_stakey_rsp *psetstakey_rsp = (struct set_stakey_rsp *)(pcmd->rsp);
2094 	struct sta_info *psta = rtw_get_stainfo(pstapriv, psetstakey_rsp->addr);
2095 
2096 	if (!psta)
2097 		goto exit;
2098 exit:
2099 	rtw_free_cmd_obj(pcmd);
2100 
2101 }
2102 
rtw_setassocsta_cmdrsp_callback(struct adapter * padapter,struct cmd_obj * pcmd)2103 void rtw_setassocsta_cmdrsp_callback(struct adapter *padapter,  struct cmd_obj *pcmd)
2104 {
2105 	struct sta_priv *pstapriv = &padapter->stapriv;
2106 	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
2107 	struct set_assocsta_parm *passocsta_parm = (struct set_assocsta_parm *)(pcmd->parmbuf);
2108 	struct set_assocsta_rsp *passocsta_rsp = (struct set_assocsta_rsp *)(pcmd->rsp);
2109 	struct sta_info *psta = rtw_get_stainfo(pstapriv, passocsta_parm->addr);
2110 
2111 	if (!psta)
2112 		goto exit;
2113 
2114 	psta->aid = passocsta_rsp->cam_id;
2115 	psta->mac_id = passocsta_rsp->cam_id;
2116 
2117 	spin_lock_bh(&pmlmepriv->lock);
2118 
2119 	if (check_fwstate(pmlmepriv, WIFI_MP_STATE) && check_fwstate(pmlmepriv, _FW_UNDER_LINKING))
2120 		_clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING);
2121 
2122 	set_fwstate(pmlmepriv, _FW_LINKED);
2123 	spin_unlock_bh(&pmlmepriv->lock);
2124 
2125 exit:
2126 	rtw_free_cmd_obj(pcmd);
2127 
2128 }
2129