mmc: mxs-mmc: Fix additional cycles after transmission stop
[pandora-kernel.git] / drivers / staging / rtl8712 / rtl871x_cmd.c
1 /******************************************************************************
2  * rtl871x_cmd.c
3  *
4  * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
5  * Linux device driver for RTL8192SU
6  *
7  * This program is free software; you can redistribute it and/or modify it
8  * under the terms of version 2 of the GNU General Public License as
9  * published by the Free Software Foundation.
10  *
11  * This program is distributed in the hope that it will be useful, but WITHOUT
12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
14  * more details.
15  *
16  * You should have received a copy of the GNU General Public License along with
17  * this program; if not, write to the Free Software Foundation, Inc.,
18  * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
19  *
20  * Modifications for inclusion into the Linux staging tree are
21  * Copyright(c) 2010 Larry Finger. All rights reserved.
22  *
23  * Contact information:
24  * WLAN FAE <wlanfae@realtek.com>
25  * Larry Finger <Larry.Finger@lwfinger.net>
26  *
27  ******************************************************************************/
28
29 #define _RTL871X_CMD_C_
30
31 #include <linux/compiler.h>
32 #include <linux/kernel.h>
33 #include <linux/errno.h>
34 #include <linux/init.h>
35 #include <linux/slab.h>
36 #include <linux/module.h>
37 #include <linux/kref.h>
38 #include <linux/netdevice.h>
39 #include <linux/skbuff.h>
40 #include <linux/usb.h>
41 #include <linux/usb/ch9.h>
42 #include <linux/circ_buf.h>
43 #include <linux/uaccess.h>
44 #include <asm/byteorder.h>
45 #include <linux/atomic.h>
46 #include <linux/semaphore.h>
47 #include <linux/rtnetlink.h>
48
49 #include "osdep_service.h"
50 #include "drv_types.h"
51 #include "recv_osdep.h"
52 #include "mlme_osdep.h"
53 #include "rtl871x_byteorder.h"
54
55 /*
56 Caller and the r8712_cmd_thread can protect cmd_q by spin_lock.
57 No irqsave is necessary.
58 */
59
60 static sint _init_cmd_priv(struct cmd_priv *pcmdpriv)
61 {
62         sema_init(&(pcmdpriv->cmd_queue_sema), 0);
63         sema_init(&(pcmdpriv->terminate_cmdthread_sema), 0);
64
65         _init_queue(&(pcmdpriv->cmd_queue));
66
67         /* allocate DMA-able/Non-Page memory for cmd_buf and rsp_buf */
68         pcmdpriv->cmd_seq = 1;
69         pcmdpriv->cmd_allocated_buf = _malloc(MAX_CMDSZ + CMDBUFF_ALIGN_SZ);
70         if (pcmdpriv->cmd_allocated_buf == NULL)
71                 return _FAIL;
72         pcmdpriv->cmd_buf = pcmdpriv->cmd_allocated_buf  +  CMDBUFF_ALIGN_SZ -
73                             ((addr_t)(pcmdpriv->cmd_allocated_buf) &
74                             (CMDBUFF_ALIGN_SZ-1));
75         pcmdpriv->rsp_allocated_buf = _malloc(MAX_RSPSZ + 4);
76         if (pcmdpriv->rsp_allocated_buf == NULL)
77                 return _FAIL;
78         pcmdpriv->rsp_buf = pcmdpriv->rsp_allocated_buf  +  4 -
79                             ((addr_t)(pcmdpriv->rsp_allocated_buf) & 3);
80         pcmdpriv->cmd_issued_cnt = 0;
81         pcmdpriv->cmd_done_cnt = 0;
82         pcmdpriv->rsp_cnt = 0;
83         return _SUCCESS;
84 }
85
86 static sint _init_evt_priv(struct evt_priv *pevtpriv)
87 {
88         /* allocate DMA-able/Non-Page memory for cmd_buf and rsp_buf */
89         pevtpriv->event_seq = 0;
90         pevtpriv->evt_allocated_buf = _malloc(MAX_EVTSZ + 4);
91
92         if (pevtpriv->evt_allocated_buf == NULL)
93                 return _FAIL;
94         pevtpriv->evt_buf = pevtpriv->evt_allocated_buf  +  4 -
95                             ((addr_t)(pevtpriv->evt_allocated_buf) & 3);
96         pevtpriv->evt_done_cnt = 0;
97         return _SUCCESS;
98 }
99
100 static void _free_evt_priv(struct evt_priv *pevtpriv)
101 {
102         kfree(pevtpriv->evt_allocated_buf);
103 }
104
105 static void _free_cmd_priv(struct cmd_priv *pcmdpriv)
106 {
107         if (pcmdpriv) {
108                 kfree(pcmdpriv->cmd_allocated_buf);
109                 kfree(pcmdpriv->rsp_allocated_buf);
110         }
111 }
112
113 /*
114 Calling Context:
115
116 _enqueue_cmd can only be called between kernel thread,
117 since only spin_lock is used.
118
119 ISR/Call-Back functions can't call this sub-function.
120
121 */
122
123 static sint _enqueue_cmd(struct  __queue *queue, struct cmd_obj *obj)
124 {
125         unsigned long irqL;
126
127         if (obj == NULL)
128                 return _SUCCESS;
129         spin_lock_irqsave(&queue->lock, irqL);
130         list_insert_tail(&obj->list, &queue->queue);
131         spin_unlock_irqrestore(&queue->lock, irqL);
132         return _SUCCESS;
133 }
134
135 static struct cmd_obj *_dequeue_cmd(struct  __queue *queue)
136 {
137         unsigned long irqL;
138         struct cmd_obj *obj;
139
140         spin_lock_irqsave(&(queue->lock), irqL);
141         if (is_list_empty(&(queue->queue)))
142                 obj = NULL;
143         else {
144                 obj = LIST_CONTAINOR(get_next(&(queue->queue)),
145                                      struct cmd_obj, list);
146                 list_delete(&obj->list);
147         }
148         spin_unlock_irqrestore(&(queue->lock), irqL);
149         return obj;
150 }
151
152 u32 r8712_init_cmd_priv(struct cmd_priv *pcmdpriv)
153 {
154         return _init_cmd_priv(pcmdpriv);
155 }
156
157 u32 r8712_init_evt_priv(struct evt_priv *pevtpriv)
158 {
159         return _init_evt_priv(pevtpriv);
160 }
161
162 void r8712_free_evt_priv(struct evt_priv *pevtpriv)
163 {
164         _free_evt_priv(pevtpriv);
165 }
166
167 void r8712_free_cmd_priv(struct cmd_priv *pcmdpriv)
168 {
169         _free_cmd_priv(pcmdpriv);
170 }
171
172 u32 r8712_enqueue_cmd(struct cmd_priv *pcmdpriv, struct cmd_obj *obj)
173 {
174         int res;
175
176         if (pcmdpriv->padapter->eeprompriv.bautoload_fail_flag == true)
177                 return _FAIL;
178         res = _enqueue_cmd(&pcmdpriv->cmd_queue, obj);
179         up(&pcmdpriv->cmd_queue_sema);
180         return res;
181 }
182
183 u32 r8712_enqueue_cmd_ex(struct cmd_priv *pcmdpriv, struct cmd_obj *obj)
184 {
185         unsigned long irqL;
186         struct  __queue *queue;
187
188         if (obj == NULL)
189                 return _SUCCESS;
190         if (pcmdpriv->padapter->eeprompriv.bautoload_fail_flag == true)
191                 return _FAIL;
192         queue = &pcmdpriv->cmd_queue;
193         spin_lock_irqsave(&queue->lock, irqL);
194         list_insert_tail(&obj->list, &queue->queue);
195         spin_unlock_irqrestore(&queue->lock, irqL);
196         up(&pcmdpriv->cmd_queue_sema);
197         return _SUCCESS;
198 }
199
200 struct cmd_obj *r8712_dequeue_cmd(struct  __queue *queue)
201 {
202         return _dequeue_cmd(queue);
203 }
204
205 void r8712_free_cmd_obj(struct cmd_obj *pcmd)
206 {
207         if ((pcmd->cmdcode != _JoinBss_CMD_) &&
208             (pcmd->cmdcode != _CreateBss_CMD_))
209                 kfree((unsigned char *)pcmd->parmbuf);
210         if (pcmd->rsp != NULL) {
211                 if (pcmd->rspsz != 0)
212                         kfree((unsigned char *)pcmd->rsp);
213         }
214         kfree((unsigned char *)pcmd);
215 }
216
217 /*
218 r8712_sitesurvey_cmd(~)
219         ### NOTE:#### (!!!!)
220         MUST TAKE CARE THAT BEFORE CALLING THIS FUNC,
221          YOU SHOULD HAVE LOCKED pmlmepriv->lock
222 */
223 u8 r8712_sitesurvey_cmd(struct _adapter *padapter,
224                         struct ndis_802_11_ssid *pssid)
225 {
226         struct cmd_obj  *ph2c;
227         struct sitesurvey_parm  *psurveyPara;
228         struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
229         struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
230
231         ph2c = (struct cmd_obj *)_malloc(sizeof(struct cmd_obj));
232         if (ph2c == NULL)
233                 return _FAIL;
234         psurveyPara = (struct sitesurvey_parm *)_malloc(
235                        sizeof(struct sitesurvey_parm));
236         if (psurveyPara == NULL) {
237                 kfree((unsigned char *) ph2c);
238                 return _FAIL;
239         }
240         init_h2fwcmd_w_parm_no_rsp(ph2c, psurveyPara,
241                                    GEN_CMD_CODE(_SiteSurvey));
242         psurveyPara->bsslimit = cpu_to_le32(48);
243         psurveyPara->passive_mode = cpu_to_le32(pmlmepriv->passive_mode);
244         psurveyPara->ss_ssidlen = 0;
245         memset(psurveyPara->ss_ssid, 0, IW_ESSID_MAX_SIZE + 1);
246         if ((pssid != NULL) && (pssid->SsidLength)) {
247                 memcpy(psurveyPara->ss_ssid, pssid->Ssid, pssid->SsidLength);
248                 psurveyPara->ss_ssidlen = cpu_to_le32(pssid->SsidLength);
249         }
250         set_fwstate(pmlmepriv, _FW_UNDER_SURVEY);
251         r8712_enqueue_cmd(pcmdpriv, ph2c);
252         _set_timer(&pmlmepriv->scan_to_timer, SCANNING_TIMEOUT);
253         padapter->ledpriv.LedControlHandler(padapter, LED_CTL_SITE_SURVEY);
254         padapter->blnEnableRxFF0Filter = 0;
255         return _SUCCESS;
256 }
257
258 u8 r8712_setdatarate_cmd(struct _adapter *padapter, u8 *rateset)
259 {
260         struct cmd_obj          *ph2c;
261         struct setdatarate_parm *pbsetdataratepara;
262         struct cmd_priv         *pcmdpriv = &padapter->cmdpriv;
263
264         ph2c = (struct cmd_obj *)_malloc(sizeof(struct cmd_obj));
265         if (ph2c == NULL)
266                 return _FAIL;
267         pbsetdataratepara = (struct setdatarate_parm *)_malloc(
268                              sizeof(struct setdatarate_parm));
269         if (pbsetdataratepara == NULL) {
270                 kfree((u8 *) ph2c);
271                 return _FAIL;
272         }
273         init_h2fwcmd_w_parm_no_rsp(ph2c, pbsetdataratepara,
274                                    GEN_CMD_CODE(_SetDataRate));
275         pbsetdataratepara->mac_id = 5;
276         memcpy(pbsetdataratepara->datarates, rateset, NumRates);
277         r8712_enqueue_cmd(pcmdpriv, ph2c);
278         return _SUCCESS;
279 }
280
281 u8 r8712_set_chplan_cmd(struct _adapter *padapter, int chplan)
282 {
283         struct cmd_obj *ph2c;
284         struct SetChannelPlan_param *psetchplanpara;
285         struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
286
287         ph2c = (struct cmd_obj *)_malloc(sizeof(struct cmd_obj));
288         if (ph2c == NULL)
289                 return _FAIL;
290         psetchplanpara = (struct SetChannelPlan_param *)
291                 _malloc(sizeof(struct SetChannelPlan_param));
292         if (psetchplanpara == NULL) {
293                 kfree((u8 *) ph2c);
294                 return _FAIL;
295         }
296         init_h2fwcmd_w_parm_no_rsp(ph2c, psetchplanpara,
297                                 GEN_CMD_CODE(_SetChannelPlan));
298         psetchplanpara->ChannelPlan = chplan;
299         r8712_enqueue_cmd(pcmdpriv, ph2c);
300         return _SUCCESS;
301 }
302
303 u8 r8712_setbasicrate_cmd(struct _adapter *padapter, u8 *rateset)
304 {
305         struct cmd_obj *ph2c;
306         struct setbasicrate_parm *pssetbasicratepara;
307         struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
308
309         ph2c = (struct cmd_obj *)_malloc(sizeof(struct cmd_obj));
310         if (ph2c == NULL)
311                 return _FAIL;
312         pssetbasicratepara = (struct setbasicrate_parm *)_malloc(
313                               sizeof(struct setbasicrate_parm));
314         if (pssetbasicratepara == NULL) {
315                 kfree((u8 *) ph2c);
316                 return _FAIL;
317         }
318         init_h2fwcmd_w_parm_no_rsp(ph2c, pssetbasicratepara,
319                 _SetBasicRate_CMD_);
320         memcpy(pssetbasicratepara->basicrates, rateset, NumRates);
321         r8712_enqueue_cmd(pcmdpriv, ph2c);
322         return _SUCCESS;
323 }
324
325 /* power tracking mechanism setting */
326 u8 r8712_setptm_cmd(struct _adapter *padapter, u8 type)
327 {
328         struct cmd_obj          *ph2c;
329         struct writePTM_parm    *pwriteptmparm;
330         struct cmd_priv         *pcmdpriv = &padapter->cmdpriv;
331
332         ph2c = (struct cmd_obj *)_malloc(sizeof(struct cmd_obj));
333         if (ph2c == NULL)
334                 return _FAIL;
335         pwriteptmparm = (struct writePTM_parm *)
336                 _malloc(sizeof(struct writePTM_parm));
337         if (pwriteptmparm == NULL) {
338                 kfree((u8 *) ph2c);
339                 return _FAIL;
340         }
341         init_h2fwcmd_w_parm_no_rsp(ph2c, pwriteptmparm, GEN_CMD_CODE(_SetPT));
342         pwriteptmparm->type = type;
343         r8712_enqueue_cmd(pcmdpriv, ph2c);
344         return _SUCCESS;
345 }
346
347 u8 r8712_setfwdig_cmd(struct _adapter *padapter, u8 type)
348 {
349         struct cmd_obj *ph2c;
350         struct writePTM_parm *pwriteptmparm;
351         struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
352
353         ph2c = (struct cmd_obj *)_malloc(sizeof(struct cmd_obj));
354         if (ph2c == NULL)
355                 return _FAIL;
356         pwriteptmparm = (struct writePTM_parm *)
357                 _malloc(sizeof(struct setdig_parm));
358         if (pwriteptmparm == NULL) {
359                 kfree((u8 *) ph2c);
360                 return _FAIL;
361         }
362         init_h2fwcmd_w_parm_no_rsp(ph2c, pwriteptmparm, GEN_CMD_CODE(_SetDIG));
363         pwriteptmparm->type = type;
364         r8712_enqueue_cmd(pcmdpriv, ph2c);
365         return _SUCCESS;
366 }
367
368 u8 r8712_setfwra_cmd(struct _adapter *padapter, u8 type)
369 {
370         struct cmd_obj *ph2c;
371         struct writePTM_parm *pwriteptmparm;
372         struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
373
374         ph2c = (struct cmd_obj *)_malloc(sizeof(struct cmd_obj));
375         if (ph2c == NULL)
376                 return _FAIL;
377         pwriteptmparm = (struct writePTM_parm *)
378                 _malloc(sizeof(struct setra_parm));
379         if (pwriteptmparm == NULL) {
380                 kfree((u8 *) ph2c);
381                 return _FAIL;
382         }
383         init_h2fwcmd_w_parm_no_rsp(ph2c, pwriteptmparm, GEN_CMD_CODE(_SetRA));
384         pwriteptmparm->type = type;
385         r8712_enqueue_cmd(pcmdpriv, ph2c);
386         return _SUCCESS;
387 }
388
389 u8 r8712_setrfreg_cmd(struct _adapter  *padapter, u8 offset, u32 val)
390 {
391         struct cmd_obj *ph2c;
392         struct writeRF_parm *pwriterfparm;
393         struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
394
395         ph2c = (struct cmd_obj *)_malloc(sizeof(struct cmd_obj));
396         if (ph2c == NULL)
397                 return _FAIL;
398         pwriterfparm = (struct writeRF_parm *)_malloc(
399                         sizeof(struct writeRF_parm));
400         if (pwriterfparm == NULL) {
401                 kfree((u8 *) ph2c);
402                 return _FAIL;
403         }
404         init_h2fwcmd_w_parm_no_rsp(ph2c, pwriterfparm, GEN_CMD_CODE(_SetRFReg));
405         pwriterfparm->offset = offset;
406         pwriterfparm->value = val;
407         r8712_enqueue_cmd(pcmdpriv, ph2c);
408         return _SUCCESS;
409 }
410
411 u8 r8712_getrfreg_cmd(struct _adapter *padapter, u8 offset, u8 *pval)
412 {
413         struct cmd_obj *ph2c;
414         struct readRF_parm *prdrfparm;
415         struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
416
417         ph2c = (struct cmd_obj *)_malloc(sizeof(struct cmd_obj));
418         if (ph2c == NULL)
419                 return _FAIL;
420         prdrfparm = (struct readRF_parm *)_malloc(sizeof(struct readRF_parm));
421         if (prdrfparm == NULL) {
422                 kfree((u8 *) ph2c);
423                 return _FAIL;
424         }
425         _init_listhead(&ph2c->list);
426         ph2c->cmdcode = GEN_CMD_CODE(_GetRFReg);
427         ph2c->parmbuf = (unsigned char *)prdrfparm;
428         ph2c->cmdsz =  sizeof(struct readRF_parm);
429         ph2c->rsp = pval;
430         ph2c->rspsz = sizeof(struct readRF_rsp);
431         prdrfparm->offset = offset;
432         r8712_enqueue_cmd(pcmdpriv, ph2c);
433         return _SUCCESS;
434 }
435
436 void r8712_getbbrfreg_cmdrsp_callback(struct _adapter *padapter,
437                                       struct cmd_obj *pcmd)
438 {
439         kfree(pcmd->parmbuf);
440         kfree(pcmd);
441         padapter->mppriv.workparam.bcompleted = true;
442 }
443
444 void r8712_readtssi_cmdrsp_callback(struct _adapter *padapter,
445                                 struct cmd_obj *pcmd)
446 {
447         kfree(pcmd->parmbuf);
448         kfree(pcmd);
449
450         padapter->mppriv.workparam.bcompleted = true;
451 }
452
453 u8 r8712_createbss_cmd(struct _adapter *padapter)
454 {
455         struct cmd_obj *pcmd;
456         struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
457         struct wlan_bssid_ex *pdev_network =
458                                  &padapter->registrypriv.dev_network;
459
460         padapter->ledpriv.LedControlHandler(padapter, LED_CTL_START_TO_LINK);
461         pcmd = (struct cmd_obj *)_malloc(sizeof(struct cmd_obj));
462         if (pcmd == NULL)
463                 return _FAIL;
464         _init_listhead(&pcmd->list);
465         pcmd->cmdcode = _CreateBss_CMD_;
466         pcmd->parmbuf = (unsigned char *)pdev_network;
467         pcmd->cmdsz = r8712_get_ndis_wlan_bssid_ex_sz((
468                         struct ndis_wlan_bssid_ex *)
469                         pdev_network);
470         pcmd->rsp = NULL;
471         pcmd->rspsz = 0;
472         /* notes: translate IELength & Length after assign to cmdsz; */
473         pdev_network->Length = cpu_to_le32(pcmd->cmdsz);
474         pdev_network->IELength = cpu_to_le32(pdev_network->IELength);
475         pdev_network->Ssid.SsidLength = cpu_to_le32(
476                                         pdev_network->Ssid.SsidLength);
477         r8712_enqueue_cmd(pcmdpriv, pcmd);
478         return _SUCCESS;
479 }
480
481 u8 r8712_joinbss_cmd(struct _adapter  *padapter, struct wlan_network *pnetwork)
482 {
483         u8 *auth;
484         uint t_len = 0;
485         struct ndis_wlan_bssid_ex *psecnetwork;
486         struct cmd_obj          *pcmd;
487         struct cmd_priv         *pcmdpriv = &padapter->cmdpriv;
488         struct mlme_priv        *pmlmepriv = &padapter->mlmepriv;
489         struct qos_priv         *pqospriv = &pmlmepriv->qospriv;
490         struct security_priv    *psecuritypriv = &padapter->securitypriv;
491         struct registry_priv    *pregistrypriv = &padapter->registrypriv;
492         enum NDIS_802_11_NETWORK_INFRASTRUCTURE ndis_network_mode = pnetwork->
493                                                 network.InfrastructureMode;
494
495         padapter->ledpriv.LedControlHandler(padapter, LED_CTL_START_TO_LINK);
496         pcmd = (struct cmd_obj *)_malloc(sizeof(struct cmd_obj));
497         if (pcmd == NULL)
498                 return _FAIL;
499         t_len = sizeof(u32) + 6 * sizeof(unsigned char) + 2 +
500                         sizeof(struct ndis_802_11_ssid) + sizeof(u32) +
501                         sizeof(s32) +
502                         sizeof(enum NDIS_802_11_NETWORK_TYPE) +
503                         sizeof(struct NDIS_802_11_CONFIGURATION) +
504                         sizeof(enum NDIS_802_11_NETWORK_INFRASTRUCTURE) +
505                         sizeof(NDIS_802_11_RATES_EX) +
506                         sizeof(u32) + MAX_IE_SZ;
507
508         /* for hidden ap to set fw_state here */
509         if (check_fwstate(pmlmepriv, WIFI_STATION_STATE|WIFI_ADHOC_STATE) !=
510             true) {
511                 switch (ndis_network_mode) {
512                 case Ndis802_11IBSS:
513                         pmlmepriv->fw_state |= WIFI_ADHOC_STATE;
514                         break;
515                 case Ndis802_11Infrastructure:
516                         pmlmepriv->fw_state |= WIFI_STATION_STATE;
517                         break;
518                 case Ndis802_11APMode:
519                 case Ndis802_11AutoUnknown:
520                 case Ndis802_11InfrastructureMax:
521                         break;
522                 }
523         }
524         psecnetwork = (struct ndis_wlan_bssid_ex *)&psecuritypriv->sec_bss;
525         if (psecnetwork == NULL) {
526                 kfree(pcmd);
527                 return _FAIL;
528         }
529         memset(psecnetwork, 0, t_len);
530         memcpy(psecnetwork, &pnetwork->network, t_len);
531         auth = &psecuritypriv->authenticator_ie[0];
532         psecuritypriv->authenticator_ie[0] = (unsigned char)
533                                              psecnetwork->IELength;
534         if ((psecnetwork->IELength-12) < (256 - 1))
535                 memcpy(&psecuritypriv->authenticator_ie[1],
536                         &psecnetwork->IEs[12], psecnetwork->IELength-12);
537         else
538                 memcpy(&psecuritypriv->authenticator_ie[1],
539                         &psecnetwork->IEs[12], (256-1));
540         psecnetwork->IELength = 0;
541         /* If the the driver wants to use the bssid to create the connection.
542          * If not,  we copy the connecting AP's MAC address to it so that
543          * the driver just has the bssid information for PMKIDList searching.
544          */
545         if (pmlmepriv->assoc_by_bssid == false)
546                 memcpy(&pmlmepriv->assoc_bssid[0],
547                         &pnetwork->network.MacAddress[0], ETH_ALEN);
548         psecnetwork->IELength = r8712_restruct_sec_ie(padapter,
549                                                 &pnetwork->network.IEs[0],
550                                                 &psecnetwork->IEs[0],
551                                                 pnetwork->network.IELength);
552         pqospriv->qos_option = 0;
553         if (pregistrypriv->wmm_enable) {
554                 u32 tmp_len;
555
556                 tmp_len = r8712_restruct_wmm_ie(padapter,
557                                           &pnetwork->network.IEs[0],
558                                           &psecnetwork->IEs[0],
559                                           pnetwork->network.IELength,
560                                           psecnetwork->IELength);
561                 if (psecnetwork->IELength != tmp_len) {
562                         psecnetwork->IELength = tmp_len;
563                         pqospriv->qos_option = 1; /* WMM IE in beacon */
564                 } else
565                         pqospriv->qos_option = 0; /* no WMM IE in beacon */
566         }
567         if (pregistrypriv->ht_enable) {
568                 /* For WEP mode, we will use the bg mode to do the connection
569                  * to avoid some IOT issues, especially for Realtek 8192u
570                  * SoftAP.
571                  */
572                 if ((padapter->securitypriv.PrivacyAlgrthm != _WEP40_) &&
573                     (padapter->securitypriv.PrivacyAlgrthm != _WEP104_)) {
574                         /* restructure_ht_ie */
575                         r8712_restructure_ht_ie(padapter,
576                                                 &pnetwork->network.IEs[0],
577                                                 &psecnetwork->IEs[0],
578                                                 pnetwork->network.IELength,
579                                                 &psecnetwork->IELength);
580                 }
581         }
582         psecuritypriv->supplicant_ie[0] = (u8)psecnetwork->IELength;
583         if (psecnetwork->IELength < 255)
584                 memcpy(&psecuritypriv->supplicant_ie[1], &psecnetwork->IEs[0],
585                         psecnetwork->IELength);
586         else
587                 memcpy(&psecuritypriv->supplicant_ie[1], &psecnetwork->IEs[0],
588                         255);
589         /* get cmdsz before endian conversion */
590         pcmd->cmdsz = r8712_get_ndis_wlan_bssid_ex_sz(psecnetwork);
591 #ifdef __BIG_ENDIAN
592         /* wlan_network endian conversion */
593         psecnetwork->Length = cpu_to_le32(psecnetwork->Length);
594         psecnetwork->Ssid.SsidLength = cpu_to_le32(
595                                        psecnetwork->Ssid.SsidLength);
596         psecnetwork->Privacy = cpu_to_le32(psecnetwork->Privacy);
597         psecnetwork->Rssi = cpu_to_le32(psecnetwork->Rssi);
598         psecnetwork->NetworkTypeInUse = cpu_to_le32(
599                                         psecnetwork->NetworkTypeInUse);
600         psecnetwork->Configuration.ATIMWindow = cpu_to_le32(
601                                 psecnetwork->Configuration.ATIMWindow);
602         psecnetwork->Configuration.BeaconPeriod = cpu_to_le32(
603                                  psecnetwork->Configuration.BeaconPeriod);
604         psecnetwork->Configuration.DSConfig = cpu_to_le32(
605                                 psecnetwork->Configuration.DSConfig);
606         psecnetwork->Configuration.FHConfig.DwellTime = cpu_to_le32(
607                                 psecnetwork->Configuration.FHConfig.DwellTime);
608         psecnetwork->Configuration.FHConfig.HopPattern = cpu_to_le32(
609                                 psecnetwork->Configuration.FHConfig.HopPattern);
610         psecnetwork->Configuration.FHConfig.HopSet = cpu_to_le32(
611                                 psecnetwork->Configuration.FHConfig.HopSet);
612         psecnetwork->Configuration.FHConfig.Length = cpu_to_le32(
613                                 psecnetwork->Configuration.FHConfig.Length);
614         psecnetwork->Configuration.Length = cpu_to_le32(
615                                 psecnetwork->Configuration.Length);
616         psecnetwork->InfrastructureMode = cpu_to_le32(
617                                 psecnetwork->InfrastructureMode);
618         psecnetwork->IELength = cpu_to_le32(psecnetwork->IELength);
619 #endif
620         _init_listhead(&pcmd->list);
621         pcmd->cmdcode = _JoinBss_CMD_;
622         pcmd->parmbuf = (unsigned char *)psecnetwork;
623         pcmd->rsp = NULL;
624         pcmd->rspsz = 0;
625         r8712_enqueue_cmd(pcmdpriv, pcmd);
626         return _SUCCESS;
627 }
628
629 u8 r8712_disassoc_cmd(struct _adapter *padapter) /* for sta_mode */
630 {
631         struct cmd_obj *pdisconnect_cmd;
632         struct disconnect_parm *pdisconnect;
633         struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
634
635         pdisconnect_cmd = (struct cmd_obj *)_malloc(sizeof(struct cmd_obj));
636         if (pdisconnect_cmd == NULL)
637                 return _FAIL;
638         pdisconnect = (struct disconnect_parm *)_malloc(
639                       sizeof(struct disconnect_parm));
640         if (pdisconnect == NULL) {
641                 kfree((u8 *)pdisconnect_cmd);
642                 return _FAIL;
643         }
644         init_h2fwcmd_w_parm_no_rsp(pdisconnect_cmd, pdisconnect,
645                                    _DisConnect_CMD_);
646         r8712_enqueue_cmd(pcmdpriv, pdisconnect_cmd);
647         return _SUCCESS;
648 }
649
650 u8 r8712_setopmode_cmd(struct _adapter *padapter,
651                  enum NDIS_802_11_NETWORK_INFRASTRUCTURE networktype)
652 {
653         struct cmd_obj *ph2c;
654         struct setopmode_parm *psetop;
655
656         struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
657
658         ph2c = (struct cmd_obj *)_malloc(sizeof(struct cmd_obj));
659         if (ph2c == NULL)
660                 return _FAIL;
661         psetop = (struct setopmode_parm *)_malloc(
662                   sizeof(struct setopmode_parm));
663         if (psetop == NULL) {
664                 kfree((u8 *) ph2c);
665                 return _FAIL;
666         }
667         init_h2fwcmd_w_parm_no_rsp(ph2c, psetop, _SetOpMode_CMD_);
668         psetop->mode = (u8)networktype;
669         r8712_enqueue_cmd(pcmdpriv, ph2c);
670         return _SUCCESS;
671 }
672
673 u8 r8712_setstakey_cmd(struct _adapter *padapter, u8 *psta, u8 unicast_key)
674 {
675         struct cmd_obj *ph2c;
676         struct set_stakey_parm *psetstakey_para;
677         struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
678         struct set_stakey_rsp *psetstakey_rsp = NULL;
679         struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
680         struct security_priv *psecuritypriv = &padapter->securitypriv;
681         struct sta_info *sta = (struct sta_info *)psta;
682
683         ph2c = (struct cmd_obj *)_malloc(sizeof(struct cmd_obj));
684         if (ph2c == NULL)
685                 return _FAIL;
686         psetstakey_para = (struct set_stakey_parm *)_malloc(
687                           sizeof(struct set_stakey_parm));
688         if (psetstakey_para == NULL) {
689                 kfree((u8 *) ph2c);
690                 return _FAIL;
691         }
692         psetstakey_rsp = (struct set_stakey_rsp *)_malloc(
693                           sizeof(struct set_stakey_rsp));
694         if (psetstakey_rsp == NULL) {
695                 kfree((u8 *) ph2c);
696                 kfree((u8 *) psetstakey_para);
697                 return _FAIL;
698         }
699         init_h2fwcmd_w_parm_no_rsp(ph2c, psetstakey_para, _SetStaKey_CMD_);
700         ph2c->rsp = (u8 *) psetstakey_rsp;
701         ph2c->rspsz = sizeof(struct set_stakey_rsp);
702         memcpy(psetstakey_para->addr, sta->hwaddr, ETH_ALEN);
703         if (check_fwstate(pmlmepriv, WIFI_STATION_STATE))
704                 psetstakey_para->algorithm = (unsigned char)
705                                             psecuritypriv->PrivacyAlgrthm;
706         else
707                 GET_ENCRY_ALGO(psecuritypriv, sta,
708                                psetstakey_para->algorithm, false);
709         if (unicast_key == true)
710                 memcpy(&psetstakey_para->key, &sta->x_UncstKey, 16);
711         else
712                 memcpy(&psetstakey_para->key,
713                         &psecuritypriv->XGrpKey[
714                         psecuritypriv->XGrpKeyid - 1]. skey, 16);
715         r8712_enqueue_cmd(pcmdpriv, ph2c);
716         return _SUCCESS;
717 }
718
719 u8 r8712_setrfintfs_cmd(struct _adapter *padapter, u8 mode)
720 {
721         struct cmd_obj *ph2c;
722         struct setrfintfs_parm *psetrfintfsparm;
723         struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
724
725         ph2c = (struct cmd_obj *)_malloc(sizeof(struct cmd_obj));
726         if (ph2c == NULL)
727                 return _FAIL;
728         psetrfintfsparm = (struct setrfintfs_parm *)_malloc(
729                            sizeof(struct setrfintfs_parm));
730         if (psetrfintfsparm == NULL) {
731                 kfree((unsigned char *) ph2c);
732                 return _FAIL;
733         }
734         init_h2fwcmd_w_parm_no_rsp(ph2c, psetrfintfsparm,
735                                    GEN_CMD_CODE(_SetRFIntFs));
736         psetrfintfsparm->rfintfs = mode;
737         r8712_enqueue_cmd(pcmdpriv, ph2c);
738         return _SUCCESS;
739 }
740
741 u8 r8712_setrttbl_cmd(struct _adapter *padapter,
742                       struct setratable_parm *prate_table)
743 {
744         struct cmd_obj *ph2c;
745         struct setratable_parm *psetrttblparm;
746         struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
747
748         ph2c = (struct cmd_obj *)_malloc(sizeof(struct cmd_obj));
749         if (ph2c == NULL)
750                 return _FAIL;
751         psetrttblparm = (struct setratable_parm *)_malloc(
752                         sizeof(struct setratable_parm));
753         if (psetrttblparm == NULL) {
754                 kfree((unsigned char *)ph2c);
755                 return _FAIL;
756         }
757         init_h2fwcmd_w_parm_no_rsp(ph2c, psetrttblparm,
758                                    GEN_CMD_CODE(_SetRaTable));
759         memcpy(psetrttblparm, prate_table, sizeof(struct setratable_parm));
760         r8712_enqueue_cmd(pcmdpriv, ph2c);
761         return _SUCCESS;
762 }
763
764 u8 r8712_gettssi_cmd(struct _adapter *padapter, u8 offset, u8 *pval)
765 {
766         struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
767         struct cmd_obj *ph2c;
768         struct readTSSI_parm *prdtssiparm;
769
770         ph2c = (struct cmd_obj *)_malloc(sizeof(struct cmd_obj));
771         if (ph2c == NULL)
772                 return _FAIL;
773         prdtssiparm = (struct readTSSI_parm *)
774                 _malloc(sizeof(struct readTSSI_parm));
775         if (prdtssiparm == NULL) {
776                 kfree((unsigned char *) ph2c);
777                 return _FAIL;
778         }
779         _init_listhead(&ph2c->list);
780         ph2c->cmdcode = GEN_CMD_CODE(_ReadTSSI);
781         ph2c->parmbuf = (unsigned char *)prdtssiparm;
782         ph2c->cmdsz = sizeof(struct readTSSI_parm);
783         ph2c->rsp = pval;
784         ph2c->rspsz = sizeof(struct readTSSI_rsp);
785
786         prdtssiparm->offset = offset;
787         r8712_enqueue_cmd(pcmdpriv, ph2c);
788         return _SUCCESS;
789 }
790
791 u8 r8712_setMacAddr_cmd(struct _adapter *padapter, u8 *mac_addr)
792 {
793         struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
794         struct cmd_obj *ph2c;
795         struct SetMacAddr_param *psetMacAddr_para;
796
797         ph2c = (struct cmd_obj *)_malloc(sizeof(struct cmd_obj));
798         if (ph2c == NULL)
799                 return _FAIL;
800         psetMacAddr_para = (struct SetMacAddr_param *)_malloc(
801                            sizeof(struct SetMacAddr_param));
802         if (psetMacAddr_para == NULL) {
803                 kfree((u8 *) ph2c);
804                 return _FAIL;
805         }
806         init_h2fwcmd_w_parm_no_rsp(ph2c, psetMacAddr_para,
807                                    _SetMacAddress_CMD_);
808         memcpy(psetMacAddr_para->MacAddr, mac_addr, ETH_ALEN);
809         r8712_enqueue_cmd(pcmdpriv, ph2c);
810         return _SUCCESS;
811 }
812
813 u8 r8712_setassocsta_cmd(struct _adapter *padapter, u8 *mac_addr)
814 {
815         struct cmd_priv                 *pcmdpriv = &padapter->cmdpriv;
816         struct cmd_obj                  *ph2c;
817         struct set_assocsta_parm        *psetassocsta_para;
818         struct set_stakey_rsp           *psetassocsta_rsp = NULL;
819
820         ph2c = (struct cmd_obj *)_malloc(sizeof(struct cmd_obj));
821         if (ph2c == NULL)
822                 return _FAIL;
823         psetassocsta_para = (struct set_assocsta_parm *)
824                             _malloc(sizeof(struct set_assocsta_parm));
825         if (psetassocsta_para == NULL) {
826                 kfree((u8 *) ph2c);
827                 return _FAIL;
828         }
829         psetassocsta_rsp = (struct set_stakey_rsp *)_malloc(
830                             sizeof(struct set_assocsta_rsp));
831         if (psetassocsta_rsp == NULL) {
832                 kfree((u8 *)ph2c);
833                 kfree((u8 *)psetassocsta_para);
834                 return _FAIL;
835         }
836         init_h2fwcmd_w_parm_no_rsp(ph2c, psetassocsta_para, _SetAssocSta_CMD_);
837         ph2c->rsp = (u8 *) psetassocsta_rsp;
838         ph2c->rspsz = sizeof(struct set_assocsta_rsp);
839         memcpy(psetassocsta_para->addr, mac_addr, ETH_ALEN);
840         r8712_enqueue_cmd(pcmdpriv, ph2c);
841         return _SUCCESS;
842 }
843
844 u8 r8712_addbareq_cmd(struct _adapter *padapter, u8 tid)
845 {
846         struct cmd_priv         *pcmdpriv = &padapter->cmdpriv;
847         struct cmd_obj          *ph2c;
848         struct addBaReq_parm    *paddbareq_parm;
849
850         ph2c = (struct cmd_obj *)_malloc(sizeof(struct cmd_obj));
851         if (ph2c == NULL)
852                 return _FAIL;
853         paddbareq_parm = (struct addBaReq_parm *)_malloc(
854                           sizeof(struct addBaReq_parm));
855         if (paddbareq_parm == NULL) {
856                 kfree((unsigned char *)ph2c);
857                 return _FAIL;
858         }
859         paddbareq_parm->tid = tid;
860         init_h2fwcmd_w_parm_no_rsp(ph2c, paddbareq_parm,
861                                    GEN_CMD_CODE(_AddBAReq));
862         r8712_enqueue_cmd_ex(pcmdpriv, ph2c);
863         return _SUCCESS;
864 }
865
866 u8 r8712_wdg_wk_cmd(struct _adapter *padapter)
867 {
868         struct cmd_obj *ph2c;
869         struct drvint_cmd_parm  *pdrvintcmd_param;
870         struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
871
872         ph2c = (struct cmd_obj *)_malloc(sizeof(struct cmd_obj));
873         if (ph2c == NULL)
874                 return _FAIL;
875         pdrvintcmd_param = (struct drvint_cmd_parm *)_malloc(
876                            sizeof(struct drvint_cmd_parm));
877         if (pdrvintcmd_param == NULL) {
878                 kfree((unsigned char *)ph2c);
879                 return _FAIL;
880         }
881         pdrvintcmd_param->i_cid = WDG_WK_CID;
882         pdrvintcmd_param->sz = 0;
883         pdrvintcmd_param->pbuf = NULL;
884         init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvintcmd_param, _DRV_INT_CMD_);
885         r8712_enqueue_cmd_ex(pcmdpriv, ph2c);
886         return _SUCCESS;
887 }
888
889 void r8712_survey_cmd_callback(struct _adapter *padapter, struct cmd_obj *pcmd)
890 {
891         struct  mlme_priv *pmlmepriv = &padapter->mlmepriv;
892
893         if (pcmd->res != H2C_SUCCESS)
894                 clr_fwstate(pmlmepriv, _FW_UNDER_SURVEY);
895         r8712_free_cmd_obj(pcmd);
896 }
897
898 void r8712_disassoc_cmd_callback(struct _adapter *padapter,
899                                  struct cmd_obj *pcmd)
900 {
901         unsigned long irqL;
902         struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
903
904         if (pcmd->res != H2C_SUCCESS) {
905                 spin_lock_irqsave(&pmlmepriv->lock, irqL);
906                 set_fwstate(pmlmepriv, _FW_LINKED);
907                 spin_unlock_irqrestore(&pmlmepriv->lock, irqL);
908                 return;
909         }
910         r8712_free_cmd_obj(pcmd);
911 }
912
913 void r8712_joinbss_cmd_callback(struct _adapter *padapter, struct cmd_obj *pcmd)
914 {
915         struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
916
917         if ((pcmd->res != H2C_SUCCESS))
918                 _set_timer(&pmlmepriv->assoc_timer, 1);
919         r8712_free_cmd_obj(pcmd);
920 }
921
922 void r8712_createbss_cmd_callback(struct _adapter *padapter,
923                                   struct cmd_obj *pcmd)
924 {
925         unsigned long irqL;
926         u8 timer_cancelled;
927         struct sta_info *psta = NULL;
928         struct wlan_network *pwlan = NULL;
929         struct  mlme_priv *pmlmepriv = &padapter->mlmepriv;
930         struct ndis_wlan_bssid_ex *pnetwork = (struct ndis_wlan_bssid_ex *)
931                                               pcmd->parmbuf;
932         struct wlan_network *tgt_network = &(pmlmepriv->cur_network);
933
934         if ((pcmd->res != H2C_SUCCESS))
935                 _set_timer(&pmlmepriv->assoc_timer, 1);
936         _cancel_timer(&pmlmepriv->assoc_timer, &timer_cancelled);
937 #ifdef __BIG_ENDIAN
938         /* endian_convert */
939         pnetwork->Length = le32_to_cpu(pnetwork->Length);
940         pnetwork->Ssid.SsidLength = le32_to_cpu(pnetwork->Ssid.SsidLength);
941         pnetwork->Privacy = le32_to_cpu(pnetwork->Privacy);
942         pnetwork->Rssi = le32_to_cpu(pnetwork->Rssi);
943         pnetwork->NetworkTypeInUse = le32_to_cpu(pnetwork->NetworkTypeInUse);
944         pnetwork->Configuration.ATIMWindow = le32_to_cpu(pnetwork->
945                                         Configuration.ATIMWindow);
946         pnetwork->Configuration.DSConfig = le32_to_cpu(pnetwork->
947                                         Configuration.DSConfig);
948         pnetwork->Configuration.FHConfig.DwellTime = le32_to_cpu(pnetwork->
949                                         Configuration.FHConfig.DwellTime);
950         pnetwork->Configuration.FHConfig.HopPattern = le32_to_cpu(pnetwork->
951                                         Configuration.FHConfig.HopPattern);
952         pnetwork->Configuration.FHConfig.HopSet = le32_to_cpu(pnetwork->
953                                         Configuration.FHConfig.HopSet);
954         pnetwork->Configuration.FHConfig.Length = le32_to_cpu(pnetwork->
955                                         Configuration.FHConfig.Length);
956         pnetwork->Configuration.Length = le32_to_cpu(pnetwork->
957                                         Configuration.Length);
958         pnetwork->InfrastructureMode = le32_to_cpu(pnetwork->
959                                            InfrastructureMode);
960         pnetwork->IELength = le32_to_cpu(pnetwork->IELength);
961 #endif
962         spin_lock_irqsave(&pmlmepriv->lock, irqL);
963         if ((pmlmepriv->fw_state) & WIFI_AP_STATE) {
964                 psta = r8712_get_stainfo(&padapter->stapriv,
965                                          pnetwork->MacAddress);
966                 if (!psta) {
967                         psta = r8712_alloc_stainfo(&padapter->stapriv,
968                                                    pnetwork->MacAddress);
969                         if (psta == NULL)
970                                 goto createbss_cmd_fail ;
971                 }
972                 r8712_indicate_connect(padapter);
973         } else {
974                 pwlan = _r8712_alloc_network(pmlmepriv);
975                 if (pwlan == NULL) {
976                         pwlan = r8712_get_oldest_wlan_network(
977                                 &pmlmepriv->scanned_queue);
978                         if (pwlan == NULL)
979                                 goto createbss_cmd_fail;
980                         pwlan->last_scanned = jiffies;
981                 } else
982                         list_insert_tail(&(pwlan->list),
983                                          &pmlmepriv->scanned_queue.queue);
984                 pnetwork->Length = r8712_get_ndis_wlan_bssid_ex_sz(pnetwork);
985                 memcpy(&(pwlan->network), pnetwork, pnetwork->Length);
986                 pwlan->fixed = true;
987                 memcpy(&tgt_network->network, pnetwork,
988                         (r8712_get_ndis_wlan_bssid_ex_sz(pnetwork)));
989                 if (pmlmepriv->fw_state & _FW_UNDER_LINKING)
990                         pmlmepriv->fw_state ^= _FW_UNDER_LINKING;
991                 /* we will set _FW_LINKED when there is one more sat to
992                  * join us (stassoc_event_callback) */
993         }
994 createbss_cmd_fail:
995         spin_unlock_irqrestore(&pmlmepriv->lock, irqL);
996         r8712_free_cmd_obj(pcmd);
997 }
998
999 void r8712_setstaKey_cmdrsp_callback(struct _adapter *padapter,
1000                                      struct cmd_obj *pcmd)
1001 {
1002         struct sta_priv *pstapriv = &padapter->stapriv;
1003         struct set_stakey_rsp *psetstakey_rsp = (struct set_stakey_rsp *)
1004                                                 (pcmd->rsp);
1005         struct sta_info *psta = r8712_get_stainfo(pstapriv,
1006                                                   psetstakey_rsp->addr);
1007
1008         if (psta == NULL)
1009                 goto exit;
1010         psta->aid = psta->mac_id = psetstakey_rsp->keyid; /*CAM_ID(CAM_ENTRY)*/
1011 exit:
1012         r8712_free_cmd_obj(pcmd);
1013 }
1014
1015 void r8712_setassocsta_cmdrsp_callback(struct _adapter *padapter,
1016                                        struct cmd_obj *pcmd)
1017 {
1018         unsigned long   irqL;
1019         struct sta_priv *pstapriv = &padapter->stapriv;
1020         struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1021         struct set_assocsta_parm *passocsta_parm =
1022                                 (struct set_assocsta_parm *)(pcmd->parmbuf);
1023         struct set_assocsta_rsp *passocsta_rsp =
1024                                 (struct set_assocsta_rsp *) (pcmd->rsp);
1025         struct sta_info *psta = r8712_get_stainfo(pstapriv,
1026                                                   passocsta_parm->addr);
1027
1028         if (psta == NULL)
1029                 return;
1030         psta->aid = psta->mac_id = passocsta_rsp->cam_id;
1031         spin_lock_irqsave(&pmlmepriv->lock, irqL);
1032         if ((check_fwstate(pmlmepriv, WIFI_MP_STATE)) &&
1033             (check_fwstate(pmlmepriv, _FW_UNDER_LINKING)))
1034                 pmlmepriv->fw_state ^= _FW_UNDER_LINKING;
1035         set_fwstate(pmlmepriv, _FW_LINKED);
1036         spin_unlock_irqrestore(&pmlmepriv->lock, irqL);
1037         r8712_free_cmd_obj(pcmd);
1038 }
1039
1040 u8 r8712_disconnectCtrlEx_cmd(struct _adapter *adapter, u32 enableDrvCtrl,
1041                         u32 tryPktCnt, u32 tryPktInterval, u32 firstStageTO)
1042 {
1043         struct cmd_obj *ph2c;
1044         struct DisconnectCtrlEx_param *param;
1045         struct cmd_priv *pcmdpriv = &adapter->cmdpriv;
1046
1047         ph2c = (struct cmd_obj *)_malloc(sizeof(struct cmd_obj));
1048         if (ph2c == NULL)
1049                 return _FAIL;
1050         param = (struct DisconnectCtrlEx_param *)
1051                 _malloc(sizeof(struct DisconnectCtrlEx_param));
1052         if (param == NULL) {
1053                 kfree((unsigned char *) ph2c);
1054                 return _FAIL;
1055         }
1056         memset(param, 0, sizeof(struct DisconnectCtrlEx_param));
1057
1058         param->EnableDrvCtrl = (unsigned char)enableDrvCtrl;
1059         param->TryPktCnt = (unsigned char)tryPktCnt;
1060         param->TryPktInterval = (unsigned char)tryPktInterval;
1061         param->FirstStageTO = (unsigned int)firstStageTO;
1062
1063         init_h2fwcmd_w_parm_no_rsp(ph2c, param,
1064                                 GEN_CMD_CODE(_DisconnectCtrlEx));
1065         r8712_enqueue_cmd(pcmdpriv, ph2c);
1066         return _SUCCESS;
1067 }