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