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