]> pilppa.org Git - linux-2.6-omap-h63xx.git/blob - drivers/net/wireless/libertas/cmd.c
[PATCH] libertas: monitor mode support for OLPC firmware
[linux-2.6-omap-h63xx.git] / drivers / net / wireless / libertas / cmd.c
1 /**
2   * This file contains the handling of command.
3   * It prepares command and sends it to firmware when it is ready.
4   */
5
6 #include <net/iw_handler.h>
7 #include "host.h"
8 #include "hostcmd.h"
9 #include "decl.h"
10 #include "defs.h"
11 #include "dev.h"
12 #include "join.h"
13 #include "wext.h"
14
15 static void cleanup_cmdnode(struct cmd_ctrl_node *ptempnode);
16
17 static u16 commands_allowed_in_ps[] = {
18         CMD_802_11_RSSI,
19 };
20
21 /**
22  *  @brief This function checks if the commans is allowed
23  *  in PS mode not.
24  *
25  *  @param command the command ID
26  *  @return        TRUE or FALSE
27  */
28 static u8 is_command_allowed_in_ps(__le16 command)
29 {
30         int i;
31
32         for (i = 0; i < ARRAY_SIZE(commands_allowed_in_ps); i++) {
33                 if (command == cpu_to_le16(commands_allowed_in_ps[i]))
34                         return 1;
35         }
36
37         return 0;
38 }
39
40 static int wlan_cmd_hw_spec(wlan_private * priv, struct cmd_ds_command *cmd)
41 {
42         struct cmd_ds_get_hw_spec *hwspec = &cmd->params.hwspec;
43
44         lbs_deb_enter(LBS_DEB_CMD);
45
46         cmd->command = cpu_to_le16(CMD_GET_HW_SPEC);
47         cmd->size = cpu_to_le16(sizeof(struct cmd_ds_get_hw_spec) + S_DS_GEN);
48         memcpy(hwspec->permanentaddr, priv->adapter->current_addr, ETH_ALEN);
49
50         lbs_deb_leave(LBS_DEB_CMD);
51         return 0;
52 }
53
54 static int wlan_cmd_802_11_ps_mode(wlan_private * priv,
55                                    struct cmd_ds_command *cmd,
56                                    u16 cmd_action)
57 {
58         struct cmd_ds_802_11_ps_mode *psm = &cmd->params.psmode;
59
60         lbs_deb_enter(LBS_DEB_CMD);
61
62         cmd->command = cpu_to_le16(CMD_802_11_PS_MODE);
63         cmd->size = cpu_to_le16(sizeof(struct cmd_ds_802_11_ps_mode) +
64                                 S_DS_GEN);
65         psm->action = cpu_to_le16(cmd_action);
66         psm->multipledtim = 0;
67         switch (cmd_action) {
68         case CMD_SUBCMD_ENTER_PS:
69                 lbs_deb_cmd("PS command:" "SubCode- Enter PS\n");
70
71                 psm->locallisteninterval = 0;
72                 psm->nullpktinterval = 0;
73                 psm->multipledtim =
74                     cpu_to_le16(MRVDRV_DEFAULT_MULTIPLE_DTIM);
75                 break;
76
77         case CMD_SUBCMD_EXIT_PS:
78                 lbs_deb_cmd("PS command:" "SubCode- Exit PS\n");
79                 break;
80
81         case CMD_SUBCMD_SLEEP_CONFIRMED:
82                 lbs_deb_cmd("PS command: SubCode- sleep confirm\n");
83                 break;
84
85         default:
86                 break;
87         }
88
89         lbs_deb_leave(LBS_DEB_CMD);
90         return 0;
91 }
92
93 static int wlan_cmd_802_11_inactivity_timeout(wlan_private * priv,
94                                               struct cmd_ds_command *cmd,
95                                               u16 cmd_action, void *pdata_buf)
96 {
97         u16 *timeout = pdata_buf;
98
99         lbs_deb_enter(LBS_DEB_CMD);
100
101         cmd->command = cpu_to_le16(CMD_802_11_INACTIVITY_TIMEOUT);
102         cmd->size =
103             cpu_to_le16(sizeof(struct cmd_ds_802_11_inactivity_timeout)
104                              + S_DS_GEN);
105
106         cmd->params.inactivity_timeout.action = cpu_to_le16(cmd_action);
107
108         if (cmd_action)
109                 cmd->params.inactivity_timeout.timeout = cpu_to_le16(*timeout);
110         else
111                 cmd->params.inactivity_timeout.timeout = 0;
112
113         lbs_deb_leave(LBS_DEB_CMD);
114         return 0;
115 }
116
117 static int wlan_cmd_802_11_sleep_params(wlan_private * priv,
118                                         struct cmd_ds_command *cmd,
119                                         u16 cmd_action)
120 {
121         wlan_adapter *adapter = priv->adapter;
122         struct cmd_ds_802_11_sleep_params *sp = &cmd->params.sleep_params;
123
124         lbs_deb_enter(LBS_DEB_CMD);
125
126         cmd->size = cpu_to_le16((sizeof(struct cmd_ds_802_11_sleep_params)) +
127                                 S_DS_GEN);
128         cmd->command = cpu_to_le16(CMD_802_11_SLEEP_PARAMS);
129
130         if (cmd_action == CMD_ACT_GET) {
131                 memset(&adapter->sp, 0, sizeof(struct sleep_params));
132                 memset(sp, 0, sizeof(struct cmd_ds_802_11_sleep_params));
133                 sp->action = cpu_to_le16(cmd_action);
134         } else if (cmd_action == CMD_ACT_SET) {
135                 sp->action = cpu_to_le16(cmd_action);
136                 sp->error = cpu_to_le16(adapter->sp.sp_error);
137                 sp->offset = cpu_to_le16(adapter->sp.sp_offset);
138                 sp->stabletime = cpu_to_le16(adapter->sp.sp_stabletime);
139                 sp->calcontrol = (u8) adapter->sp.sp_calcontrol;
140                 sp->externalsleepclk = (u8) adapter->sp.sp_extsleepclk;
141                 sp->reserved = cpu_to_le16(adapter->sp.sp_reserved);
142         }
143
144         lbs_deb_leave(LBS_DEB_CMD);
145         return 0;
146 }
147
148 static int wlan_cmd_802_11_set_wep(wlan_private * priv,
149                                    struct cmd_ds_command *cmd,
150                                    u32 cmd_act,
151                                    void * pdata_buf)
152 {
153         struct cmd_ds_802_11_set_wep *wep = &cmd->params.wep;
154         wlan_adapter *adapter = priv->adapter;
155         int ret = 0;
156         struct assoc_request * assoc_req = pdata_buf;
157
158         lbs_deb_enter(LBS_DEB_CMD);
159
160         cmd->command = cpu_to_le16(CMD_802_11_SET_WEP);
161         cmd->size = cpu_to_le16(sizeof(*wep) + S_DS_GEN);
162
163         if (cmd_act == CMD_ACT_ADD) {
164                 int i;
165
166                 if (!assoc_req) {
167                         lbs_deb_cmd("Invalid association request!");
168                         ret = -1;
169                         goto done;
170                 }
171
172                 wep->action = cpu_to_le16(CMD_ACT_ADD);
173
174                 /* default tx key index */
175                 wep->keyindex = cpu_to_le16((u16)(assoc_req->wep_tx_keyidx &
176                                                   (u32)CMD_WEP_KEY_INDEX_MASK));
177
178                 /* Copy key types and material to host command structure */
179                 for (i = 0; i < 4; i++) {
180                         struct enc_key * pkey = &assoc_req->wep_keys[i];
181
182                         switch (pkey->len) {
183                         case KEY_LEN_WEP_40:
184                                 wep->keytype[i] =
185                                         cpu_to_le16(CMD_TYPE_WEP_40_BIT);
186                                 memmove(&wep->keymaterial[i], pkey->key,
187                                         pkey->len);
188                                 lbs_deb_cmd("SET_WEP: add key %d (40 bit)\n", i);
189                                 break;
190                         case KEY_LEN_WEP_104:
191                                 wep->keytype[i] =
192                                         cpu_to_le16(CMD_TYPE_WEP_104_BIT);
193                                 memmove(&wep->keymaterial[i], pkey->key,
194                                         pkey->len);
195                                 lbs_deb_cmd("SET_WEP: add key %d (104 bit)\n", i);
196                                 break;
197                         case 0:
198                                 break;
199                         default:
200                                 lbs_deb_cmd("SET_WEP: invalid key %d, length %d\n",
201                                        i, pkey->len);
202                                 ret = -1;
203                                 goto done;
204                                 break;
205                         }
206                 }
207         } else if (cmd_act == CMD_ACT_REMOVE) {
208                 /* ACT_REMOVE clears _all_ WEP keys */
209                 wep->action = cpu_to_le16(CMD_ACT_REMOVE);
210
211                 /* default tx key index */
212                 wep->keyindex = cpu_to_le16((u16)(adapter->wep_tx_keyidx &
213                                                   (u32)CMD_WEP_KEY_INDEX_MASK));
214                 lbs_deb_cmd("SET_WEP: remove key %d\n", adapter->wep_tx_keyidx);
215         }
216
217         ret = 0;
218
219 done:
220         lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
221         return ret;
222 }
223
224 static int wlan_cmd_802_11_enable_rsn(wlan_private * priv,
225                                       struct cmd_ds_command *cmd,
226                                       u16 cmd_action,
227                                       void * pdata_buf)
228 {
229         struct cmd_ds_802_11_enable_rsn *penableRSN = &cmd->params.enbrsn;
230         u32 * enable = pdata_buf;
231
232         lbs_deb_enter(LBS_DEB_CMD);
233
234         cmd->command = cpu_to_le16(CMD_802_11_ENABLE_RSN);
235         cmd->size = cpu_to_le16(sizeof(*penableRSN) + S_DS_GEN);
236         penableRSN->action = cpu_to_le16(cmd_action);
237
238         if (cmd_action == CMD_ACT_SET) {
239                 if (*enable)
240                         penableRSN->enable = cpu_to_le16(CMD_ENABLE_RSN);
241                 else
242                         penableRSN->enable = cpu_to_le16(CMD_DISABLE_RSN);
243                 lbs_deb_cmd("ENABLE_RSN: %d\n", *enable);
244         }
245
246         lbs_deb_leave(LBS_DEB_CMD);
247         return 0;
248 }
249
250
251 static void set_one_wpa_key(struct MrvlIEtype_keyParamSet * pkeyparamset,
252                             struct enc_key * pkey)
253 {
254         lbs_deb_enter(LBS_DEB_CMD);
255
256         if (pkey->flags & KEY_INFO_WPA_ENABLED) {
257                 pkeyparamset->keyinfo |= cpu_to_le16(KEY_INFO_WPA_ENABLED);
258         }
259         if (pkey->flags & KEY_INFO_WPA_UNICAST) {
260                 pkeyparamset->keyinfo |= cpu_to_le16(KEY_INFO_WPA_UNICAST);
261         }
262         if (pkey->flags & KEY_INFO_WPA_MCAST) {
263                 pkeyparamset->keyinfo |= cpu_to_le16(KEY_INFO_WPA_MCAST);
264         }
265
266         pkeyparamset->type = cpu_to_le16(TLV_TYPE_KEY_MATERIAL);
267         pkeyparamset->keytypeid = cpu_to_le16(pkey->type);
268         pkeyparamset->keylen = cpu_to_le16(pkey->len);
269         memcpy(pkeyparamset->key, pkey->key, pkey->len);
270         pkeyparamset->length = cpu_to_le16(  sizeof(pkeyparamset->keytypeid)
271                                                 + sizeof(pkeyparamset->keyinfo)
272                                                 + sizeof(pkeyparamset->keylen)
273                                                 + sizeof(pkeyparamset->key));
274         lbs_deb_leave(LBS_DEB_CMD);
275 }
276
277 static int wlan_cmd_802_11_key_material(wlan_private * priv,
278                                         struct cmd_ds_command *cmd,
279                                         u16 cmd_action,
280                                         u32 cmd_oid, void *pdata_buf)
281 {
282         struct cmd_ds_802_11_key_material *pkeymaterial =
283             &cmd->params.keymaterial;
284         struct assoc_request * assoc_req = pdata_buf;
285         int ret = 0;
286         int index = 0;
287
288         lbs_deb_enter(LBS_DEB_CMD);
289
290         cmd->command = cpu_to_le16(CMD_802_11_KEY_MATERIAL);
291         pkeymaterial->action = cpu_to_le16(cmd_action);
292
293         if (cmd_action == CMD_ACT_GET) {
294                 cmd->size = cpu_to_le16(S_DS_GEN + sizeof (pkeymaterial->action));
295                 ret = 0;
296                 goto done;
297         }
298
299         memset(&pkeymaterial->keyParamSet, 0, sizeof(pkeymaterial->keyParamSet));
300
301         if (test_bit(ASSOC_FLAG_WPA_UCAST_KEY, &assoc_req->flags)) {
302                 set_one_wpa_key(&pkeymaterial->keyParamSet[index],
303                                 &assoc_req->wpa_unicast_key);
304                 index++;
305         }
306
307         if (test_bit(ASSOC_FLAG_WPA_MCAST_KEY, &assoc_req->flags)) {
308                 set_one_wpa_key(&pkeymaterial->keyParamSet[index],
309                                 &assoc_req->wpa_mcast_key);
310                 index++;
311         }
312
313         cmd->size = cpu_to_le16(  S_DS_GEN
314                                 + sizeof (pkeymaterial->action)
315                                 + (index * sizeof(struct MrvlIEtype_keyParamSet)));
316
317         ret = 0;
318
319 done:
320         lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
321         return ret;
322 }
323
324 static int wlan_cmd_802_11_reset(wlan_private * priv,
325                                  struct cmd_ds_command *cmd, int cmd_action)
326 {
327         struct cmd_ds_802_11_reset *reset = &cmd->params.reset;
328
329         lbs_deb_enter(LBS_DEB_CMD);
330
331         cmd->command = cpu_to_le16(CMD_802_11_RESET);
332         cmd->size = cpu_to_le16(sizeof(struct cmd_ds_802_11_reset) + S_DS_GEN);
333         reset->action = cpu_to_le16(cmd_action);
334
335         lbs_deb_leave(LBS_DEB_CMD);
336         return 0;
337 }
338
339 static int wlan_cmd_802_11_get_log(wlan_private * priv,
340                                    struct cmd_ds_command *cmd)
341 {
342         lbs_deb_enter(LBS_DEB_CMD);
343         cmd->command = cpu_to_le16(CMD_802_11_GET_LOG);
344         cmd->size =
345                 cpu_to_le16(sizeof(struct cmd_ds_802_11_get_log) + S_DS_GEN);
346
347         lbs_deb_leave(LBS_DEB_CMD);
348         return 0;
349 }
350
351 static int wlan_cmd_802_11_get_stat(wlan_private * priv,
352                                     struct cmd_ds_command *cmd)
353 {
354         lbs_deb_enter(LBS_DEB_CMD);
355         cmd->command = cpu_to_le16(CMD_802_11_GET_STAT);
356         cmd->size =
357             cpu_to_le16(sizeof(struct cmd_ds_802_11_get_stat) + S_DS_GEN);
358
359         lbs_deb_leave(LBS_DEB_CMD);
360         return 0;
361 }
362
363 static int wlan_cmd_802_11_snmp_mib(wlan_private * priv,
364                                     struct cmd_ds_command *cmd,
365                                     int cmd_action,
366                                     int cmd_oid, void *pdata_buf)
367 {
368         struct cmd_ds_802_11_snmp_mib *pSNMPMIB = &cmd->params.smib;
369         wlan_adapter *adapter = priv->adapter;
370         u8 ucTemp;
371
372         lbs_deb_enter(LBS_DEB_CMD);
373
374         lbs_deb_cmd("SNMP_CMD: cmd_oid = 0x%x\n", cmd_oid);
375
376         cmd->command = cpu_to_le16(CMD_802_11_SNMP_MIB);
377         cmd->size = cpu_to_le16(sizeof(*pSNMPMIB) + S_DS_GEN);
378
379         switch (cmd_oid) {
380         case OID_802_11_INFRASTRUCTURE_MODE:
381         {
382                 u8 mode = (u8) (size_t) pdata_buf;
383                 pSNMPMIB->querytype = cpu_to_le16(CMD_ACT_SET);
384                 pSNMPMIB->oid = cpu_to_le16((u16) DESIRED_BSSTYPE_I);
385                 pSNMPMIB->bufsize = sizeof(u8);
386                 if (mode == IW_MODE_ADHOC) {
387                         ucTemp = SNMP_MIB_VALUE_ADHOC;
388                 } else {
389                         /* Infra and Auto modes */
390                         ucTemp = SNMP_MIB_VALUE_INFRA;
391                 }
392
393                 memmove(pSNMPMIB->value, &ucTemp, sizeof(u8));
394
395                 break;
396         }
397
398         case OID_802_11D_ENABLE:
399                 {
400                         u32 ulTemp;
401
402                         pSNMPMIB->oid = cpu_to_le16((u16) DOT11D_I);
403
404                         if (cmd_action == CMD_ACT_SET) {
405                                 pSNMPMIB->querytype = CMD_ACT_SET;
406                                 pSNMPMIB->bufsize = sizeof(u16);
407                                 ulTemp = *(u32 *)pdata_buf;
408                                 *((__le16 *)(pSNMPMIB->value)) =
409                                     cpu_to_le16((u16) ulTemp);
410                         }
411                         break;
412                 }
413
414         case OID_802_11_FRAGMENTATION_THRESHOLD:
415                 {
416                         u32 ulTemp;
417
418                         pSNMPMIB->oid = cpu_to_le16((u16) FRAGTHRESH_I);
419
420                         if (cmd_action == CMD_ACT_GET) {
421                                 pSNMPMIB->querytype = cpu_to_le16(CMD_ACT_GET);
422                         } else if (cmd_action == CMD_ACT_SET) {
423                                 pSNMPMIB->querytype = cpu_to_le16(CMD_ACT_SET);
424                                 pSNMPMIB->bufsize = cpu_to_le16(sizeof(u16));
425                                 ulTemp = *((u32 *) pdata_buf);
426                                 *((__le16 *)(pSNMPMIB->value)) =
427                                     cpu_to_le16((u16) ulTemp);
428
429                         }
430
431                         break;
432                 }
433
434         case OID_802_11_RTS_THRESHOLD:
435                 {
436
437                         u32 ulTemp;
438                         pSNMPMIB->oid = le16_to_cpu((u16) RTSTHRESH_I);
439
440                         if (cmd_action == CMD_ACT_GET) {
441                                 pSNMPMIB->querytype = cpu_to_le16(CMD_ACT_GET);
442                         } else if (cmd_action == CMD_ACT_SET) {
443                                 pSNMPMIB->querytype = cpu_to_le16(CMD_ACT_SET);
444                                 pSNMPMIB->bufsize = cpu_to_le16(sizeof(u16));
445                                 ulTemp = *((u32 *)pdata_buf);
446                                 *(__le16 *)(pSNMPMIB->value) =
447                                     cpu_to_le16((u16) ulTemp);
448
449                         }
450                         break;
451                 }
452         case OID_802_11_TX_RETRYCOUNT:
453                 pSNMPMIB->oid = cpu_to_le16((u16) SHORT_RETRYLIM_I);
454
455                 if (cmd_action == CMD_ACT_GET) {
456                         pSNMPMIB->querytype = cpu_to_le16(CMD_ACT_GET);
457                 } else if (cmd_action == CMD_ACT_SET) {
458                         pSNMPMIB->querytype = cpu_to_le16(CMD_ACT_SET);
459                         pSNMPMIB->bufsize = cpu_to_le16(sizeof(u16));
460                         *((__le16 *)(pSNMPMIB->value)) =
461                             cpu_to_le16((u16) adapter->txretrycount);
462                 }
463
464                 break;
465         default:
466                 break;
467         }
468
469         lbs_deb_cmd(
470                "SNMP_CMD: command=0x%x, size=0x%x, seqnum=0x%x, result=0x%x\n",
471                le16_to_cpu(cmd->command), le16_to_cpu(cmd->size),
472                le16_to_cpu(cmd->seqnum), le16_to_cpu(cmd->result));
473
474         lbs_deb_cmd(
475                "SNMP_CMD: action 0x%x, oid 0x%x, oidsize 0x%x, value 0x%x\n",
476                le16_to_cpu(pSNMPMIB->querytype), le16_to_cpu(pSNMPMIB->oid),
477                le16_to_cpu(pSNMPMIB->bufsize),
478                le16_to_cpu(*(__le16 *) pSNMPMIB->value));
479
480         lbs_deb_leave(LBS_DEB_CMD);
481         return 0;
482 }
483
484 static int wlan_cmd_802_11_radio_control(wlan_private * priv,
485                                          struct cmd_ds_command *cmd,
486                                          int cmd_action)
487 {
488         wlan_adapter *adapter = priv->adapter;
489         struct cmd_ds_802_11_radio_control *pradiocontrol = &cmd->params.radio;
490
491         lbs_deb_enter(LBS_DEB_CMD);
492
493         cmd->size =
494             cpu_to_le16((sizeof(struct cmd_ds_802_11_radio_control)) +
495                              S_DS_GEN);
496         cmd->command = cpu_to_le16(CMD_802_11_RADIO_CONTROL);
497
498         pradiocontrol->action = cpu_to_le16(cmd_action);
499
500         switch (adapter->preamble) {
501         case CMD_TYPE_SHORT_PREAMBLE:
502                 pradiocontrol->control = cpu_to_le16(SET_SHORT_PREAMBLE);
503                 break;
504
505         case CMD_TYPE_LONG_PREAMBLE:
506                 pradiocontrol->control = cpu_to_le16(SET_LONG_PREAMBLE);
507                 break;
508
509         case CMD_TYPE_AUTO_PREAMBLE:
510         default:
511                 pradiocontrol->control = cpu_to_le16(SET_AUTO_PREAMBLE);
512                 break;
513         }
514
515         if (adapter->radioon)
516                 pradiocontrol->control |= cpu_to_le16(TURN_ON_RF);
517         else
518                 pradiocontrol->control &= cpu_to_le16(~TURN_ON_RF);
519
520         lbs_deb_leave(LBS_DEB_CMD);
521         return 0;
522 }
523
524 static int wlan_cmd_802_11_rf_tx_power(wlan_private * priv,
525                                        struct cmd_ds_command *cmd,
526                                        u16 cmd_action, void *pdata_buf)
527 {
528
529         struct cmd_ds_802_11_rf_tx_power *prtp = &cmd->params.txp;
530
531         lbs_deb_enter(LBS_DEB_CMD);
532
533         cmd->size =
534             cpu_to_le16((sizeof(struct cmd_ds_802_11_rf_tx_power)) + S_DS_GEN);
535         cmd->command = cpu_to_le16(CMD_802_11_RF_TX_POWER);
536         prtp->action = cpu_to_le16(cmd_action);
537
538         lbs_deb_cmd("RF_TX_POWER_CMD: size:%d cmd:0x%x Act:%d\n",
539                     le16_to_cpu(cmd->size), le16_to_cpu(cmd->command),
540                     le16_to_cpu(prtp->action));
541
542         switch (cmd_action) {
543         case CMD_ACT_TX_POWER_OPT_GET:
544                 prtp->action = cpu_to_le16(CMD_ACT_GET);
545                 prtp->currentlevel = 0;
546                 break;
547
548         case CMD_ACT_TX_POWER_OPT_SET_HIGH:
549                 prtp->action = cpu_to_le16(CMD_ACT_SET);
550                 prtp->currentlevel = cpu_to_le16(CMD_ACT_TX_POWER_INDEX_HIGH);
551                 break;
552
553         case CMD_ACT_TX_POWER_OPT_SET_MID:
554                 prtp->action = cpu_to_le16(CMD_ACT_SET);
555                 prtp->currentlevel = cpu_to_le16(CMD_ACT_TX_POWER_INDEX_MID);
556                 break;
557
558         case CMD_ACT_TX_POWER_OPT_SET_LOW:
559                 prtp->action = cpu_to_le16(CMD_ACT_SET);
560                 prtp->currentlevel = cpu_to_le16(*((u16 *) pdata_buf));
561                 break;
562         }
563
564         lbs_deb_leave(LBS_DEB_CMD);
565         return 0;
566 }
567
568 static int wlan_cmd_802_11_monitor_mode(wlan_private * priv,
569                                       struct cmd_ds_command *cmd,
570                                       u16 cmd_action, void *pdata_buf)
571 {
572         struct cmd_ds_802_11_monitor_mode *monitor = &cmd->params.monitor;
573
574         cmd->command = cpu_to_le16(CMD_802_11_MONITOR_MODE);
575         cmd->size =
576             cpu_to_le16(sizeof(struct cmd_ds_802_11_monitor_mode) +
577                              S_DS_GEN);
578
579         monitor->action = cpu_to_le16(cmd_action);
580         if (cmd_action == CMD_ACT_SET) {
581                 monitor->mode =
582                     cpu_to_le16((u16) (*(u32 *) pdata_buf));
583         }
584
585         return 0;
586 }
587
588 static int wlan_cmd_802_11_rate_adapt_rateset(wlan_private * priv,
589                                               struct cmd_ds_command *cmd,
590                                               u16 cmd_action)
591 {
592         struct cmd_ds_802_11_rate_adapt_rateset
593         *rateadapt = &cmd->params.rateset;
594         wlan_adapter *adapter = priv->adapter;
595
596         lbs_deb_enter(LBS_DEB_CMD);
597         cmd->size =
598             cpu_to_le16(sizeof(struct cmd_ds_802_11_rate_adapt_rateset)
599                              + S_DS_GEN);
600         cmd->command = cpu_to_le16(CMD_802_11_RATE_ADAPT_RATESET);
601
602         rateadapt->action = cpu_to_le16(cmd_action);
603         rateadapt->enablehwauto = cpu_to_le16(adapter->enablehwauto);
604         rateadapt->bitmap = cpu_to_le16(adapter->ratebitmap);
605
606         lbs_deb_leave(LBS_DEB_CMD);
607         return 0;
608 }
609
610 static int wlan_cmd_802_11_data_rate(wlan_private * priv,
611                                      struct cmd_ds_command *cmd,
612                                      u16 cmd_action)
613 {
614         struct cmd_ds_802_11_data_rate *pdatarate = &cmd->params.drate;
615         wlan_adapter *adapter = priv->adapter;
616
617         lbs_deb_enter(LBS_DEB_CMD);
618
619         cmd->size = cpu_to_le16(sizeof(struct cmd_ds_802_11_data_rate) +
620                              S_DS_GEN);
621         cmd->command = cpu_to_le16(CMD_802_11_DATA_RATE);
622         memset(pdatarate, 0, sizeof(struct cmd_ds_802_11_data_rate));
623         pdatarate->action = cpu_to_le16(cmd_action);
624
625         if (cmd_action == CMD_ACT_SET_TX_FIX_RATE) {
626                 pdatarate->rates[0] = libertas_data_rate_to_fw_index(adapter->cur_rate);
627                 lbs_deb_cmd("DATA_RATE: set fixed 0x%02X\n",
628                        adapter->cur_rate);
629         } else if (cmd_action == CMD_ACT_SET_TX_AUTO) {
630                 lbs_deb_cmd("DATA_RATE: setting auto\n");
631         }
632
633         lbs_deb_leave(LBS_DEB_CMD);
634         return 0;
635 }
636
637 static int wlan_cmd_mac_multicast_adr(wlan_private * priv,
638                                       struct cmd_ds_command *cmd,
639                                       u16 cmd_action)
640 {
641         struct cmd_ds_mac_multicast_adr *pMCastAdr = &cmd->params.madr;
642         wlan_adapter *adapter = priv->adapter;
643
644         lbs_deb_enter(LBS_DEB_CMD);
645         cmd->size = cpu_to_le16(sizeof(struct cmd_ds_mac_multicast_adr) +
646                              S_DS_GEN);
647         cmd->command = cpu_to_le16(CMD_MAC_MULTICAST_ADR);
648
649         lbs_deb_cmd("MULTICAST_ADR: setting %d addresses\n", pMCastAdr->nr_of_adrs);
650         pMCastAdr->action = cpu_to_le16(cmd_action);
651         pMCastAdr->nr_of_adrs =
652             cpu_to_le16((u16) adapter->nr_of_multicastmacaddr);
653         memcpy(pMCastAdr->maclist, adapter->multicastlist,
654                adapter->nr_of_multicastmacaddr * ETH_ALEN);
655
656         lbs_deb_leave(LBS_DEB_CMD);
657         return 0;
658 }
659
660 static int wlan_cmd_802_11_rf_channel(wlan_private * priv,
661                                       struct cmd_ds_command *cmd,
662                                       int option, void *pdata_buf)
663 {
664         struct cmd_ds_802_11_rf_channel *rfchan = &cmd->params.rfchannel;
665
666         lbs_deb_enter(LBS_DEB_CMD);
667         cmd->command = cpu_to_le16(CMD_802_11_RF_CHANNEL);
668         cmd->size = cpu_to_le16(sizeof(struct cmd_ds_802_11_rf_channel) +
669                                 S_DS_GEN);
670
671         if (option == CMD_OPT_802_11_RF_CHANNEL_SET) {
672                 rfchan->currentchannel = cpu_to_le16(*((u16 *) pdata_buf));
673         }
674
675         rfchan->action = cpu_to_le16(option);
676
677         lbs_deb_leave(LBS_DEB_CMD);
678         return 0;
679 }
680
681 static int wlan_cmd_802_11_rssi(wlan_private * priv,
682                                 struct cmd_ds_command *cmd)
683 {
684         wlan_adapter *adapter = priv->adapter;
685
686         lbs_deb_enter(LBS_DEB_CMD);
687         cmd->command = cpu_to_le16(CMD_802_11_RSSI);
688         cmd->size = cpu_to_le16(sizeof(struct cmd_ds_802_11_rssi) + S_DS_GEN);
689         cmd->params.rssi.N = cpu_to_le16(DEFAULT_BCN_AVG_FACTOR);
690
691         /* reset Beacon SNR/NF/RSSI values */
692         adapter->SNR[TYPE_BEACON][TYPE_NOAVG] = 0;
693         adapter->SNR[TYPE_BEACON][TYPE_AVG] = 0;
694         adapter->NF[TYPE_BEACON][TYPE_NOAVG] = 0;
695         adapter->NF[TYPE_BEACON][TYPE_AVG] = 0;
696         adapter->RSSI[TYPE_BEACON][TYPE_NOAVG] = 0;
697         adapter->RSSI[TYPE_BEACON][TYPE_AVG] = 0;
698
699         lbs_deb_leave(LBS_DEB_CMD);
700         return 0;
701 }
702
703 static int wlan_cmd_reg_access(wlan_private * priv,
704                                struct cmd_ds_command *cmdptr,
705                                u8 cmd_action, void *pdata_buf)
706 {
707         struct wlan_offset_value *offval;
708
709         lbs_deb_enter(LBS_DEB_CMD);
710
711         offval = (struct wlan_offset_value *)pdata_buf;
712
713         switch (cmdptr->command) {
714         case CMD_MAC_REG_ACCESS:
715                 {
716                         struct cmd_ds_mac_reg_access *macreg;
717
718                         cmdptr->size =
719                             cpu_to_le16(sizeof (struct cmd_ds_mac_reg_access)
720                                         + S_DS_GEN);
721                         macreg =
722                             (struct cmd_ds_mac_reg_access *)&cmdptr->params.
723                             macreg;
724
725                         macreg->action = cpu_to_le16(cmd_action);
726                         macreg->offset = cpu_to_le16((u16) offval->offset);
727                         macreg->value = cpu_to_le32(offval->value);
728
729                         break;
730                 }
731
732         case CMD_BBP_REG_ACCESS:
733                 {
734                         struct cmd_ds_bbp_reg_access *bbpreg;
735
736                         cmdptr->size =
737                             cpu_to_le16(sizeof
738                                              (struct cmd_ds_bbp_reg_access)
739                                              + S_DS_GEN);
740                         bbpreg =
741                             (struct cmd_ds_bbp_reg_access *)&cmdptr->params.
742                             bbpreg;
743
744                         bbpreg->action = cpu_to_le16(cmd_action);
745                         bbpreg->offset = cpu_to_le16((u16) offval->offset);
746                         bbpreg->value = (u8) offval->value;
747
748                         break;
749                 }
750
751         case CMD_RF_REG_ACCESS:
752                 {
753                         struct cmd_ds_rf_reg_access *rfreg;
754
755                         cmdptr->size =
756                             cpu_to_le16(sizeof
757                                              (struct cmd_ds_rf_reg_access) +
758                                              S_DS_GEN);
759                         rfreg =
760                             (struct cmd_ds_rf_reg_access *)&cmdptr->params.
761                             rfreg;
762
763                         rfreg->action = cpu_to_le16(cmd_action);
764                         rfreg->offset = cpu_to_le16((u16) offval->offset);
765                         rfreg->value = (u8) offval->value;
766
767                         break;
768                 }
769
770         default:
771                 break;
772         }
773
774         lbs_deb_leave(LBS_DEB_CMD);
775         return 0;
776 }
777
778 static int wlan_cmd_802_11_mac_address(wlan_private * priv,
779                                        struct cmd_ds_command *cmd,
780                                        u16 cmd_action)
781 {
782         wlan_adapter *adapter = priv->adapter;
783
784         lbs_deb_enter(LBS_DEB_CMD);
785         cmd->command = cpu_to_le16(CMD_802_11_MAC_ADDRESS);
786         cmd->size = cpu_to_le16(sizeof(struct cmd_ds_802_11_mac_address) +
787                              S_DS_GEN);
788         cmd->result = 0;
789
790         cmd->params.macadd.action = cpu_to_le16(cmd_action);
791
792         if (cmd_action == CMD_ACT_SET) {
793                 memcpy(cmd->params.macadd.macadd,
794                        adapter->current_addr, ETH_ALEN);
795                 lbs_deb_hex(LBS_DEB_CMD, "SET_CMD: MAC addr", adapter->current_addr, 6);
796         }
797
798         lbs_deb_leave(LBS_DEB_CMD);
799         return 0;
800 }
801
802 static int wlan_cmd_802_11_eeprom_access(wlan_private * priv,
803                                          struct cmd_ds_command *cmd,
804                                          int cmd_action, void *pdata_buf)
805 {
806         struct wlan_ioctl_regrdwr *ea = pdata_buf;
807
808         lbs_deb_enter(LBS_DEB_CMD);
809
810         cmd->command = cpu_to_le16(CMD_802_11_EEPROM_ACCESS);
811         cmd->size = cpu_to_le16(sizeof(struct cmd_ds_802_11_eeprom_access) +
812                                 S_DS_GEN);
813         cmd->result = 0;
814
815         cmd->params.rdeeprom.action = cpu_to_le16(ea->action);
816         cmd->params.rdeeprom.offset = cpu_to_le16(ea->offset);
817         cmd->params.rdeeprom.bytecount = cpu_to_le16(ea->NOB);
818         cmd->params.rdeeprom.value = 0;
819
820         lbs_deb_leave(LBS_DEB_CMD);
821         return 0;
822 }
823
824 static int wlan_cmd_bt_access(wlan_private * priv,
825                                struct cmd_ds_command *cmd,
826                                u16 cmd_action, void *pdata_buf)
827 {
828         struct cmd_ds_bt_access *bt_access = &cmd->params.bt;
829         lbs_deb_enter_args(LBS_DEB_CMD, "action %d", cmd_action);
830
831         cmd->command = cpu_to_le16(CMD_BT_ACCESS);
832         cmd->size = cpu_to_le16(sizeof(struct cmd_ds_bt_access) + S_DS_GEN);
833         cmd->result = 0;
834         bt_access->action = cpu_to_le16(cmd_action);
835
836         switch (cmd_action) {
837         case CMD_ACT_BT_ACCESS_ADD:
838                 memcpy(bt_access->addr1, pdata_buf, 2 * ETH_ALEN);
839                 lbs_deb_hex(LBS_DEB_MESH, "BT_ADD: blinded MAC addr", bt_access->addr1, 6);
840                 break;
841         case CMD_ACT_BT_ACCESS_DEL:
842                 memcpy(bt_access->addr1, pdata_buf, 1 * ETH_ALEN);
843                 lbs_deb_hex(LBS_DEB_MESH, "BT_DEL: blinded MAC addr", bt_access->addr1, 6);
844                 break;
845         case CMD_ACT_BT_ACCESS_LIST:
846                 bt_access->id = cpu_to_le32(*(u32 *) pdata_buf);
847                 break;
848         case CMD_ACT_BT_ACCESS_RESET:
849                 break;
850         case CMD_ACT_BT_ACCESS_SET_INVERT:
851                 bt_access->id = cpu_to_le32(*(u32 *) pdata_buf);
852                 break;
853         case CMD_ACT_BT_ACCESS_GET_INVERT:
854                 break;
855         default:
856                 break;
857         }
858         lbs_deb_leave(LBS_DEB_CMD);
859         return 0;
860 }
861
862 static int wlan_cmd_fwt_access(wlan_private * priv,
863                                struct cmd_ds_command *cmd,
864                                u16 cmd_action, void *pdata_buf)
865 {
866         struct cmd_ds_fwt_access *fwt_access = &cmd->params.fwt;
867         lbs_deb_enter_args(LBS_DEB_CMD, "action %d", cmd_action);
868
869         cmd->command = cpu_to_le16(CMD_FWT_ACCESS);
870         cmd->size = cpu_to_le16(sizeof(struct cmd_ds_fwt_access) + S_DS_GEN);
871         cmd->result = 0;
872
873         if (pdata_buf)
874                 memcpy(fwt_access, pdata_buf, sizeof(*fwt_access));
875         else
876                 memset(fwt_access, 0, sizeof(*fwt_access));
877
878         fwt_access->action = cpu_to_le16(cmd_action);
879
880         lbs_deb_leave(LBS_DEB_CMD);
881         return 0;
882 }
883
884 static int wlan_cmd_mesh_access(wlan_private * priv,
885                                 struct cmd_ds_command *cmd,
886                                 u16 cmd_action, void *pdata_buf)
887 {
888         struct cmd_ds_mesh_access *mesh_access = &cmd->params.mesh;
889         lbs_deb_enter_args(LBS_DEB_CMD, "action %d", cmd_action);
890
891         cmd->command = cpu_to_le16(CMD_MESH_ACCESS);
892         cmd->size = cpu_to_le16(sizeof(struct cmd_ds_mesh_access) + S_DS_GEN);
893         cmd->result = 0;
894
895         if (pdata_buf)
896                 memcpy(mesh_access, pdata_buf, sizeof(*mesh_access));
897         else
898                 memset(mesh_access, 0, sizeof(*mesh_access));
899
900         mesh_access->action = cpu_to_le16(cmd_action);
901
902         lbs_deb_leave(LBS_DEB_CMD);
903         return 0;
904 }
905
906 void libertas_queue_cmd(wlan_adapter * adapter, struct cmd_ctrl_node *cmdnode, u8 addtail)
907 {
908         unsigned long flags;
909         struct cmd_ds_command *cmdptr;
910
911         lbs_deb_enter(LBS_DEB_HOST);
912
913         if (!cmdnode) {
914                 lbs_deb_host("QUEUE_CMD: cmdnode is NULL\n");
915                 goto done;
916         }
917
918         cmdptr = (struct cmd_ds_command *)cmdnode->bufvirtualaddr;
919         if (!cmdptr) {
920                 lbs_deb_host("QUEUE_CMD: cmdptr is NULL\n");
921                 goto done;
922         }
923
924         /* Exit_PS command needs to be queued in the header always. */
925         if (cmdptr->command == CMD_802_11_PS_MODE) {
926                 struct cmd_ds_802_11_ps_mode *psm = &cmdptr->params.psmode;
927                 if (psm->action == cpu_to_le16(CMD_SUBCMD_EXIT_PS)) {
928                         if (adapter->psstate != PS_STATE_FULL_POWER)
929                                 addtail = 0;
930                 }
931         }
932
933         spin_lock_irqsave(&adapter->driver_lock, flags);
934
935         if (addtail)
936                 list_add_tail((struct list_head *)cmdnode,
937                               &adapter->cmdpendingq);
938         else
939                 list_add((struct list_head *)cmdnode, &adapter->cmdpendingq);
940
941         spin_unlock_irqrestore(&adapter->driver_lock, flags);
942
943         lbs_deb_host("QUEUE_CMD: inserted command 0x%04x into cmdpendingq\n",
944                le16_to_cpu(((struct cmd_ds_gen*)cmdnode->bufvirtualaddr)->command));
945
946 done:
947         lbs_deb_leave(LBS_DEB_HOST);
948 }
949
950 /*
951  * TODO: Fix the issue when DownloadcommandToStation is being called the
952  * second time when the command times out. All the cmdptr->xxx are in little
953  * endian and therefore all the comparissions will fail.
954  * For now - we are not performing the endian conversion the second time - but
955  * for PS and DEEP_SLEEP we need to worry
956  */
957 static int DownloadcommandToStation(wlan_private * priv,
958                                     struct cmd_ctrl_node *cmdnode)
959 {
960         unsigned long flags;
961         struct cmd_ds_command *cmdptr;
962         wlan_adapter *adapter = priv->adapter;
963         int ret = 0;
964         u16 cmdsize;
965         u16 command;
966
967         lbs_deb_enter(LBS_DEB_HOST);
968
969         if (!adapter || !cmdnode) {
970                 lbs_deb_host("DNLD_CMD: adapter or cmdmode is NULL\n");
971                 if (cmdnode) {
972                         spin_lock_irqsave(&adapter->driver_lock, flags);
973                         __libertas_cleanup_and_insert_cmd(priv, cmdnode);
974                         spin_unlock_irqrestore(&adapter->driver_lock, flags);
975                 }
976                 ret = -1;
977                 goto done;
978         }
979
980         cmdptr = (struct cmd_ds_command *)cmdnode->bufvirtualaddr;
981
982         spin_lock_irqsave(&adapter->driver_lock, flags);
983         if (!cmdptr || !cmdptr->size) {
984                 lbs_deb_host("DNLD_CMD: cmdptr is NULL or zero\n");
985                 __libertas_cleanup_and_insert_cmd(priv, cmdnode);
986                 spin_unlock_irqrestore(&adapter->driver_lock, flags);
987                 ret = -1;
988                 goto done;
989         }
990
991         adapter->cur_cmd = cmdnode;
992         adapter->cur_cmd_retcode = 0;
993         spin_unlock_irqrestore(&adapter->driver_lock, flags);
994
995         cmdsize = cmdptr->size;
996         command = cpu_to_le16(cmdptr->command);
997
998         lbs_deb_host("DNLD_CMD: command 0x%04x, size %d, jiffies %lu\n",
999                     command, le16_to_cpu(cmdptr->size), jiffies);
1000         lbs_deb_hex(LBS_DEB_HOST, "DNLD_CMD", cmdnode->bufvirtualaddr, cmdsize);
1001
1002         cmdnode->cmdwaitqwoken = 0;
1003         cmdsize = cpu_to_le16(cmdsize);
1004
1005         ret = priv->hw_host_to_card(priv, MVMS_CMD, (u8 *) cmdptr, cmdsize);
1006
1007         if (ret != 0) {
1008                 lbs_deb_host("DNLD_CMD: hw_host_to_card failed\n");
1009                 spin_lock_irqsave(&adapter->driver_lock, flags);
1010                 __libertas_cleanup_and_insert_cmd(priv, adapter->cur_cmd);
1011                 adapter->cur_cmd = NULL;
1012                 spin_unlock_irqrestore(&adapter->driver_lock, flags);
1013                 ret = -1;
1014                 goto done;
1015         }
1016
1017         lbs_deb_cmd("DNLD_CMD: sent command 0x%04x, jiffies %lu\n", command, jiffies);
1018
1019         /* Setup the timer after transmit command */
1020         if (command == CMD_802_11_SCAN || command == CMD_802_11_AUTHENTICATE
1021             || command == CMD_802_11_ASSOCIATE)
1022                 mod_timer(&adapter->command_timer, jiffies + (10*HZ));
1023         else
1024                 mod_timer(&adapter->command_timer, jiffies + (5*HZ));
1025
1026         ret = 0;
1027
1028 done:
1029         lbs_deb_leave_args(LBS_DEB_HOST, "ret %d", ret);
1030         return ret;
1031 }
1032
1033 static int wlan_cmd_mac_control(wlan_private * priv,
1034                                 struct cmd_ds_command *cmd)
1035 {
1036         struct cmd_ds_mac_control *mac = &cmd->params.macctrl;
1037
1038         lbs_deb_enter(LBS_DEB_CMD);
1039
1040         cmd->command = cpu_to_le16(CMD_MAC_CONTROL);
1041         cmd->size = cpu_to_le16(sizeof(struct cmd_ds_mac_control) + S_DS_GEN);
1042         mac->action = cpu_to_le16(priv->adapter->currentpacketfilter);
1043
1044         lbs_deb_cmd("MAC_CONTROL: action 0x%x, size %d\n",
1045                     le16_to_cpu(mac->action), le16_to_cpu(cmd->size));
1046
1047         lbs_deb_leave(LBS_DEB_CMD);
1048         return 0;
1049 }
1050
1051 /**
1052  *  This function inserts command node to cmdfreeq
1053  *  after cleans it. Requires adapter->driver_lock held.
1054  */
1055 void __libertas_cleanup_and_insert_cmd(wlan_private * priv, struct cmd_ctrl_node *ptempcmd)
1056 {
1057         wlan_adapter *adapter = priv->adapter;
1058
1059         if (!ptempcmd)
1060                 return;
1061
1062         cleanup_cmdnode(ptempcmd);
1063         list_add_tail((struct list_head *)ptempcmd, &adapter->cmdfreeq);
1064 }
1065
1066 static void libertas_cleanup_and_insert_cmd(wlan_private * priv, struct cmd_ctrl_node *ptempcmd)
1067 {
1068         unsigned long flags;
1069
1070         spin_lock_irqsave(&priv->adapter->driver_lock, flags);
1071         __libertas_cleanup_and_insert_cmd(priv, ptempcmd);
1072         spin_unlock_irqrestore(&priv->adapter->driver_lock, flags);
1073 }
1074
1075 int libertas_set_radio_control(wlan_private * priv)
1076 {
1077         int ret = 0;
1078
1079         lbs_deb_enter(LBS_DEB_CMD);
1080
1081         ret = libertas_prepare_and_send_command(priv,
1082                                     CMD_802_11_RADIO_CONTROL,
1083                                     CMD_ACT_SET,
1084                                     CMD_OPTION_WAITFORRSP, 0, NULL);
1085
1086         lbs_deb_cmd("RADIO_SET: radio %d, preamble %d\n",
1087                priv->adapter->radioon, priv->adapter->preamble);
1088
1089         lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
1090         return ret;
1091 }
1092
1093 int libertas_set_mac_packet_filter(wlan_private * priv)
1094 {
1095         int ret = 0;
1096
1097         lbs_deb_enter(LBS_DEB_CMD);
1098
1099         /* Send MAC control command to station */
1100         ret = libertas_prepare_and_send_command(priv,
1101                                     CMD_MAC_CONTROL, 0, 0, 0, NULL);
1102
1103         lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
1104         return ret;
1105 }
1106
1107 /**
1108  *  @brief This function prepare the command before send to firmware.
1109  *
1110  *  @param priv         A pointer to wlan_private structure
1111  *  @param cmd_no       command number
1112  *  @param cmd_action   command action: GET or SET
1113  *  @param wait_option  wait option: wait response or not
1114  *  @param cmd_oid      cmd oid: treated as sub command
1115  *  @param pdata_buf    A pointer to informaion buffer
1116  *  @return             0 or -1
1117  */
1118 int libertas_prepare_and_send_command(wlan_private * priv,
1119                           u16 cmd_no,
1120                           u16 cmd_action,
1121                           u16 wait_option, u32 cmd_oid, void *pdata_buf)
1122 {
1123         int ret = 0;
1124         wlan_adapter *adapter = priv->adapter;
1125         struct cmd_ctrl_node *cmdnode;
1126         struct cmd_ds_command *cmdptr;
1127         unsigned long flags;
1128
1129         lbs_deb_enter(LBS_DEB_HOST);
1130
1131         if (!adapter) {
1132                 lbs_deb_host("PREP_CMD: adapter is NULL\n");
1133                 ret = -1;
1134                 goto done;
1135         }
1136
1137         if (adapter->surpriseremoved) {
1138                 lbs_deb_host("PREP_CMD: card removed\n");
1139                 ret = -1;
1140                 goto done;
1141         }
1142
1143         cmdnode = libertas_get_free_cmd_ctrl_node(priv);
1144
1145         if (cmdnode == NULL) {
1146                 lbs_deb_host("PREP_CMD: cmdnode is NULL\n");
1147
1148                 /* Wake up main thread to execute next command */
1149                 wake_up_interruptible(&priv->waitq);
1150                 ret = -1;
1151                 goto done;
1152         }
1153
1154         libertas_set_cmd_ctrl_node(priv, cmdnode, cmd_oid, wait_option, pdata_buf);
1155
1156         cmdptr = (struct cmd_ds_command *)cmdnode->bufvirtualaddr;
1157
1158         lbs_deb_host("PREP_CMD: command 0x%04x\n", cmd_no);
1159
1160         if (!cmdptr) {
1161                 lbs_deb_host("PREP_CMD: cmdptr is NULL\n");
1162                 libertas_cleanup_and_insert_cmd(priv, cmdnode);
1163                 ret = -1;
1164                 goto done;
1165         }
1166
1167         /* Set sequence number, command and INT option */
1168         adapter->seqnum++;
1169         cmdptr->seqnum = cpu_to_le16(adapter->seqnum);
1170
1171         cmdptr->command = cpu_to_le16(cmd_no);
1172         cmdptr->result = 0;
1173
1174         switch (cmd_no) {
1175         case CMD_GET_HW_SPEC:
1176                 ret = wlan_cmd_hw_spec(priv, cmdptr);
1177                 break;
1178         case CMD_802_11_PS_MODE:
1179                 ret = wlan_cmd_802_11_ps_mode(priv, cmdptr, cmd_action);
1180                 break;
1181
1182         case CMD_802_11_SCAN:
1183                 ret = libertas_cmd_80211_scan(priv, cmdptr, pdata_buf);
1184                 break;
1185
1186         case CMD_MAC_CONTROL:
1187                 ret = wlan_cmd_mac_control(priv, cmdptr);
1188                 break;
1189
1190         case CMD_802_11_ASSOCIATE:
1191         case CMD_802_11_REASSOCIATE:
1192                 ret = libertas_cmd_80211_associate(priv, cmdptr, pdata_buf);
1193                 break;
1194
1195         case CMD_802_11_DEAUTHENTICATE:
1196                 ret = libertas_cmd_80211_deauthenticate(priv, cmdptr);
1197                 break;
1198
1199         case CMD_802_11_SET_WEP:
1200                 ret = wlan_cmd_802_11_set_wep(priv, cmdptr, cmd_action, pdata_buf);
1201                 break;
1202
1203         case CMD_802_11_AD_HOC_START:
1204                 ret = libertas_cmd_80211_ad_hoc_start(priv, cmdptr, pdata_buf);
1205                 break;
1206         case CMD_CODE_DNLD:
1207                 break;
1208
1209         case CMD_802_11_RESET:
1210                 ret = wlan_cmd_802_11_reset(priv, cmdptr, cmd_action);
1211                 break;
1212
1213         case CMD_802_11_GET_LOG:
1214                 ret = wlan_cmd_802_11_get_log(priv, cmdptr);
1215                 break;
1216
1217         case CMD_802_11_AUTHENTICATE:
1218                 ret = libertas_cmd_80211_authenticate(priv, cmdptr, pdata_buf);
1219                 break;
1220
1221         case CMD_802_11_GET_STAT:
1222                 ret = wlan_cmd_802_11_get_stat(priv, cmdptr);
1223                 break;
1224
1225         case CMD_802_11_SNMP_MIB:
1226                 ret = wlan_cmd_802_11_snmp_mib(priv, cmdptr,
1227                                                cmd_action, cmd_oid, pdata_buf);
1228                 break;
1229
1230         case CMD_MAC_REG_ACCESS:
1231         case CMD_BBP_REG_ACCESS:
1232         case CMD_RF_REG_ACCESS:
1233                 ret = wlan_cmd_reg_access(priv, cmdptr, cmd_action, pdata_buf);
1234                 break;
1235
1236         case CMD_802_11_RF_CHANNEL:
1237                 ret = wlan_cmd_802_11_rf_channel(priv, cmdptr,
1238                                                  cmd_action, pdata_buf);
1239                 break;
1240
1241         case CMD_802_11_RF_TX_POWER:
1242                 ret = wlan_cmd_802_11_rf_tx_power(priv, cmdptr,
1243                                                   cmd_action, pdata_buf);
1244                 break;
1245
1246         case CMD_802_11_RADIO_CONTROL:
1247                 ret = wlan_cmd_802_11_radio_control(priv, cmdptr, cmd_action);
1248                 break;
1249
1250         case CMD_802_11_DATA_RATE:
1251                 ret = wlan_cmd_802_11_data_rate(priv, cmdptr, cmd_action);
1252                 break;
1253         case CMD_802_11_RATE_ADAPT_RATESET:
1254                 ret = wlan_cmd_802_11_rate_adapt_rateset(priv,
1255                                                          cmdptr, cmd_action);
1256                 break;
1257
1258         case CMD_MAC_MULTICAST_ADR:
1259                 ret = wlan_cmd_mac_multicast_adr(priv, cmdptr, cmd_action);
1260                 break;
1261
1262         case CMD_802_11_MONITOR_MODE:
1263                 ret = wlan_cmd_802_11_monitor_mode(priv, cmdptr,
1264                                           cmd_action, pdata_buf);
1265                 break;
1266
1267         case CMD_802_11_AD_HOC_JOIN:
1268                 ret = libertas_cmd_80211_ad_hoc_join(priv, cmdptr, pdata_buf);
1269                 break;
1270
1271         case CMD_802_11_RSSI:
1272                 ret = wlan_cmd_802_11_rssi(priv, cmdptr);
1273                 break;
1274
1275         case CMD_802_11_AD_HOC_STOP:
1276                 ret = libertas_cmd_80211_ad_hoc_stop(priv, cmdptr);
1277                 break;
1278
1279         case CMD_802_11_ENABLE_RSN:
1280                 ret = wlan_cmd_802_11_enable_rsn(priv, cmdptr, cmd_action,
1281                                 pdata_buf);
1282                 break;
1283
1284         case CMD_802_11_KEY_MATERIAL:
1285                 ret = wlan_cmd_802_11_key_material(priv, cmdptr, cmd_action,
1286                                 cmd_oid, pdata_buf);
1287                 break;
1288
1289         case CMD_802_11_PAIRWISE_TSC:
1290                 break;
1291         case CMD_802_11_GROUP_TSC:
1292                 break;
1293
1294         case CMD_802_11_MAC_ADDRESS:
1295                 ret = wlan_cmd_802_11_mac_address(priv, cmdptr, cmd_action);
1296                 break;
1297
1298         case CMD_802_11_EEPROM_ACCESS:
1299                 ret = wlan_cmd_802_11_eeprom_access(priv, cmdptr,
1300                                                     cmd_action, pdata_buf);
1301                 break;
1302
1303         case CMD_802_11_SET_AFC:
1304         case CMD_802_11_GET_AFC:
1305
1306                 cmdptr->command = cpu_to_le16(cmd_no);
1307                 cmdptr->size = cpu_to_le16(sizeof(struct cmd_ds_802_11_afc) +
1308                                            S_DS_GEN);
1309
1310                 memmove(&cmdptr->params.afc,
1311                         pdata_buf, sizeof(struct cmd_ds_802_11_afc));
1312
1313                 ret = 0;
1314                 goto done;
1315
1316         case CMD_802_11D_DOMAIN_INFO:
1317                 ret = libertas_cmd_802_11d_domain_info(priv, cmdptr,
1318                                                    cmd_no, cmd_action);
1319                 break;
1320
1321         case CMD_802_11_SLEEP_PARAMS:
1322                 ret = wlan_cmd_802_11_sleep_params(priv, cmdptr, cmd_action);
1323                 break;
1324         case CMD_802_11_INACTIVITY_TIMEOUT:
1325                 ret = wlan_cmd_802_11_inactivity_timeout(priv, cmdptr,
1326                                                          cmd_action, pdata_buf);
1327                 libertas_set_cmd_ctrl_node(priv, cmdnode, 0, 0, pdata_buf);
1328                 break;
1329
1330         case CMD_802_11_TPC_CFG:
1331                 cmdptr->command = cpu_to_le16(CMD_802_11_TPC_CFG);
1332                 cmdptr->size =
1333                     cpu_to_le16(sizeof(struct cmd_ds_802_11_tpc_cfg) +
1334                                      S_DS_GEN);
1335
1336                 memmove(&cmdptr->params.tpccfg,
1337                         pdata_buf, sizeof(struct cmd_ds_802_11_tpc_cfg));
1338
1339                 ret = 0;
1340                 break;
1341         case CMD_802_11_LED_GPIO_CTRL:
1342                 {
1343                         struct mrvlietypes_ledgpio *gpio =
1344                             (struct mrvlietypes_ledgpio*)
1345                             cmdptr->params.ledgpio.data;
1346
1347                         memmove(&cmdptr->params.ledgpio,
1348                                 pdata_buf,
1349                                 sizeof(struct cmd_ds_802_11_led_ctrl));
1350
1351                         cmdptr->command =
1352                             cpu_to_le16(CMD_802_11_LED_GPIO_CTRL);
1353
1354 #define ACTION_NUMLED_TLVTYPE_LEN_FIELDS_LEN 8
1355                         cmdptr->size =
1356                             cpu_to_le16(gpio->header.len + S_DS_GEN +
1357                                              ACTION_NUMLED_TLVTYPE_LEN_FIELDS_LEN);
1358                         gpio->header.len = cpu_to_le16(gpio->header.len);
1359
1360                         ret = 0;
1361                         break;
1362                 }
1363         case CMD_802_11_PWR_CFG:
1364                 cmdptr->command = cpu_to_le16(CMD_802_11_PWR_CFG);
1365                 cmdptr->size =
1366                     cpu_to_le16(sizeof(struct cmd_ds_802_11_pwr_cfg) +
1367                                      S_DS_GEN);
1368                 memmove(&cmdptr->params.pwrcfg, pdata_buf,
1369                         sizeof(struct cmd_ds_802_11_pwr_cfg));
1370
1371                 ret = 0;
1372                 break;
1373         case CMD_BT_ACCESS:
1374                 ret = wlan_cmd_bt_access(priv, cmdptr, cmd_action, pdata_buf);
1375                 break;
1376
1377         case CMD_FWT_ACCESS:
1378                 ret = wlan_cmd_fwt_access(priv, cmdptr, cmd_action, pdata_buf);
1379                 break;
1380
1381         case CMD_MESH_ACCESS:
1382                 ret = wlan_cmd_mesh_access(priv, cmdptr, cmd_action, pdata_buf);
1383                 break;
1384
1385         case CMD_GET_TSF:
1386                 cmdptr->command = cpu_to_le16(CMD_GET_TSF);
1387                 cmdptr->size = cpu_to_le16(sizeof(struct cmd_ds_get_tsf) +
1388                                            S_DS_GEN);
1389                 ret = 0;
1390                 break;
1391         default:
1392                 lbs_deb_host("PREP_CMD: unknown command 0x%04x\n", cmd_no);
1393                 ret = -1;
1394                 break;
1395         }
1396
1397         /* return error, since the command preparation failed */
1398         if (ret != 0) {
1399                 lbs_deb_host("PREP_CMD: command preparation failed\n");
1400                 libertas_cleanup_and_insert_cmd(priv, cmdnode);
1401                 ret = -1;
1402                 goto done;
1403         }
1404
1405         cmdnode->cmdwaitqwoken = 0;
1406
1407         libertas_queue_cmd(adapter, cmdnode, 1);
1408         adapter->nr_cmd_pending++;
1409         wake_up_interruptible(&priv->waitq);
1410
1411         if (wait_option & CMD_OPTION_WAITFORRSP) {
1412                 lbs_deb_host("PREP_CMD: wait for response\n");
1413                 might_sleep();
1414                 wait_event_interruptible(cmdnode->cmdwait_q,
1415                                          cmdnode->cmdwaitqwoken);
1416         }
1417
1418         spin_lock_irqsave(&adapter->driver_lock, flags);
1419         if (adapter->cur_cmd_retcode) {
1420                 lbs_deb_host("PREP_CMD: command failed with return code %d\n",
1421                        adapter->cur_cmd_retcode);
1422                 adapter->cur_cmd_retcode = 0;
1423                 ret = -1;
1424         }
1425         spin_unlock_irqrestore(&adapter->driver_lock, flags);
1426
1427 done:
1428         lbs_deb_leave_args(LBS_DEB_HOST, "ret %d", ret);
1429         return ret;
1430 }
1431 EXPORT_SYMBOL_GPL(libertas_prepare_and_send_command);
1432
1433 /**
1434  *  @brief This function allocates the command buffer and link
1435  *  it to command free queue.
1436  *
1437  *  @param priv         A pointer to wlan_private structure
1438  *  @return             0 or -1
1439  */
1440 int libertas_allocate_cmd_buffer(wlan_private * priv)
1441 {
1442         int ret = 0;
1443         u32 ulbufsize;
1444         u32 i;
1445         struct cmd_ctrl_node *tempcmd_array;
1446         u8 *ptempvirtualaddr;
1447         wlan_adapter *adapter = priv->adapter;
1448
1449         lbs_deb_enter(LBS_DEB_HOST);
1450
1451         /* Allocate and initialize cmdCtrlNode */
1452         ulbufsize = sizeof(struct cmd_ctrl_node) * MRVDRV_NUM_OF_CMD_BUFFER;
1453
1454         if (!(tempcmd_array = kzalloc(ulbufsize, GFP_KERNEL))) {
1455                 lbs_deb_host("ALLOC_CMD_BUF: tempcmd_array is NULL\n");
1456                 ret = -1;
1457                 goto done;
1458         }
1459         adapter->cmd_array = tempcmd_array;
1460
1461         /* Allocate and initialize command buffers */
1462         ulbufsize = MRVDRV_SIZE_OF_CMD_BUFFER;
1463         for (i = 0; i < MRVDRV_NUM_OF_CMD_BUFFER; i++) {
1464                 if (!(ptempvirtualaddr = kzalloc(ulbufsize, GFP_KERNEL))) {
1465                         lbs_deb_host("ALLOC_CMD_BUF: ptempvirtualaddr is NULL\n");
1466                         ret = -1;
1467                         goto done;
1468                 }
1469
1470                 /* Update command buffer virtual */
1471                 tempcmd_array[i].bufvirtualaddr = ptempvirtualaddr;
1472         }
1473
1474         for (i = 0; i < MRVDRV_NUM_OF_CMD_BUFFER; i++) {
1475                 init_waitqueue_head(&tempcmd_array[i].cmdwait_q);
1476                 libertas_cleanup_and_insert_cmd(priv, &tempcmd_array[i]);
1477         }
1478
1479         ret = 0;
1480
1481 done:
1482         lbs_deb_leave_args(LBS_DEB_HOST, "ret %d", ret);
1483         return ret;
1484 }
1485
1486 /**
1487  *  @brief This function frees the command buffer.
1488  *
1489  *  @param priv         A pointer to wlan_private structure
1490  *  @return             0 or -1
1491  */
1492 int libertas_free_cmd_buffer(wlan_private * priv)
1493 {
1494         u32 ulbufsize; /* Someone needs to die for this. Slowly and painfully */
1495         unsigned int i;
1496         struct cmd_ctrl_node *tempcmd_array;
1497         wlan_adapter *adapter = priv->adapter;
1498
1499         lbs_deb_enter(LBS_DEB_HOST);
1500
1501         /* need to check if cmd array is allocated or not */
1502         if (adapter->cmd_array == NULL) {
1503                 lbs_deb_host("FREE_CMD_BUF: cmd_array is NULL\n");
1504                 goto done;
1505         }
1506
1507         tempcmd_array = adapter->cmd_array;
1508
1509         /* Release shared memory buffers */
1510         ulbufsize = MRVDRV_SIZE_OF_CMD_BUFFER;
1511         for (i = 0; i < MRVDRV_NUM_OF_CMD_BUFFER; i++) {
1512                 if (tempcmd_array[i].bufvirtualaddr) {
1513                         kfree(tempcmd_array[i].bufvirtualaddr);
1514                         tempcmd_array[i].bufvirtualaddr = NULL;
1515                 }
1516         }
1517
1518         /* Release cmd_ctrl_node */
1519         if (adapter->cmd_array) {
1520                 kfree(adapter->cmd_array);
1521                 adapter->cmd_array = NULL;
1522         }
1523
1524 done:
1525         lbs_deb_leave(LBS_DEB_HOST);
1526         return 0;
1527 }
1528
1529 /**
1530  *  @brief This function gets a free command node if available in
1531  *  command free queue.
1532  *
1533  *  @param priv         A pointer to wlan_private structure
1534  *  @return cmd_ctrl_node A pointer to cmd_ctrl_node structure or NULL
1535  */
1536 struct cmd_ctrl_node *libertas_get_free_cmd_ctrl_node(wlan_private * priv)
1537 {
1538         struct cmd_ctrl_node *tempnode;
1539         wlan_adapter *adapter = priv->adapter;
1540         unsigned long flags;
1541
1542         lbs_deb_enter(LBS_DEB_HOST);
1543
1544         if (!adapter)
1545                 return NULL;
1546
1547         spin_lock_irqsave(&adapter->driver_lock, flags);
1548
1549         if (!list_empty(&adapter->cmdfreeq)) {
1550                 tempnode = (struct cmd_ctrl_node *)adapter->cmdfreeq.next;
1551                 list_del((struct list_head *)tempnode);
1552         } else {
1553                 lbs_deb_host("GET_CMD_NODE: cmd_ctrl_node is not available\n");
1554                 tempnode = NULL;
1555         }
1556
1557         spin_unlock_irqrestore(&adapter->driver_lock, flags);
1558
1559         if (tempnode)
1560                 cleanup_cmdnode(tempnode);
1561
1562         lbs_deb_leave(LBS_DEB_HOST);
1563         return tempnode;
1564 }
1565
1566 /**
1567  *  @brief This function cleans command node.
1568  *
1569  *  @param ptempnode    A pointer to cmdCtrlNode structure
1570  *  @return             n/a
1571  */
1572 static void cleanup_cmdnode(struct cmd_ctrl_node *ptempnode)
1573 {
1574         lbs_deb_enter(LBS_DEB_HOST);
1575
1576         if (!ptempnode)
1577                 return;
1578         ptempnode->cmdwaitqwoken = 1;
1579         wake_up_interruptible(&ptempnode->cmdwait_q);
1580         ptempnode->status = 0;
1581         ptempnode->cmd_oid = (u32) 0;
1582         ptempnode->wait_option = 0;
1583         ptempnode->pdata_buf = NULL;
1584
1585         if (ptempnode->bufvirtualaddr != NULL)
1586                 memset(ptempnode->bufvirtualaddr, 0, MRVDRV_SIZE_OF_CMD_BUFFER);
1587
1588         lbs_deb_leave(LBS_DEB_HOST);
1589 }
1590
1591 /**
1592  *  @brief This function initializes the command node.
1593  *
1594  *  @param priv         A pointer to wlan_private structure
1595  *  @param ptempnode    A pointer to cmd_ctrl_node structure
1596  *  @param cmd_oid      cmd oid: treated as sub command
1597  *  @param wait_option  wait option: wait response or not
1598  *  @param pdata_buf    A pointer to informaion buffer
1599  *  @return             0 or -1
1600  */
1601 void libertas_set_cmd_ctrl_node(wlan_private * priv,
1602                     struct cmd_ctrl_node *ptempnode,
1603                     u32 cmd_oid, u16 wait_option, void *pdata_buf)
1604 {
1605         lbs_deb_enter(LBS_DEB_HOST);
1606
1607         if (!ptempnode)
1608                 return;
1609
1610         ptempnode->cmd_oid = cmd_oid;
1611         ptempnode->wait_option = wait_option;
1612         ptempnode->pdata_buf = pdata_buf;
1613
1614         lbs_deb_leave(LBS_DEB_HOST);
1615 }
1616
1617 /**
1618  *  @brief This function executes next command in command
1619  *  pending queue. It will put fimware back to PS mode
1620  *  if applicable.
1621  *
1622  *  @param priv     A pointer to wlan_private structure
1623  *  @return        0 or -1
1624  */
1625 int libertas_execute_next_command(wlan_private * priv)
1626 {
1627         wlan_adapter *adapter = priv->adapter;
1628         struct cmd_ctrl_node *cmdnode = NULL;
1629         struct cmd_ds_command *cmdptr;
1630         unsigned long flags;
1631         int ret = 0;
1632
1633         // Debug group is LBS_DEB_THREAD and not LBS_DEB_HOST, because the
1634         // only caller to us is libertas_thread() and we get even when a
1635         // data packet is received
1636         lbs_deb_enter(LBS_DEB_THREAD);
1637
1638         spin_lock_irqsave(&adapter->driver_lock, flags);
1639
1640         if (adapter->cur_cmd) {
1641                 lbs_pr_alert( "EXEC_NEXT_CMD: already processing command!\n");
1642                 spin_unlock_irqrestore(&adapter->driver_lock, flags);
1643                 ret = -1;
1644                 goto done;
1645         }
1646
1647         if (!list_empty(&adapter->cmdpendingq)) {
1648                 cmdnode = (struct cmd_ctrl_node *)
1649                     adapter->cmdpendingq.next;
1650         }
1651
1652         spin_unlock_irqrestore(&adapter->driver_lock, flags);
1653
1654         if (cmdnode) {
1655                 cmdptr = (struct cmd_ds_command *)cmdnode->bufvirtualaddr;
1656
1657                 if (is_command_allowed_in_ps(cmdptr->command)) {
1658                         if ((adapter->psstate == PS_STATE_SLEEP) ||
1659                             (adapter->psstate == PS_STATE_PRE_SLEEP)) {
1660                                 lbs_deb_host(
1661                                        "EXEC_NEXT_CMD: cannot send cmd 0x%04x in psstate %d\n",
1662                                        le16_to_cpu(cmdptr->command),
1663                                        adapter->psstate);
1664                                 ret = -1;
1665                                 goto done;
1666                         }
1667                         lbs_deb_host("EXEC_NEXT_CMD: OK to send command "
1668                                "0x%04x in psstate %d\n",
1669                                     le16_to_cpu(cmdptr->command),
1670                                     adapter->psstate);
1671                 } else if (adapter->psstate != PS_STATE_FULL_POWER) {
1672                         /*
1673                          * 1. Non-PS command:
1674                          * Queue it. set needtowakeup to TRUE if current state
1675                          * is SLEEP, otherwise call libertas_ps_wakeup to send Exit_PS.
1676                          * 2. PS command but not Exit_PS:
1677                          * Ignore it.
1678                          * 3. PS command Exit_PS:
1679                          * Set needtowakeup to TRUE if current state is SLEEP,
1680                          * otherwise send this command down to firmware
1681                          * immediately.
1682                          */
1683                         if (cmdptr->command !=
1684                             cpu_to_le16(CMD_802_11_PS_MODE)) {
1685                                 /*  Prepare to send Exit PS,
1686                                  *  this non PS command will be sent later */
1687                                 if ((adapter->psstate == PS_STATE_SLEEP)
1688                                     || (adapter->psstate == PS_STATE_PRE_SLEEP)
1689                                     ) {
1690                                         /* w/ new scheme, it will not reach here.
1691                                            since it is blocked in main_thread. */
1692                                         adapter->needtowakeup = 1;
1693                                 } else
1694                                         libertas_ps_wakeup(priv, 0);
1695
1696                                 ret = 0;
1697                                 goto done;
1698                         } else {
1699                                 /*
1700                                  * PS command. Ignore it if it is not Exit_PS.
1701                                  * otherwise send it down immediately.
1702                                  */
1703                                 struct cmd_ds_802_11_ps_mode *psm =
1704                                     &cmdptr->params.psmode;
1705
1706                                 lbs_deb_host(
1707                                        "EXEC_NEXT_CMD: PS cmd, action 0x%02x\n",
1708                                        psm->action);
1709                                 if (psm->action !=
1710                                     cpu_to_le16(CMD_SUBCMD_EXIT_PS)) {
1711                                         lbs_deb_host(
1712                                                "EXEC_NEXT_CMD: ignore ENTER_PS cmd\n");
1713                                         list_del((struct list_head *)cmdnode);
1714                                         libertas_cleanup_and_insert_cmd(priv, cmdnode);
1715
1716                                         ret = 0;
1717                                         goto done;
1718                                 }
1719
1720                                 if ((adapter->psstate == PS_STATE_SLEEP) ||
1721                                     (adapter->psstate == PS_STATE_PRE_SLEEP)) {
1722                                         lbs_deb_host(
1723                                                "EXEC_NEXT_CMD: ignore EXIT_PS cmd in sleep\n");
1724                                         list_del((struct list_head *)cmdnode);
1725                                         libertas_cleanup_and_insert_cmd(priv, cmdnode);
1726                                         adapter->needtowakeup = 1;
1727
1728                                         ret = 0;
1729                                         goto done;
1730                                 }
1731
1732                                 lbs_deb_host(
1733                                        "EXEC_NEXT_CMD: sending EXIT_PS\n");
1734                         }
1735                 }
1736                 list_del((struct list_head *)cmdnode);
1737                 lbs_deb_host("EXEC_NEXT_CMD: sending command 0x%04x\n",
1738                             le16_to_cpu(cmdptr->command));
1739                 DownloadcommandToStation(priv, cmdnode);
1740         } else {
1741                 /*
1742                  * check if in power save mode, if yes, put the device back
1743                  * to PS mode
1744                  */
1745                 if ((adapter->psmode != WLAN802_11POWERMODECAM) &&
1746                     (adapter->psstate == PS_STATE_FULL_POWER) &&
1747                     (adapter->connect_status == LIBERTAS_CONNECTED)) {
1748                         if (adapter->secinfo.WPAenabled ||
1749                             adapter->secinfo.WPA2enabled) {
1750                                 /* check for valid WPA group keys */
1751                                 if (adapter->wpa_mcast_key.len ||
1752                                     adapter->wpa_unicast_key.len) {
1753                                         lbs_deb_host(
1754                                                "EXEC_NEXT_CMD: WPA enabled and GTK_SET"
1755                                                " go back to PS_SLEEP");
1756                                         libertas_ps_sleep(priv, 0);
1757                                 }
1758                         } else {
1759                                 lbs_deb_host(
1760                                        "EXEC_NEXT_CMD: cmdpendingq empty, "
1761                                        "go back to PS_SLEEP");
1762                                 libertas_ps_sleep(priv, 0);
1763                         }
1764                 }
1765         }
1766
1767         ret = 0;
1768 done:
1769         lbs_deb_leave(LBS_DEB_THREAD);
1770         return ret;
1771 }
1772
1773 void libertas_send_iwevcustom_event(wlan_private * priv, s8 * str)
1774 {
1775         union iwreq_data iwrq;
1776         u8 buf[50];
1777
1778         lbs_deb_enter(LBS_DEB_WEXT);
1779
1780         memset(&iwrq, 0, sizeof(union iwreq_data));
1781         memset(buf, 0, sizeof(buf));
1782
1783         snprintf(buf, sizeof(buf) - 1, "%s", str);
1784
1785         iwrq.data.length = strlen(buf) + 1 + IW_EV_LCP_LEN;
1786
1787         /* Send Event to upper layer */
1788         lbs_deb_wext("event indication string %s\n", (char *)buf);
1789         lbs_deb_wext("event indication length %d\n", iwrq.data.length);
1790         lbs_deb_wext("sending wireless event IWEVCUSTOM for %s\n", str);
1791
1792         wireless_send_event(priv->dev, IWEVCUSTOM, &iwrq, buf);
1793
1794         lbs_deb_leave(LBS_DEB_WEXT);
1795 }
1796
1797 static int sendconfirmsleep(wlan_private * priv, u8 * cmdptr, u16 size)
1798 {
1799         unsigned long flags;
1800         wlan_adapter *adapter = priv->adapter;
1801         int ret = 0;
1802
1803         lbs_deb_enter(LBS_DEB_HOST);
1804
1805         lbs_deb_host("SEND_SLEEPC_CMD: before download, cmd size %d\n",
1806                size);
1807
1808         lbs_deb_hex(LBS_DEB_HOST, "sleep confirm command", cmdptr, size);
1809
1810         ret = priv->hw_host_to_card(priv, MVMS_CMD, cmdptr, size);
1811         priv->dnld_sent = DNLD_RES_RECEIVED;
1812
1813         spin_lock_irqsave(&adapter->driver_lock, flags);
1814         if (adapter->intcounter || adapter->currenttxskb)
1815                 lbs_deb_host("SEND_SLEEPC_CMD: intcounter %d, currenttxskb %p\n",
1816                        adapter->intcounter, adapter->currenttxskb);
1817         spin_unlock_irqrestore(&adapter->driver_lock, flags);
1818
1819         if (ret) {
1820                 lbs_pr_alert(
1821                        "SEND_SLEEPC_CMD: Host to Card failed for Confirm Sleep\n");
1822         } else {
1823                 spin_lock_irqsave(&adapter->driver_lock, flags);
1824                 if (!adapter->intcounter) {
1825                         adapter->psstate = PS_STATE_SLEEP;
1826                 } else {
1827                         lbs_deb_host("SEND_SLEEPC_CMD: after sent, intcounter %d\n",
1828                                adapter->intcounter);
1829                 }
1830                 spin_unlock_irqrestore(&adapter->driver_lock, flags);
1831
1832                 lbs_deb_host("SEND_SLEEPC_CMD: sent confirm sleep\n");
1833         }
1834
1835         lbs_deb_leave_args(LBS_DEB_HOST, "ret %d", ret);
1836         return ret;
1837 }
1838
1839 void libertas_ps_sleep(wlan_private * priv, int wait_option)
1840 {
1841         lbs_deb_enter(LBS_DEB_HOST);
1842
1843         /*
1844          * PS is currently supported only in Infrastructure mode
1845          * Remove this check if it is to be supported in IBSS mode also
1846          */
1847
1848         libertas_prepare_and_send_command(priv, CMD_802_11_PS_MODE,
1849                               CMD_SUBCMD_ENTER_PS, wait_option, 0, NULL);
1850
1851         lbs_deb_leave(LBS_DEB_HOST);
1852 }
1853
1854 /**
1855  *  @brief This function sends Exit_PS command to firmware.
1856  *
1857  *  @param priv         A pointer to wlan_private structure
1858  *  @param wait_option  wait response or not
1859  *  @return             n/a
1860  */
1861 void libertas_ps_wakeup(wlan_private * priv, int wait_option)
1862 {
1863         __le32 Localpsmode;
1864
1865         lbs_deb_enter(LBS_DEB_HOST);
1866
1867         Localpsmode = cpu_to_le32(WLAN802_11POWERMODECAM);
1868
1869         libertas_prepare_and_send_command(priv, CMD_802_11_PS_MODE,
1870                               CMD_SUBCMD_EXIT_PS,
1871                               wait_option, 0, &Localpsmode);
1872
1873         lbs_deb_leave(LBS_DEB_HOST);
1874 }
1875
1876 /**
1877  *  @brief This function checks condition and prepares to
1878  *  send sleep confirm command to firmware if ok.
1879  *
1880  *  @param priv         A pointer to wlan_private structure
1881  *  @param psmode       Power Saving mode
1882  *  @return             n/a
1883  */
1884 void libertas_ps_confirm_sleep(wlan_private * priv, u16 psmode)
1885 {
1886         unsigned long flags =0;
1887         wlan_adapter *adapter = priv->adapter;
1888         u8 allowed = 1;
1889
1890         lbs_deb_enter(LBS_DEB_HOST);
1891
1892         if (priv->dnld_sent) {
1893                 allowed = 0;
1894                 lbs_deb_host("dnld_sent was set");
1895         }
1896
1897         spin_lock_irqsave(&adapter->driver_lock, flags);
1898         if (adapter->cur_cmd) {
1899                 allowed = 0;
1900                 lbs_deb_host("cur_cmd was set");
1901         }
1902         if (adapter->intcounter > 0) {
1903                 allowed = 0;
1904                 lbs_deb_host("intcounter %d", adapter->intcounter);
1905         }
1906         spin_unlock_irqrestore(&adapter->driver_lock, flags);
1907
1908         if (allowed) {
1909                 lbs_deb_host("sending libertas_ps_confirm_sleep\n");
1910                 sendconfirmsleep(priv, (u8 *) & adapter->libertas_ps_confirm_sleep,
1911                                  sizeof(struct PS_CMD_ConfirmSleep));
1912         } else {
1913                 lbs_deb_host("sleep confirm has been delayed\n");
1914         }
1915
1916         lbs_deb_leave(LBS_DEB_HOST);
1917 }