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