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