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