libertas: add opaque extra argument to cmd callback function
[linux-2.6/openmoko-kernel/knife-kernel.git] / drivers / net / wireless / libertas / cmd.c
blob228e3fee20fb4d9dbc18d3a8b001df2a5982eb0d
1 /**
2 * This file contains the handling of command.
3 * It prepares command and sends it to firmware when it is ready.
4 */
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"
15 static void cleanup_cmdnode(struct cmd_ctrl_node *ptempnode);
16 struct cmd_ctrl_node *lbs_get_cmd_ctrl_node(struct lbs_private *priv);
17 void lbs_set_cmd_ctrl_node(struct lbs_private *priv,
18 struct cmd_ctrl_node *ptempnode,
19 u16 wait_option, void *pdata_buf);
22 static u16 commands_allowed_in_ps[] = {
23 CMD_802_11_RSSI,
26 /**
27 * @brief This function checks if the commans is allowed
28 * in PS mode not.
30 * @param command the command ID
31 * @return TRUE or FALSE
33 static u8 is_command_allowed_in_ps(__le16 command)
35 int i;
37 for (i = 0; i < ARRAY_SIZE(commands_allowed_in_ps); i++) {
38 if (command == cpu_to_le16(commands_allowed_in_ps[i]))
39 return 1;
42 return 0;
45 static int lbs_cmd_hw_spec(struct lbs_private *priv, struct cmd_ds_command *cmd)
47 struct cmd_ds_get_hw_spec *hwspec = &cmd->params.hwspec;
49 lbs_deb_enter(LBS_DEB_CMD);
51 cmd->command = cpu_to_le16(CMD_GET_HW_SPEC);
52 cmd->size = cpu_to_le16(sizeof(struct cmd_ds_get_hw_spec) + S_DS_GEN);
53 memcpy(hwspec->permanentaddr, priv->current_addr, ETH_ALEN);
55 lbs_deb_leave(LBS_DEB_CMD);
56 return 0;
59 static int lbs_cmd_802_11_ps_mode(struct lbs_private *priv,
60 struct cmd_ds_command *cmd,
61 u16 cmd_action)
63 struct cmd_ds_802_11_ps_mode *psm = &cmd->params.psmode;
65 lbs_deb_enter(LBS_DEB_CMD);
67 cmd->command = cpu_to_le16(CMD_802_11_PS_MODE);
68 cmd->size = cpu_to_le16(sizeof(struct cmd_ds_802_11_ps_mode) +
69 S_DS_GEN);
70 psm->action = cpu_to_le16(cmd_action);
71 psm->multipledtim = 0;
72 switch (cmd_action) {
73 case CMD_SUBCMD_ENTER_PS:
74 lbs_deb_cmd("PS command:" "SubCode- Enter PS\n");
76 psm->locallisteninterval = 0;
77 psm->nullpktinterval = 0;
78 psm->multipledtim =
79 cpu_to_le16(MRVDRV_DEFAULT_MULTIPLE_DTIM);
80 break;
82 case CMD_SUBCMD_EXIT_PS:
83 lbs_deb_cmd("PS command:" "SubCode- Exit PS\n");
84 break;
86 case CMD_SUBCMD_SLEEP_CONFIRMED:
87 lbs_deb_cmd("PS command: SubCode- sleep confirm\n");
88 break;
90 default:
91 break;
94 lbs_deb_leave(LBS_DEB_CMD);
95 return 0;
98 static int lbs_cmd_802_11_inactivity_timeout(struct lbs_private *priv,
99 struct cmd_ds_command *cmd,
100 u16 cmd_action, void *pdata_buf)
102 u16 *timeout = pdata_buf;
104 lbs_deb_enter(LBS_DEB_CMD);
106 cmd->command = cpu_to_le16(CMD_802_11_INACTIVITY_TIMEOUT);
107 cmd->size =
108 cpu_to_le16(sizeof(struct cmd_ds_802_11_inactivity_timeout)
109 + S_DS_GEN);
111 cmd->params.inactivity_timeout.action = cpu_to_le16(cmd_action);
113 if (cmd_action)
114 cmd->params.inactivity_timeout.timeout = cpu_to_le16(*timeout);
115 else
116 cmd->params.inactivity_timeout.timeout = 0;
118 lbs_deb_leave(LBS_DEB_CMD);
119 return 0;
122 static int lbs_cmd_802_11_sleep_params(struct lbs_private *priv,
123 struct cmd_ds_command *cmd,
124 u16 cmd_action)
126 struct cmd_ds_802_11_sleep_params *sp = &cmd->params.sleep_params;
128 lbs_deb_enter(LBS_DEB_CMD);
130 cmd->size = cpu_to_le16((sizeof(struct cmd_ds_802_11_sleep_params)) +
131 S_DS_GEN);
132 cmd->command = cpu_to_le16(CMD_802_11_SLEEP_PARAMS);
134 if (cmd_action == CMD_ACT_GET) {
135 memset(&priv->sp, 0, sizeof(struct sleep_params));
136 memset(sp, 0, sizeof(struct cmd_ds_802_11_sleep_params));
137 sp->action = cpu_to_le16(cmd_action);
138 } else if (cmd_action == CMD_ACT_SET) {
139 sp->action = cpu_to_le16(cmd_action);
140 sp->error = cpu_to_le16(priv->sp.sp_error);
141 sp->offset = cpu_to_le16(priv->sp.sp_offset);
142 sp->stabletime = cpu_to_le16(priv->sp.sp_stabletime);
143 sp->calcontrol = (u8) priv->sp.sp_calcontrol;
144 sp->externalsleepclk = (u8) priv->sp.sp_extsleepclk;
145 sp->reserved = cpu_to_le16(priv->sp.sp_reserved);
148 lbs_deb_leave(LBS_DEB_CMD);
149 return 0;
152 static int lbs_cmd_802_11_set_wep(struct lbs_private *priv,
153 struct cmd_ds_command *cmd,
154 u32 cmd_act,
155 void * pdata_buf)
157 struct cmd_ds_802_11_set_wep *wep = &cmd->params.wep;
158 int ret = 0;
159 struct assoc_request * assoc_req = pdata_buf;
161 lbs_deb_enter(LBS_DEB_CMD);
163 cmd->command = cpu_to_le16(CMD_802_11_SET_WEP);
164 cmd->size = cpu_to_le16(sizeof(*wep) + S_DS_GEN);
166 if (cmd_act == CMD_ACT_ADD) {
167 int i;
169 if (!assoc_req) {
170 lbs_deb_cmd("Invalid association request!");
171 ret = -1;
172 goto done;
175 wep->action = cpu_to_le16(CMD_ACT_ADD);
177 /* default tx key index */
178 wep->keyindex = cpu_to_le16((u16)(assoc_req->wep_tx_keyidx &
179 (u32)CMD_WEP_KEY_INDEX_MASK));
181 /* Copy key types and material to host command structure */
182 for (i = 0; i < 4; i++) {
183 struct enc_key * pkey = &assoc_req->wep_keys[i];
185 switch (pkey->len) {
186 case KEY_LEN_WEP_40:
187 wep->keytype[i] = CMD_TYPE_WEP_40_BIT;
188 memmove(&wep->keymaterial[i], pkey->key,
189 pkey->len);
190 lbs_deb_cmd("SET_WEP: add key %d (40 bit)\n", i);
191 break;
192 case KEY_LEN_WEP_104:
193 wep->keytype[i] = CMD_TYPE_WEP_104_BIT;
194 memmove(&wep->keymaterial[i], pkey->key,
195 pkey->len);
196 lbs_deb_cmd("SET_WEP: add key %d (104 bit)\n", i);
197 break;
198 case 0:
199 break;
200 default:
201 lbs_deb_cmd("SET_WEP: invalid key %d, length %d\n",
202 i, pkey->len);
203 ret = -1;
204 goto done;
205 break;
208 } else if (cmd_act == CMD_ACT_REMOVE) {
209 /* ACT_REMOVE clears _all_ WEP keys */
210 wep->action = cpu_to_le16(CMD_ACT_REMOVE);
212 /* default tx key index */
213 wep->keyindex = cpu_to_le16((u16)(priv->wep_tx_keyidx &
214 (u32)CMD_WEP_KEY_INDEX_MASK));
215 lbs_deb_cmd("SET_WEP: remove key %d\n", priv->wep_tx_keyidx);
218 ret = 0;
220 done:
221 lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
222 return ret;
225 static int lbs_cmd_802_11_enable_rsn(struct lbs_private *priv,
226 struct cmd_ds_command *cmd,
227 u16 cmd_action,
228 void * pdata_buf)
230 struct cmd_ds_802_11_enable_rsn *penableRSN = &cmd->params.enbrsn;
231 u32 * enable = pdata_buf;
233 lbs_deb_enter(LBS_DEB_CMD);
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);
239 if (cmd_action == CMD_ACT_SET) {
240 if (*enable)
241 penableRSN->enable = cpu_to_le16(CMD_ENABLE_RSN);
242 else
243 penableRSN->enable = cpu_to_le16(CMD_DISABLE_RSN);
244 lbs_deb_cmd("ENABLE_RSN: %d\n", *enable);
247 lbs_deb_leave(LBS_DEB_CMD);
248 return 0;
252 static ssize_t lbs_tlv_size(const u8 *tlv, u16 size)
254 ssize_t pos = 0;
255 struct mrvlietypesheader *tlv_h;
256 while (pos < size) {
257 u16 length;
258 tlv_h = (struct mrvlietypesheader *) tlv;
259 if (tlv_h->len == 0)
260 return pos;
261 length = le16_to_cpu(tlv_h->len) +
262 sizeof(struct mrvlietypesheader);
263 pos += length;
264 tlv += length;
266 return pos;
270 static void lbs_cmd_802_11_subscribe_event(struct lbs_private *priv,
271 struct cmd_ds_command *cmd, u16 cmd_action,
272 void *pdata_buf)
274 struct cmd_ds_802_11_subscribe_event *events =
275 (struct cmd_ds_802_11_subscribe_event *) pdata_buf;
277 /* pdata_buf points to a struct cmd_ds_802_11_subscribe_event and room
278 * for various Marvell TLVs */
280 lbs_deb_enter(LBS_DEB_CMD);
282 cmd->size = cpu_to_le16(sizeof(*events)
283 - sizeof(events->tlv)
284 + S_DS_GEN);
285 cmd->params.subscribe_event.action = cpu_to_le16(cmd_action);
286 if (cmd_action == CMD_ACT_GET) {
287 cmd->params.subscribe_event.events = 0;
288 } else {
289 ssize_t sz = lbs_tlv_size(events->tlv, sizeof(events->tlv));
290 cmd->size = cpu_to_le16(le16_to_cpu(cmd->size) + sz);
291 cmd->params.subscribe_event.events = events->events;
292 memcpy(cmd->params.subscribe_event.tlv, events->tlv, sz);
295 lbs_deb_leave(LBS_DEB_CMD);
298 static void set_one_wpa_key(struct MrvlIEtype_keyParamSet * pkeyparamset,
299 struct enc_key * pkey)
301 lbs_deb_enter(LBS_DEB_CMD);
303 if (pkey->flags & KEY_INFO_WPA_ENABLED) {
304 pkeyparamset->keyinfo |= cpu_to_le16(KEY_INFO_WPA_ENABLED);
306 if (pkey->flags & KEY_INFO_WPA_UNICAST) {
307 pkeyparamset->keyinfo |= cpu_to_le16(KEY_INFO_WPA_UNICAST);
309 if (pkey->flags & KEY_INFO_WPA_MCAST) {
310 pkeyparamset->keyinfo |= cpu_to_le16(KEY_INFO_WPA_MCAST);
313 pkeyparamset->type = cpu_to_le16(TLV_TYPE_KEY_MATERIAL);
314 pkeyparamset->keytypeid = cpu_to_le16(pkey->type);
315 pkeyparamset->keylen = cpu_to_le16(pkey->len);
316 memcpy(pkeyparamset->key, pkey->key, pkey->len);
317 pkeyparamset->length = cpu_to_le16( sizeof(pkeyparamset->keytypeid)
318 + sizeof(pkeyparamset->keyinfo)
319 + sizeof(pkeyparamset->keylen)
320 + sizeof(pkeyparamset->key));
321 lbs_deb_leave(LBS_DEB_CMD);
324 static int lbs_cmd_802_11_key_material(struct lbs_private *priv,
325 struct cmd_ds_command *cmd,
326 u16 cmd_action,
327 u32 cmd_oid, void *pdata_buf)
329 struct cmd_ds_802_11_key_material *pkeymaterial =
330 &cmd->params.keymaterial;
331 struct assoc_request * assoc_req = pdata_buf;
332 int ret = 0;
333 int index = 0;
335 lbs_deb_enter(LBS_DEB_CMD);
337 cmd->command = cpu_to_le16(CMD_802_11_KEY_MATERIAL);
338 pkeymaterial->action = cpu_to_le16(cmd_action);
340 if (cmd_action == CMD_ACT_GET) {
341 cmd->size = cpu_to_le16(S_DS_GEN + sizeof (pkeymaterial->action));
342 ret = 0;
343 goto done;
346 memset(&pkeymaterial->keyParamSet, 0, sizeof(pkeymaterial->keyParamSet));
348 if (test_bit(ASSOC_FLAG_WPA_UCAST_KEY, &assoc_req->flags)) {
349 set_one_wpa_key(&pkeymaterial->keyParamSet[index],
350 &assoc_req->wpa_unicast_key);
351 index++;
354 if (test_bit(ASSOC_FLAG_WPA_MCAST_KEY, &assoc_req->flags)) {
355 set_one_wpa_key(&pkeymaterial->keyParamSet[index],
356 &assoc_req->wpa_mcast_key);
357 index++;
360 cmd->size = cpu_to_le16( S_DS_GEN
361 + sizeof (pkeymaterial->action)
362 + (index * sizeof(struct MrvlIEtype_keyParamSet)));
364 ret = 0;
366 done:
367 lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
368 return ret;
371 static int lbs_cmd_802_11_reset(struct lbs_private *priv,
372 struct cmd_ds_command *cmd, int cmd_action)
374 struct cmd_ds_802_11_reset *reset = &cmd->params.reset;
376 lbs_deb_enter(LBS_DEB_CMD);
378 cmd->command = cpu_to_le16(CMD_802_11_RESET);
379 cmd->size = cpu_to_le16(sizeof(struct cmd_ds_802_11_reset) + S_DS_GEN);
380 reset->action = cpu_to_le16(cmd_action);
382 lbs_deb_leave(LBS_DEB_CMD);
383 return 0;
386 static int lbs_cmd_802_11_get_log(struct lbs_private *priv,
387 struct cmd_ds_command *cmd)
389 lbs_deb_enter(LBS_DEB_CMD);
390 cmd->command = cpu_to_le16(CMD_802_11_GET_LOG);
391 cmd->size =
392 cpu_to_le16(sizeof(struct cmd_ds_802_11_get_log) + S_DS_GEN);
394 lbs_deb_leave(LBS_DEB_CMD);
395 return 0;
398 static int lbs_cmd_802_11_get_stat(struct lbs_private *priv,
399 struct cmd_ds_command *cmd)
401 lbs_deb_enter(LBS_DEB_CMD);
402 cmd->command = cpu_to_le16(CMD_802_11_GET_STAT);
403 cmd->size =
404 cpu_to_le16(sizeof(struct cmd_ds_802_11_get_stat) + S_DS_GEN);
406 lbs_deb_leave(LBS_DEB_CMD);
407 return 0;
410 static int lbs_cmd_802_11_snmp_mib(struct lbs_private *priv,
411 struct cmd_ds_command *cmd,
412 int cmd_action,
413 int cmd_oid, void *pdata_buf)
415 struct cmd_ds_802_11_snmp_mib *pSNMPMIB = &cmd->params.smib;
416 u8 ucTemp;
418 lbs_deb_enter(LBS_DEB_CMD);
420 lbs_deb_cmd("SNMP_CMD: cmd_oid = 0x%x\n", cmd_oid);
422 cmd->command = cpu_to_le16(CMD_802_11_SNMP_MIB);
423 cmd->size = cpu_to_le16(sizeof(*pSNMPMIB) + S_DS_GEN);
425 switch (cmd_oid) {
426 case OID_802_11_INFRASTRUCTURE_MODE:
428 u8 mode = (u8) (size_t) pdata_buf;
429 pSNMPMIB->querytype = cpu_to_le16(CMD_ACT_SET);
430 pSNMPMIB->oid = cpu_to_le16((u16) DESIRED_BSSTYPE_I);
431 pSNMPMIB->bufsize = cpu_to_le16(sizeof(u8));
432 if (mode == IW_MODE_ADHOC) {
433 ucTemp = SNMP_MIB_VALUE_ADHOC;
434 } else {
435 /* Infra and Auto modes */
436 ucTemp = SNMP_MIB_VALUE_INFRA;
439 memmove(pSNMPMIB->value, &ucTemp, sizeof(u8));
441 break;
444 case OID_802_11D_ENABLE:
446 u32 ulTemp;
448 pSNMPMIB->oid = cpu_to_le16((u16) DOT11D_I);
450 if (cmd_action == CMD_ACT_SET) {
451 pSNMPMIB->querytype = cpu_to_le16(CMD_ACT_SET);
452 pSNMPMIB->bufsize = cpu_to_le16(sizeof(u16));
453 ulTemp = *(u32 *)pdata_buf;
454 *((__le16 *)(pSNMPMIB->value)) =
455 cpu_to_le16((u16) ulTemp);
457 break;
460 case OID_802_11_FRAGMENTATION_THRESHOLD:
462 u32 ulTemp;
464 pSNMPMIB->oid = cpu_to_le16((u16) FRAGTHRESH_I);
466 if (cmd_action == CMD_ACT_GET) {
467 pSNMPMIB->querytype = cpu_to_le16(CMD_ACT_GET);
468 } else if (cmd_action == CMD_ACT_SET) {
469 pSNMPMIB->querytype = cpu_to_le16(CMD_ACT_SET);
470 pSNMPMIB->bufsize = cpu_to_le16(sizeof(u16));
471 ulTemp = *((u32 *) pdata_buf);
472 *((__le16 *)(pSNMPMIB->value)) =
473 cpu_to_le16((u16) ulTemp);
477 break;
480 case OID_802_11_RTS_THRESHOLD:
483 u32 ulTemp;
484 pSNMPMIB->oid = cpu_to_le16(RTSTHRESH_I);
486 if (cmd_action == CMD_ACT_GET) {
487 pSNMPMIB->querytype = cpu_to_le16(CMD_ACT_GET);
488 } else if (cmd_action == CMD_ACT_SET) {
489 pSNMPMIB->querytype = cpu_to_le16(CMD_ACT_SET);
490 pSNMPMIB->bufsize = cpu_to_le16(sizeof(u16));
491 ulTemp = *((u32 *)pdata_buf);
492 *(__le16 *)(pSNMPMIB->value) =
493 cpu_to_le16((u16) ulTemp);
496 break;
498 case OID_802_11_TX_RETRYCOUNT:
499 pSNMPMIB->oid = cpu_to_le16((u16) SHORT_RETRYLIM_I);
501 if (cmd_action == CMD_ACT_GET) {
502 pSNMPMIB->querytype = cpu_to_le16(CMD_ACT_GET);
503 } else if (cmd_action == CMD_ACT_SET) {
504 pSNMPMIB->querytype = cpu_to_le16(CMD_ACT_SET);
505 pSNMPMIB->bufsize = cpu_to_le16(sizeof(u16));
506 *((__le16 *)(pSNMPMIB->value)) =
507 cpu_to_le16((u16) priv->txretrycount);
510 break;
511 default:
512 break;
515 lbs_deb_cmd(
516 "SNMP_CMD: command=0x%x, size=0x%x, seqnum=0x%x, result=0x%x\n",
517 le16_to_cpu(cmd->command), le16_to_cpu(cmd->size),
518 le16_to_cpu(cmd->seqnum), le16_to_cpu(cmd->result));
520 lbs_deb_cmd(
521 "SNMP_CMD: action 0x%x, oid 0x%x, oidsize 0x%x, value 0x%x\n",
522 le16_to_cpu(pSNMPMIB->querytype), le16_to_cpu(pSNMPMIB->oid),
523 le16_to_cpu(pSNMPMIB->bufsize),
524 le16_to_cpu(*(__le16 *) pSNMPMIB->value));
526 lbs_deb_leave(LBS_DEB_CMD);
527 return 0;
530 static int lbs_cmd_802_11_radio_control(struct lbs_private *priv,
531 struct cmd_ds_command *cmd,
532 int cmd_action)
534 struct cmd_ds_802_11_radio_control *pradiocontrol = &cmd->params.radio;
536 lbs_deb_enter(LBS_DEB_CMD);
538 cmd->size =
539 cpu_to_le16((sizeof(struct cmd_ds_802_11_radio_control)) +
540 S_DS_GEN);
541 cmd->command = cpu_to_le16(CMD_802_11_RADIO_CONTROL);
543 pradiocontrol->action = cpu_to_le16(cmd_action);
545 switch (priv->preamble) {
546 case CMD_TYPE_SHORT_PREAMBLE:
547 pradiocontrol->control = cpu_to_le16(SET_SHORT_PREAMBLE);
548 break;
550 case CMD_TYPE_LONG_PREAMBLE:
551 pradiocontrol->control = cpu_to_le16(SET_LONG_PREAMBLE);
552 break;
554 case CMD_TYPE_AUTO_PREAMBLE:
555 default:
556 pradiocontrol->control = cpu_to_le16(SET_AUTO_PREAMBLE);
557 break;
560 if (priv->radioon)
561 pradiocontrol->control |= cpu_to_le16(TURN_ON_RF);
562 else
563 pradiocontrol->control &= cpu_to_le16(~TURN_ON_RF);
565 lbs_deb_leave(LBS_DEB_CMD);
566 return 0;
569 static int lbs_cmd_802_11_rf_tx_power(struct lbs_private *priv,
570 struct cmd_ds_command *cmd,
571 u16 cmd_action, void *pdata_buf)
574 struct cmd_ds_802_11_rf_tx_power *prtp = &cmd->params.txp;
576 lbs_deb_enter(LBS_DEB_CMD);
578 cmd->size =
579 cpu_to_le16((sizeof(struct cmd_ds_802_11_rf_tx_power)) + S_DS_GEN);
580 cmd->command = cpu_to_le16(CMD_802_11_RF_TX_POWER);
581 prtp->action = cpu_to_le16(cmd_action);
583 lbs_deb_cmd("RF_TX_POWER_CMD: size:%d cmd:0x%x Act:%d\n",
584 le16_to_cpu(cmd->size), le16_to_cpu(cmd->command),
585 le16_to_cpu(prtp->action));
587 switch (cmd_action) {
588 case CMD_ACT_TX_POWER_OPT_GET:
589 prtp->action = cpu_to_le16(CMD_ACT_GET);
590 prtp->currentlevel = 0;
591 break;
593 case CMD_ACT_TX_POWER_OPT_SET_HIGH:
594 prtp->action = cpu_to_le16(CMD_ACT_SET);
595 prtp->currentlevel = cpu_to_le16(CMD_ACT_TX_POWER_INDEX_HIGH);
596 break;
598 case CMD_ACT_TX_POWER_OPT_SET_MID:
599 prtp->action = cpu_to_le16(CMD_ACT_SET);
600 prtp->currentlevel = cpu_to_le16(CMD_ACT_TX_POWER_INDEX_MID);
601 break;
603 case CMD_ACT_TX_POWER_OPT_SET_LOW:
604 prtp->action = cpu_to_le16(CMD_ACT_SET);
605 prtp->currentlevel = cpu_to_le16(*((u16 *) pdata_buf));
606 break;
609 lbs_deb_leave(LBS_DEB_CMD);
610 return 0;
613 static int lbs_cmd_802_11_monitor_mode(struct lbs_private *priv,
614 struct cmd_ds_command *cmd,
615 u16 cmd_action, void *pdata_buf)
617 struct cmd_ds_802_11_monitor_mode *monitor = &cmd->params.monitor;
619 cmd->command = cpu_to_le16(CMD_802_11_MONITOR_MODE);
620 cmd->size =
621 cpu_to_le16(sizeof(struct cmd_ds_802_11_monitor_mode) +
622 S_DS_GEN);
624 monitor->action = cpu_to_le16(cmd_action);
625 if (cmd_action == CMD_ACT_SET) {
626 monitor->mode =
627 cpu_to_le16((u16) (*(u32 *) pdata_buf));
630 return 0;
633 static int lbs_cmd_802_11_rate_adapt_rateset(struct lbs_private *priv,
634 struct cmd_ds_command *cmd,
635 u16 cmd_action)
637 struct cmd_ds_802_11_rate_adapt_rateset
638 *rateadapt = &cmd->params.rateset;
640 lbs_deb_enter(LBS_DEB_CMD);
641 cmd->size =
642 cpu_to_le16(sizeof(struct cmd_ds_802_11_rate_adapt_rateset)
643 + S_DS_GEN);
644 cmd->command = cpu_to_le16(CMD_802_11_RATE_ADAPT_RATESET);
646 rateadapt->action = cpu_to_le16(cmd_action);
647 rateadapt->enablehwauto = cpu_to_le16(priv->enablehwauto);
648 rateadapt->bitmap = cpu_to_le16(priv->ratebitmap);
650 lbs_deb_leave(LBS_DEB_CMD);
651 return 0;
654 static int lbs_cmd_802_11_data_rate(struct lbs_private *priv,
655 struct cmd_ds_command *cmd,
656 u16 cmd_action)
658 struct cmd_ds_802_11_data_rate *pdatarate = &cmd->params.drate;
660 lbs_deb_enter(LBS_DEB_CMD);
662 cmd->size = cpu_to_le16(sizeof(struct cmd_ds_802_11_data_rate) +
663 S_DS_GEN);
664 cmd->command = cpu_to_le16(CMD_802_11_DATA_RATE);
665 memset(pdatarate, 0, sizeof(struct cmd_ds_802_11_data_rate));
666 pdatarate->action = cpu_to_le16(cmd_action);
668 if (cmd_action == CMD_ACT_SET_TX_FIX_RATE) {
669 pdatarate->rates[0] = lbs_data_rate_to_fw_index(priv->cur_rate);
670 lbs_deb_cmd("DATA_RATE: set fixed 0x%02X\n",
671 priv->cur_rate);
672 } else if (cmd_action == CMD_ACT_SET_TX_AUTO) {
673 lbs_deb_cmd("DATA_RATE: setting auto\n");
676 lbs_deb_leave(LBS_DEB_CMD);
677 return 0;
680 static int lbs_cmd_mac_multicast_adr(struct lbs_private *priv,
681 struct cmd_ds_command *cmd,
682 u16 cmd_action)
684 struct cmd_ds_mac_multicast_adr *pMCastAdr = &cmd->params.madr;
686 lbs_deb_enter(LBS_DEB_CMD);
687 cmd->size = cpu_to_le16(sizeof(struct cmd_ds_mac_multicast_adr) +
688 S_DS_GEN);
689 cmd->command = cpu_to_le16(CMD_MAC_MULTICAST_ADR);
691 lbs_deb_cmd("MULTICAST_ADR: setting %d addresses\n", pMCastAdr->nr_of_adrs);
692 pMCastAdr->action = cpu_to_le16(cmd_action);
693 pMCastAdr->nr_of_adrs =
694 cpu_to_le16((u16) priv->nr_of_multicastmacaddr);
695 memcpy(pMCastAdr->maclist, priv->multicastlist,
696 priv->nr_of_multicastmacaddr * ETH_ALEN);
698 lbs_deb_leave(LBS_DEB_CMD);
699 return 0;
702 static int lbs_cmd_802_11_rf_channel(struct lbs_private *priv,
703 struct cmd_ds_command *cmd,
704 int option, void *pdata_buf)
706 struct cmd_ds_802_11_rf_channel *rfchan = &cmd->params.rfchannel;
708 lbs_deb_enter(LBS_DEB_CMD);
709 cmd->command = cpu_to_le16(CMD_802_11_RF_CHANNEL);
710 cmd->size = cpu_to_le16(sizeof(struct cmd_ds_802_11_rf_channel) +
711 S_DS_GEN);
713 if (option == CMD_OPT_802_11_RF_CHANNEL_SET) {
714 rfchan->currentchannel = cpu_to_le16(*((u16 *) pdata_buf));
717 rfchan->action = cpu_to_le16(option);
719 lbs_deb_leave(LBS_DEB_CMD);
720 return 0;
723 static int lbs_cmd_802_11_rssi(struct lbs_private *priv,
724 struct cmd_ds_command *cmd)
727 lbs_deb_enter(LBS_DEB_CMD);
728 cmd->command = cpu_to_le16(CMD_802_11_RSSI);
729 cmd->size = cpu_to_le16(sizeof(struct cmd_ds_802_11_rssi) + S_DS_GEN);
730 cmd->params.rssi.N = cpu_to_le16(DEFAULT_BCN_AVG_FACTOR);
732 /* reset Beacon SNR/NF/RSSI values */
733 priv->SNR[TYPE_BEACON][TYPE_NOAVG] = 0;
734 priv->SNR[TYPE_BEACON][TYPE_AVG] = 0;
735 priv->NF[TYPE_BEACON][TYPE_NOAVG] = 0;
736 priv->NF[TYPE_BEACON][TYPE_AVG] = 0;
737 priv->RSSI[TYPE_BEACON][TYPE_NOAVG] = 0;
738 priv->RSSI[TYPE_BEACON][TYPE_AVG] = 0;
740 lbs_deb_leave(LBS_DEB_CMD);
741 return 0;
744 static int lbs_cmd_reg_access(struct lbs_private *priv,
745 struct cmd_ds_command *cmdptr,
746 u8 cmd_action, void *pdata_buf)
748 struct lbs_offset_value *offval;
750 lbs_deb_enter(LBS_DEB_CMD);
752 offval = (struct lbs_offset_value *)pdata_buf;
754 switch (le16_to_cpu(cmdptr->command)) {
755 case CMD_MAC_REG_ACCESS:
757 struct cmd_ds_mac_reg_access *macreg;
759 cmdptr->size =
760 cpu_to_le16(sizeof (struct cmd_ds_mac_reg_access)
761 + S_DS_GEN);
762 macreg =
763 (struct cmd_ds_mac_reg_access *)&cmdptr->params.
764 macreg;
766 macreg->action = cpu_to_le16(cmd_action);
767 macreg->offset = cpu_to_le16((u16) offval->offset);
768 macreg->value = cpu_to_le32(offval->value);
770 break;
773 case CMD_BBP_REG_ACCESS:
775 struct cmd_ds_bbp_reg_access *bbpreg;
777 cmdptr->size =
778 cpu_to_le16(sizeof
779 (struct cmd_ds_bbp_reg_access)
780 + S_DS_GEN);
781 bbpreg =
782 (struct cmd_ds_bbp_reg_access *)&cmdptr->params.
783 bbpreg;
785 bbpreg->action = cpu_to_le16(cmd_action);
786 bbpreg->offset = cpu_to_le16((u16) offval->offset);
787 bbpreg->value = (u8) offval->value;
789 break;
792 case CMD_RF_REG_ACCESS:
794 struct cmd_ds_rf_reg_access *rfreg;
796 cmdptr->size =
797 cpu_to_le16(sizeof
798 (struct cmd_ds_rf_reg_access) +
799 S_DS_GEN);
800 rfreg =
801 (struct cmd_ds_rf_reg_access *)&cmdptr->params.
802 rfreg;
804 rfreg->action = cpu_to_le16(cmd_action);
805 rfreg->offset = cpu_to_le16((u16) offval->offset);
806 rfreg->value = (u8) offval->value;
808 break;
811 default:
812 break;
815 lbs_deb_leave(LBS_DEB_CMD);
816 return 0;
819 static int lbs_cmd_802_11_mac_address(struct lbs_private *priv,
820 struct cmd_ds_command *cmd,
821 u16 cmd_action)
824 lbs_deb_enter(LBS_DEB_CMD);
825 cmd->command = cpu_to_le16(CMD_802_11_MAC_ADDRESS);
826 cmd->size = cpu_to_le16(sizeof(struct cmd_ds_802_11_mac_address) +
827 S_DS_GEN);
828 cmd->result = 0;
830 cmd->params.macadd.action = cpu_to_le16(cmd_action);
832 if (cmd_action == CMD_ACT_SET) {
833 memcpy(cmd->params.macadd.macadd,
834 priv->current_addr, ETH_ALEN);
835 lbs_deb_hex(LBS_DEB_CMD, "SET_CMD: MAC addr", priv->current_addr, 6);
838 lbs_deb_leave(LBS_DEB_CMD);
839 return 0;
842 static int lbs_cmd_802_11_eeprom_access(struct lbs_private *priv,
843 struct cmd_ds_command *cmd,
844 int cmd_action, void *pdata_buf)
846 struct lbs_ioctl_regrdwr *ea = pdata_buf;
848 lbs_deb_enter(LBS_DEB_CMD);
850 cmd->command = cpu_to_le16(CMD_802_11_EEPROM_ACCESS);
851 cmd->size = cpu_to_le16(sizeof(struct cmd_ds_802_11_eeprom_access) +
852 S_DS_GEN);
853 cmd->result = 0;
855 cmd->params.rdeeprom.action = cpu_to_le16(ea->action);
856 cmd->params.rdeeprom.offset = cpu_to_le16(ea->offset);
857 cmd->params.rdeeprom.bytecount = cpu_to_le16(ea->NOB);
858 cmd->params.rdeeprom.value = 0;
860 lbs_deb_leave(LBS_DEB_CMD);
861 return 0;
864 static int lbs_cmd_bt_access(struct lbs_private *priv,
865 struct cmd_ds_command *cmd,
866 u16 cmd_action, void *pdata_buf)
868 struct cmd_ds_bt_access *bt_access = &cmd->params.bt;
869 lbs_deb_enter_args(LBS_DEB_CMD, "action %d", cmd_action);
871 cmd->command = cpu_to_le16(CMD_BT_ACCESS);
872 cmd->size = cpu_to_le16(sizeof(struct cmd_ds_bt_access) + S_DS_GEN);
873 cmd->result = 0;
874 bt_access->action = cpu_to_le16(cmd_action);
876 switch (cmd_action) {
877 case CMD_ACT_BT_ACCESS_ADD:
878 memcpy(bt_access->addr1, pdata_buf, 2 * ETH_ALEN);
879 lbs_deb_hex(LBS_DEB_MESH, "BT_ADD: blinded MAC addr", bt_access->addr1, 6);
880 break;
881 case CMD_ACT_BT_ACCESS_DEL:
882 memcpy(bt_access->addr1, pdata_buf, 1 * ETH_ALEN);
883 lbs_deb_hex(LBS_DEB_MESH, "BT_DEL: blinded MAC addr", bt_access->addr1, 6);
884 break;
885 case CMD_ACT_BT_ACCESS_LIST:
886 bt_access->id = cpu_to_le32(*(u32 *) pdata_buf);
887 break;
888 case CMD_ACT_BT_ACCESS_RESET:
889 break;
890 case CMD_ACT_BT_ACCESS_SET_INVERT:
891 bt_access->id = cpu_to_le32(*(u32 *) pdata_buf);
892 break;
893 case CMD_ACT_BT_ACCESS_GET_INVERT:
894 break;
895 default:
896 break;
898 lbs_deb_leave(LBS_DEB_CMD);
899 return 0;
902 static int lbs_cmd_fwt_access(struct lbs_private *priv,
903 struct cmd_ds_command *cmd,
904 u16 cmd_action, void *pdata_buf)
906 struct cmd_ds_fwt_access *fwt_access = &cmd->params.fwt;
907 lbs_deb_enter_args(LBS_DEB_CMD, "action %d", cmd_action);
909 cmd->command = cpu_to_le16(CMD_FWT_ACCESS);
910 cmd->size = cpu_to_le16(sizeof(struct cmd_ds_fwt_access) + S_DS_GEN);
911 cmd->result = 0;
913 if (pdata_buf)
914 memcpy(fwt_access, pdata_buf, sizeof(*fwt_access));
915 else
916 memset(fwt_access, 0, sizeof(*fwt_access));
918 fwt_access->action = cpu_to_le16(cmd_action);
920 lbs_deb_leave(LBS_DEB_CMD);
921 return 0;
924 static int lbs_cmd_mesh_access(struct lbs_private *priv,
925 struct cmd_ds_command *cmd,
926 u16 cmd_action, void *pdata_buf)
928 struct cmd_ds_mesh_access *mesh_access = &cmd->params.mesh;
929 lbs_deb_enter_args(LBS_DEB_CMD, "action %d", cmd_action);
931 cmd->command = cpu_to_le16(CMD_MESH_ACCESS);
932 cmd->size = cpu_to_le16(sizeof(struct cmd_ds_mesh_access) + S_DS_GEN);
933 cmd->result = 0;
935 if (pdata_buf)
936 memcpy(mesh_access, pdata_buf, sizeof(*mesh_access));
937 else
938 memset(mesh_access, 0, sizeof(*mesh_access));
940 mesh_access->action = cpu_to_le16(cmd_action);
942 lbs_deb_leave(LBS_DEB_CMD);
943 return 0;
946 static int lbs_cmd_bcn_ctrl(struct lbs_private * priv,
947 struct cmd_ds_command *cmd,
948 u16 cmd_action)
950 struct cmd_ds_802_11_beacon_control
951 *bcn_ctrl = &cmd->params.bcn_ctrl;
953 lbs_deb_enter(LBS_DEB_CMD);
954 cmd->size =
955 cpu_to_le16(sizeof(struct cmd_ds_802_11_beacon_control)
956 + S_DS_GEN);
957 cmd->command = cpu_to_le16(CMD_802_11_BEACON_CTRL);
959 bcn_ctrl->action = cpu_to_le16(cmd_action);
960 bcn_ctrl->beacon_enable = cpu_to_le16(priv->beacon_enable);
961 bcn_ctrl->beacon_period = cpu_to_le16(priv->beacon_period);
963 lbs_deb_leave(LBS_DEB_CMD);
964 return 0;
968 * Note: NEVER use lbs_queue_cmd() with addtail==0 other than for
969 * the command timer, because it does not account for queued commands.
971 void lbs_queue_cmd(struct lbs_private *priv,
972 struct cmd_ctrl_node *cmdnode,
973 u8 addtail)
975 unsigned long flags;
976 struct cmd_ds_command *cmdptr;
978 lbs_deb_enter(LBS_DEB_HOST);
980 if (!cmdnode) {
981 lbs_deb_host("QUEUE_CMD: cmdnode is NULL\n");
982 goto done;
985 cmdptr = (struct cmd_ds_command *)cmdnode->bufvirtualaddr;
986 if (!cmdptr) {
987 lbs_deb_host("QUEUE_CMD: cmdptr is NULL\n");
988 goto done;
991 /* Exit_PS command needs to be queued in the header always. */
992 if (le16_to_cpu(cmdptr->command) == CMD_802_11_PS_MODE) {
993 struct cmd_ds_802_11_ps_mode *psm = &cmdptr->params.psmode;
994 if (psm->action == cpu_to_le16(CMD_SUBCMD_EXIT_PS)) {
995 if (priv->psstate != PS_STATE_FULL_POWER)
996 addtail = 0;
1000 spin_lock_irqsave(&priv->driver_lock, flags);
1002 if (addtail)
1003 list_add_tail(&cmdnode->list, &priv->cmdpendingq);
1004 else
1005 list_add(&cmdnode->list, &priv->cmdpendingq);
1007 spin_unlock_irqrestore(&priv->driver_lock, flags);
1009 lbs_deb_host("QUEUE_CMD: inserted command 0x%04x into cmdpendingq\n",
1010 le16_to_cpu(((struct cmd_ds_gen*)cmdnode->bufvirtualaddr)->command));
1012 done:
1013 lbs_deb_leave(LBS_DEB_HOST);
1017 * TODO: Fix the issue when DownloadcommandToStation is being called the
1018 * second time when the command times out. All the cmdptr->xxx are in little
1019 * endian and therefore all the comparissions will fail.
1020 * For now - we are not performing the endian conversion the second time - but
1021 * for PS and DEEP_SLEEP we need to worry
1023 static int DownloadcommandToStation(struct lbs_private *priv,
1024 struct cmd_ctrl_node *cmdnode)
1026 unsigned long flags;
1027 struct cmd_ds_command *cmdptr;
1028 int ret = -1;
1029 u16 cmdsize;
1030 u16 command;
1032 lbs_deb_enter(LBS_DEB_HOST);
1034 if (!priv || !cmdnode) {
1035 lbs_deb_host("DNLD_CMD: priv or cmdmode is NULL\n");
1036 goto done;
1039 cmdptr = (struct cmd_ds_command *)cmdnode->bufvirtualaddr;
1041 spin_lock_irqsave(&priv->driver_lock, flags);
1042 if (!cmdptr || !cmdptr->size) {
1043 lbs_deb_host("DNLD_CMD: cmdptr is NULL or zero\n");
1044 __lbs_cleanup_and_insert_cmd(priv, cmdnode);
1045 spin_unlock_irqrestore(&priv->driver_lock, flags);
1046 goto done;
1049 priv->cur_cmd = cmdnode;
1050 priv->cur_cmd_retcode = 0;
1051 spin_unlock_irqrestore(&priv->driver_lock, flags);
1053 cmdsize = le16_to_cpu(cmdptr->size);
1054 command = le16_to_cpu(cmdptr->command);
1056 lbs_deb_host("DNLD_CMD: command 0x%04x, size %d, jiffies %lu\n",
1057 command, cmdsize, jiffies);
1058 lbs_deb_hex(LBS_DEB_HOST, "DNLD_CMD", cmdnode->bufvirtualaddr, cmdsize);
1060 cmdnode->cmdwaitqwoken = 0;
1062 ret = priv->hw_host_to_card(priv, MVMS_CMD, (u8 *) cmdptr, cmdsize);
1064 if (ret != 0) {
1065 lbs_deb_host("DNLD_CMD: hw_host_to_card failed\n");
1066 spin_lock_irqsave(&priv->driver_lock, flags);
1067 priv->cur_cmd_retcode = ret;
1068 __lbs_cleanup_and_insert_cmd(priv, priv->cur_cmd);
1069 priv->cur_cmd = NULL;
1070 spin_unlock_irqrestore(&priv->driver_lock, flags);
1071 goto done;
1074 lbs_deb_cmd("DNLD_CMD: sent command 0x%04x, jiffies %lu\n", command, jiffies);
1076 /* Setup the timer after transmit command */
1077 if (command == CMD_802_11_SCAN || command == CMD_802_11_AUTHENTICATE
1078 || command == CMD_802_11_ASSOCIATE)
1079 mod_timer(&priv->command_timer, jiffies + (10*HZ));
1080 else
1081 mod_timer(&priv->command_timer, jiffies + (5*HZ));
1083 ret = 0;
1085 done:
1086 lbs_deb_leave_args(LBS_DEB_HOST, "ret %d", ret);
1087 return ret;
1090 static int lbs_cmd_mac_control(struct lbs_private *priv,
1091 struct cmd_ds_command *cmd)
1093 struct cmd_ds_mac_control *mac = &cmd->params.macctrl;
1095 lbs_deb_enter(LBS_DEB_CMD);
1097 cmd->command = cpu_to_le16(CMD_MAC_CONTROL);
1098 cmd->size = cpu_to_le16(sizeof(struct cmd_ds_mac_control) + S_DS_GEN);
1099 mac->action = cpu_to_le16(priv->currentpacketfilter);
1101 lbs_deb_cmd("MAC_CONTROL: action 0x%x, size %d\n",
1102 le16_to_cpu(mac->action), le16_to_cpu(cmd->size));
1104 lbs_deb_leave(LBS_DEB_CMD);
1105 return 0;
1109 * This function inserts command node to cmdfreeq
1110 * after cleans it. Requires priv->driver_lock held.
1112 void __lbs_cleanup_and_insert_cmd(struct lbs_private *priv,
1113 struct cmd_ctrl_node *ptempcmd)
1116 if (!ptempcmd)
1117 return;
1119 cleanup_cmdnode(ptempcmd);
1120 list_add_tail(&ptempcmd->list, &priv->cmdfreeq);
1123 static void lbs_cleanup_and_insert_cmd(struct lbs_private *priv,
1124 struct cmd_ctrl_node *ptempcmd)
1126 unsigned long flags;
1128 spin_lock_irqsave(&priv->driver_lock, flags);
1129 __lbs_cleanup_and_insert_cmd(priv, ptempcmd);
1130 spin_unlock_irqrestore(&priv->driver_lock, flags);
1133 int lbs_set_radio_control(struct lbs_private *priv)
1135 int ret = 0;
1137 lbs_deb_enter(LBS_DEB_CMD);
1139 ret = lbs_prepare_and_send_command(priv,
1140 CMD_802_11_RADIO_CONTROL,
1141 CMD_ACT_SET,
1142 CMD_OPTION_WAITFORRSP, 0, NULL);
1144 lbs_deb_cmd("RADIO_SET: radio %d, preamble %d\n",
1145 priv->radioon, priv->preamble);
1147 lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
1148 return ret;
1151 int lbs_set_mac_packet_filter(struct lbs_private *priv)
1153 int ret = 0;
1155 lbs_deb_enter(LBS_DEB_CMD);
1157 /* Send MAC control command to station */
1158 ret = lbs_prepare_and_send_command(priv,
1159 CMD_MAC_CONTROL, 0, 0, 0, NULL);
1161 lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
1162 return ret;
1166 * @brief This function prepare the command before send to firmware.
1168 * @param priv A pointer to struct lbs_private structure
1169 * @param cmd_no command number
1170 * @param cmd_action command action: GET or SET
1171 * @param wait_option wait option: wait response or not
1172 * @param cmd_oid cmd oid: treated as sub command
1173 * @param pdata_buf A pointer to informaion buffer
1174 * @return 0 or -1
1176 int lbs_prepare_and_send_command(struct lbs_private *priv,
1177 u16 cmd_no,
1178 u16 cmd_action,
1179 u16 wait_option, u32 cmd_oid, void *pdata_buf)
1181 int ret = 0;
1182 struct cmd_ctrl_node *cmdnode;
1183 struct cmd_ds_command *cmdptr;
1184 unsigned long flags;
1186 lbs_deb_enter(LBS_DEB_HOST);
1188 if (!priv) {
1189 lbs_deb_host("PREP_CMD: priv is NULL\n");
1190 ret = -1;
1191 goto done;
1194 if (priv->surpriseremoved) {
1195 lbs_deb_host("PREP_CMD: card removed\n");
1196 ret = -1;
1197 goto done;
1200 cmdnode = lbs_get_cmd_ctrl_node(priv);
1202 if (cmdnode == NULL) {
1203 lbs_deb_host("PREP_CMD: cmdnode is NULL\n");
1205 /* Wake up main thread to execute next command */
1206 wake_up_interruptible(&priv->waitq);
1207 ret = -1;
1208 goto done;
1211 lbs_set_cmd_ctrl_node(priv, cmdnode, wait_option, pdata_buf);
1213 cmdptr = (struct cmd_ds_command *)cmdnode->bufvirtualaddr;
1215 lbs_deb_host("PREP_CMD: command 0x%04x\n", cmd_no);
1217 if (!cmdptr) {
1218 lbs_deb_host("PREP_CMD: cmdptr is NULL\n");
1219 lbs_cleanup_and_insert_cmd(priv, cmdnode);
1220 ret = -1;
1221 goto done;
1224 /* Set sequence number, command and INT option */
1225 priv->seqnum++;
1226 cmdptr->seqnum = cpu_to_le16(priv->seqnum);
1228 cmdptr->command = cpu_to_le16(cmd_no);
1229 cmdptr->result = 0;
1231 switch (cmd_no) {
1232 case CMD_GET_HW_SPEC:
1233 ret = lbs_cmd_hw_spec(priv, cmdptr);
1234 break;
1235 case CMD_802_11_PS_MODE:
1236 ret = lbs_cmd_802_11_ps_mode(priv, cmdptr, cmd_action);
1237 break;
1239 case CMD_802_11_SCAN:
1240 ret = lbs_cmd_80211_scan(priv, cmdptr, pdata_buf);
1241 break;
1243 case CMD_MAC_CONTROL:
1244 ret = lbs_cmd_mac_control(priv, cmdptr);
1245 break;
1247 case CMD_802_11_ASSOCIATE:
1248 case CMD_802_11_REASSOCIATE:
1249 ret = lbs_cmd_80211_associate(priv, cmdptr, pdata_buf);
1250 break;
1252 case CMD_802_11_DEAUTHENTICATE:
1253 ret = lbs_cmd_80211_deauthenticate(priv, cmdptr);
1254 break;
1256 case CMD_802_11_SET_WEP:
1257 ret = lbs_cmd_802_11_set_wep(priv, cmdptr, cmd_action, pdata_buf);
1258 break;
1260 case CMD_802_11_AD_HOC_START:
1261 ret = lbs_cmd_80211_ad_hoc_start(priv, cmdptr, pdata_buf);
1262 break;
1263 case CMD_CODE_DNLD:
1264 break;
1266 case CMD_802_11_RESET:
1267 ret = lbs_cmd_802_11_reset(priv, cmdptr, cmd_action);
1268 break;
1270 case CMD_802_11_GET_LOG:
1271 ret = lbs_cmd_802_11_get_log(priv, cmdptr);
1272 break;
1274 case CMD_802_11_AUTHENTICATE:
1275 ret = lbs_cmd_80211_authenticate(priv, cmdptr, pdata_buf);
1276 break;
1278 case CMD_802_11_GET_STAT:
1279 ret = lbs_cmd_802_11_get_stat(priv, cmdptr);
1280 break;
1282 case CMD_802_11_SNMP_MIB:
1283 ret = lbs_cmd_802_11_snmp_mib(priv, cmdptr,
1284 cmd_action, cmd_oid, pdata_buf);
1285 break;
1287 case CMD_MAC_REG_ACCESS:
1288 case CMD_BBP_REG_ACCESS:
1289 case CMD_RF_REG_ACCESS:
1290 ret = lbs_cmd_reg_access(priv, cmdptr, cmd_action, pdata_buf);
1291 break;
1293 case CMD_802_11_RF_CHANNEL:
1294 ret = lbs_cmd_802_11_rf_channel(priv, cmdptr,
1295 cmd_action, pdata_buf);
1296 break;
1298 case CMD_802_11_RF_TX_POWER:
1299 ret = lbs_cmd_802_11_rf_tx_power(priv, cmdptr,
1300 cmd_action, pdata_buf);
1301 break;
1303 case CMD_802_11_RADIO_CONTROL:
1304 ret = lbs_cmd_802_11_radio_control(priv, cmdptr, cmd_action);
1305 break;
1307 case CMD_802_11_DATA_RATE:
1308 ret = lbs_cmd_802_11_data_rate(priv, cmdptr, cmd_action);
1309 break;
1310 case CMD_802_11_RATE_ADAPT_RATESET:
1311 ret = lbs_cmd_802_11_rate_adapt_rateset(priv,
1312 cmdptr, cmd_action);
1313 break;
1315 case CMD_MAC_MULTICAST_ADR:
1316 ret = lbs_cmd_mac_multicast_adr(priv, cmdptr, cmd_action);
1317 break;
1319 case CMD_802_11_MONITOR_MODE:
1320 ret = lbs_cmd_802_11_monitor_mode(priv, cmdptr,
1321 cmd_action, pdata_buf);
1322 break;
1324 case CMD_802_11_AD_HOC_JOIN:
1325 ret = lbs_cmd_80211_ad_hoc_join(priv, cmdptr, pdata_buf);
1326 break;
1328 case CMD_802_11_RSSI:
1329 ret = lbs_cmd_802_11_rssi(priv, cmdptr);
1330 break;
1332 case CMD_802_11_AD_HOC_STOP:
1333 ret = lbs_cmd_80211_ad_hoc_stop(priv, cmdptr);
1334 break;
1336 case CMD_802_11_ENABLE_RSN:
1337 ret = lbs_cmd_802_11_enable_rsn(priv, cmdptr, cmd_action,
1338 pdata_buf);
1339 break;
1341 case CMD_802_11_KEY_MATERIAL:
1342 ret = lbs_cmd_802_11_key_material(priv, cmdptr, cmd_action,
1343 cmd_oid, pdata_buf);
1344 break;
1346 case CMD_802_11_PAIRWISE_TSC:
1347 break;
1348 case CMD_802_11_GROUP_TSC:
1349 break;
1351 case CMD_802_11_MAC_ADDRESS:
1352 ret = lbs_cmd_802_11_mac_address(priv, cmdptr, cmd_action);
1353 break;
1355 case CMD_802_11_EEPROM_ACCESS:
1356 ret = lbs_cmd_802_11_eeprom_access(priv, cmdptr,
1357 cmd_action, pdata_buf);
1358 break;
1360 case CMD_802_11_SET_AFC:
1361 case CMD_802_11_GET_AFC:
1363 cmdptr->command = cpu_to_le16(cmd_no);
1364 cmdptr->size = cpu_to_le16(sizeof(struct cmd_ds_802_11_afc) +
1365 S_DS_GEN);
1367 memmove(&cmdptr->params.afc,
1368 pdata_buf, sizeof(struct cmd_ds_802_11_afc));
1370 ret = 0;
1371 goto done;
1373 case CMD_802_11D_DOMAIN_INFO:
1374 ret = lbs_cmd_802_11d_domain_info(priv, cmdptr,
1375 cmd_no, cmd_action);
1376 break;
1378 case CMD_802_11_SLEEP_PARAMS:
1379 ret = lbs_cmd_802_11_sleep_params(priv, cmdptr, cmd_action);
1380 break;
1381 case CMD_802_11_INACTIVITY_TIMEOUT:
1382 ret = lbs_cmd_802_11_inactivity_timeout(priv, cmdptr,
1383 cmd_action, pdata_buf);
1384 lbs_set_cmd_ctrl_node(priv, cmdnode, 0, pdata_buf);
1385 break;
1387 case CMD_802_11_TPC_CFG:
1388 cmdptr->command = cpu_to_le16(CMD_802_11_TPC_CFG);
1389 cmdptr->size =
1390 cpu_to_le16(sizeof(struct cmd_ds_802_11_tpc_cfg) +
1391 S_DS_GEN);
1393 memmove(&cmdptr->params.tpccfg,
1394 pdata_buf, sizeof(struct cmd_ds_802_11_tpc_cfg));
1396 ret = 0;
1397 break;
1398 case CMD_802_11_LED_GPIO_CTRL:
1400 struct mrvlietypes_ledgpio *gpio =
1401 (struct mrvlietypes_ledgpio*)
1402 cmdptr->params.ledgpio.data;
1404 memmove(&cmdptr->params.ledgpio,
1405 pdata_buf,
1406 sizeof(struct cmd_ds_802_11_led_ctrl));
1408 cmdptr->command =
1409 cpu_to_le16(CMD_802_11_LED_GPIO_CTRL);
1411 #define ACTION_NUMLED_TLVTYPE_LEN_FIELDS_LEN 8
1412 cmdptr->size =
1413 cpu_to_le16(le16_to_cpu(gpio->header.len)
1414 + S_DS_GEN
1415 + ACTION_NUMLED_TLVTYPE_LEN_FIELDS_LEN);
1416 gpio->header.len = gpio->header.len;
1418 ret = 0;
1419 break;
1421 case CMD_802_11_SUBSCRIBE_EVENT:
1422 lbs_cmd_802_11_subscribe_event(priv, cmdptr,
1423 cmd_action, pdata_buf);
1424 break;
1425 case CMD_802_11_PWR_CFG:
1426 cmdptr->command = cpu_to_le16(CMD_802_11_PWR_CFG);
1427 cmdptr->size =
1428 cpu_to_le16(sizeof(struct cmd_ds_802_11_pwr_cfg) +
1429 S_DS_GEN);
1430 memmove(&cmdptr->params.pwrcfg, pdata_buf,
1431 sizeof(struct cmd_ds_802_11_pwr_cfg));
1433 ret = 0;
1434 break;
1435 case CMD_BT_ACCESS:
1436 ret = lbs_cmd_bt_access(priv, cmdptr, cmd_action, pdata_buf);
1437 break;
1439 case CMD_FWT_ACCESS:
1440 ret = lbs_cmd_fwt_access(priv, cmdptr, cmd_action, pdata_buf);
1441 break;
1443 case CMD_MESH_ACCESS:
1444 ret = lbs_cmd_mesh_access(priv, cmdptr, cmd_action, pdata_buf);
1445 break;
1447 case CMD_GET_TSF:
1448 cmdptr->command = cpu_to_le16(CMD_GET_TSF);
1449 cmdptr->size = cpu_to_le16(sizeof(struct cmd_ds_get_tsf) +
1450 S_DS_GEN);
1451 ret = 0;
1452 break;
1453 case CMD_802_11_BEACON_CTRL:
1454 ret = lbs_cmd_bcn_ctrl(priv, cmdptr, cmd_action);
1455 break;
1456 default:
1457 lbs_deb_host("PREP_CMD: unknown command 0x%04x\n", cmd_no);
1458 ret = -1;
1459 break;
1462 /* return error, since the command preparation failed */
1463 if (ret != 0) {
1464 lbs_deb_host("PREP_CMD: command preparation failed\n");
1465 lbs_cleanup_and_insert_cmd(priv, cmdnode);
1466 ret = -1;
1467 goto done;
1470 cmdnode->cmdwaitqwoken = 0;
1472 lbs_queue_cmd(priv, cmdnode, 1);
1473 wake_up_interruptible(&priv->waitq);
1475 if (wait_option & CMD_OPTION_WAITFORRSP) {
1476 lbs_deb_host("PREP_CMD: wait for response\n");
1477 might_sleep();
1478 wait_event_interruptible(cmdnode->cmdwait_q,
1479 cmdnode->cmdwaitqwoken);
1482 spin_lock_irqsave(&priv->driver_lock, flags);
1483 if (priv->cur_cmd_retcode) {
1484 lbs_deb_host("PREP_CMD: command failed with return code %d\n",
1485 priv->cur_cmd_retcode);
1486 priv->cur_cmd_retcode = 0;
1487 ret = -1;
1489 spin_unlock_irqrestore(&priv->driver_lock, flags);
1491 done:
1492 lbs_deb_leave_args(LBS_DEB_HOST, "ret %d", ret);
1493 return ret;
1495 EXPORT_SYMBOL_GPL(lbs_prepare_and_send_command);
1498 * @brief This function allocates the command buffer and link
1499 * it to command free queue.
1501 * @param priv A pointer to struct lbs_private structure
1502 * @return 0 or -1
1504 int lbs_allocate_cmd_buffer(struct lbs_private *priv)
1506 int ret = 0;
1507 u32 ulbufsize;
1508 u32 i;
1509 struct cmd_ctrl_node *tempcmd_array;
1510 u8 *ptempvirtualaddr;
1512 lbs_deb_enter(LBS_DEB_HOST);
1514 /* Allocate and initialize cmdCtrlNode */
1515 ulbufsize = sizeof(struct cmd_ctrl_node) * MRVDRV_NUM_OF_CMD_BUFFER;
1517 if (!(tempcmd_array = kzalloc(ulbufsize, GFP_KERNEL))) {
1518 lbs_deb_host("ALLOC_CMD_BUF: tempcmd_array is NULL\n");
1519 ret = -1;
1520 goto done;
1522 priv->cmd_array = tempcmd_array;
1524 /* Allocate and initialize command buffers */
1525 ulbufsize = MRVDRV_SIZE_OF_CMD_BUFFER;
1526 for (i = 0; i < MRVDRV_NUM_OF_CMD_BUFFER; i++) {
1527 if (!(ptempvirtualaddr = kzalloc(ulbufsize, GFP_KERNEL))) {
1528 lbs_deb_host("ALLOC_CMD_BUF: ptempvirtualaddr is NULL\n");
1529 ret = -1;
1530 goto done;
1533 /* Update command buffer virtual */
1534 tempcmd_array[i].bufvirtualaddr = ptempvirtualaddr;
1537 for (i = 0; i < MRVDRV_NUM_OF_CMD_BUFFER; i++) {
1538 init_waitqueue_head(&tempcmd_array[i].cmdwait_q);
1539 lbs_cleanup_and_insert_cmd(priv, &tempcmd_array[i]);
1542 ret = 0;
1544 done:
1545 lbs_deb_leave_args(LBS_DEB_HOST, "ret %d", ret);
1546 return ret;
1550 * @brief This function frees the command buffer.
1552 * @param priv A pointer to struct lbs_private structure
1553 * @return 0 or -1
1555 int lbs_free_cmd_buffer(struct lbs_private *priv)
1557 u32 ulbufsize; /* Someone needs to die for this. Slowly and painfully */
1558 unsigned int i;
1559 struct cmd_ctrl_node *tempcmd_array;
1561 lbs_deb_enter(LBS_DEB_HOST);
1563 /* need to check if cmd array is allocated or not */
1564 if (priv->cmd_array == NULL) {
1565 lbs_deb_host("FREE_CMD_BUF: cmd_array is NULL\n");
1566 goto done;
1569 tempcmd_array = priv->cmd_array;
1571 /* Release shared memory buffers */
1572 ulbufsize = MRVDRV_SIZE_OF_CMD_BUFFER;
1573 for (i = 0; i < MRVDRV_NUM_OF_CMD_BUFFER; i++) {
1574 if (tempcmd_array[i].bufvirtualaddr) {
1575 kfree(tempcmd_array[i].bufvirtualaddr);
1576 tempcmd_array[i].bufvirtualaddr = NULL;
1580 /* Release cmd_ctrl_node */
1581 if (priv->cmd_array) {
1582 kfree(priv->cmd_array);
1583 priv->cmd_array = NULL;
1586 done:
1587 lbs_deb_leave(LBS_DEB_HOST);
1588 return 0;
1592 * @brief This function gets a free command node if available in
1593 * command free queue.
1595 * @param priv A pointer to struct lbs_private structure
1596 * @return cmd_ctrl_node A pointer to cmd_ctrl_node structure or NULL
1598 struct cmd_ctrl_node *lbs_get_cmd_ctrl_node(struct lbs_private *priv)
1600 struct cmd_ctrl_node *tempnode;
1601 unsigned long flags;
1603 lbs_deb_enter(LBS_DEB_HOST);
1605 if (!priv)
1606 return NULL;
1608 spin_lock_irqsave(&priv->driver_lock, flags);
1610 if (!list_empty(&priv->cmdfreeq)) {
1611 tempnode = list_first_entry(&priv->cmdfreeq,
1612 struct cmd_ctrl_node, list);
1613 list_del(&tempnode->list);
1614 } else {
1615 lbs_deb_host("GET_CMD_NODE: cmd_ctrl_node is not available\n");
1616 tempnode = NULL;
1619 spin_unlock_irqrestore(&priv->driver_lock, flags);
1621 if (tempnode)
1622 cleanup_cmdnode(tempnode);
1624 lbs_deb_leave(LBS_DEB_HOST);
1625 return tempnode;
1629 * @brief This function cleans command node.
1631 * @param ptempnode A pointer to cmdCtrlNode structure
1632 * @return n/a
1634 static void cleanup_cmdnode(struct cmd_ctrl_node *ptempnode)
1636 lbs_deb_enter(LBS_DEB_HOST);
1638 if (!ptempnode)
1639 return;
1640 ptempnode->cmdwaitqwoken = 1;
1641 wake_up_interruptible(&ptempnode->cmdwait_q);
1642 ptempnode->wait_option = 0;
1643 ptempnode->pdata_buf = NULL;
1644 ptempnode->callback = NULL;
1645 ptempnode->callback_arg = 0;
1647 if (ptempnode->bufvirtualaddr != NULL)
1648 memset(ptempnode->bufvirtualaddr, 0, MRVDRV_SIZE_OF_CMD_BUFFER);
1650 lbs_deb_leave(LBS_DEB_HOST);
1654 * @brief This function initializes the command node.
1656 * @param priv A pointer to struct lbs_private structure
1657 * @param ptempnode A pointer to cmd_ctrl_node structure
1658 * @param wait_option wait option: wait response or not
1659 * @param pdata_buf A pointer to informaion buffer
1660 * @return 0 or -1
1662 void lbs_set_cmd_ctrl_node(struct lbs_private *priv,
1663 struct cmd_ctrl_node *ptempnode,
1664 u16 wait_option, void *pdata_buf)
1666 lbs_deb_enter(LBS_DEB_HOST);
1668 if (!ptempnode)
1669 return;
1671 ptempnode->wait_option = wait_option;
1672 ptempnode->pdata_buf = pdata_buf;
1673 ptempnode->callback = NULL;
1674 ptempnode->callback_arg = 0;
1676 lbs_deb_leave(LBS_DEB_HOST);
1680 * @brief This function executes next command in command
1681 * pending queue. It will put fimware back to PS mode
1682 * if applicable.
1684 * @param priv A pointer to struct lbs_private structure
1685 * @return 0 or -1
1687 int lbs_execute_next_command(struct lbs_private *priv)
1689 struct cmd_ctrl_node *cmdnode = NULL;
1690 struct cmd_ds_command *cmdptr;
1691 unsigned long flags;
1692 int ret = 0;
1694 // Debug group is LBS_DEB_THREAD and not LBS_DEB_HOST, because the
1695 // only caller to us is lbs_thread() and we get even when a
1696 // data packet is received
1697 lbs_deb_enter(LBS_DEB_THREAD);
1699 spin_lock_irqsave(&priv->driver_lock, flags);
1701 if (priv->cur_cmd) {
1702 lbs_pr_alert( "EXEC_NEXT_CMD: already processing command!\n");
1703 spin_unlock_irqrestore(&priv->driver_lock, flags);
1704 ret = -1;
1705 goto done;
1708 if (!list_empty(&priv->cmdpendingq)) {
1709 cmdnode = list_first_entry(&priv->cmdpendingq,
1710 struct cmd_ctrl_node, list);
1713 spin_unlock_irqrestore(&priv->driver_lock, flags);
1715 if (cmdnode) {
1716 cmdptr = (struct cmd_ds_command *)cmdnode->bufvirtualaddr;
1718 if (is_command_allowed_in_ps(cmdptr->command)) {
1719 if ((priv->psstate == PS_STATE_SLEEP) ||
1720 (priv->psstate == PS_STATE_PRE_SLEEP)) {
1721 lbs_deb_host(
1722 "EXEC_NEXT_CMD: cannot send cmd 0x%04x in psstate %d\n",
1723 le16_to_cpu(cmdptr->command),
1724 priv->psstate);
1725 ret = -1;
1726 goto done;
1728 lbs_deb_host("EXEC_NEXT_CMD: OK to send command "
1729 "0x%04x in psstate %d\n",
1730 le16_to_cpu(cmdptr->command),
1731 priv->psstate);
1732 } else if (priv->psstate != PS_STATE_FULL_POWER) {
1734 * 1. Non-PS command:
1735 * Queue it. set needtowakeup to TRUE if current state
1736 * is SLEEP, otherwise call lbs_ps_wakeup to send Exit_PS.
1737 * 2. PS command but not Exit_PS:
1738 * Ignore it.
1739 * 3. PS command Exit_PS:
1740 * Set needtowakeup to TRUE if current state is SLEEP,
1741 * otherwise send this command down to firmware
1742 * immediately.
1744 if (cmdptr->command !=
1745 cpu_to_le16(CMD_802_11_PS_MODE)) {
1746 /* Prepare to send Exit PS,
1747 * this non PS command will be sent later */
1748 if ((priv->psstate == PS_STATE_SLEEP)
1749 || (priv->psstate == PS_STATE_PRE_SLEEP)
1751 /* w/ new scheme, it will not reach here.
1752 since it is blocked in main_thread. */
1753 priv->needtowakeup = 1;
1754 } else
1755 lbs_ps_wakeup(priv, 0);
1757 ret = 0;
1758 goto done;
1759 } else {
1761 * PS command. Ignore it if it is not Exit_PS.
1762 * otherwise send it down immediately.
1764 struct cmd_ds_802_11_ps_mode *psm =
1765 &cmdptr->params.psmode;
1767 lbs_deb_host(
1768 "EXEC_NEXT_CMD: PS cmd, action 0x%02x\n",
1769 psm->action);
1770 if (psm->action !=
1771 cpu_to_le16(CMD_SUBCMD_EXIT_PS)) {
1772 lbs_deb_host(
1773 "EXEC_NEXT_CMD: ignore ENTER_PS cmd\n");
1774 list_del(&cmdnode->list);
1775 lbs_cleanup_and_insert_cmd(priv, cmdnode);
1777 ret = 0;
1778 goto done;
1781 if ((priv->psstate == PS_STATE_SLEEP) ||
1782 (priv->psstate == PS_STATE_PRE_SLEEP)) {
1783 lbs_deb_host(
1784 "EXEC_NEXT_CMD: ignore EXIT_PS cmd in sleep\n");
1785 list_del(&cmdnode->list);
1786 lbs_cleanup_and_insert_cmd(priv, cmdnode);
1787 priv->needtowakeup = 1;
1789 ret = 0;
1790 goto done;
1793 lbs_deb_host(
1794 "EXEC_NEXT_CMD: sending EXIT_PS\n");
1797 list_del(&cmdnode->list);
1798 lbs_deb_host("EXEC_NEXT_CMD: sending command 0x%04x\n",
1799 le16_to_cpu(cmdptr->command));
1800 DownloadcommandToStation(priv, cmdnode);
1801 } else {
1803 * check if in power save mode, if yes, put the device back
1804 * to PS mode
1806 if ((priv->psmode != LBS802_11POWERMODECAM) &&
1807 (priv->psstate == PS_STATE_FULL_POWER) &&
1808 ((priv->connect_status == LBS_CONNECTED) ||
1809 (priv->mesh_connect_status == LBS_CONNECTED))) {
1810 if (priv->secinfo.WPAenabled ||
1811 priv->secinfo.WPA2enabled) {
1812 /* check for valid WPA group keys */
1813 if (priv->wpa_mcast_key.len ||
1814 priv->wpa_unicast_key.len) {
1815 lbs_deb_host(
1816 "EXEC_NEXT_CMD: WPA enabled and GTK_SET"
1817 " go back to PS_SLEEP");
1818 lbs_ps_sleep(priv, 0);
1820 } else {
1821 lbs_deb_host(
1822 "EXEC_NEXT_CMD: cmdpendingq empty, "
1823 "go back to PS_SLEEP");
1824 lbs_ps_sleep(priv, 0);
1829 ret = 0;
1830 done:
1831 lbs_deb_leave(LBS_DEB_THREAD);
1832 return ret;
1835 void lbs_send_iwevcustom_event(struct lbs_private *priv, s8 *str)
1837 union iwreq_data iwrq;
1838 u8 buf[50];
1840 lbs_deb_enter(LBS_DEB_WEXT);
1842 memset(&iwrq, 0, sizeof(union iwreq_data));
1843 memset(buf, 0, sizeof(buf));
1845 snprintf(buf, sizeof(buf) - 1, "%s", str);
1847 iwrq.data.length = strlen(buf) + 1 + IW_EV_LCP_LEN;
1849 /* Send Event to upper layer */
1850 lbs_deb_wext("event indication string %s\n", (char *)buf);
1851 lbs_deb_wext("event indication length %d\n", iwrq.data.length);
1852 lbs_deb_wext("sending wireless event IWEVCUSTOM for %s\n", str);
1854 wireless_send_event(priv->dev, IWEVCUSTOM, &iwrq, buf);
1856 lbs_deb_leave(LBS_DEB_WEXT);
1859 static int sendconfirmsleep(struct lbs_private *priv, u8 *cmdptr, u16 size)
1861 unsigned long flags;
1862 int ret = 0;
1864 lbs_deb_enter(LBS_DEB_HOST);
1866 lbs_deb_host("SEND_SLEEPC_CMD: before download, cmd size %d\n",
1867 size);
1869 lbs_deb_hex(LBS_DEB_HOST, "sleep confirm command", cmdptr, size);
1871 ret = priv->hw_host_to_card(priv, MVMS_CMD, cmdptr, size);
1872 priv->dnld_sent = DNLD_RES_RECEIVED;
1874 spin_lock_irqsave(&priv->driver_lock, flags);
1875 if (priv->intcounter || priv->currenttxskb)
1876 lbs_deb_host("SEND_SLEEPC_CMD: intcounter %d, currenttxskb %p\n",
1877 priv->intcounter, priv->currenttxskb);
1878 spin_unlock_irqrestore(&priv->driver_lock, flags);
1880 if (ret) {
1881 lbs_pr_alert(
1882 "SEND_SLEEPC_CMD: Host to Card failed for Confirm Sleep\n");
1883 } else {
1884 spin_lock_irqsave(&priv->driver_lock, flags);
1885 if (!priv->intcounter) {
1886 priv->psstate = PS_STATE_SLEEP;
1887 } else {
1888 lbs_deb_host("SEND_SLEEPC_CMD: after sent, intcounter %d\n",
1889 priv->intcounter);
1891 spin_unlock_irqrestore(&priv->driver_lock, flags);
1893 lbs_deb_host("SEND_SLEEPC_CMD: sent confirm sleep\n");
1896 lbs_deb_leave_args(LBS_DEB_HOST, "ret %d", ret);
1897 return ret;
1900 void lbs_ps_sleep(struct lbs_private *priv, int wait_option)
1902 lbs_deb_enter(LBS_DEB_HOST);
1905 * PS is currently supported only in Infrastructure mode
1906 * Remove this check if it is to be supported in IBSS mode also
1909 lbs_prepare_and_send_command(priv, CMD_802_11_PS_MODE,
1910 CMD_SUBCMD_ENTER_PS, wait_option, 0, NULL);
1912 lbs_deb_leave(LBS_DEB_HOST);
1916 * @brief This function sends Exit_PS command to firmware.
1918 * @param priv A pointer to struct lbs_private structure
1919 * @param wait_option wait response or not
1920 * @return n/a
1922 void lbs_ps_wakeup(struct lbs_private *priv, int wait_option)
1924 __le32 Localpsmode;
1926 lbs_deb_enter(LBS_DEB_HOST);
1928 Localpsmode = cpu_to_le32(LBS802_11POWERMODECAM);
1930 lbs_prepare_and_send_command(priv, CMD_802_11_PS_MODE,
1931 CMD_SUBCMD_EXIT_PS,
1932 wait_option, 0, &Localpsmode);
1934 lbs_deb_leave(LBS_DEB_HOST);
1938 * @brief This function checks condition and prepares to
1939 * send sleep confirm command to firmware if ok.
1941 * @param priv A pointer to struct lbs_private structure
1942 * @param psmode Power Saving mode
1943 * @return n/a
1945 void lbs_ps_confirm_sleep(struct lbs_private *priv, u16 psmode)
1947 unsigned long flags =0;
1948 u8 allowed = 1;
1950 lbs_deb_enter(LBS_DEB_HOST);
1952 if (priv->dnld_sent) {
1953 allowed = 0;
1954 lbs_deb_host("dnld_sent was set");
1957 spin_lock_irqsave(&priv->driver_lock, flags);
1958 if (priv->cur_cmd) {
1959 allowed = 0;
1960 lbs_deb_host("cur_cmd was set");
1962 if (priv->intcounter > 0) {
1963 allowed = 0;
1964 lbs_deb_host("intcounter %d", priv->intcounter);
1966 spin_unlock_irqrestore(&priv->driver_lock, flags);
1968 if (allowed) {
1969 lbs_deb_host("sending lbs_ps_confirm_sleep\n");
1970 sendconfirmsleep(priv, (u8 *) & priv->lbs_ps_confirm_sleep,
1971 sizeof(struct PS_CMD_ConfirmSleep));
1972 } else {
1973 lbs_deb_host("sleep confirm has been delayed\n");
1976 lbs_deb_leave(LBS_DEB_HOST);
1981 * @brief Simple way to call firmware functions
1983 * @param priv A pointer to struct lbs_private structure
1984 * @param psmode one of the many CMD_802_11_xxxx
1985 * @param cmd pointer to the parameters structure for above command
1986 * (this should not include the command, size, sequence
1987 * and result fields from struct cmd_ds_gen)
1988 * @param cmd_size size structure pointed to by cmd
1989 * @param rsp pointer to an area where the result should be placed
1990 * @param rsp_size pointer to the size of the rsp area. If the firmware
1991 * returns fewer bytes, then this *rsp_size will be
1992 * changed to the actual size.
1993 * @return -1 in case of a higher level error, otherwise
1994 * the result code from the firmware
1997 int lbs_cmd(struct lbs_private *priv, uint16_t command, void *cmd, int cmd_size,
1998 int (*callback)(struct lbs_private *, unsigned long, struct cmd_ds_command *),
1999 unsigned long callback_arg)
2001 struct cmd_ctrl_node *cmdnode;
2002 struct cmd_ds_gen *cmdptr;
2003 unsigned long flags;
2004 int ret = 0;
2006 lbs_deb_enter(LBS_DEB_HOST);
2008 if (!priv) {
2009 lbs_deb_host("PREP_CMD: priv is NULL\n");
2010 ret = -1;
2011 goto done;
2014 if (priv->surpriseremoved) {
2015 lbs_deb_host("PREP_CMD: card removed\n");
2016 ret = -1;
2017 goto done;
2020 cmdnode = lbs_get_cmd_ctrl_node(priv);
2022 if (cmdnode == NULL) {
2023 lbs_deb_host("PREP_CMD: cmdnode is NULL\n");
2025 /* Wake up main thread to execute next command */
2026 wake_up_interruptible(&priv->waitq);
2027 ret = -1;
2028 goto done;
2031 cmdptr = (struct cmd_ds_gen *)cmdnode->bufvirtualaddr;
2032 cmdnode->wait_option = CMD_OPTION_WAITFORRSP;
2033 cmdnode->callback = callback;
2034 cmdnode->callback_arg = callback_arg;
2036 /* Set sequence number, clean result, move to buffer */
2037 priv->seqnum++;
2038 cmdptr->command = cpu_to_le16(command);
2039 cmdptr->size = cpu_to_le16(cmd_size + S_DS_GEN);
2040 cmdptr->seqnum = cpu_to_le16(priv->seqnum);
2041 cmdptr->result = 0;
2042 memcpy(cmdptr->cmdresp, cmd, cmd_size);
2044 lbs_deb_host("PREP_CMD: command 0x%04x\n", command);
2046 /* here was the big old switch() statement, which is now obsolete,
2047 * because the caller of lbs_cmd() sets up all of *cmd for us. */
2049 cmdnode->cmdwaitqwoken = 0;
2050 lbs_queue_cmd(priv, cmdnode, 1);
2051 wake_up_interruptible(&priv->waitq);
2053 might_sleep();
2054 wait_event_interruptible(cmdnode->cmdwait_q, cmdnode->cmdwaitqwoken);
2056 spin_lock_irqsave(&priv->driver_lock, flags);
2057 if (priv->cur_cmd_retcode) {
2058 lbs_deb_host("PREP_CMD: command failed with return code %d\n",
2059 priv->cur_cmd_retcode);
2060 priv->cur_cmd_retcode = 0;
2061 ret = -1;
2063 spin_unlock_irqrestore(&priv->driver_lock, flags);
2065 done:
2066 lbs_deb_leave_args(LBS_DEB_HOST, "ret %d", ret);
2067 return ret;
2069 EXPORT_SYMBOL_GPL(lbs_cmd);