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