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