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