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