]> git.karo-electronics.de Git - karo-tx-linux.git/blob - drivers/staging/rtl8188eu/core/rtw_cmd.c
Merge remote-tracking branch 'staging/staging-next'
[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 <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 == NULL) {
398                 res = _FAIL;
399                 RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_, ("rtw_joinbss_cmd: memory allocate for cmd_obj fail!!!\n"));
400                 goto exit;
401         }
402         /* for IEs is fix buf size */
403         t_len = sizeof(struct wlan_bssid_ex);
404
405
406         /* for hidden ap to set fw_state here */
407         if (!check_fwstate(pmlmepriv, WIFI_STATION_STATE|WIFI_ADHOC_STATE)) {
408                 switch (ndis_network_mode) {
409                 case Ndis802_11IBSS:
410                         set_fwstate(pmlmepriv, WIFI_ADHOC_STATE);
411                         break;
412                 case Ndis802_11Infrastructure:
413                         set_fwstate(pmlmepriv, WIFI_STATION_STATE);
414                         break;
415                 case Ndis802_11APMode:
416                 case Ndis802_11AutoUnknown:
417                 case Ndis802_11InfrastructureMax:
418                         break;
419                 }
420         }
421
422         psecnetwork = (struct wlan_bssid_ex *)&psecuritypriv->sec_bss;
423         if (psecnetwork == NULL) {
424                 kfree(pcmd);
425
426                 res = _FAIL;
427
428                 RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_, ("rtw_joinbss_cmd :psecnetwork == NULL!!!\n"));
429
430                 goto exit;
431         }
432
433         memset(psecnetwork, 0, t_len);
434
435         memcpy(psecnetwork, &pnetwork->network, get_wlan_bssid_ex_sz(&pnetwork->network));
436
437         psecuritypriv->authenticator_ie[0] = (unsigned char)psecnetwork->IELength;
438
439         if ((psecnetwork->IELength-12) < (256-1))
440                 memcpy(&psecuritypriv->authenticator_ie[1], &psecnetwork->IEs[12], psecnetwork->IELength-12);
441         else
442                 memcpy(&psecuritypriv->authenticator_ie[1], &psecnetwork->IEs[12], (256-1));
443
444         psecnetwork->IELength = 0;
445         /*  Added by Albert 2009/02/18 */
446         /*  If the driver wants to use the bssid to create the connection. */
447         /*  If not,  we have to copy the connecting AP's MAC address to it so that */
448         /*  the driver just has the bssid information for PMKIDList searching. */
449
450         if (!pmlmepriv->assoc_by_bssid)
451                 memcpy(&pmlmepriv->assoc_bssid[0], &pnetwork->network.MacAddress[0], ETH_ALEN);
452
453         psecnetwork->IELength = rtw_restruct_sec_ie(padapter, &pnetwork->network.IEs[0], &psecnetwork->IEs[0], pnetwork->network.IELength);
454
455
456         pqospriv->qos_option = 0;
457
458         if (pregistrypriv->wmm_enable) {
459                 u32 tmp_len;
460
461                 tmp_len = rtw_restruct_wmm_ie(padapter, &pnetwork->network.IEs[0], &psecnetwork->IEs[0], pnetwork->network.IELength, psecnetwork->IELength);
462
463                 if (psecnetwork->IELength != tmp_len) {
464                         psecnetwork->IELength = tmp_len;
465                         pqospriv->qos_option = 1; /* There is WMM IE in this corresp. beacon */
466                 } else {
467                         pqospriv->qos_option = 0;/* There is no WMM IE in this corresp. beacon */
468                 }
469         }
470
471         phtpriv->ht_option = false;
472         if (pregistrypriv->ht_enable) {
473                 /*
474                  * Added by Albert 2010/06/23
475                  * For the WEP mode, we will use the bg mode to do
476                  * the connection to avoid some IOT issue.
477                  * Especially for Realtek 8192u SoftAP.
478                  */
479                 if ((padapter->securitypriv.dot11PrivacyAlgrthm != _WEP40_) &&
480                     (padapter->securitypriv.dot11PrivacyAlgrthm != _WEP104_) &&
481                     (padapter->securitypriv.dot11PrivacyAlgrthm != _TKIP_)) {
482                         /* rtw_restructure_ht_ie */
483                         rtw_restructure_ht_ie(padapter, &pnetwork->network.IEs[0], &psecnetwork->IEs[0],
484                                                                         pnetwork->network.IELength, &psecnetwork->IELength);
485                 }
486         }
487
488         pmlmeinfo->assoc_AP_vendor = check_assoc_AP(pnetwork->network.IEs, pnetwork->network.IELength);
489
490         if (pmlmeinfo->assoc_AP_vendor == HT_IOT_PEER_TENDA)
491                 padapter->pwrctrlpriv.smart_ps = 0;
492         else
493                 padapter->pwrctrlpriv.smart_ps = padapter->registrypriv.smart_ps;
494
495         DBG_88E("%s: smart_ps =%d\n", __func__, padapter->pwrctrlpriv.smart_ps);
496
497         pcmd->cmdsz = get_wlan_bssid_ex_sz(psecnetwork);/* get cmdsz before endian conversion */
498
499         INIT_LIST_HEAD(&pcmd->list);
500         pcmd->cmdcode = _JoinBss_CMD_;/* GEN_CMD_CODE(_JoinBss) */
501         pcmd->parmbuf = (unsigned char *)psecnetwork;
502         pcmd->rsp = NULL;
503         pcmd->rspsz = 0;
504
505         res = rtw_enqueue_cmd(pcmdpriv, pcmd);
506
507 exit:
508
509
510         return res;
511 }
512
513 u8 rtw_disassoc_cmd(struct adapter *padapter, u32 deauth_timeout_ms, bool enqueue) /* for sta_mode */
514 {
515         struct cmd_obj *cmdobj = NULL;
516         struct disconnect_parm *param = NULL;
517         struct cmd_priv *cmdpriv = &padapter->cmdpriv;
518         u8 res = _SUCCESS;
519
520
521         RT_TRACE(_module_rtl871x_cmd_c_, _drv_notice_, ("+rtw_disassoc_cmd\n"));
522
523         /* prepare cmd parameter */
524         param = kzalloc(sizeof(*param), GFP_KERNEL);
525         if (param == NULL) {
526                 res = _FAIL;
527                 goto exit;
528         }
529         param->deauth_timeout_ms = deauth_timeout_ms;
530
531         if (enqueue) {
532                 /* need enqueue, prepare cmd_obj and enqueue */
533                 cmdobj = kzalloc(sizeof(*cmdobj), GFP_KERNEL);
534                 if (cmdobj == NULL) {
535                         res = _FAIL;
536                         kfree(param);
537                         goto exit;
538                 }
539                 init_h2fwcmd_w_parm_no_rsp(cmdobj, param, _DisConnect_CMD_);
540                 res = rtw_enqueue_cmd(cmdpriv, cmdobj);
541         } else {
542                 /* no need to enqueue, do the cmd hdl directly and free cmd parameter */
543                 if (disconnect_hdl(padapter, (u8 *)param) != H2C_SUCCESS)
544                         res = _FAIL;
545                 kfree(param);
546         }
547
548 exit:
549
550
551         return res;
552 }
553
554 u8 rtw_setopmode_cmd(struct adapter  *padapter, enum ndis_802_11_network_infra networktype)
555 {
556         struct  cmd_obj *ph2c;
557         struct  setopmode_parm *psetop;
558
559         struct  cmd_priv   *pcmdpriv = &padapter->cmdpriv;
560
561         ph2c = kzalloc(sizeof(struct cmd_obj), GFP_KERNEL);
562         psetop = kzalloc(sizeof(struct setopmode_parm), GFP_KERNEL);
563         if (!ph2c || !psetop) {
564                 kfree(ph2c);
565                 kfree(psetop);
566                 return false;
567         }
568
569         init_h2fwcmd_w_parm_no_rsp(ph2c, psetop, _SetOpMode_CMD_);
570         psetop->mode = (u8)networktype;
571
572         return rtw_enqueue_cmd(pcmdpriv, ph2c);
573 }
574
575 u8 rtw_setstakey_cmd(struct adapter *padapter, u8 *psta, u8 unicast_key)
576 {
577         struct cmd_obj *ph2c;
578         struct set_stakey_parm *psetstakey_para;
579         struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
580         struct set_stakey_rsp *psetstakey_rsp = NULL;
581
582         struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
583         struct security_priv *psecuritypriv = &padapter->securitypriv;
584         struct sta_info *sta = (struct sta_info *)psta;
585
586         ph2c = kzalloc(sizeof(struct cmd_obj), GFP_KERNEL);
587         psetstakey_para = kzalloc(sizeof(struct set_stakey_parm), GFP_KERNEL);
588         psetstakey_rsp = kzalloc(sizeof(struct set_stakey_rsp), GFP_KERNEL);
589
590         if (!ph2c || !psetstakey_para || !psetstakey_rsp) {
591                 kfree(ph2c);
592                 kfree(psetstakey_para);
593                 kfree(psetstakey_rsp);
594                 return _FAIL;
595         }
596
597         init_h2fwcmd_w_parm_no_rsp(ph2c, psetstakey_para, _SetStaKey_CMD_);
598         ph2c->rsp = (u8 *)psetstakey_rsp;
599         ph2c->rspsz = sizeof(struct set_stakey_rsp);
600
601         ether_addr_copy(psetstakey_para->addr, sta->hwaddr);
602
603         if (check_fwstate(pmlmepriv, WIFI_STATION_STATE))
604                 psetstakey_para->algorithm = (unsigned char)psecuritypriv->dot11PrivacyAlgrthm;
605         else
606                 GET_ENCRY_ALGO(psecuritypriv, sta, psetstakey_para->algorithm, false);
607
608         if (unicast_key)
609                 memcpy(&psetstakey_para->key, &sta->dot118021x_UncstKey, 16);
610         else
611                 memcpy(&psetstakey_para->key, &psecuritypriv->dot118021XGrpKey[psecuritypriv->dot118021XGrpKeyid].skey, 16);
612
613         /* jeff: set this because at least sw key is ready */
614         padapter->securitypriv.busetkipkey = true;
615
616         return rtw_enqueue_cmd(pcmdpriv, ph2c);
617 }
618
619 u8 rtw_clearstakey_cmd(struct adapter *padapter, u8 *psta, u8 entry, u8 enqueue)
620 {
621         struct cmd_obj *ph2c;
622         struct set_stakey_parm  *psetstakey_para;
623         struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
624         struct set_stakey_rsp *psetstakey_rsp = NULL;
625         struct sta_info *sta = (struct sta_info *)psta;
626         u8      res = _SUCCESS;
627
628
629         if (!enqueue) {
630                 clear_cam_entry(padapter, entry);
631         } else {
632                 ph2c = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC);
633                 if (ph2c == NULL) {
634                         res = _FAIL;
635                         goto exit;
636                 }
637
638                 psetstakey_para = kzalloc(sizeof(struct set_stakey_parm), GFP_ATOMIC);
639                 if (psetstakey_para == NULL) {
640                         kfree(ph2c);
641                         res = _FAIL;
642                         goto exit;
643                 }
644
645                 psetstakey_rsp = kzalloc(sizeof(struct set_stakey_rsp), GFP_ATOMIC);
646                 if (psetstakey_rsp == NULL) {
647                         kfree(ph2c);
648                         kfree(psetstakey_para);
649                         res = _FAIL;
650                         goto exit;
651                 }
652
653                 init_h2fwcmd_w_parm_no_rsp(ph2c, psetstakey_para, _SetStaKey_CMD_);
654                 ph2c->rsp = (u8 *)psetstakey_rsp;
655                 ph2c->rspsz = sizeof(struct set_stakey_rsp);
656
657                 ether_addr_copy(psetstakey_para->addr, sta->hwaddr);
658
659                 psetstakey_para->algorithm = _NO_PRIVACY_;
660
661                 psetstakey_para->id = entry;
662
663                 res = rtw_enqueue_cmd(pcmdpriv, ph2c);
664         }
665 exit:
666
667
668         return res;
669 }
670
671 u8 rtw_addbareq_cmd(struct adapter *padapter, u8 tid, u8 *addr)
672 {
673         struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
674         struct cmd_obj *ph2c;
675         struct addBaReq_parm *paddbareq_parm;
676         u8      res = _SUCCESS;
677
678
679         ph2c = kzalloc(sizeof(struct cmd_obj), GFP_KERNEL);
680         if (ph2c == NULL) {
681                 res = _FAIL;
682                 goto exit;
683         }
684
685         paddbareq_parm = kzalloc(sizeof(struct addBaReq_parm), GFP_KERNEL);
686         if (paddbareq_parm == NULL) {
687                 kfree(ph2c);
688                 res = _FAIL;
689                 goto exit;
690         }
691
692         paddbareq_parm->tid = tid;
693         memcpy(paddbareq_parm->addr, addr, ETH_ALEN);
694
695         init_h2fwcmd_w_parm_no_rsp(ph2c, paddbareq_parm, GEN_CMD_CODE(_AddBAReq));
696
697         /* DBG_88E("rtw_addbareq_cmd, tid =%d\n", tid); */
698
699         /* rtw_enqueue_cmd(pcmdpriv, ph2c); */
700         res = rtw_enqueue_cmd(pcmdpriv, ph2c);
701
702 exit:
703
704
705         return res;
706 }
707
708 u8 rtw_dynamic_chk_wk_cmd(struct adapter *padapter)
709 {
710         struct cmd_obj *ph2c;
711         struct drvextra_cmd_parm *pdrvextra_cmd_parm;
712         struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
713         u8      res = _SUCCESS;
714
715
716         ph2c = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC);
717         if (ph2c == NULL) {
718                 res = _FAIL;
719                 goto exit;
720         }
721
722         pdrvextra_cmd_parm = kzalloc(sizeof(struct drvextra_cmd_parm), GFP_ATOMIC);
723         if (pdrvextra_cmd_parm == NULL) {
724                 kfree(ph2c);
725                 res = _FAIL;
726                 goto exit;
727         }
728
729         pdrvextra_cmd_parm->ec_id = DYNAMIC_CHK_WK_CID;
730         pdrvextra_cmd_parm->type_size = 0;
731         pdrvextra_cmd_parm->pbuf = (u8 *)padapter;
732
733         init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, GEN_CMD_CODE(_Set_Drv_Extra));
734
735
736         /* rtw_enqueue_cmd(pcmdpriv, ph2c); */
737         res = rtw_enqueue_cmd(pcmdpriv, ph2c);
738 exit:
739         return res;
740 }
741
742 u8 rtw_set_chplan_cmd(struct adapter *padapter, u8 chplan, u8 enqueue)
743 {
744         struct  cmd_obj *pcmdobj;
745         struct  SetChannelPlan_param *setChannelPlan_param;
746         struct  cmd_priv   *pcmdpriv = &padapter->cmdpriv;
747
748         u8      res = _SUCCESS;
749
750
751         RT_TRACE(_module_rtl871x_cmd_c_, _drv_notice_, ("+rtw_set_chplan_cmd\n"));
752
753         /* check input parameter */
754         if (!rtw_is_channel_plan_valid(chplan)) {
755                 res = _FAIL;
756                 goto exit;
757         }
758
759         /* prepare cmd parameter */
760         setChannelPlan_param = kzalloc(sizeof(struct SetChannelPlan_param), GFP_KERNEL);
761         if (setChannelPlan_param == NULL) {
762                 res = _FAIL;
763                 goto exit;
764         }
765         setChannelPlan_param->channel_plan = chplan;
766
767         if (enqueue) {
768                 /* need enqueue, prepare cmd_obj and enqueue */
769                 pcmdobj = kzalloc(sizeof(struct cmd_obj), GFP_KERNEL);
770                 if (pcmdobj == NULL) {
771                         kfree(setChannelPlan_param);
772                         res = _FAIL;
773                         goto exit;
774                 }
775
776                 init_h2fwcmd_w_parm_no_rsp(pcmdobj, setChannelPlan_param, GEN_CMD_CODE(_SetChannelPlan));
777                 res = rtw_enqueue_cmd(pcmdpriv, pcmdobj);
778         } else {
779                 /* no need to enqueue, do the cmd hdl directly and free cmd parameter */
780                 if (set_chplan_hdl(padapter, (unsigned char *)setChannelPlan_param) != H2C_SUCCESS)
781                         res = _FAIL;
782
783                 kfree(setChannelPlan_param);
784         }
785
786         /* do something based on res... */
787         if (res == _SUCCESS)
788                 padapter->mlmepriv.ChannelPlan = chplan;
789
790 exit:
791
792
793         return res;
794 }
795
796 static void traffic_status_watchdog(struct adapter *padapter)
797 {
798         u8      bEnterPS;
799         u8      bBusyTraffic = false, bTxBusyTraffic = false, bRxBusyTraffic = false;
800         u8      bHigherBusyTraffic = false, bHigherBusyRxTraffic = false, bHigherBusyTxTraffic = false;
801         struct mlme_priv                *pmlmepriv = &(padapter->mlmepriv);
802
803         /*  */
804         /*  Determine if our traffic is busy now */
805         /*  */
806         if (check_fwstate(pmlmepriv, _FW_LINKED)) {
807                 if (pmlmepriv->LinkDetectInfo.NumRxOkInPeriod > 100 ||
808                     pmlmepriv->LinkDetectInfo.NumTxOkInPeriod > 100) {
809                         bBusyTraffic = true;
810
811                         if (pmlmepriv->LinkDetectInfo.NumRxOkInPeriod > pmlmepriv->LinkDetectInfo.NumTxOkInPeriod)
812                                 bRxBusyTraffic = true;
813                         else
814                                 bTxBusyTraffic = true;
815                 }
816
817                 /*  Higher Tx/Rx data. */
818                 if (pmlmepriv->LinkDetectInfo.NumRxOkInPeriod > 4000 ||
819                     pmlmepriv->LinkDetectInfo.NumTxOkInPeriod > 4000) {
820                         bHigherBusyTraffic = true;
821
822                         if (pmlmepriv->LinkDetectInfo.NumRxOkInPeriod > pmlmepriv->LinkDetectInfo.NumTxOkInPeriod)
823                                 bHigherBusyRxTraffic = true;
824                         else
825                                 bHigherBusyTxTraffic = true;
826                 }
827
828                 /*  check traffic for  powersaving. */
829                 if (((pmlmepriv->LinkDetectInfo.NumRxUnicastOkInPeriod + pmlmepriv->LinkDetectInfo.NumTxOkInPeriod) > 8) ||
830                     (pmlmepriv->LinkDetectInfo.NumRxUnicastOkInPeriod > 2))
831                         bEnterPS = false;
832                 else
833                         bEnterPS = true;
834
835                 /*  LeisurePS only work in infra mode. */
836                 if (bEnterPS)
837                         LPS_Enter(padapter);
838                 else
839                         LPS_Leave(padapter);
840         } else {
841                 LPS_Leave(padapter);
842         }
843
844         pmlmepriv->LinkDetectInfo.NumRxOkInPeriod = 0;
845         pmlmepriv->LinkDetectInfo.NumTxOkInPeriod = 0;
846         pmlmepriv->LinkDetectInfo.NumRxUnicastOkInPeriod = 0;
847         pmlmepriv->LinkDetectInfo.bBusyTraffic = bBusyTraffic;
848         pmlmepriv->LinkDetectInfo.bTxBusyTraffic = bTxBusyTraffic;
849         pmlmepriv->LinkDetectInfo.bRxBusyTraffic = bRxBusyTraffic;
850         pmlmepriv->LinkDetectInfo.bHigherBusyTraffic = bHigherBusyTraffic;
851         pmlmepriv->LinkDetectInfo.bHigherBusyRxTraffic = bHigherBusyRxTraffic;
852         pmlmepriv->LinkDetectInfo.bHigherBusyTxTraffic = bHigherBusyTxTraffic;
853 }
854
855 static void dynamic_chk_wk_hdl(struct adapter *padapter, u8 *pbuf, int sz)
856 {
857         struct mlme_priv *pmlmepriv;
858
859         padapter = (struct adapter *)pbuf;
860         pmlmepriv = &(padapter->mlmepriv);
861
862 #ifdef CONFIG_88EU_AP_MODE
863         if (check_fwstate(pmlmepriv, WIFI_AP_STATE) == true)
864                 expire_timeout_chk(padapter);
865 #endif
866
867         linked_status_chk(padapter);
868         traffic_status_watchdog(padapter);
869
870         rtw_hal_dm_watchdog(padapter);
871 }
872
873 static void lps_ctrl_wk_hdl(struct adapter *padapter, u8 lps_ctrl_type)
874 {
875         struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv;
876         struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
877         u8      mstatus;
878
879
880         if ((check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) == true) ||
881             (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE) == true))
882                 return;
883
884         switch (lps_ctrl_type) {
885         case LPS_CTRL_SCAN:
886                 if (check_fwstate(pmlmepriv, _FW_LINKED) == true) {
887                         /* connect */
888                         LPS_Leave(padapter);
889                 }
890                 break;
891         case LPS_CTRL_JOINBSS:
892                 LPS_Leave(padapter);
893                 break;
894         case LPS_CTRL_CONNECT:
895                 mstatus = 1;/* connect */
896                 /*  Reset LPS Setting */
897                 padapter->pwrctrlpriv.LpsIdleCount = 0;
898                 rtw_hal_set_hwreg(padapter, HW_VAR_H2C_FW_JOINBSSRPT, (u8 *)(&mstatus));
899                 break;
900         case LPS_CTRL_DISCONNECT:
901                 mstatus = 0;/* disconnect */
902                 LPS_Leave(padapter);
903                 rtw_hal_set_hwreg(padapter, HW_VAR_H2C_FW_JOINBSSRPT, (u8 *)(&mstatus));
904                 break;
905         case LPS_CTRL_SPECIAL_PACKET:
906                 /* DBG_88E("LPS_CTRL_SPECIAL_PACKET\n"); */
907                 pwrpriv->DelayLPSLastTimeStamp = jiffies;
908                 LPS_Leave(padapter);
909                 break;
910         case LPS_CTRL_LEAVE:
911                 LPS_Leave(padapter);
912                 break;
913         default:
914                 break;
915         }
916
917 }
918
919 u8 rtw_lps_ctrl_wk_cmd(struct adapter *padapter, u8 lps_ctrl_type, u8 enqueue)
920 {
921         struct cmd_obj  *ph2c;
922         struct drvextra_cmd_parm        *pdrvextra_cmd_parm;
923         struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
924         /* struct pwrctrl_priv *pwrctrlpriv = &padapter->pwrctrlpriv; */
925         u8      res = _SUCCESS;
926
927         if (enqueue) {
928                 ph2c = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC);
929                 if (ph2c == NULL) {
930                         res = _FAIL;
931                         goto exit;
932                 }
933
934                 pdrvextra_cmd_parm = kzalloc(sizeof(struct drvextra_cmd_parm), GFP_ATOMIC);
935                 if (pdrvextra_cmd_parm == NULL) {
936                         kfree(ph2c);
937                         res = _FAIL;
938                         goto exit;
939                 }
940
941                 pdrvextra_cmd_parm->ec_id = LPS_CTRL_WK_CID;
942                 pdrvextra_cmd_parm->type_size = lps_ctrl_type;
943                 pdrvextra_cmd_parm->pbuf = NULL;
944
945                 init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, GEN_CMD_CODE(_Set_Drv_Extra));
946
947                 res = rtw_enqueue_cmd(pcmdpriv, ph2c);
948         } else {
949                 lps_ctrl_wk_hdl(padapter, lps_ctrl_type);
950         }
951
952 exit:
953
954
955         return res;
956 }
957
958 static void rpt_timer_setting_wk_hdl(struct adapter *padapter, u16 min_time)
959 {
960         rtw_hal_set_hwreg(padapter, HW_VAR_RPT_TIMER_SETTING, (u8 *)(&min_time));
961 }
962
963 u8 rtw_rpt_timer_cfg_cmd(struct adapter *padapter, u16 min_time)
964 {
965         struct cmd_obj          *ph2c;
966         struct drvextra_cmd_parm        *pdrvextra_cmd_parm;
967         struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
968
969         u8      res = _SUCCESS;
970
971         ph2c = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC);
972         if (ph2c == NULL) {
973                 res = _FAIL;
974                 goto exit;
975         }
976
977         pdrvextra_cmd_parm = kzalloc(sizeof(struct drvextra_cmd_parm), GFP_ATOMIC);
978         if (pdrvextra_cmd_parm == NULL) {
979                 kfree(ph2c);
980                 res = _FAIL;
981                 goto exit;
982         }
983
984         pdrvextra_cmd_parm->ec_id = RTP_TIMER_CFG_WK_CID;
985         pdrvextra_cmd_parm->type_size = min_time;
986         pdrvextra_cmd_parm->pbuf = NULL;
987         init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, GEN_CMD_CODE(_Set_Drv_Extra));
988         res = rtw_enqueue_cmd(pcmdpriv, ph2c);
989 exit:
990
991
992         return res;
993 }
994
995 static void antenna_select_wk_hdl(struct adapter *padapter, u8 antenna)
996 {
997         rtw_hal_set_hwreg(padapter, HW_VAR_ANTENNA_DIVERSITY_SELECT, (u8 *)(&antenna));
998 }
999
1000 u8 rtw_antenna_select_cmd(struct adapter *padapter, u8 antenna, u8 enqueue)
1001 {
1002         struct cmd_obj          *ph2c;
1003         struct drvextra_cmd_parm        *pdrvextra_cmd_parm;
1004         struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
1005         u8      support_ant_div;
1006         u8      res = _SUCCESS;
1007
1008         rtw_hal_get_def_var(padapter, HAL_DEF_IS_SUPPORT_ANT_DIV, &support_ant_div);
1009         if (!support_ant_div)
1010                 return res;
1011
1012         if (enqueue) {
1013                 ph2c = kzalloc(sizeof(struct cmd_obj), GFP_KERNEL);
1014                 if (ph2c == NULL) {
1015                         res = _FAIL;
1016                         goto exit;
1017                 }
1018
1019                 pdrvextra_cmd_parm = kzalloc(sizeof(struct drvextra_cmd_parm), GFP_KERNEL);
1020                 if (pdrvextra_cmd_parm == NULL) {
1021                         kfree(ph2c);
1022                         res = _FAIL;
1023                         goto exit;
1024                 }
1025
1026                 pdrvextra_cmd_parm->ec_id = ANT_SELECT_WK_CID;
1027                 pdrvextra_cmd_parm->type_size = antenna;
1028                 pdrvextra_cmd_parm->pbuf = NULL;
1029                 init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, GEN_CMD_CODE(_Set_Drv_Extra));
1030
1031                 res = rtw_enqueue_cmd(pcmdpriv, ph2c);
1032         } else {
1033                 antenna_select_wk_hdl(padapter, antenna);
1034         }
1035 exit:
1036
1037
1038         return res;
1039 }
1040
1041 u8 rtw_ps_cmd(struct adapter *padapter)
1042 {
1043         struct cmd_obj          *ppscmd;
1044         struct drvextra_cmd_parm        *pdrvextra_cmd_parm;
1045         struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
1046
1047         ppscmd = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC);
1048         pdrvextra_cmd_parm = kzalloc(sizeof(struct drvextra_cmd_parm), GFP_ATOMIC);
1049         if (!ppscmd || !pdrvextra_cmd_parm) {
1050                 kfree(ppscmd);
1051                 kfree(pdrvextra_cmd_parm);
1052                 return _FAIL;
1053         }
1054
1055         pdrvextra_cmd_parm->ec_id = POWER_SAVING_CTRL_WK_CID;
1056         pdrvextra_cmd_parm->pbuf = NULL;
1057         init_h2fwcmd_w_parm_no_rsp(ppscmd, pdrvextra_cmd_parm, GEN_CMD_CODE(_Set_Drv_Extra));
1058
1059         return rtw_enqueue_cmd(pcmdpriv, ppscmd);
1060 }
1061
1062 #ifdef CONFIG_88EU_AP_MODE
1063
1064 static void rtw_chk_hi_queue_hdl(struct adapter *padapter)
1065 {
1066         int cnt = 0;
1067         struct sta_info *psta_bmc;
1068         struct sta_priv *pstapriv = &padapter->stapriv;
1069
1070         psta_bmc = rtw_get_bcmc_stainfo(padapter);
1071         if (!psta_bmc)
1072                 return;
1073
1074         if (psta_bmc->sleepq_len == 0) {
1075                 u8 val = 0;
1076
1077                 /* while ((rtw_read32(padapter, 0x414)&0x00ffff00)!= 0) */
1078                 /* while ((rtw_read32(padapter, 0x414)&0x0000ff00)!= 0) */
1079
1080                 rtw_hal_get_hwreg(padapter, HW_VAR_CHK_HI_QUEUE_EMPTY, &val);
1081
1082                 while (!val) {
1083                         msleep(100);
1084
1085                         cnt++;
1086
1087                         if (cnt > 10)
1088                                 break;
1089
1090                         rtw_hal_get_hwreg(padapter, HW_VAR_CHK_HI_QUEUE_EMPTY, &val);
1091                 }
1092
1093                 if (cnt <= 10) {
1094                         pstapriv->tim_bitmap &= ~BIT(0);
1095                         pstapriv->sta_dz_bitmap &= ~BIT(0);
1096
1097                         update_beacon(padapter, _TIM_IE_, NULL, false);
1098                 } else { /* re check again */
1099                         rtw_chk_hi_queue_cmd(padapter);
1100                 }
1101         }
1102 }
1103
1104 u8 rtw_chk_hi_queue_cmd(struct adapter *padapter)
1105 {
1106         struct cmd_obj  *ph2c;
1107         struct drvextra_cmd_parm        *pdrvextra_cmd_parm;
1108         struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
1109         u8      res = _SUCCESS;
1110
1111         ph2c = kzalloc(sizeof(struct cmd_obj), GFP_KERNEL);
1112         if (ph2c == NULL) {
1113                 res = _FAIL;
1114                 goto exit;
1115         }
1116
1117         pdrvextra_cmd_parm = kzalloc(sizeof(struct drvextra_cmd_parm), GFP_KERNEL);
1118         if (pdrvextra_cmd_parm == NULL) {
1119                 kfree(ph2c);
1120                 res = _FAIL;
1121                 goto exit;
1122         }
1123
1124         pdrvextra_cmd_parm->ec_id = CHECK_HIQ_WK_CID;
1125         pdrvextra_cmd_parm->type_size = 0;
1126         pdrvextra_cmd_parm->pbuf = NULL;
1127
1128         init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, GEN_CMD_CODE(_Set_Drv_Extra));
1129
1130         res = rtw_enqueue_cmd(pcmdpriv, ph2c);
1131 exit:
1132         return res;
1133 }
1134 #endif
1135
1136 u8 rtw_drvextra_cmd_hdl(struct adapter *padapter, unsigned char *pbuf)
1137 {
1138         struct drvextra_cmd_parm *pdrvextra_cmd;
1139
1140         if (!pbuf)
1141                 return H2C_PARAMETERS_ERROR;
1142
1143         pdrvextra_cmd = (struct drvextra_cmd_parm *)pbuf;
1144
1145         switch (pdrvextra_cmd->ec_id) {
1146         case DYNAMIC_CHK_WK_CID:
1147                 dynamic_chk_wk_hdl(padapter, pdrvextra_cmd->pbuf, pdrvextra_cmd->type_size);
1148                 break;
1149         case POWER_SAVING_CTRL_WK_CID:
1150                 rtw_ps_processor(padapter);
1151                 break;
1152         case LPS_CTRL_WK_CID:
1153                 lps_ctrl_wk_hdl(padapter, (u8)pdrvextra_cmd->type_size);
1154                 break;
1155         case RTP_TIMER_CFG_WK_CID:
1156                 rpt_timer_setting_wk_hdl(padapter, pdrvextra_cmd->type_size);
1157                 break;
1158         case ANT_SELECT_WK_CID:
1159                 antenna_select_wk_hdl(padapter, pdrvextra_cmd->type_size);
1160                 break;
1161 #ifdef CONFIG_88EU_AP_MODE
1162         case CHECK_HIQ_WK_CID:
1163                 rtw_chk_hi_queue_hdl(padapter);
1164                 break;
1165 #endif /* CONFIG_88EU_AP_MODE */
1166         default:
1167                 break;
1168         }
1169
1170         if (pdrvextra_cmd->pbuf && pdrvextra_cmd->type_size > 0)
1171                 kfree(pdrvextra_cmd->pbuf);
1172
1173         return H2C_SUCCESS;
1174 }
1175
1176 void rtw_survey_cmd_callback(struct adapter *padapter,  struct cmd_obj *pcmd)
1177 {
1178         struct  mlme_priv *pmlmepriv = &padapter->mlmepriv;
1179
1180
1181         if (pcmd->res == H2C_DROPPED) {
1182                 /* TODO: cancel timer and do timeout handler directly... */
1183                 /* need to make timeout handlerOS independent */
1184                 mod_timer(&pmlmepriv->scan_to_timer,
1185                           jiffies + msecs_to_jiffies(1));
1186         } else if (pcmd->res != H2C_SUCCESS) {
1187                 mod_timer(&pmlmepriv->scan_to_timer,
1188                           jiffies + msecs_to_jiffies(1));
1189                 RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_, ("\n ********Error: MgntActrtw_set_802_11_bssid_LIST_SCAN Fail ************\n\n."));
1190         }
1191
1192         /*  free cmd */
1193         rtw_free_cmd_obj(pcmd);
1194
1195 }
1196 void rtw_disassoc_cmd_callback(struct adapter *padapter, struct cmd_obj *pcmd)
1197 {
1198         struct  mlme_priv *pmlmepriv = &padapter->mlmepriv;
1199
1200
1201         if (pcmd->res != H2C_SUCCESS) {
1202                 spin_lock_bh(&pmlmepriv->lock);
1203                 set_fwstate(pmlmepriv, _FW_LINKED);
1204                 spin_unlock_bh(&pmlmepriv->lock);
1205
1206                 RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_, ("\n ***Error: disconnect_cmd_callback Fail ***\n."));
1207                 return;
1208         }
1209
1210         /*  free cmd */
1211         rtw_free_cmd_obj(pcmd);
1212 }
1213
1214 void rtw_joinbss_cmd_callback(struct adapter *padapter,  struct cmd_obj *pcmd)
1215 {
1216         struct  mlme_priv *pmlmepriv = &padapter->mlmepriv;
1217
1218
1219         if (pcmd->res == H2C_DROPPED) {
1220                 /* TODO: cancel timer and do timeout handler directly... */
1221                 /* need to make timeout handlerOS independent */
1222                 mod_timer(&pmlmepriv->assoc_timer,
1223                           jiffies + msecs_to_jiffies(1));
1224         } else if (pcmd->res != H2C_SUCCESS) {
1225                 RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_, ("********Error:rtw_select_and_join_from_scanned_queue Wait Sema  Fail ************\n"));
1226                 mod_timer(&pmlmepriv->assoc_timer,
1227                           jiffies + msecs_to_jiffies(1));
1228         }
1229
1230         rtw_free_cmd_obj(pcmd);
1231
1232 }
1233
1234 void rtw_createbss_cmd_callback(struct adapter *padapter, struct cmd_obj *pcmd)
1235 {
1236         struct sta_info *psta = NULL;
1237         struct wlan_network *pwlan = NULL;
1238         struct  mlme_priv *pmlmepriv = &padapter->mlmepriv;
1239         struct wlan_bssid_ex *pnetwork = (struct wlan_bssid_ex *)pcmd->parmbuf;
1240         struct wlan_network *tgt_network = &(pmlmepriv->cur_network);
1241
1242
1243         if (pcmd->res != H2C_SUCCESS) {
1244                 RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_, ("\n ********Error: rtw_createbss_cmd_callback  Fail ************\n\n."));
1245                 mod_timer(&pmlmepriv->assoc_timer,
1246                           jiffies + msecs_to_jiffies(1));
1247         }
1248
1249         del_timer_sync(&pmlmepriv->assoc_timer);
1250
1251         spin_lock_bh(&pmlmepriv->lock);
1252
1253         if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) {
1254                 psta = rtw_get_stainfo(&padapter->stapriv, pnetwork->MacAddress);
1255                 if (!psta) {
1256                         psta = rtw_alloc_stainfo(&padapter->stapriv, pnetwork->MacAddress);
1257                         if (psta == NULL) {
1258                                 RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_, ("\nCan't alloc sta_info when createbss_cmd_callback\n"));
1259                                 goto createbss_cmd_fail;
1260                         }
1261                 }
1262
1263                 rtw_indicate_connect(padapter);
1264         } else {
1265                 pwlan = _rtw_alloc_network(pmlmepriv);
1266                 spin_lock_bh(&(pmlmepriv->scanned_queue.lock));
1267                 if (pwlan == NULL) {
1268                         pwlan = rtw_get_oldest_wlan_network(&pmlmepriv->scanned_queue);
1269                         if (pwlan == NULL) {
1270                                 RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_, ("\n Error:  can't get pwlan in rtw_joinbss_event_callback\n"));
1271                                 spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
1272                                 goto createbss_cmd_fail;
1273                         }
1274                         pwlan->last_scanned = jiffies;
1275                 } else {
1276                         list_add_tail(&(pwlan->list), &pmlmepriv->scanned_queue.queue);
1277                 }
1278
1279                 pnetwork->Length = get_wlan_bssid_ex_sz(pnetwork);
1280                 memcpy(&(pwlan->network), pnetwork, pnetwork->Length);
1281
1282                 memcpy(&tgt_network->network, pnetwork, (get_wlan_bssid_ex_sz(pnetwork)));
1283
1284                 _clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING);
1285
1286                 spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
1287                 /*  we will set _FW_LINKED when there is one more sat to join us (rtw_stassoc_event_callback) */
1288         }
1289
1290 createbss_cmd_fail:
1291
1292         spin_unlock_bh(&pmlmepriv->lock);
1293
1294         rtw_free_cmd_obj(pcmd);
1295
1296 }
1297
1298 void rtw_setstaKey_cmdrsp_callback(struct adapter *padapter,  struct cmd_obj *pcmd)
1299 {
1300         struct sta_priv *pstapriv = &padapter->stapriv;
1301         struct set_stakey_rsp *psetstakey_rsp = (struct set_stakey_rsp *)(pcmd->rsp);
1302         struct sta_info *psta = rtw_get_stainfo(pstapriv, psetstakey_rsp->addr);
1303
1304
1305         if (psta == NULL) {
1306                 RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_, ("\nERROR: rtw_setstaKey_cmdrsp_callback => can't get sta_info\n\n"));
1307                 goto exit;
1308         }
1309 exit:
1310         rtw_free_cmd_obj(pcmd);
1311 }
1312
1313 void rtw_setassocsta_cmdrsp_callback(struct adapter *padapter,  struct cmd_obj *pcmd)
1314 {
1315         struct sta_priv *pstapriv = &padapter->stapriv;
1316         struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1317         struct set_assocsta_parm *passocsta_parm = (struct set_assocsta_parm *)(pcmd->parmbuf);
1318         struct set_assocsta_rsp *passocsta_rsp = (struct set_assocsta_rsp *)(pcmd->rsp);
1319         struct sta_info *psta = rtw_get_stainfo(pstapriv, passocsta_parm->addr);
1320
1321
1322         if (psta == NULL) {
1323                 RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_, ("\nERROR: setassocsta_cmdrsp_callbac => can't get sta_info\n\n"));
1324                 goto exit;
1325         }
1326
1327         psta->aid = passocsta_rsp->cam_id;
1328         psta->mac_id = passocsta_rsp->cam_id;
1329
1330         spin_lock_bh(&pmlmepriv->lock);
1331
1332         if ((check_fwstate(pmlmepriv, WIFI_MP_STATE) == true) && (check_fwstate(pmlmepriv, _FW_UNDER_LINKING) == true))
1333                 _clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING);
1334
1335         set_fwstate(pmlmepriv, _FW_LINKED);
1336         spin_unlock_bh(&pmlmepriv->lock);
1337
1338 exit:
1339         rtw_free_cmd_obj(pcmd);
1340
1341 }