aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/libertas/cmd.c
diff options
context:
space:
mode:
authorAmitkumar Karwar <akarwar@marvell.com>2009-09-30 23:04:38 -0400
committerJohn W. Linville <linville@tuxdriver.com>2009-10-07 16:39:43 -0400
commit4912545472d71e3dd546b18b397aec4c89fd7403 (patch)
treeb7b0d520cdbee35303caf69881f7898e38966bc7 /drivers/net/wireless/libertas/cmd.c
parent125b181aec7a67c71234284ecf6d9c729d05deda (diff)
libertas: Add auto deep sleep support for SD8385/SD8686/SD8688
Add timer based auto deep sleep feature in libertas driver which can be configured using iwconfig command. This is tested on SD8688, SD8686 cards with firmware versions 10.38.1.p25, 9.70.4.p0 respectively on 32-bit and 64-bit platforms. Tests have been done for USB/CS cards to make sure that the patch won't break USB/CS code. We didn't test the if_spi driver. Signed-off-by: Amitkumar Karwar <akarwar@marvell.com> Signed-off-by: Bing Zhao <bzhao@marvell.com> Acked-by: Dan Williams <dcbw@redhat.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/libertas/cmd.c')
-rw-r--r--drivers/net/wireless/libertas/cmd.c72
1 files changed, 69 insertions, 3 deletions
diff --git a/drivers/net/wireless/libertas/cmd.c b/drivers/net/wireless/libertas/cmd.c
index 685098148e10..3a3e8947e84a 100644
--- a/drivers/net/wireless/libertas/cmd.c
+++ b/drivers/net/wireless/libertas/cmd.c
@@ -17,7 +17,6 @@
17 17
18static struct cmd_ctrl_node *lbs_get_cmd_ctrl_node(struct lbs_private *priv); 18static struct cmd_ctrl_node *lbs_get_cmd_ctrl_node(struct lbs_private *priv);
19 19
20
21/** 20/**
22 * @brief Simple callback that copies response back into command 21 * @brief Simple callback that copies response back into command
23 * 22 *
@@ -319,6 +318,60 @@ int lbs_cmd_802_11_sleep_params(struct lbs_private *priv, uint16_t cmd_action,
319 return 0; 318 return 0;
320} 319}
321 320
321static int lbs_wait_for_ds_awake(struct lbs_private *priv)
322{
323 int ret = 0;
324
325 lbs_deb_enter(LBS_DEB_CMD);
326
327 if (priv->is_deep_sleep) {
328 if (!wait_event_interruptible_timeout(priv->ds_awake_q,
329 !priv->is_deep_sleep, (10 * HZ))) {
330 lbs_pr_err("ds_awake_q: timer expired\n");
331 ret = -1;
332 }
333 }
334
335 lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
336 return ret;
337}
338
339int lbs_set_deep_sleep(struct lbs_private *priv, int deep_sleep)
340{
341 int ret = 0;
342
343 lbs_deb_enter(LBS_DEB_CMD);
344
345 if (deep_sleep) {
346 if (priv->is_deep_sleep != 1) {
347 lbs_deb_cmd("deep sleep: sleep\n");
348 BUG_ON(!priv->enter_deep_sleep);
349 ret = priv->enter_deep_sleep(priv);
350 if (!ret) {
351 netif_stop_queue(priv->dev);
352 netif_carrier_off(priv->dev);
353 }
354 } else {
355 lbs_pr_err("deep sleep: already enabled\n");
356 }
357 } else {
358 if (priv->is_deep_sleep) {
359 lbs_deb_cmd("deep sleep: wakeup\n");
360 BUG_ON(!priv->exit_deep_sleep);
361 ret = priv->exit_deep_sleep(priv);
362 if (!ret) {
363 ret = lbs_wait_for_ds_awake(priv);
364 if (ret)
365 lbs_pr_err("deep sleep: wakeup"
366 "failed\n");
367 }
368 }
369 }
370
371 lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
372 return ret;
373}
374
322int lbs_cmd_802_11_set_wep(struct lbs_private *priv, uint16_t cmd_action, 375int lbs_cmd_802_11_set_wep(struct lbs_private *priv, uint16_t cmd_action,
323 struct assoc_request *assoc) 376 struct assoc_request *assoc)
324{ 377{
@@ -1242,8 +1295,17 @@ static void lbs_submit_command(struct lbs_private *priv,
1242 timeo = HZ/4; 1295 timeo = HZ/4;
1243 } 1296 }
1244 1297
1245 /* Setup the timer after transmit command */ 1298 if (command == CMD_802_11_DEEP_SLEEP) {
1246 mod_timer(&priv->command_timer, jiffies + timeo); 1299 if (priv->is_auto_deep_sleep_enabled) {
1300 priv->wakeup_dev_required = 1;
1301 priv->dnld_sent = 0;
1302 }
1303 priv->is_deep_sleep = 1;
1304 lbs_complete_command(priv, cmdnode, 0);
1305 } else {
1306 /* Setup the timer after transmit command */
1307 mod_timer(&priv->command_timer, jiffies + timeo);
1308 }
1247 1309
1248 lbs_deb_leave(LBS_DEB_HOST); 1310 lbs_deb_leave(LBS_DEB_HOST);
1249} 1311}
@@ -1505,6 +1567,10 @@ int lbs_prepare_and_send_command(struct lbs_private *priv,
1505 case CMD_802_11_BEACON_CTRL: 1567 case CMD_802_11_BEACON_CTRL:
1506 ret = lbs_cmd_bcn_ctrl(priv, cmdptr, cmd_action); 1568 ret = lbs_cmd_bcn_ctrl(priv, cmdptr, cmd_action);
1507 break; 1569 break;
1570 case CMD_802_11_DEEP_SLEEP:
1571 cmdptr->command = cpu_to_le16(CMD_802_11_DEEP_SLEEP);
1572 cmdptr->size = cpu_to_le16(S_DS_GEN);
1573 break;
1508 default: 1574 default:
1509 lbs_pr_err("PREP_CMD: unknown command 0x%04x\n", cmd_no); 1575 lbs_pr_err("PREP_CMD: unknown command 0x%04x\n", cmd_no);
1510 ret = -1; 1576 ret = -1;