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