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