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