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