These changes are the raw update to linux-4.4.6-rt14. Kernel sources
[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)
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)
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_wlan_bssid_ex_sz(pdev_network);
460         pcmd->rsp = NULL;
461         pcmd->rspsz = 0;
462         /* notes: translate IELength & Length after assign to cmdsz; */
463         pdev_network->Length = pcmd->cmdsz;
464         pdev_network->IELength = pdev_network->IELength;
465         pdev_network->Ssid.SsidLength = pdev_network->Ssid.SsidLength;
466         r8712_enqueue_cmd(pcmdpriv, pcmd);
467         return _SUCCESS;
468 }
469
470 u8 r8712_joinbss_cmd(struct _adapter  *padapter, struct wlan_network *pnetwork)
471 {
472         struct wlan_bssid_ex *psecnetwork;
473         struct cmd_obj          *pcmd;
474         struct cmd_priv         *pcmdpriv = &padapter->cmdpriv;
475         struct mlme_priv        *pmlmepriv = &padapter->mlmepriv;
476         struct qos_priv         *pqospriv = &pmlmepriv->qospriv;
477         struct security_priv    *psecuritypriv = &padapter->securitypriv;
478         struct registry_priv    *pregistrypriv = &padapter->registrypriv;
479         enum NDIS_802_11_NETWORK_INFRASTRUCTURE ndis_network_mode = pnetwork->
480                                                 network.InfrastructureMode;
481
482         padapter->ledpriv.LedControlHandler(padapter, LED_CTL_START_TO_LINK);
483         pcmd = kmalloc(sizeof(*pcmd), GFP_ATOMIC);
484         if (pcmd == NULL)
485                 return _FAIL;
486
487         /* for hidden ap to set fw_state here */
488         if (check_fwstate(pmlmepriv, WIFI_STATION_STATE | WIFI_ADHOC_STATE) !=
489             true) {
490                 switch (ndis_network_mode) {
491                 case Ndis802_11IBSS:
492                         pmlmepriv->fw_state |= WIFI_ADHOC_STATE;
493                         break;
494                 case Ndis802_11Infrastructure:
495                         pmlmepriv->fw_state |= WIFI_STATION_STATE;
496                         break;
497                 case Ndis802_11APMode:
498                 case Ndis802_11AutoUnknown:
499                 case Ndis802_11InfrastructureMax:
500                         break;
501                 }
502         }
503         psecnetwork = &psecuritypriv->sec_bss;
504         if (psecnetwork == NULL) {
505                 kfree(pcmd);
506                 return _FAIL;
507         }
508         memcpy(psecnetwork, &pnetwork->network, sizeof(*psecnetwork));
509         psecuritypriv->authenticator_ie[0] = (unsigned char)
510                                              psecnetwork->IELength;
511         if ((psecnetwork->IELength - 12) < (256 - 1))
512                 memcpy(&psecuritypriv->authenticator_ie[1],
513                         &psecnetwork->IEs[12], psecnetwork->IELength - 12);
514         else
515                 memcpy(&psecuritypriv->authenticator_ie[1],
516                         &psecnetwork->IEs[12], (256 - 1));
517         psecnetwork->IELength = 0;
518         /* If the driver wants to use the bssid to create the connection.
519          * If not,  we copy the connecting AP's MAC address to it so that
520          * the driver just has the bssid information for PMKIDList searching.
521          */
522         if (!pmlmepriv->assoc_by_bssid)
523                 ether_addr_copy(&pmlmepriv->assoc_bssid[0],
524                                 &pnetwork->network.MacAddress[0]);
525         psecnetwork->IELength = r8712_restruct_sec_ie(padapter,
526                                                 &pnetwork->network.IEs[0],
527                                                 &psecnetwork->IEs[0],
528                                                 pnetwork->network.IELength);
529         pqospriv->qos_option = 0;
530         if (pregistrypriv->wmm_enable) {
531                 u32 tmp_len;
532
533                 tmp_len = r8712_restruct_wmm_ie(padapter,
534                                           &pnetwork->network.IEs[0],
535                                           &psecnetwork->IEs[0],
536                                           pnetwork->network.IELength,
537                                           psecnetwork->IELength);
538                 if (psecnetwork->IELength != tmp_len) {
539                         psecnetwork->IELength = tmp_len;
540                         pqospriv->qos_option = 1; /* WMM IE in beacon */
541                 } else {
542                         pqospriv->qos_option = 0; /* no WMM IE in beacon */
543                 }
544         }
545         if (pregistrypriv->ht_enable) {
546                 /* For WEP mode, we will use the bg mode to do the connection
547                  * to avoid some IOT issues, especially for Realtek 8192u
548                  * SoftAP.
549                  */
550                 if ((padapter->securitypriv.PrivacyAlgrthm != _WEP40_) &&
551                     (padapter->securitypriv.PrivacyAlgrthm != _WEP104_)) {
552                         /* restructure_ht_ie */
553                         r8712_restructure_ht_ie(padapter,
554                                                 &pnetwork->network.IEs[0],
555                                                 &psecnetwork->IEs[0],
556                                                 pnetwork->network.IELength,
557                                                 &psecnetwork->IELength);
558                 }
559         }
560         psecuritypriv->supplicant_ie[0] = (u8)psecnetwork->IELength;
561         if (psecnetwork->IELength < 255)
562                 memcpy(&psecuritypriv->supplicant_ie[1], &psecnetwork->IEs[0],
563                         psecnetwork->IELength);
564         else
565                 memcpy(&psecuritypriv->supplicant_ie[1], &psecnetwork->IEs[0],
566                         255);
567         /* get cmdsz before endian conversion */
568         pcmd->cmdsz = r8712_get_wlan_bssid_ex_sz(psecnetwork);
569 #ifdef __BIG_ENDIAN
570         /* wlan_network endian conversion */
571         psecnetwork->Length = cpu_to_le32(psecnetwork->Length);
572         psecnetwork->Ssid.SsidLength = cpu_to_le32(
573                                        psecnetwork->Ssid.SsidLength);
574         psecnetwork->Privacy = cpu_to_le32(psecnetwork->Privacy);
575         psecnetwork->Rssi = cpu_to_le32(psecnetwork->Rssi);
576         psecnetwork->NetworkTypeInUse = cpu_to_le32(
577                                         psecnetwork->NetworkTypeInUse);
578         psecnetwork->Configuration.ATIMWindow = cpu_to_le32(
579                                 psecnetwork->Configuration.ATIMWindow);
580         psecnetwork->Configuration.BeaconPeriod = cpu_to_le32(
581                                  psecnetwork->Configuration.BeaconPeriod);
582         psecnetwork->Configuration.DSConfig = cpu_to_le32(
583                                 psecnetwork->Configuration.DSConfig);
584         psecnetwork->Configuration.FHConfig.DwellTime = cpu_to_le32(
585                                 psecnetwork->Configuration.FHConfig.DwellTime);
586         psecnetwork->Configuration.FHConfig.HopPattern = cpu_to_le32(
587                                 psecnetwork->Configuration.FHConfig.HopPattern);
588         psecnetwork->Configuration.FHConfig.HopSet = cpu_to_le32(
589                                 psecnetwork->Configuration.FHConfig.HopSet);
590         psecnetwork->Configuration.FHConfig.Length = cpu_to_le32(
591                                 psecnetwork->Configuration.FHConfig.Length);
592         psecnetwork->Configuration.Length = cpu_to_le32(
593                                 psecnetwork->Configuration.Length);
594         psecnetwork->InfrastructureMode = cpu_to_le32(
595                                 psecnetwork->InfrastructureMode);
596         psecnetwork->IELength = cpu_to_le32(psecnetwork->IELength);
597 #endif
598         INIT_LIST_HEAD(&pcmd->list);
599         pcmd->cmdcode = _JoinBss_CMD_;
600         pcmd->parmbuf = (unsigned char *)psecnetwork;
601         pcmd->rsp = NULL;
602         pcmd->rspsz = 0;
603         r8712_enqueue_cmd(pcmdpriv, pcmd);
604         return _SUCCESS;
605 }
606
607 u8 r8712_disassoc_cmd(struct _adapter *padapter) /* for sta_mode */
608 {
609         struct cmd_obj *pdisconnect_cmd;
610         struct disconnect_parm *pdisconnect;
611         struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
612
613         pdisconnect_cmd = kmalloc(sizeof(*pdisconnect_cmd), GFP_ATOMIC);
614         if (pdisconnect_cmd == NULL)
615                 return _FAIL;
616         pdisconnect = kmalloc(sizeof(*pdisconnect), GFP_ATOMIC);
617         if (pdisconnect == NULL) {
618                 kfree(pdisconnect_cmd);
619                 return _FAIL;
620         }
621         init_h2fwcmd_w_parm_no_rsp(pdisconnect_cmd, pdisconnect,
622                                    _DisConnect_CMD_);
623         r8712_enqueue_cmd(pcmdpriv, pdisconnect_cmd);
624         return _SUCCESS;
625 }
626
627 u8 r8712_setopmode_cmd(struct _adapter *padapter,
628                  enum NDIS_802_11_NETWORK_INFRASTRUCTURE networktype)
629 {
630         struct cmd_obj *ph2c;
631         struct setopmode_parm *psetop;
632
633         struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
634
635         ph2c = kmalloc(sizeof(*ph2c), GFP_ATOMIC);
636         if (ph2c == NULL)
637                 return _FAIL;
638         psetop = kmalloc(sizeof(*psetop), GFP_ATOMIC);
639         if (psetop == NULL) {
640                 kfree(ph2c);
641                 return _FAIL;
642         }
643         init_h2fwcmd_w_parm_no_rsp(ph2c, psetop, _SetOpMode_CMD_);
644         psetop->mode = (u8)networktype;
645         r8712_enqueue_cmd(pcmdpriv, ph2c);
646         return _SUCCESS;
647 }
648
649 u8 r8712_setstakey_cmd(struct _adapter *padapter, u8 *psta, u8 unicast_key)
650 {
651         struct cmd_obj *ph2c;
652         struct set_stakey_parm *psetstakey_para;
653         struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
654         struct set_stakey_rsp *psetstakey_rsp = NULL;
655         struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
656         struct security_priv *psecuritypriv = &padapter->securitypriv;
657         struct sta_info *sta = (struct sta_info *)psta;
658
659         ph2c = kmalloc(sizeof(*ph2c), GFP_ATOMIC);
660         if (ph2c == NULL)
661                 return _FAIL;
662         psetstakey_para = kmalloc(sizeof(*psetstakey_para), GFP_ATOMIC);
663         if (psetstakey_para == NULL) {
664                 kfree(ph2c);
665                 return _FAIL;
666         }
667         psetstakey_rsp = kmalloc(sizeof(*psetstakey_rsp), GFP_ATOMIC);
668         if (psetstakey_rsp == NULL) {
669                 kfree(ph2c);
670                 kfree(psetstakey_para);
671                 return _FAIL;
672         }
673         init_h2fwcmd_w_parm_no_rsp(ph2c, psetstakey_para, _SetStaKey_CMD_);
674         ph2c->rsp = (u8 *) psetstakey_rsp;
675         ph2c->rspsz = sizeof(struct set_stakey_rsp);
676         ether_addr_copy(psetstakey_para->addr, sta->hwaddr);
677         if (check_fwstate(pmlmepriv, WIFI_STATION_STATE))
678                 psetstakey_para->algorithm = (unsigned char)
679                                             psecuritypriv->PrivacyAlgrthm;
680         else
681                 GET_ENCRY_ALGO(psecuritypriv, sta,
682                                psetstakey_para->algorithm, false);
683         if (unicast_key)
684                 memcpy(&psetstakey_para->key, &sta->x_UncstKey, 16);
685         else
686                 memcpy(&psetstakey_para->key,
687                         &psecuritypriv->XGrpKey[
688                         psecuritypriv->XGrpKeyid - 1]. skey, 16);
689         r8712_enqueue_cmd(pcmdpriv, ph2c);
690         return _SUCCESS;
691 }
692
693 u8 r8712_setrfintfs_cmd(struct _adapter *padapter, u8 mode)
694 {
695         struct cmd_obj *ph2c;
696         struct setrfintfs_parm *psetrfintfsparm;
697         struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
698
699         ph2c = kmalloc(sizeof(*ph2c), GFP_ATOMIC);
700         if (ph2c == NULL)
701                 return _FAIL;
702         psetrfintfsparm = kmalloc(sizeof(*psetrfintfsparm), GFP_ATOMIC);
703         if (psetrfintfsparm == NULL) {
704                 kfree(ph2c);
705                 return _FAIL;
706         }
707         init_h2fwcmd_w_parm_no_rsp(ph2c, psetrfintfsparm,
708                                    GEN_CMD_CODE(_SetRFIntFs));
709         psetrfintfsparm->rfintfs = mode;
710         r8712_enqueue_cmd(pcmdpriv, ph2c);
711         return _SUCCESS;
712 }
713
714 u8 r8712_setrttbl_cmd(struct _adapter *padapter,
715                       struct setratable_parm *prate_table)
716 {
717         struct cmd_obj *ph2c;
718         struct setratable_parm *psetrttblparm;
719         struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
720
721         ph2c = kmalloc(sizeof(*ph2c), GFP_ATOMIC);
722         if (ph2c == NULL)
723                 return _FAIL;
724         psetrttblparm = kmalloc(sizeof(*psetrttblparm), GFP_ATOMIC);
725         if (psetrttblparm == NULL) {
726                 kfree(ph2c);
727                 return _FAIL;
728         }
729         init_h2fwcmd_w_parm_no_rsp(ph2c, psetrttblparm,
730                                    GEN_CMD_CODE(_SetRaTable));
731         memcpy(psetrttblparm, prate_table, sizeof(struct setratable_parm));
732         r8712_enqueue_cmd(pcmdpriv, ph2c);
733         return _SUCCESS;
734 }
735
736 u8 r8712_gettssi_cmd(struct _adapter *padapter, u8 offset, u8 *pval)
737 {
738         struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
739         struct cmd_obj *ph2c;
740         struct readTSSI_parm *prdtssiparm;
741
742         ph2c = kmalloc(sizeof(*ph2c), GFP_ATOMIC);
743         if (ph2c == NULL)
744                 return _FAIL;
745         prdtssiparm = kmalloc(sizeof(*prdtssiparm), GFP_ATOMIC);
746         if (prdtssiparm == NULL) {
747                 kfree(ph2c);
748                 return _FAIL;
749         }
750         INIT_LIST_HEAD(&ph2c->list);
751         ph2c->cmdcode = GEN_CMD_CODE(_ReadTSSI);
752         ph2c->parmbuf = (unsigned char *)prdtssiparm;
753         ph2c->cmdsz = sizeof(struct readTSSI_parm);
754         ph2c->rsp = pval;
755         ph2c->rspsz = sizeof(struct readTSSI_rsp);
756
757         prdtssiparm->offset = offset;
758         r8712_enqueue_cmd(pcmdpriv, ph2c);
759         return _SUCCESS;
760 }
761
762 u8 r8712_setMacAddr_cmd(struct _adapter *padapter, u8 *mac_addr)
763 {
764         struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
765         struct cmd_obj *ph2c;
766         struct SetMacAddr_param *psetMacAddr_para;
767
768         ph2c = kmalloc(sizeof(*ph2c), GFP_ATOMIC);
769         if (ph2c == NULL)
770                 return _FAIL;
771         psetMacAddr_para = kmalloc(sizeof(*psetMacAddr_para), GFP_ATOMIC);
772         if (psetMacAddr_para == NULL) {
773                 kfree(ph2c);
774                 return _FAIL;
775         }
776         init_h2fwcmd_w_parm_no_rsp(ph2c, psetMacAddr_para,
777                                    _SetMacAddress_CMD_);
778         ether_addr_copy(psetMacAddr_para->MacAddr, mac_addr);
779         r8712_enqueue_cmd(pcmdpriv, ph2c);
780         return _SUCCESS;
781 }
782
783 u8 r8712_setassocsta_cmd(struct _adapter *padapter, u8 *mac_addr)
784 {
785         struct cmd_priv                 *pcmdpriv = &padapter->cmdpriv;
786         struct cmd_obj                  *ph2c;
787         struct set_assocsta_parm        *psetassocsta_para;
788         struct set_assocsta_rsp         *psetassocsta_rsp = NULL;
789
790         ph2c = kmalloc(sizeof(*ph2c), GFP_ATOMIC);
791         if (ph2c == NULL)
792                 return _FAIL;
793         psetassocsta_para = kmalloc(sizeof(*psetassocsta_para), GFP_ATOMIC);
794         if (psetassocsta_para == NULL) {
795                 kfree(ph2c);
796                 return _FAIL;
797         }
798         psetassocsta_rsp = kmalloc(sizeof(*psetassocsta_rsp), GFP_ATOMIC);
799         if (psetassocsta_rsp == NULL) {
800                 kfree(ph2c);
801                 kfree(psetassocsta_para);
802                 return _FAIL;
803         }
804         init_h2fwcmd_w_parm_no_rsp(ph2c, psetassocsta_para, _SetAssocSta_CMD_);
805         ph2c->rsp = (u8 *) psetassocsta_rsp;
806         ph2c->rspsz = sizeof(struct set_assocsta_rsp);
807         ether_addr_copy(psetassocsta_para->addr, mac_addr);
808         r8712_enqueue_cmd(pcmdpriv, ph2c);
809         return _SUCCESS;
810 }
811
812 u8 r8712_addbareq_cmd(struct _adapter *padapter, u8 tid)
813 {
814         struct cmd_priv         *pcmdpriv = &padapter->cmdpriv;
815         struct cmd_obj          *ph2c;
816         struct addBaReq_parm    *paddbareq_parm;
817
818         ph2c = kmalloc(sizeof(*ph2c), GFP_ATOMIC);
819         if (ph2c == NULL)
820                 return _FAIL;
821         paddbareq_parm = kmalloc(sizeof(*paddbareq_parm), GFP_ATOMIC);
822         if (paddbareq_parm == NULL) {
823                 kfree(ph2c);
824                 return _FAIL;
825         }
826         paddbareq_parm->tid = tid;
827         init_h2fwcmd_w_parm_no_rsp(ph2c, paddbareq_parm,
828                                    GEN_CMD_CODE(_AddBAReq));
829         r8712_enqueue_cmd_ex(pcmdpriv, ph2c);
830         return _SUCCESS;
831 }
832
833 u8 r8712_wdg_wk_cmd(struct _adapter *padapter)
834 {
835         struct cmd_obj *ph2c;
836         struct drvint_cmd_parm  *pdrvintcmd_param;
837         struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
838
839         ph2c = kmalloc(sizeof(*ph2c), GFP_ATOMIC);
840         if (ph2c == NULL)
841                 return _FAIL;
842         pdrvintcmd_param = kmalloc(sizeof(*pdrvintcmd_param), GFP_ATOMIC);
843         if (pdrvintcmd_param == NULL) {
844                 kfree(ph2c);
845                 return _FAIL;
846         }
847         pdrvintcmd_param->i_cid = WDG_WK_CID;
848         pdrvintcmd_param->sz = 0;
849         pdrvintcmd_param->pbuf = NULL;
850         init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvintcmd_param, _DRV_INT_CMD_);
851         r8712_enqueue_cmd_ex(pcmdpriv, ph2c);
852         return _SUCCESS;
853 }
854
855 void r8712_survey_cmd_callback(struct _adapter *padapter, struct cmd_obj *pcmd)
856 {
857         struct  mlme_priv *pmlmepriv = &padapter->mlmepriv;
858
859         if (pcmd->res != H2C_SUCCESS)
860                 clr_fwstate(pmlmepriv, _FW_UNDER_SURVEY);
861         r8712_free_cmd_obj(pcmd);
862 }
863
864 void r8712_disassoc_cmd_callback(struct _adapter *padapter,
865                                  struct cmd_obj *pcmd)
866 {
867         unsigned long irqL;
868         struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
869
870         if (pcmd->res != H2C_SUCCESS) {
871                 spin_lock_irqsave(&pmlmepriv->lock, irqL);
872                 set_fwstate(pmlmepriv, _FW_LINKED);
873                 spin_unlock_irqrestore(&pmlmepriv->lock, irqL);
874                 return;
875         }
876         r8712_free_cmd_obj(pcmd);
877 }
878
879 void r8712_joinbss_cmd_callback(struct _adapter *padapter, struct cmd_obj *pcmd)
880 {
881         struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
882
883         if (pcmd->res != H2C_SUCCESS)
884                 mod_timer(&pmlmepriv->assoc_timer,
885                           jiffies + msecs_to_jiffies(1));
886         r8712_free_cmd_obj(pcmd);
887 }
888
889 void r8712_createbss_cmd_callback(struct _adapter *padapter,
890                                   struct cmd_obj *pcmd)
891 {
892         unsigned long irqL;
893         struct sta_info *psta = NULL;
894         struct wlan_network *pwlan = NULL;
895         struct  mlme_priv *pmlmepriv = &padapter->mlmepriv;
896         struct wlan_bssid_ex *pnetwork = (struct wlan_bssid_ex *)pcmd->parmbuf;
897         struct wlan_network *tgt_network = &(pmlmepriv->cur_network);
898
899         if (pcmd->res != H2C_SUCCESS)
900                 mod_timer(&pmlmepriv->assoc_timer,
901                           jiffies + msecs_to_jiffies(1));
902         del_timer(&pmlmepriv->assoc_timer);
903 #ifdef __BIG_ENDIAN
904         /* endian_convert */
905         pnetwork->Length = le32_to_cpu(pnetwork->Length);
906         pnetwork->Ssid.SsidLength = le32_to_cpu(pnetwork->Ssid.SsidLength);
907         pnetwork->Privacy = le32_to_cpu(pnetwork->Privacy);
908         pnetwork->Rssi = le32_to_cpu(pnetwork->Rssi);
909         pnetwork->NetworkTypeInUse = le32_to_cpu(pnetwork->NetworkTypeInUse);
910         pnetwork->Configuration.ATIMWindow = le32_to_cpu(pnetwork->
911                                         Configuration.ATIMWindow);
912         pnetwork->Configuration.DSConfig = le32_to_cpu(pnetwork->
913                                         Configuration.DSConfig);
914         pnetwork->Configuration.FHConfig.DwellTime = le32_to_cpu(pnetwork->
915                                         Configuration.FHConfig.DwellTime);
916         pnetwork->Configuration.FHConfig.HopPattern = le32_to_cpu(pnetwork->
917                                         Configuration.FHConfig.HopPattern);
918         pnetwork->Configuration.FHConfig.HopSet = le32_to_cpu(pnetwork->
919                                         Configuration.FHConfig.HopSet);
920         pnetwork->Configuration.FHConfig.Length = le32_to_cpu(pnetwork->
921                                         Configuration.FHConfig.Length);
922         pnetwork->Configuration.Length = le32_to_cpu(pnetwork->
923                                         Configuration.Length);
924         pnetwork->InfrastructureMode = le32_to_cpu(pnetwork->
925                                            InfrastructureMode);
926         pnetwork->IELength = le32_to_cpu(pnetwork->IELength);
927 #endif
928         spin_lock_irqsave(&pmlmepriv->lock, irqL);
929         if ((pmlmepriv->fw_state) & WIFI_AP_STATE) {
930                 psta = r8712_get_stainfo(&padapter->stapriv,
931                                          pnetwork->MacAddress);
932                 if (!psta) {
933                         psta = r8712_alloc_stainfo(&padapter->stapriv,
934                                                    pnetwork->MacAddress);
935                         if (psta == NULL)
936                                 goto createbss_cmd_fail;
937                 }
938                 r8712_indicate_connect(padapter);
939         } else {
940                 pwlan = _r8712_alloc_network(pmlmepriv);
941                 if (pwlan == NULL) {
942                         pwlan = r8712_get_oldest_wlan_network(
943                                 &pmlmepriv->scanned_queue);
944                         if (pwlan == NULL)
945                                 goto createbss_cmd_fail;
946                         pwlan->last_scanned = jiffies;
947                 } else
948                         list_add_tail(&(pwlan->list),
949                                          &pmlmepriv->scanned_queue.queue);
950                 pnetwork->Length = r8712_get_wlan_bssid_ex_sz(pnetwork);
951                 memcpy(&(pwlan->network), pnetwork, pnetwork->Length);
952                 pwlan->fixed = true;
953                 memcpy(&tgt_network->network, pnetwork,
954                         (r8712_get_wlan_bssid_ex_sz(pnetwork)));
955                 if (pmlmepriv->fw_state & _FW_UNDER_LINKING)
956                         pmlmepriv->fw_state ^= _FW_UNDER_LINKING;
957                 /* we will set _FW_LINKED when there is one more sat to
958                  * join us (stassoc_event_callback) */
959         }
960 createbss_cmd_fail:
961         spin_unlock_irqrestore(&pmlmepriv->lock, irqL);
962         r8712_free_cmd_obj(pcmd);
963 }
964
965 void r8712_setstaKey_cmdrsp_callback(struct _adapter *padapter,
966                                      struct cmd_obj *pcmd)
967 {
968         struct sta_priv *pstapriv = &padapter->stapriv;
969         struct set_stakey_rsp *psetstakey_rsp = (struct set_stakey_rsp *)
970                                                 (pcmd->rsp);
971         struct sta_info *psta = r8712_get_stainfo(pstapriv,
972                                                   psetstakey_rsp->addr);
973
974         if (psta == NULL)
975                 goto exit;
976         psta->aid = psta->mac_id = psetstakey_rsp->keyid; /*CAM_ID(CAM_ENTRY)*/
977 exit:
978         r8712_free_cmd_obj(pcmd);
979 }
980
981 void r8712_setassocsta_cmdrsp_callback(struct _adapter *padapter,
982                                        struct cmd_obj *pcmd)
983 {
984         unsigned long   irqL;
985         struct sta_priv *pstapriv = &padapter->stapriv;
986         struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
987         struct set_assocsta_parm *passocsta_parm =
988                                 (struct set_assocsta_parm *)(pcmd->parmbuf);
989         struct set_assocsta_rsp *passocsta_rsp =
990                                 (struct set_assocsta_rsp *) (pcmd->rsp);
991         struct sta_info *psta = r8712_get_stainfo(pstapriv,
992                                                   passocsta_parm->addr);
993
994         if (psta == NULL)
995                 return;
996         psta->aid = psta->mac_id = passocsta_rsp->cam_id;
997         spin_lock_irqsave(&pmlmepriv->lock, irqL);
998         if ((check_fwstate(pmlmepriv, WIFI_MP_STATE)) &&
999             (check_fwstate(pmlmepriv, _FW_UNDER_LINKING)))
1000                 pmlmepriv->fw_state ^= _FW_UNDER_LINKING;
1001         set_fwstate(pmlmepriv, _FW_LINKED);
1002         spin_unlock_irqrestore(&pmlmepriv->lock, irqL);
1003         r8712_free_cmd_obj(pcmd);
1004 }
1005
1006 u8 r8712_disconnectCtrlEx_cmd(struct _adapter *adapter, u32 enableDrvCtrl,
1007                         u32 tryPktCnt, u32 tryPktInterval, u32 firstStageTO)
1008 {
1009         struct cmd_obj *ph2c;
1010         struct DisconnectCtrlEx_param *param;
1011         struct cmd_priv *pcmdpriv = &adapter->cmdpriv;
1012
1013         ph2c = kmalloc(sizeof(*ph2c), GFP_ATOMIC);
1014         if (ph2c == NULL)
1015                 return _FAIL;
1016         param = kzalloc(sizeof(*param), GFP_ATOMIC);
1017         if (param == NULL) {
1018                 kfree(ph2c);
1019                 return _FAIL;
1020         }
1021
1022         param->EnableDrvCtrl = (unsigned char)enableDrvCtrl;
1023         param->TryPktCnt = (unsigned char)tryPktCnt;
1024         param->TryPktInterval = (unsigned char)tryPktInterval;
1025         param->FirstStageTO = (unsigned int)firstStageTO;
1026
1027         init_h2fwcmd_w_parm_no_rsp(ph2c, param,
1028                                 GEN_CMD_CODE(_DisconnectCtrlEx));
1029         r8712_enqueue_cmd(pcmdpriv, ph2c);
1030         return _SUCCESS;
1031 }