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