[PATCH] libertas: remove adapter->{rx,tx}antenna
[linux-2.6] / 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_rate_adapt_rateset(wlan_private * priv,
574                                               struct cmd_ds_command *cmd,
575                                               u16 cmd_action)
576 {
577         struct cmd_ds_802_11_rate_adapt_rateset
578         *rateadapt = &cmd->params.rateset;
579         wlan_adapter *adapter = priv->adapter;
580
581         lbs_deb_enter(LBS_DEB_CMD);
582         cmd->size =
583             cpu_to_le16(sizeof(struct cmd_ds_802_11_rate_adapt_rateset)
584                              + S_DS_GEN);
585         cmd->command = cpu_to_le16(CMD_802_11_RATE_ADAPT_RATESET);
586
587         rateadapt->action = cpu_to_le16(cmd_action);
588         rateadapt->enablehwauto = cpu_to_le16(adapter->enablehwauto);
589         rateadapt->bitmap = cpu_to_le16(adapter->ratebitmap);
590
591         lbs_deb_leave(LBS_DEB_CMD);
592         return 0;
593 }
594
595 static int wlan_cmd_802_11_data_rate(wlan_private * priv,
596                                      struct cmd_ds_command *cmd,
597                                      u16 cmd_action)
598 {
599         struct cmd_ds_802_11_data_rate *pdatarate = &cmd->params.drate;
600         wlan_adapter *adapter = priv->adapter;
601
602         lbs_deb_enter(LBS_DEB_CMD);
603
604         cmd->size = cpu_to_le16(sizeof(struct cmd_ds_802_11_data_rate) +
605                              S_DS_GEN);
606         cmd->command = cpu_to_le16(CMD_802_11_DATA_RATE);
607         memset(pdatarate, 0, sizeof(struct cmd_ds_802_11_data_rate));
608         pdatarate->action = cpu_to_le16(cmd_action);
609
610         if (cmd_action == CMD_ACT_SET_TX_FIX_RATE) {
611                 pdatarate->rates[0] = libertas_data_rate_to_fw_index(adapter->cur_rate);
612                 lbs_deb_cmd("DATA_RATE: set fixed 0x%02X\n",
613                        adapter->cur_rate);
614         } else if (cmd_action == CMD_ACT_SET_TX_AUTO) {
615                 lbs_deb_cmd("DATA_RATE: setting auto\n");
616         }
617
618         lbs_deb_leave(LBS_DEB_CMD);
619         return 0;
620 }
621
622 static int wlan_cmd_mac_multicast_adr(wlan_private * priv,
623                                       struct cmd_ds_command *cmd,
624                                       u16 cmd_action)
625 {
626         struct cmd_ds_mac_multicast_adr *pMCastAdr = &cmd->params.madr;
627         wlan_adapter *adapter = priv->adapter;
628
629         lbs_deb_enter(LBS_DEB_CMD);
630         cmd->size = cpu_to_le16(sizeof(struct cmd_ds_mac_multicast_adr) +
631                              S_DS_GEN);
632         cmd->command = cpu_to_le16(CMD_MAC_MULTICAST_ADR);
633
634         lbs_deb_cmd("MULTICAST_ADR: setting %d addresses\n", pMCastAdr->nr_of_adrs);
635         pMCastAdr->action = cpu_to_le16(cmd_action);
636         pMCastAdr->nr_of_adrs =
637             cpu_to_le16((u16) adapter->nr_of_multicastmacaddr);
638         memcpy(pMCastAdr->maclist, adapter->multicastlist,
639                adapter->nr_of_multicastmacaddr * ETH_ALEN);
640
641         lbs_deb_leave(LBS_DEB_CMD);
642         return 0;
643 }
644
645 static int wlan_cmd_802_11_rf_channel(wlan_private * priv,
646                                       struct cmd_ds_command *cmd,
647                                       int option, void *pdata_buf)
648 {
649         struct cmd_ds_802_11_rf_channel *rfchan = &cmd->params.rfchannel;
650
651         lbs_deb_enter(LBS_DEB_CMD);
652         cmd->command = cpu_to_le16(CMD_802_11_RF_CHANNEL);
653         cmd->size = cpu_to_le16(sizeof(struct cmd_ds_802_11_rf_channel) +
654                                 S_DS_GEN);
655
656         if (option == CMD_OPT_802_11_RF_CHANNEL_SET) {
657                 rfchan->currentchannel = cpu_to_le16(*((u16 *) pdata_buf));
658         }
659
660         rfchan->action = cpu_to_le16(option);
661
662         lbs_deb_leave(LBS_DEB_CMD);
663         return 0;
664 }
665
666 static int wlan_cmd_802_11_rssi(wlan_private * priv,
667                                 struct cmd_ds_command *cmd)
668 {
669         wlan_adapter *adapter = priv->adapter;
670
671         lbs_deb_enter(LBS_DEB_CMD);
672         cmd->command = cpu_to_le16(CMD_802_11_RSSI);
673         cmd->size = cpu_to_le16(sizeof(struct cmd_ds_802_11_rssi) + S_DS_GEN);
674         cmd->params.rssi.N = cpu_to_le16(priv->adapter->bcn_avg_factor);
675
676         /* reset Beacon SNR/NF/RSSI values */
677         adapter->SNR[TYPE_BEACON][TYPE_NOAVG] = 0;
678         adapter->SNR[TYPE_BEACON][TYPE_AVG] = 0;
679         adapter->NF[TYPE_BEACON][TYPE_NOAVG] = 0;
680         adapter->NF[TYPE_BEACON][TYPE_AVG] = 0;
681         adapter->RSSI[TYPE_BEACON][TYPE_NOAVG] = 0;
682         adapter->RSSI[TYPE_BEACON][TYPE_AVG] = 0;
683
684         lbs_deb_leave(LBS_DEB_CMD);
685         return 0;
686 }
687
688 static int wlan_cmd_reg_access(wlan_private * priv,
689                                struct cmd_ds_command *cmdptr,
690                                u8 cmd_action, void *pdata_buf)
691 {
692         struct wlan_offset_value *offval;
693
694         lbs_deb_enter(LBS_DEB_CMD);
695
696         offval = (struct wlan_offset_value *)pdata_buf;
697
698         switch (cmdptr->command) {
699         case CMD_MAC_REG_ACCESS:
700                 {
701                         struct cmd_ds_mac_reg_access *macreg;
702
703                         cmdptr->size =
704                             cpu_to_le16(sizeof (struct cmd_ds_mac_reg_access)
705                                         + S_DS_GEN);
706                         macreg =
707                             (struct cmd_ds_mac_reg_access *)&cmdptr->params.
708                             macreg;
709
710                         macreg->action = cpu_to_le16(cmd_action);
711                         macreg->offset = cpu_to_le16((u16) offval->offset);
712                         macreg->value = cpu_to_le32(offval->value);
713
714                         break;
715                 }
716
717         case CMD_BBP_REG_ACCESS:
718                 {
719                         struct cmd_ds_bbp_reg_access *bbpreg;
720
721                         cmdptr->size =
722                             cpu_to_le16(sizeof
723                                              (struct cmd_ds_bbp_reg_access)
724                                              + S_DS_GEN);
725                         bbpreg =
726                             (struct cmd_ds_bbp_reg_access *)&cmdptr->params.
727                             bbpreg;
728
729                         bbpreg->action = cpu_to_le16(cmd_action);
730                         bbpreg->offset = cpu_to_le16((u16) offval->offset);
731                         bbpreg->value = (u8) offval->value;
732
733                         break;
734                 }
735
736         case CMD_RF_REG_ACCESS:
737                 {
738                         struct cmd_ds_rf_reg_access *rfreg;
739
740                         cmdptr->size =
741                             cpu_to_le16(sizeof
742                                              (struct cmd_ds_rf_reg_access) +
743                                              S_DS_GEN);
744                         rfreg =
745                             (struct cmd_ds_rf_reg_access *)&cmdptr->params.
746                             rfreg;
747
748                         rfreg->action = cpu_to_le16(cmd_action);
749                         rfreg->offset = cpu_to_le16((u16) offval->offset);
750                         rfreg->value = (u8) offval->value;
751
752                         break;
753                 }
754
755         default:
756                 break;
757         }
758
759         lbs_deb_leave(LBS_DEB_CMD);
760         return 0;
761 }
762
763 static int wlan_cmd_802_11_mac_address(wlan_private * priv,
764                                        struct cmd_ds_command *cmd,
765                                        u16 cmd_action)
766 {
767         wlan_adapter *adapter = priv->adapter;
768
769         lbs_deb_enter(LBS_DEB_CMD);
770         cmd->command = cpu_to_le16(CMD_802_11_MAC_ADDRESS);
771         cmd->size = cpu_to_le16(sizeof(struct cmd_ds_802_11_mac_address) +
772                              S_DS_GEN);
773         cmd->result = 0;
774
775         cmd->params.macadd.action = cpu_to_le16(cmd_action);
776
777         if (cmd_action == CMD_ACT_SET) {
778                 memcpy(cmd->params.macadd.macadd,
779                        adapter->current_addr, ETH_ALEN);
780                 lbs_deb_hex(LBS_DEB_CMD, "SET_CMD: MAC addr", adapter->current_addr, 6);
781         }
782
783         lbs_deb_leave(LBS_DEB_CMD);
784         return 0;
785 }
786
787 static int wlan_cmd_802_11_eeprom_access(wlan_private * priv,
788                                          struct cmd_ds_command *cmd,
789                                          int cmd_action, void *pdata_buf)
790 {
791         struct wlan_ioctl_regrdwr *ea = pdata_buf;
792
793         lbs_deb_enter(LBS_DEB_CMD);
794
795         cmd->command = cpu_to_le16(CMD_802_11_EEPROM_ACCESS);
796         cmd->size = cpu_to_le16(sizeof(struct cmd_ds_802_11_eeprom_access) +
797                                 S_DS_GEN);
798         cmd->result = 0;
799
800         cmd->params.rdeeprom.action = cpu_to_le16(ea->action);
801         cmd->params.rdeeprom.offset = cpu_to_le16(ea->offset);
802         cmd->params.rdeeprom.bytecount = cpu_to_le16(ea->NOB);
803         cmd->params.rdeeprom.value = 0;
804
805         lbs_deb_leave(LBS_DEB_CMD);
806         return 0;
807 }
808
809 static int wlan_cmd_bt_access(wlan_private * priv,
810                                struct cmd_ds_command *cmd,
811                                u16 cmd_action, void *pdata_buf)
812 {
813         struct cmd_ds_bt_access *bt_access = &cmd->params.bt;
814         lbs_deb_enter_args(LBS_DEB_CMD, "action %d", cmd_action);
815
816         cmd->command = cpu_to_le16(CMD_BT_ACCESS);
817         cmd->size = cpu_to_le16(sizeof(struct cmd_ds_bt_access) + S_DS_GEN);
818         cmd->result = 0;
819         bt_access->action = cpu_to_le16(cmd_action);
820
821         switch (cmd_action) {
822         case CMD_ACT_BT_ACCESS_ADD:
823                 memcpy(bt_access->addr1, pdata_buf, 2 * ETH_ALEN);
824                 lbs_deb_hex(LBS_DEB_MESH, "BT_ADD: blinded MAC addr", bt_access->addr1, 6);
825                 break;
826         case CMD_ACT_BT_ACCESS_DEL:
827                 memcpy(bt_access->addr1, pdata_buf, 1 * ETH_ALEN);
828                 lbs_deb_hex(LBS_DEB_MESH, "BT_DEL: blinded MAC addr", bt_access->addr1, 6);
829                 break;
830         case CMD_ACT_BT_ACCESS_LIST:
831                 bt_access->id = cpu_to_le32(*(u32 *) pdata_buf);
832                 break;
833         case CMD_ACT_BT_ACCESS_RESET:
834                 break;
835         case CMD_ACT_BT_ACCESS_SET_INVERT:
836                 bt_access->id = cpu_to_le32(*(u32 *) pdata_buf);
837                 break;
838         case CMD_ACT_BT_ACCESS_GET_INVERT:
839                 break;
840         default:
841                 break;
842         }
843         lbs_deb_leave(LBS_DEB_CMD);
844         return 0;
845 }
846
847 static int wlan_cmd_fwt_access(wlan_private * priv,
848                                struct cmd_ds_command *cmd,
849                                u16 cmd_action, void *pdata_buf)
850 {
851         struct cmd_ds_fwt_access *fwt_access = &cmd->params.fwt;
852         lbs_deb_enter_args(LBS_DEB_CMD, "action %d", cmd_action);
853
854         cmd->command = cpu_to_le16(CMD_FWT_ACCESS);
855         cmd->size = cpu_to_le16(sizeof(struct cmd_ds_fwt_access) + S_DS_GEN);
856         cmd->result = 0;
857
858         if (pdata_buf)
859                 memcpy(fwt_access, pdata_buf, sizeof(*fwt_access));
860         else
861                 memset(fwt_access, 0, sizeof(*fwt_access));
862
863         fwt_access->action = cpu_to_le16(cmd_action);
864
865         lbs_deb_leave(LBS_DEB_CMD);
866         return 0;
867 }
868
869 static int wlan_cmd_mesh_access(wlan_private * priv,
870                                 struct cmd_ds_command *cmd,
871                                 u16 cmd_action, void *pdata_buf)
872 {
873         struct cmd_ds_mesh_access *mesh_access = &cmd->params.mesh;
874         lbs_deb_enter_args(LBS_DEB_CMD, "action %d", cmd_action);
875
876         cmd->command = cpu_to_le16(CMD_MESH_ACCESS);
877         cmd->size = cpu_to_le16(sizeof(struct cmd_ds_mesh_access) + S_DS_GEN);
878         cmd->result = 0;
879
880         if (pdata_buf)
881                 memcpy(mesh_access, pdata_buf, sizeof(*mesh_access));
882         else
883                 memset(mesh_access, 0, sizeof(*mesh_access));
884
885         mesh_access->action = cpu_to_le16(cmd_action);
886
887         lbs_deb_leave(LBS_DEB_CMD);
888         return 0;
889 }
890
891 void libertas_queue_cmd(wlan_adapter * adapter, struct cmd_ctrl_node *cmdnode, u8 addtail)
892 {
893         unsigned long flags;
894         struct cmd_ds_command *cmdptr;
895
896         lbs_deb_enter(LBS_DEB_HOST);
897
898         if (!cmdnode) {
899                 lbs_deb_host("QUEUE_CMD: cmdnode is NULL\n");
900                 goto done;
901         }
902
903         cmdptr = (struct cmd_ds_command *)cmdnode->bufvirtualaddr;
904         if (!cmdptr) {
905                 lbs_deb_host("QUEUE_CMD: cmdptr is NULL\n");
906                 goto done;
907         }
908
909         /* Exit_PS command needs to be queued in the header always. */
910         if (cmdptr->command == CMD_802_11_PS_MODE) {
911                 struct cmd_ds_802_11_ps_mode *psm = &cmdptr->params.psmode;
912                 if (psm->action == cpu_to_le16(CMD_SUBCMD_EXIT_PS)) {
913                         if (adapter->psstate != PS_STATE_FULL_POWER)
914                                 addtail = 0;
915                 }
916         }
917
918         spin_lock_irqsave(&adapter->driver_lock, flags);
919
920         if (addtail)
921                 list_add_tail((struct list_head *)cmdnode,
922                               &adapter->cmdpendingq);
923         else
924                 list_add((struct list_head *)cmdnode, &adapter->cmdpendingq);
925
926         spin_unlock_irqrestore(&adapter->driver_lock, flags);
927
928         lbs_deb_host("QUEUE_CMD: inserted command 0x%04x into cmdpendingq\n",
929                le16_to_cpu(((struct cmd_ds_gen*)cmdnode->bufvirtualaddr)->command));
930
931 done:
932         lbs_deb_leave(LBS_DEB_HOST);
933 }
934
935 /*
936  * TODO: Fix the issue when DownloadcommandToStation is being called the
937  * second time when the command times out. All the cmdptr->xxx are in little
938  * endian and therefore all the comparissions will fail.
939  * For now - we are not performing the endian conversion the second time - but
940  * for PS and DEEP_SLEEP we need to worry
941  */
942 static int DownloadcommandToStation(wlan_private * priv,
943                                     struct cmd_ctrl_node *cmdnode)
944 {
945         unsigned long flags;
946         struct cmd_ds_command *cmdptr;
947         wlan_adapter *adapter = priv->adapter;
948         int ret = 0;
949         u16 cmdsize;
950         u16 command;
951
952         lbs_deb_enter(LBS_DEB_HOST);
953
954         if (!adapter || !cmdnode) {
955                 lbs_deb_host("DNLD_CMD: adapter or cmdmode is NULL\n");
956                 if (cmdnode) {
957                         spin_lock_irqsave(&adapter->driver_lock, flags);
958                         __libertas_cleanup_and_insert_cmd(priv, cmdnode);
959                         spin_unlock_irqrestore(&adapter->driver_lock, flags);
960                 }
961                 ret = -1;
962                 goto done;
963         }
964
965         cmdptr = (struct cmd_ds_command *)cmdnode->bufvirtualaddr;
966
967         spin_lock_irqsave(&adapter->driver_lock, flags);
968         if (!cmdptr || !cmdptr->size) {
969                 lbs_deb_host("DNLD_CMD: cmdptr is NULL or zero\n");
970                 __libertas_cleanup_and_insert_cmd(priv, cmdnode);
971                 spin_unlock_irqrestore(&adapter->driver_lock, flags);
972                 ret = -1;
973                 goto done;
974         }
975
976         adapter->cur_cmd = cmdnode;
977         adapter->cur_cmd_retcode = 0;
978         spin_unlock_irqrestore(&adapter->driver_lock, flags);
979
980         cmdsize = cmdptr->size;
981         command = cpu_to_le16(cmdptr->command);
982
983         lbs_deb_host("DNLD_CMD: command 0x%04x, size %d, jiffies %lu\n",
984                     command, le16_to_cpu(cmdptr->size), jiffies);
985         lbs_deb_hex(LBS_DEB_HOST, "DNLD_CMD", cmdnode->bufvirtualaddr, cmdsize);
986
987         cmdnode->cmdwaitqwoken = 0;
988         cmdsize = cpu_to_le16(cmdsize);
989
990         ret = priv->hw_host_to_card(priv, MVMS_CMD, (u8 *) cmdptr, cmdsize);
991
992         if (ret != 0) {
993                 lbs_deb_host("DNLD_CMD: hw_host_to_card failed\n");
994                 spin_lock_irqsave(&adapter->driver_lock, flags);
995                 __libertas_cleanup_and_insert_cmd(priv, adapter->cur_cmd);
996                 adapter->cur_cmd = NULL;
997                 spin_unlock_irqrestore(&adapter->driver_lock, flags);
998                 ret = -1;
999                 goto done;
1000         }
1001
1002         lbs_deb_cmd("DNLD_CMD: sent command 0x%04x, jiffies %lu\n", command, jiffies);
1003
1004         /* Setup the timer after transmit command */
1005         if (command == CMD_802_11_SCAN || command == CMD_802_11_AUTHENTICATE
1006             || command == CMD_802_11_ASSOCIATE)
1007                 mod_timer(&adapter->command_timer, jiffies + (10*HZ));
1008         else
1009                 mod_timer(&adapter->command_timer, jiffies + (5*HZ));
1010
1011         ret = 0;
1012
1013 done:
1014         lbs_deb_leave_args(LBS_DEB_HOST, "ret %d", ret);
1015         return ret;
1016 }
1017
1018 static int wlan_cmd_mac_control(wlan_private * priv,
1019                                 struct cmd_ds_command *cmd)
1020 {
1021         struct cmd_ds_mac_control *mac = &cmd->params.macctrl;
1022
1023         lbs_deb_enter(LBS_DEB_CMD);
1024
1025         cmd->command = cpu_to_le16(CMD_MAC_CONTROL);
1026         cmd->size = cpu_to_le16(sizeof(struct cmd_ds_mac_control) + S_DS_GEN);
1027         mac->action = cpu_to_le16(priv->adapter->currentpacketfilter);
1028
1029         lbs_deb_cmd("MAC_CONTROL: action 0x%x, size %d\n",
1030                     le16_to_cpu(mac->action), le16_to_cpu(cmd->size));
1031
1032         lbs_deb_leave(LBS_DEB_CMD);
1033         return 0;
1034 }
1035
1036 /**
1037  *  This function inserts command node to cmdfreeq
1038  *  after cleans it. Requires adapter->driver_lock held.
1039  */
1040 void __libertas_cleanup_and_insert_cmd(wlan_private * priv, struct cmd_ctrl_node *ptempcmd)
1041 {
1042         wlan_adapter *adapter = priv->adapter;
1043
1044         if (!ptempcmd)
1045                 return;
1046
1047         cleanup_cmdnode(ptempcmd);
1048         list_add_tail((struct list_head *)ptempcmd, &adapter->cmdfreeq);
1049 }
1050
1051 static void libertas_cleanup_and_insert_cmd(wlan_private * priv, struct cmd_ctrl_node *ptempcmd)
1052 {
1053         unsigned long flags;
1054
1055         spin_lock_irqsave(&priv->adapter->driver_lock, flags);
1056         __libertas_cleanup_and_insert_cmd(priv, ptempcmd);
1057         spin_unlock_irqrestore(&priv->adapter->driver_lock, flags);
1058 }
1059
1060 int libertas_set_radio_control(wlan_private * priv)
1061 {
1062         int ret = 0;
1063
1064         lbs_deb_enter(LBS_DEB_CMD);
1065
1066         ret = libertas_prepare_and_send_command(priv,
1067                                     CMD_802_11_RADIO_CONTROL,
1068                                     CMD_ACT_SET,
1069                                     CMD_OPTION_WAITFORRSP, 0, NULL);
1070
1071         lbs_deb_cmd("RADIO_SET: radio %d, preamble %d\n",
1072                priv->adapter->radioon, priv->adapter->preamble);
1073
1074         lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
1075         return ret;
1076 }
1077
1078 int libertas_set_mac_packet_filter(wlan_private * priv)
1079 {
1080         int ret = 0;
1081
1082         lbs_deb_enter(LBS_DEB_CMD);
1083
1084         /* Send MAC control command to station */
1085         ret = libertas_prepare_and_send_command(priv,
1086                                     CMD_MAC_CONTROL, 0, 0, 0, NULL);
1087
1088         lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
1089         return ret;
1090 }
1091
1092 /**
1093  *  @brief This function prepare the command before send to firmware.
1094  *
1095  *  @param priv         A pointer to wlan_private structure
1096  *  @param cmd_no       command number
1097  *  @param cmd_action   command action: GET or SET
1098  *  @param wait_option  wait option: wait response or not
1099  *  @param cmd_oid      cmd oid: treated as sub command
1100  *  @param pdata_buf    A pointer to informaion buffer
1101  *  @return             0 or -1
1102  */
1103 int libertas_prepare_and_send_command(wlan_private * priv,
1104                           u16 cmd_no,
1105                           u16 cmd_action,
1106                           u16 wait_option, u32 cmd_oid, void *pdata_buf)
1107 {
1108         int ret = 0;
1109         wlan_adapter *adapter = priv->adapter;
1110         struct cmd_ctrl_node *cmdnode;
1111         struct cmd_ds_command *cmdptr;
1112         unsigned long flags;
1113
1114         lbs_deb_enter(LBS_DEB_HOST);
1115
1116         if (!adapter) {
1117                 lbs_deb_host("PREP_CMD: adapter is NULL\n");
1118                 ret = -1;
1119                 goto done;
1120         }
1121
1122         if (adapter->surpriseremoved) {
1123                 lbs_deb_host("PREP_CMD: card removed\n");
1124                 ret = -1;
1125                 goto done;
1126         }
1127
1128         cmdnode = libertas_get_free_cmd_ctrl_node(priv);
1129
1130         if (cmdnode == NULL) {
1131                 lbs_deb_host("PREP_CMD: cmdnode is NULL\n");
1132
1133                 /* Wake up main thread to execute next command */
1134                 wake_up_interruptible(&priv->waitq);
1135                 ret = -1;
1136                 goto done;
1137         }
1138
1139         libertas_set_cmd_ctrl_node(priv, cmdnode, cmd_oid, wait_option, pdata_buf);
1140
1141         cmdptr = (struct cmd_ds_command *)cmdnode->bufvirtualaddr;
1142
1143         lbs_deb_host("PREP_CMD: command 0x%04x\n", cmd_no);
1144
1145         if (!cmdptr) {
1146                 lbs_deb_host("PREP_CMD: cmdptr is NULL\n");
1147                 libertas_cleanup_and_insert_cmd(priv, cmdnode);
1148                 ret = -1;
1149                 goto done;
1150         }
1151
1152         /* Set sequence number, command and INT option */
1153         adapter->seqnum++;
1154         cmdptr->seqnum = cpu_to_le16(adapter->seqnum);
1155
1156         cmdptr->command = cpu_to_le16(cmd_no);
1157         cmdptr->result = 0;
1158
1159         switch (cmd_no) {
1160         case CMD_GET_HW_SPEC:
1161                 ret = wlan_cmd_hw_spec(priv, cmdptr);
1162                 break;
1163         case CMD_802_11_PS_MODE:
1164                 ret = wlan_cmd_802_11_ps_mode(priv, cmdptr, cmd_action);
1165                 break;
1166
1167         case CMD_802_11_SCAN:
1168                 ret = libertas_cmd_80211_scan(priv, cmdptr, pdata_buf);
1169                 break;
1170
1171         case CMD_MAC_CONTROL:
1172                 ret = wlan_cmd_mac_control(priv, cmdptr);
1173                 break;
1174
1175         case CMD_802_11_ASSOCIATE:
1176         case CMD_802_11_REASSOCIATE:
1177                 ret = libertas_cmd_80211_associate(priv, cmdptr, pdata_buf);
1178                 break;
1179
1180         case CMD_802_11_DEAUTHENTICATE:
1181                 ret = libertas_cmd_80211_deauthenticate(priv, cmdptr);
1182                 break;
1183
1184         case CMD_802_11_SET_WEP:
1185                 ret = wlan_cmd_802_11_set_wep(priv, cmdptr, cmd_action, pdata_buf);
1186                 break;
1187
1188         case CMD_802_11_AD_HOC_START:
1189                 ret = libertas_cmd_80211_ad_hoc_start(priv, cmdptr, pdata_buf);
1190                 break;
1191         case CMD_CODE_DNLD:
1192                 break;
1193
1194         case CMD_802_11_RESET:
1195                 ret = wlan_cmd_802_11_reset(priv, cmdptr, cmd_action);
1196                 break;
1197
1198         case CMD_802_11_GET_LOG:
1199                 ret = wlan_cmd_802_11_get_log(priv, cmdptr);
1200                 break;
1201
1202         case CMD_802_11_AUTHENTICATE:
1203                 ret = libertas_cmd_80211_authenticate(priv, cmdptr, pdata_buf);
1204                 break;
1205
1206         case CMD_802_11_GET_STAT:
1207                 ret = wlan_cmd_802_11_get_stat(priv, cmdptr);
1208                 break;
1209
1210         case CMD_802_11_SNMP_MIB:
1211                 ret = wlan_cmd_802_11_snmp_mib(priv, cmdptr,
1212                                                cmd_action, cmd_oid, pdata_buf);
1213                 break;
1214
1215         case CMD_MAC_REG_ACCESS:
1216         case CMD_BBP_REG_ACCESS:
1217         case CMD_RF_REG_ACCESS:
1218                 ret = wlan_cmd_reg_access(priv, cmdptr, cmd_action, pdata_buf);
1219                 break;
1220
1221         case CMD_802_11_RF_CHANNEL:
1222                 ret = wlan_cmd_802_11_rf_channel(priv, cmdptr,
1223                                                  cmd_action, pdata_buf);
1224                 break;
1225
1226         case CMD_802_11_RF_TX_POWER:
1227                 ret = wlan_cmd_802_11_rf_tx_power(priv, cmdptr,
1228                                                   cmd_action, pdata_buf);
1229                 break;
1230
1231         case CMD_802_11_RADIO_CONTROL:
1232                 ret = wlan_cmd_802_11_radio_control(priv, cmdptr, cmd_action);
1233                 break;
1234
1235         case CMD_802_11_DATA_RATE:
1236                 ret = wlan_cmd_802_11_data_rate(priv, cmdptr, cmd_action);
1237                 break;
1238         case CMD_802_11_RATE_ADAPT_RATESET:
1239                 ret = wlan_cmd_802_11_rate_adapt_rateset(priv,
1240                                                          cmdptr, cmd_action);
1241                 break;
1242
1243         case CMD_MAC_MULTICAST_ADR:
1244                 ret = wlan_cmd_mac_multicast_adr(priv, cmdptr, cmd_action);
1245                 break;
1246
1247         case CMD_802_11_AD_HOC_JOIN:
1248                 ret = libertas_cmd_80211_ad_hoc_join(priv, cmdptr, pdata_buf);
1249                 break;
1250
1251         case CMD_802_11_RSSI:
1252                 ret = wlan_cmd_802_11_rssi(priv, cmdptr);
1253                 break;
1254
1255         case CMD_802_11_AD_HOC_STOP:
1256                 ret = libertas_cmd_80211_ad_hoc_stop(priv, cmdptr);
1257                 break;
1258
1259         case CMD_802_11_ENABLE_RSN:
1260                 ret = wlan_cmd_802_11_enable_rsn(priv, cmdptr, cmd_action,
1261                                 pdata_buf);
1262                 break;
1263
1264         case CMD_802_11_KEY_MATERIAL:
1265                 ret = wlan_cmd_802_11_key_material(priv, cmdptr, cmd_action,
1266                                 cmd_oid, pdata_buf);
1267                 break;
1268
1269         case CMD_802_11_PAIRWISE_TSC:
1270                 break;
1271         case CMD_802_11_GROUP_TSC:
1272                 break;
1273
1274         case CMD_802_11_MAC_ADDRESS:
1275                 ret = wlan_cmd_802_11_mac_address(priv, cmdptr, cmd_action);
1276                 break;
1277
1278         case CMD_802_11_EEPROM_ACCESS:
1279                 ret = wlan_cmd_802_11_eeprom_access(priv, cmdptr,
1280                                                     cmd_action, pdata_buf);
1281                 break;
1282
1283         case CMD_802_11_SET_AFC:
1284         case CMD_802_11_GET_AFC:
1285
1286                 cmdptr->command = cpu_to_le16(cmd_no);
1287                 cmdptr->size = cpu_to_le16(sizeof(struct cmd_ds_802_11_afc) +
1288                                            S_DS_GEN);
1289
1290                 memmove(&cmdptr->params.afc,
1291                         pdata_buf, sizeof(struct cmd_ds_802_11_afc));
1292
1293                 ret = 0;
1294                 goto done;
1295
1296         case CMD_802_11D_DOMAIN_INFO:
1297                 ret = libertas_cmd_802_11d_domain_info(priv, cmdptr,
1298                                                    cmd_no, cmd_action);
1299                 break;
1300
1301         case CMD_802_11_SLEEP_PARAMS:
1302                 ret = wlan_cmd_802_11_sleep_params(priv, cmdptr, cmd_action);
1303                 break;
1304         case CMD_802_11_INACTIVITY_TIMEOUT:
1305                 ret = wlan_cmd_802_11_inactivity_timeout(priv, cmdptr,
1306                                                          cmd_action, pdata_buf);
1307                 libertas_set_cmd_ctrl_node(priv, cmdnode, 0, 0, pdata_buf);
1308                 break;
1309
1310         case CMD_802_11_TPC_CFG:
1311                 cmdptr->command = cpu_to_le16(CMD_802_11_TPC_CFG);
1312                 cmdptr->size =
1313                     cpu_to_le16(sizeof(struct cmd_ds_802_11_tpc_cfg) +
1314                                      S_DS_GEN);
1315
1316                 memmove(&cmdptr->params.tpccfg,
1317                         pdata_buf, sizeof(struct cmd_ds_802_11_tpc_cfg));
1318
1319                 ret = 0;
1320                 break;
1321         case CMD_802_11_LED_GPIO_CTRL:
1322                 {
1323                         struct mrvlietypes_ledgpio *gpio =
1324                             (struct mrvlietypes_ledgpio*)
1325                             cmdptr->params.ledgpio.data;
1326
1327                         memmove(&cmdptr->params.ledgpio,
1328                                 pdata_buf,
1329                                 sizeof(struct cmd_ds_802_11_led_ctrl));
1330
1331                         cmdptr->command =
1332                             cpu_to_le16(CMD_802_11_LED_GPIO_CTRL);
1333
1334 #define ACTION_NUMLED_TLVTYPE_LEN_FIELDS_LEN 8
1335                         cmdptr->size =
1336                             cpu_to_le16(gpio->header.len + S_DS_GEN +
1337                                              ACTION_NUMLED_TLVTYPE_LEN_FIELDS_LEN);
1338                         gpio->header.len = cpu_to_le16(gpio->header.len);
1339
1340                         ret = 0;
1341                         break;
1342                 }
1343         case CMD_802_11_PWR_CFG:
1344                 cmdptr->command = cpu_to_le16(CMD_802_11_PWR_CFG);
1345                 cmdptr->size =
1346                     cpu_to_le16(sizeof(struct cmd_ds_802_11_pwr_cfg) +
1347                                      S_DS_GEN);
1348                 memmove(&cmdptr->params.pwrcfg, pdata_buf,
1349                         sizeof(struct cmd_ds_802_11_pwr_cfg));
1350
1351                 ret = 0;
1352                 break;
1353         case CMD_BT_ACCESS:
1354                 ret = wlan_cmd_bt_access(priv, cmdptr, cmd_action, pdata_buf);
1355                 break;
1356
1357         case CMD_FWT_ACCESS:
1358                 ret = wlan_cmd_fwt_access(priv, cmdptr, cmd_action, pdata_buf);
1359                 break;
1360
1361         case CMD_MESH_ACCESS:
1362                 ret = wlan_cmd_mesh_access(priv, cmdptr, cmd_action, pdata_buf);
1363                 break;
1364
1365         case CMD_GET_TSF:
1366                 cmdptr->command = cpu_to_le16(CMD_GET_TSF);
1367                 cmdptr->size = cpu_to_le16(sizeof(struct cmd_ds_get_tsf) +
1368                                            S_DS_GEN);
1369                 ret = 0;
1370                 break;
1371         case CMD_802_11_TX_RATE_QUERY:
1372                 cmdptr->command = cpu_to_le16(CMD_802_11_TX_RATE_QUERY);
1373                 cmdptr->size = cpu_to_le16(sizeof(struct cmd_tx_rate_query) +
1374                                            S_DS_GEN);
1375                 adapter->txrate = 0;
1376                 ret = 0;
1377                 break;
1378         default:
1379                 lbs_deb_host("PREP_CMD: unknown command 0x%04x\n", cmd_no);
1380                 ret = -1;
1381                 break;
1382         }
1383
1384         /* return error, since the command preparation failed */
1385         if (ret != 0) {
1386                 lbs_deb_host("PREP_CMD: command preparation failed\n");
1387                 libertas_cleanup_and_insert_cmd(priv, cmdnode);
1388                 ret = -1;
1389                 goto done;
1390         }
1391
1392         cmdnode->cmdwaitqwoken = 0;
1393
1394         libertas_queue_cmd(adapter, cmdnode, 1);
1395         adapter->nr_cmd_pending++;
1396         wake_up_interruptible(&priv->waitq);
1397
1398         if (wait_option & CMD_OPTION_WAITFORRSP) {
1399                 lbs_deb_host("PREP_CMD: wait for response\n");
1400                 might_sleep();
1401                 wait_event_interruptible(cmdnode->cmdwait_q,
1402                                          cmdnode->cmdwaitqwoken);
1403         }
1404
1405         spin_lock_irqsave(&adapter->driver_lock, flags);
1406         if (adapter->cur_cmd_retcode) {
1407                 lbs_deb_host("PREP_CMD: command failed with return code %d\n",
1408                        adapter->cur_cmd_retcode);
1409                 adapter->cur_cmd_retcode = 0;
1410                 ret = -1;
1411         }
1412         spin_unlock_irqrestore(&adapter->driver_lock, flags);
1413
1414 done:
1415         lbs_deb_leave_args(LBS_DEB_HOST, "ret %d", ret);
1416         return ret;
1417 }
1418 EXPORT_SYMBOL_GPL(libertas_prepare_and_send_command);
1419
1420 /**
1421  *  @brief This function allocates the command buffer and link
1422  *  it to command free queue.
1423  *
1424  *  @param priv         A pointer to wlan_private structure
1425  *  @return             0 or -1
1426  */
1427 int libertas_allocate_cmd_buffer(wlan_private * priv)
1428 {
1429         int ret = 0;
1430         u32 ulbufsize;
1431         u32 i;
1432         struct cmd_ctrl_node *tempcmd_array;
1433         u8 *ptempvirtualaddr;
1434         wlan_adapter *adapter = priv->adapter;
1435
1436         lbs_deb_enter(LBS_DEB_HOST);
1437
1438         /* Allocate and initialize cmdCtrlNode */
1439         ulbufsize = sizeof(struct cmd_ctrl_node) * MRVDRV_NUM_OF_CMD_BUFFER;
1440
1441         if (!(tempcmd_array = kzalloc(ulbufsize, GFP_KERNEL))) {
1442                 lbs_deb_host("ALLOC_CMD_BUF: tempcmd_array is NULL\n");
1443                 ret = -1;
1444                 goto done;
1445         }
1446         adapter->cmd_array = tempcmd_array;
1447
1448         /* Allocate and initialize command buffers */
1449         ulbufsize = MRVDRV_SIZE_OF_CMD_BUFFER;
1450         for (i = 0; i < MRVDRV_NUM_OF_CMD_BUFFER; i++) {
1451                 if (!(ptempvirtualaddr = kzalloc(ulbufsize, GFP_KERNEL))) {
1452                         lbs_deb_host("ALLOC_CMD_BUF: ptempvirtualaddr is NULL\n");
1453                         ret = -1;
1454                         goto done;
1455                 }
1456
1457                 /* Update command buffer virtual */
1458                 tempcmd_array[i].bufvirtualaddr = ptempvirtualaddr;
1459         }
1460
1461         for (i = 0; i < MRVDRV_NUM_OF_CMD_BUFFER; i++) {
1462                 init_waitqueue_head(&tempcmd_array[i].cmdwait_q);
1463                 libertas_cleanup_and_insert_cmd(priv, &tempcmd_array[i]);
1464         }
1465
1466         ret = 0;
1467
1468 done:
1469         lbs_deb_leave_args(LBS_DEB_HOST, "ret %d", ret);
1470         return ret;
1471 }
1472
1473 /**
1474  *  @brief This function frees the command buffer.
1475  *
1476  *  @param priv         A pointer to wlan_private structure
1477  *  @return             0 or -1
1478  */
1479 int libertas_free_cmd_buffer(wlan_private * priv)
1480 {
1481         u32 ulbufsize; /* Someone needs to die for this. Slowly and painfully */
1482         unsigned int i;
1483         struct cmd_ctrl_node *tempcmd_array;
1484         wlan_adapter *adapter = priv->adapter;
1485
1486         lbs_deb_enter(LBS_DEB_HOST);
1487
1488         /* need to check if cmd array is allocated or not */
1489         if (adapter->cmd_array == NULL) {
1490                 lbs_deb_host("FREE_CMD_BUF: cmd_array is NULL\n");
1491                 goto done;
1492         }
1493
1494         tempcmd_array = adapter->cmd_array;
1495
1496         /* Release shared memory buffers */
1497         ulbufsize = MRVDRV_SIZE_OF_CMD_BUFFER;
1498         for (i = 0; i < MRVDRV_NUM_OF_CMD_BUFFER; i++) {
1499                 if (tempcmd_array[i].bufvirtualaddr) {
1500                         kfree(tempcmd_array[i].bufvirtualaddr);
1501                         tempcmd_array[i].bufvirtualaddr = NULL;
1502                 }
1503         }
1504
1505         /* Release cmd_ctrl_node */
1506         if (adapter->cmd_array) {
1507                 kfree(adapter->cmd_array);
1508                 adapter->cmd_array = NULL;
1509         }
1510
1511 done:
1512         lbs_deb_leave(LBS_DEB_HOST);
1513         return 0;
1514 }
1515
1516 /**
1517  *  @brief This function gets a free command node if available in
1518  *  command free queue.
1519  *
1520  *  @param priv         A pointer to wlan_private structure
1521  *  @return cmd_ctrl_node A pointer to cmd_ctrl_node structure or NULL
1522  */
1523 struct cmd_ctrl_node *libertas_get_free_cmd_ctrl_node(wlan_private * priv)
1524 {
1525         struct cmd_ctrl_node *tempnode;
1526         wlan_adapter *adapter = priv->adapter;
1527         unsigned long flags;
1528
1529         lbs_deb_enter(LBS_DEB_HOST);
1530
1531         if (!adapter)
1532                 return NULL;
1533
1534         spin_lock_irqsave(&adapter->driver_lock, flags);
1535
1536         if (!list_empty(&adapter->cmdfreeq)) {
1537                 tempnode = (struct cmd_ctrl_node *)adapter->cmdfreeq.next;
1538                 list_del((struct list_head *)tempnode);
1539         } else {
1540                 lbs_deb_host("GET_CMD_NODE: cmd_ctrl_node is not available\n");
1541                 tempnode = NULL;
1542         }
1543
1544         spin_unlock_irqrestore(&adapter->driver_lock, flags);
1545
1546         if (tempnode)
1547                 cleanup_cmdnode(tempnode);
1548
1549         lbs_deb_leave(LBS_DEB_HOST);
1550         return tempnode;
1551 }
1552
1553 /**
1554  *  @brief This function cleans command node.
1555  *
1556  *  @param ptempnode    A pointer to cmdCtrlNode structure
1557  *  @return             n/a
1558  */
1559 static void cleanup_cmdnode(struct cmd_ctrl_node *ptempnode)
1560 {
1561         lbs_deb_enter(LBS_DEB_HOST);
1562
1563         if (!ptempnode)
1564                 return;
1565         ptempnode->cmdwaitqwoken = 1;
1566         wake_up_interruptible(&ptempnode->cmdwait_q);
1567         ptempnode->status = 0;
1568         ptempnode->cmd_oid = (u32) 0;
1569         ptempnode->wait_option = 0;
1570         ptempnode->pdata_buf = NULL;
1571
1572         if (ptempnode->bufvirtualaddr != NULL)
1573                 memset(ptempnode->bufvirtualaddr, 0, MRVDRV_SIZE_OF_CMD_BUFFER);
1574
1575         lbs_deb_leave(LBS_DEB_HOST);
1576 }
1577
1578 /**
1579  *  @brief This function initializes the command node.
1580  *
1581  *  @param priv         A pointer to wlan_private structure
1582  *  @param ptempnode    A pointer to cmd_ctrl_node structure
1583  *  @param cmd_oid      cmd oid: treated as sub command
1584  *  @param wait_option  wait option: wait response or not
1585  *  @param pdata_buf    A pointer to informaion buffer
1586  *  @return             0 or -1
1587  */
1588 void libertas_set_cmd_ctrl_node(wlan_private * priv,
1589                     struct cmd_ctrl_node *ptempnode,
1590                     u32 cmd_oid, u16 wait_option, void *pdata_buf)
1591 {
1592         lbs_deb_enter(LBS_DEB_HOST);
1593
1594         if (!ptempnode)
1595                 return;
1596
1597         ptempnode->cmd_oid = cmd_oid;
1598         ptempnode->wait_option = wait_option;
1599         ptempnode->pdata_buf = pdata_buf;
1600
1601         lbs_deb_leave(LBS_DEB_HOST);
1602 }
1603
1604 /**
1605  *  @brief This function executes next command in command
1606  *  pending queue. It will put fimware back to PS mode
1607  *  if applicable.
1608  *
1609  *  @param priv     A pointer to wlan_private structure
1610  *  @return        0 or -1
1611  */
1612 int libertas_execute_next_command(wlan_private * priv)
1613 {
1614         wlan_adapter *adapter = priv->adapter;
1615         struct cmd_ctrl_node *cmdnode = NULL;
1616         struct cmd_ds_command *cmdptr;
1617         unsigned long flags;
1618         int ret = 0;
1619
1620         // Debug group is LBS_DEB_THREAD and not LBS_DEB_HOST, because the
1621         // only caller to us is libertas_thread() and we get even when a
1622         // data packet is received
1623         lbs_deb_enter(LBS_DEB_THREAD);
1624
1625         spin_lock_irqsave(&adapter->driver_lock, flags);
1626
1627         if (adapter->cur_cmd) {
1628                 lbs_pr_alert( "EXEC_NEXT_CMD: already processing command!\n");
1629                 spin_unlock_irqrestore(&adapter->driver_lock, flags);
1630                 ret = -1;
1631                 goto done;
1632         }
1633
1634         if (!list_empty(&adapter->cmdpendingq)) {
1635                 cmdnode = (struct cmd_ctrl_node *)
1636                     adapter->cmdpendingq.next;
1637         }
1638
1639         spin_unlock_irqrestore(&adapter->driver_lock, flags);
1640
1641         if (cmdnode) {
1642                 cmdptr = (struct cmd_ds_command *)cmdnode->bufvirtualaddr;
1643
1644                 if (is_command_allowed_in_ps(cmdptr->command)) {
1645                         if ((adapter->psstate == PS_STATE_SLEEP) ||
1646                             (adapter->psstate == PS_STATE_PRE_SLEEP)) {
1647                                 lbs_deb_host(
1648                                        "EXEC_NEXT_CMD: cannot send cmd 0x%04x in psstate %d\n",
1649                                        le16_to_cpu(cmdptr->command),
1650                                        adapter->psstate);
1651                                 ret = -1;
1652                                 goto done;
1653                         }
1654                         lbs_deb_host("EXEC_NEXT_CMD: OK to send command "
1655                                "0x%04x in psstate %d\n",
1656                                     le16_to_cpu(cmdptr->command),
1657                                     adapter->psstate);
1658                 } else if (adapter->psstate != PS_STATE_FULL_POWER) {
1659                         /*
1660                          * 1. Non-PS command:
1661                          * Queue it. set needtowakeup to TRUE if current state
1662                          * is SLEEP, otherwise call libertas_ps_wakeup to send Exit_PS.
1663                          * 2. PS command but not Exit_PS:
1664                          * Ignore it.
1665                          * 3. PS command Exit_PS:
1666                          * Set needtowakeup to TRUE if current state is SLEEP,
1667                          * otherwise send this command down to firmware
1668                          * immediately.
1669                          */
1670                         if (cmdptr->command !=
1671                             cpu_to_le16(CMD_802_11_PS_MODE)) {
1672                                 /*  Prepare to send Exit PS,
1673                                  *  this non PS command will be sent later */
1674                                 if ((adapter->psstate == PS_STATE_SLEEP)
1675                                     || (adapter->psstate == PS_STATE_PRE_SLEEP)
1676                                     ) {
1677                                         /* w/ new scheme, it will not reach here.
1678                                            since it is blocked in main_thread. */
1679                                         adapter->needtowakeup = 1;
1680                                 } else
1681                                         libertas_ps_wakeup(priv, 0);
1682
1683                                 ret = 0;
1684                                 goto done;
1685                         } else {
1686                                 /*
1687                                  * PS command. Ignore it if it is not Exit_PS.
1688                                  * otherwise send it down immediately.
1689                                  */
1690                                 struct cmd_ds_802_11_ps_mode *psm =
1691                                     &cmdptr->params.psmode;
1692
1693                                 lbs_deb_host(
1694                                        "EXEC_NEXT_CMD: PS cmd, action 0x%02x\n",
1695                                        psm->action);
1696                                 if (psm->action !=
1697                                     cpu_to_le16(CMD_SUBCMD_EXIT_PS)) {
1698                                         lbs_deb_host(
1699                                                "EXEC_NEXT_CMD: ignore ENTER_PS cmd\n");
1700                                         list_del((struct list_head *)cmdnode);
1701                                         libertas_cleanup_and_insert_cmd(priv, cmdnode);
1702
1703                                         ret = 0;
1704                                         goto done;
1705                                 }
1706
1707                                 if ((adapter->psstate == PS_STATE_SLEEP) ||
1708                                     (adapter->psstate == PS_STATE_PRE_SLEEP)) {
1709                                         lbs_deb_host(
1710                                                "EXEC_NEXT_CMD: ignore EXIT_PS cmd in sleep\n");
1711                                         list_del((struct list_head *)cmdnode);
1712                                         libertas_cleanup_and_insert_cmd(priv, cmdnode);
1713                                         adapter->needtowakeup = 1;
1714
1715                                         ret = 0;
1716                                         goto done;
1717                                 }
1718
1719                                 lbs_deb_host(
1720                                        "EXEC_NEXT_CMD: sending EXIT_PS\n");
1721                         }
1722                 }
1723                 list_del((struct list_head *)cmdnode);
1724                 lbs_deb_host("EXEC_NEXT_CMD: sending command 0x%04x\n",
1725                             le16_to_cpu(cmdptr->command));
1726                 DownloadcommandToStation(priv, cmdnode);
1727         } else {
1728                 /*
1729                  * check if in power save mode, if yes, put the device back
1730                  * to PS mode
1731                  */
1732                 if ((adapter->psmode != WLAN802_11POWERMODECAM) &&
1733                     (adapter->psstate == PS_STATE_FULL_POWER) &&
1734                     (adapter->connect_status == LIBERTAS_CONNECTED)) {
1735                         if (adapter->secinfo.WPAenabled ||
1736                             adapter->secinfo.WPA2enabled) {
1737                                 /* check for valid WPA group keys */
1738                                 if (adapter->wpa_mcast_key.len ||
1739                                     adapter->wpa_unicast_key.len) {
1740                                         lbs_deb_host(
1741                                                "EXEC_NEXT_CMD: WPA enabled and GTK_SET"
1742                                                " go back to PS_SLEEP");
1743                                         libertas_ps_sleep(priv, 0);
1744                                 }
1745                         } else {
1746                                 lbs_deb_host(
1747                                        "EXEC_NEXT_CMD: cmdpendingq empty, "
1748                                        "go back to PS_SLEEP");
1749                                 libertas_ps_sleep(priv, 0);
1750                         }
1751                 }
1752         }
1753
1754         ret = 0;
1755 done:
1756         lbs_deb_leave(LBS_DEB_THREAD);
1757         return ret;
1758 }
1759
1760 void libertas_send_iwevcustom_event(wlan_private * priv, s8 * str)
1761 {
1762         union iwreq_data iwrq;
1763         u8 buf[50];
1764
1765         lbs_deb_enter(LBS_DEB_WEXT);
1766
1767         memset(&iwrq, 0, sizeof(union iwreq_data));
1768         memset(buf, 0, sizeof(buf));
1769
1770         snprintf(buf, sizeof(buf) - 1, "%s", str);
1771
1772         iwrq.data.length = strlen(buf) + 1 + IW_EV_LCP_LEN;
1773
1774         /* Send Event to upper layer */
1775         lbs_deb_wext("event indication string %s\n", (char *)buf);
1776         lbs_deb_wext("event indication length %d\n", iwrq.data.length);
1777         lbs_deb_wext("sending wireless event IWEVCUSTOM for %s\n", str);
1778
1779         wireless_send_event(priv->dev, IWEVCUSTOM, &iwrq, buf);
1780
1781         lbs_deb_leave(LBS_DEB_WEXT);
1782 }
1783
1784 static int sendconfirmsleep(wlan_private * priv, u8 * cmdptr, u16 size)
1785 {
1786         unsigned long flags;
1787         wlan_adapter *adapter = priv->adapter;
1788         int ret = 0;
1789
1790         lbs_deb_enter(LBS_DEB_HOST);
1791
1792         lbs_deb_host("SEND_SLEEPC_CMD: before download, cmd size %d\n",
1793                size);
1794
1795         lbs_deb_hex(LBS_DEB_HOST, "sleep confirm command", cmdptr, size);
1796
1797         ret = priv->hw_host_to_card(priv, MVMS_CMD, cmdptr, size);
1798         priv->dnld_sent = DNLD_RES_RECEIVED;
1799
1800         spin_lock_irqsave(&adapter->driver_lock, flags);
1801         if (adapter->intcounter || adapter->currenttxskb)
1802                 lbs_deb_host("SEND_SLEEPC_CMD: intcounter %d, currenttxskb %p\n",
1803                        adapter->intcounter, adapter->currenttxskb);
1804         spin_unlock_irqrestore(&adapter->driver_lock, flags);
1805
1806         if (ret) {
1807                 lbs_pr_alert(
1808                        "SEND_SLEEPC_CMD: Host to Card failed for Confirm Sleep\n");
1809         } else {
1810                 spin_lock_irqsave(&adapter->driver_lock, flags);
1811                 if (!adapter->intcounter) {
1812                         adapter->psstate = PS_STATE_SLEEP;
1813                 } else {
1814                         lbs_deb_host("SEND_SLEEPC_CMD: after sent, intcounter %d\n",
1815                                adapter->intcounter);
1816                 }
1817                 spin_unlock_irqrestore(&adapter->driver_lock, flags);
1818
1819                 lbs_deb_host("SEND_SLEEPC_CMD: sent confirm sleep\n");
1820         }
1821
1822         lbs_deb_leave_args(LBS_DEB_HOST, "ret %d", ret);
1823         return ret;
1824 }
1825
1826 void libertas_ps_sleep(wlan_private * priv, int wait_option)
1827 {
1828         lbs_deb_enter(LBS_DEB_HOST);
1829
1830         /*
1831          * PS is currently supported only in Infrastructure mode
1832          * Remove this check if it is to be supported in IBSS mode also
1833          */
1834
1835         libertas_prepare_and_send_command(priv, CMD_802_11_PS_MODE,
1836                               CMD_SUBCMD_ENTER_PS, wait_option, 0, NULL);
1837
1838         lbs_deb_leave(LBS_DEB_HOST);
1839 }
1840
1841 /**
1842  *  @brief This function sends Exit_PS command to firmware.
1843  *
1844  *  @param priv         A pointer to wlan_private structure
1845  *  @param wait_option  wait response or not
1846  *  @return             n/a
1847  */
1848 void libertas_ps_wakeup(wlan_private * priv, int wait_option)
1849 {
1850         __le32 Localpsmode;
1851
1852         lbs_deb_enter(LBS_DEB_HOST);
1853
1854         Localpsmode = cpu_to_le32(WLAN802_11POWERMODECAM);
1855
1856         libertas_prepare_and_send_command(priv, CMD_802_11_PS_MODE,
1857                               CMD_SUBCMD_EXIT_PS,
1858                               wait_option, 0, &Localpsmode);
1859
1860         lbs_deb_leave(LBS_DEB_HOST);
1861 }
1862
1863 /**
1864  *  @brief This function checks condition and prepares to
1865  *  send sleep confirm command to firmware if ok.
1866  *
1867  *  @param priv         A pointer to wlan_private structure
1868  *  @param psmode       Power Saving mode
1869  *  @return             n/a
1870  */
1871 void libertas_ps_confirm_sleep(wlan_private * priv, u16 psmode)
1872 {
1873         unsigned long flags =0;
1874         wlan_adapter *adapter = priv->adapter;
1875         u8 allowed = 1;
1876
1877         lbs_deb_enter(LBS_DEB_HOST);
1878
1879         if (priv->dnld_sent) {
1880                 allowed = 0;
1881                 lbs_deb_host("dnld_sent was set");
1882         }
1883
1884         spin_lock_irqsave(&adapter->driver_lock, flags);
1885         if (adapter->cur_cmd) {
1886                 allowed = 0;
1887                 lbs_deb_host("cur_cmd was set");
1888         }
1889         if (adapter->intcounter > 0) {
1890                 allowed = 0;
1891                 lbs_deb_host("intcounter %d", adapter->intcounter);
1892         }
1893         spin_unlock_irqrestore(&adapter->driver_lock, flags);
1894
1895         if (allowed) {
1896                 lbs_deb_host("sending libertas_ps_confirm_sleep\n");
1897                 sendconfirmsleep(priv, (u8 *) & adapter->libertas_ps_confirm_sleep,
1898                                  sizeof(struct PS_CMD_ConfirmSleep));
1899         } else {
1900                 lbs_deb_host("sleep confirm has been delayed\n");
1901         }
1902
1903         lbs_deb_leave(LBS_DEB_HOST);
1904 }