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