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