aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/libertas
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2010-06-11 14:34:06 -0400
committerDavid S. Miller <davem@davemloft.net>2010-06-11 14:34:06 -0400
commit14599f1e341ee219abdd15f4eee5872d6f2d29f1 (patch)
tree3875181429010e58416ab34e6c06ef42de52e756 /drivers/net/wireless/libertas
parentd8d1f30b95a635dbd610dcc5eb641aca8f4768cf (diff)
parent832c10fd733893f86c63bde1c65b005d5a2fe346 (diff)
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next-2.6
Conflicts: drivers/net/wireless/wl12xx/wl1271.h drivers/net/wireless/wl12xx/wl1271_cmd.h
Diffstat (limited to 'drivers/net/wireless/libertas')
-rw-r--r--drivers/net/wireless/libertas/cmd.c37
-rw-r--r--drivers/net/wireless/libertas/cmdresp.c30
-rw-r--r--drivers/net/wireless/libertas/decl.h2
-rw-r--r--drivers/net/wireless/libertas/dev.h6
-rw-r--r--drivers/net/wireless/libertas/ethtool.c24
-rw-r--r--drivers/net/wireless/libertas/if_sdio.c58
-rw-r--r--drivers/net/wireless/libertas/if_usb.c12
-rw-r--r--drivers/net/wireless/libertas/main.c79
-rw-r--r--drivers/net/wireless/libertas/scan.c2
9 files changed, 177 insertions, 73 deletions
diff --git a/drivers/net/wireless/libertas/cmd.c b/drivers/net/wireless/libertas/cmd.c
index cdb9b9650d73..0fa6b0e59ea5 100644
--- a/drivers/net/wireless/libertas/cmd.c
+++ b/drivers/net/wireless/libertas/cmd.c
@@ -70,6 +70,8 @@ static u8 is_command_allowed_in_ps(u16 cmd)
70 switch (cmd) { 70 switch (cmd) {
71 case CMD_802_11_RSSI: 71 case CMD_802_11_RSSI:
72 return 1; 72 return 1;
73 case CMD_802_11_HOST_SLEEP_CFG:
74 return 1;
73 default: 75 default:
74 break; 76 break;
75 } 77 }
@@ -185,6 +187,23 @@ out:
185 return ret; 187 return ret;
186} 188}
187 189
190static int lbs_ret_host_sleep_cfg(struct lbs_private *priv, unsigned long dummy,
191 struct cmd_header *resp)
192{
193 lbs_deb_enter(LBS_DEB_CMD);
194 if (priv->wol_criteria == EHS_REMOVE_WAKEUP) {
195 priv->is_host_sleep_configured = 0;
196 if (priv->psstate == PS_STATE_FULL_POWER) {
197 priv->is_host_sleep_activated = 0;
198 wake_up_interruptible(&priv->host_sleep_q);
199 }
200 } else {
201 priv->is_host_sleep_configured = 1;
202 }
203 lbs_deb_leave(LBS_DEB_CMD);
204 return 0;
205}
206
188int lbs_host_sleep_cfg(struct lbs_private *priv, uint32_t criteria, 207int lbs_host_sleep_cfg(struct lbs_private *priv, uint32_t criteria,
189 struct wol_config *p_wol_config) 208 struct wol_config *p_wol_config)
190{ 209{
@@ -202,12 +221,11 @@ int lbs_host_sleep_cfg(struct lbs_private *priv, uint32_t criteria,
202 else 221 else
203 cmd_config.wol_conf.action = CMD_ACT_ACTION_NONE; 222 cmd_config.wol_conf.action = CMD_ACT_ACTION_NONE;
204 223
205 ret = lbs_cmd_with_response(priv, CMD_802_11_HOST_SLEEP_CFG, &cmd_config); 224 ret = __lbs_cmd(priv, CMD_802_11_HOST_SLEEP_CFG, &cmd_config.hdr,
225 le16_to_cpu(cmd_config.hdr.size),
226 lbs_ret_host_sleep_cfg, 0);
206 if (!ret) { 227 if (!ret) {
207 if (criteria) { 228 if (p_wol_config)
208 lbs_deb_cmd("Set WOL criteria to %x\n", criteria);
209 priv->wol_criteria = criteria;
210 } else
211 memcpy((uint8_t *) p_wol_config, 229 memcpy((uint8_t *) p_wol_config,
212 (uint8_t *)&cmd_config.wol_conf, 230 (uint8_t *)&cmd_config.wol_conf,
213 sizeof(struct wol_config)); 231 sizeof(struct wol_config));
@@ -712,6 +730,10 @@ static void lbs_queue_cmd(struct lbs_private *priv,
712 } 730 }
713 } 731 }
714 732
733 if (le16_to_cpu(cmdnode->cmdbuf->command) ==
734 CMD_802_11_WAKEUP_CONFIRM)
735 addtail = 0;
736
715 spin_lock_irqsave(&priv->driver_lock, flags); 737 spin_lock_irqsave(&priv->driver_lock, flags);
716 738
717 if (addtail) 739 if (addtail)
@@ -1353,6 +1375,11 @@ static void lbs_send_confirmsleep(struct lbs_private *priv)
1353 /* We don't get a response on the sleep-confirmation */ 1375 /* We don't get a response on the sleep-confirmation */
1354 priv->dnld_sent = DNLD_RES_RECEIVED; 1376 priv->dnld_sent = DNLD_RES_RECEIVED;
1355 1377
1378 if (priv->is_host_sleep_configured) {
1379 priv->is_host_sleep_activated = 1;
1380 wake_up_interruptible(&priv->host_sleep_q);
1381 }
1382
1356 /* If nothing to do, go back to sleep (?) */ 1383 /* If nothing to do, go back to sleep (?) */
1357 if (!kfifo_len(&priv->event_fifo) && !priv->resp_len[priv->resp_idx]) 1384 if (!kfifo_len(&priv->event_fifo) && !priv->resp_len[priv->resp_idx])
1358 priv->psstate = PS_STATE_SLEEP; 1385 priv->psstate = PS_STATE_SLEEP;
diff --git a/drivers/net/wireless/libertas/cmdresp.c b/drivers/net/wireless/libertas/cmdresp.c
index 88f7131d66e9..d6c306353640 100644
--- a/drivers/net/wireless/libertas/cmdresp.c
+++ b/drivers/net/wireless/libertas/cmdresp.c
@@ -17,6 +17,7 @@
17#include "dev.h" 17#include "dev.h"
18#include "assoc.h" 18#include "assoc.h"
19#include "wext.h" 19#include "wext.h"
20#include "cmd.h"
20 21
21/** 22/**
22 * @brief This function handles disconnect event. it 23 * @brief This function handles disconnect event. it
@@ -341,32 +342,10 @@ done:
341 return ret; 342 return ret;
342} 343}
343 344
344static int lbs_send_confirmwake(struct lbs_private *priv)
345{
346 struct cmd_header cmd;
347 int ret = 0;
348
349 lbs_deb_enter(LBS_DEB_HOST);
350
351 cmd.command = cpu_to_le16(CMD_802_11_WAKEUP_CONFIRM);
352 cmd.size = cpu_to_le16(sizeof(cmd));
353 cmd.seqnum = cpu_to_le16(++priv->seqnum);
354 cmd.result = 0;
355
356 lbs_deb_hex(LBS_DEB_HOST, "wake confirm", (u8 *) &cmd,
357 sizeof(cmd));
358
359 ret = priv->hw_host_to_card(priv, MVMS_CMD, (u8 *) &cmd, sizeof(cmd));
360 if (ret)
361 lbs_pr_alert("SEND_WAKEC_CMD: Host to Card failed for Confirm Wake\n");
362
363 lbs_deb_leave_args(LBS_DEB_HOST, "ret %d", ret);
364 return ret;
365}
366
367int lbs_process_event(struct lbs_private *priv, u32 event) 345int lbs_process_event(struct lbs_private *priv, u32 event)
368{ 346{
369 int ret = 0; 347 int ret = 0;
348 struct cmd_header cmd;
370 349
371 lbs_deb_enter(LBS_DEB_CMD); 350 lbs_deb_enter(LBS_DEB_CMD);
372 351
@@ -410,7 +389,10 @@ int lbs_process_event(struct lbs_private *priv, u32 event)
410 if (priv->reset_deep_sleep_wakeup) 389 if (priv->reset_deep_sleep_wakeup)
411 priv->reset_deep_sleep_wakeup(priv); 390 priv->reset_deep_sleep_wakeup(priv);
412 priv->is_deep_sleep = 0; 391 priv->is_deep_sleep = 0;
413 lbs_send_confirmwake(priv); 392 lbs_cmd_async(priv, CMD_802_11_WAKEUP_CONFIRM, &cmd,
393 sizeof(cmd));
394 priv->is_host_sleep_activated = 0;
395 wake_up_interruptible(&priv->host_sleep_q);
414 break; 396 break;
415 397
416 case MACREG_INT_CODE_DEEP_SLEEP_AWAKE: 398 case MACREG_INT_CODE_DEEP_SLEEP_AWAKE:
diff --git a/drivers/net/wireless/libertas/decl.h b/drivers/net/wireless/libertas/decl.h
index 709ffcad22ad..61db8bc62b3c 100644
--- a/drivers/net/wireless/libertas/decl.h
+++ b/drivers/net/wireless/libertas/decl.h
@@ -38,7 +38,7 @@ int lbs_set_mac_address(struct net_device *dev, void *addr);
38void lbs_set_multicast_list(struct net_device *dev); 38void lbs_set_multicast_list(struct net_device *dev);
39 39
40int lbs_suspend(struct lbs_private *priv); 40int lbs_suspend(struct lbs_private *priv);
41void lbs_resume(struct lbs_private *priv); 41int lbs_resume(struct lbs_private *priv);
42 42
43void lbs_queue_event(struct lbs_private *priv, u32 event); 43void lbs_queue_event(struct lbs_private *priv, u32 event);
44void lbs_notify_command_response(struct lbs_private *priv, u8 resp_idx); 44void lbs_notify_command_response(struct lbs_private *priv, u8 resp_idx);
diff --git a/drivers/net/wireless/libertas/dev.h b/drivers/net/wireless/libertas/dev.h
index a54880e4ad2b..71c5ad46ebf6 100644
--- a/drivers/net/wireless/libertas/dev.h
+++ b/drivers/net/wireless/libertas/dev.h
@@ -75,6 +75,7 @@ struct lbs_private {
75 75
76 /* Deep sleep */ 76 /* Deep sleep */
77 int is_deep_sleep; 77 int is_deep_sleep;
78 int deep_sleep_required;
78 int is_auto_deep_sleep_enabled; 79 int is_auto_deep_sleep_enabled;
79 int wakeup_dev_required; 80 int wakeup_dev_required;
80 int is_activity_detected; 81 int is_activity_detected;
@@ -82,6 +83,11 @@ struct lbs_private {
82 wait_queue_head_t ds_awake_q; 83 wait_queue_head_t ds_awake_q;
83 struct timer_list auto_deepsleep_timer; 84 struct timer_list auto_deepsleep_timer;
84 85
86 /* Host sleep*/
87 int is_host_sleep_configured;
88 int is_host_sleep_activated;
89 wait_queue_head_t host_sleep_q;
90
85 /* Hardware access */ 91 /* Hardware access */
86 void *card; 92 void *card;
87 u8 fw_ready; 93 u8 fw_ready;
diff --git a/drivers/net/wireless/libertas/ethtool.c b/drivers/net/wireless/libertas/ethtool.c
index 3804a58d7f4e..0cf31bbf6567 100644
--- a/drivers/net/wireless/libertas/ethtool.c
+++ b/drivers/net/wireless/libertas/ethtool.c
@@ -69,14 +69,11 @@ static void lbs_ethtool_get_wol(struct net_device *dev,
69{ 69{
70 struct lbs_private *priv = dev->ml_priv; 70 struct lbs_private *priv = dev->ml_priv;
71 71
72 if (priv->wol_criteria == 0xffffffff) {
73 /* Interface driver didn't configure wake */
74 wol->supported = wol->wolopts = 0;
75 return;
76 }
77
78 wol->supported = WAKE_UCAST|WAKE_MCAST|WAKE_BCAST|WAKE_PHY; 72 wol->supported = WAKE_UCAST|WAKE_MCAST|WAKE_BCAST|WAKE_PHY;
79 73
74 if (priv->wol_criteria == EHS_REMOVE_WAKEUP)
75 return;
76
80 if (priv->wol_criteria & EHS_WAKE_ON_UNICAST_DATA) 77 if (priv->wol_criteria & EHS_WAKE_ON_UNICAST_DATA)
81 wol->wolopts |= WAKE_UCAST; 78 wol->wolopts |= WAKE_UCAST;
82 if (priv->wol_criteria & EHS_WAKE_ON_MULTICAST_DATA) 79 if (priv->wol_criteria & EHS_WAKE_ON_MULTICAST_DATA)
@@ -91,23 +88,22 @@ static int lbs_ethtool_set_wol(struct net_device *dev,
91 struct ethtool_wolinfo *wol) 88 struct ethtool_wolinfo *wol)
92{ 89{
93 struct lbs_private *priv = dev->ml_priv; 90 struct lbs_private *priv = dev->ml_priv;
94 uint32_t criteria = 0;
95 91
96 if (wol->wolopts & ~(WAKE_UCAST|WAKE_MCAST|WAKE_BCAST|WAKE_PHY)) 92 if (wol->wolopts & ~(WAKE_UCAST|WAKE_MCAST|WAKE_BCAST|WAKE_PHY))
97 return -EOPNOTSUPP; 93 return -EOPNOTSUPP;
98 94
95 priv->wol_criteria = 0;
99 if (wol->wolopts & WAKE_UCAST) 96 if (wol->wolopts & WAKE_UCAST)
100 criteria |= EHS_WAKE_ON_UNICAST_DATA; 97 priv->wol_criteria |= EHS_WAKE_ON_UNICAST_DATA;
101 if (wol->wolopts & WAKE_MCAST) 98 if (wol->wolopts & WAKE_MCAST)
102 criteria |= EHS_WAKE_ON_MULTICAST_DATA; 99 priv->wol_criteria |= EHS_WAKE_ON_MULTICAST_DATA;
103 if (wol->wolopts & WAKE_BCAST) 100 if (wol->wolopts & WAKE_BCAST)
104 criteria |= EHS_WAKE_ON_BROADCAST_DATA; 101 priv->wol_criteria |= EHS_WAKE_ON_BROADCAST_DATA;
105 if (wol->wolopts & WAKE_PHY) 102 if (wol->wolopts & WAKE_PHY)
106 criteria |= EHS_WAKE_ON_MAC_EVENT; 103 priv->wol_criteria |= EHS_WAKE_ON_MAC_EVENT;
107 if (wol->wolopts == 0) 104 if (wol->wolopts == 0)
108 criteria |= EHS_REMOVE_WAKEUP; 105 priv->wol_criteria |= EHS_REMOVE_WAKEUP;
109 106 return 0;
110 return lbs_host_sleep_cfg(priv, criteria, (struct wol_config *)NULL);
111} 107}
112 108
113const struct ethtool_ops lbs_ethtool_ops = { 109const struct ethtool_ops lbs_ethtool_ops = {
diff --git a/drivers/net/wireless/libertas/if_sdio.c b/drivers/net/wireless/libertas/if_sdio.c
index 64dd345d30f5..6e71346a7550 100644
--- a/drivers/net/wireless/libertas/if_sdio.c
+++ b/drivers/net/wireless/libertas/if_sdio.c
@@ -1182,11 +1182,69 @@ static void if_sdio_remove(struct sdio_func *func)
1182 lbs_deb_leave(LBS_DEB_SDIO); 1182 lbs_deb_leave(LBS_DEB_SDIO);
1183} 1183}
1184 1184
1185static int if_sdio_suspend(struct device *dev)
1186{
1187 struct sdio_func *func = dev_to_sdio_func(dev);
1188 int ret;
1189 struct if_sdio_card *card = sdio_get_drvdata(func);
1190
1191 mmc_pm_flag_t flags = sdio_get_host_pm_caps(func);
1192
1193 lbs_pr_info("%s: suspend: PM flags = 0x%x\n",
1194 sdio_func_id(func), flags);
1195
1196 /* If we aren't being asked to wake on anything, we should bail out
1197 * and let the SD stack power down the card.
1198 */
1199 if (card->priv->wol_criteria == EHS_REMOVE_WAKEUP) {
1200 lbs_pr_info("Suspend without wake params -- "
1201 "powering down card.");
1202 return -ENOSYS;
1203 }
1204
1205 if (!(flags & MMC_PM_KEEP_POWER)) {
1206 lbs_pr_err("%s: cannot remain alive while host is suspended\n",
1207 sdio_func_id(func));
1208 return -ENOSYS;
1209 }
1210
1211 ret = sdio_set_host_pm_flags(func, MMC_PM_KEEP_POWER);
1212 if (ret)
1213 return ret;
1214
1215 ret = lbs_suspend(card->priv);
1216 if (ret)
1217 return ret;
1218
1219 return sdio_set_host_pm_flags(func, MMC_PM_WAKE_SDIO_IRQ);
1220}
1221
1222static int if_sdio_resume(struct device *dev)
1223{
1224 struct sdio_func *func = dev_to_sdio_func(dev);
1225 struct if_sdio_card *card = sdio_get_drvdata(func);
1226 int ret;
1227
1228 lbs_pr_info("%s: resume: we're back\n", sdio_func_id(func));
1229
1230 ret = lbs_resume(card->priv);
1231
1232 return ret;
1233}
1234
1235static const struct dev_pm_ops if_sdio_pm_ops = {
1236 .suspend = if_sdio_suspend,
1237 .resume = if_sdio_resume,
1238};
1239
1185static struct sdio_driver if_sdio_driver = { 1240static struct sdio_driver if_sdio_driver = {
1186 .name = "libertas_sdio", 1241 .name = "libertas_sdio",
1187 .id_table = if_sdio_ids, 1242 .id_table = if_sdio_ids,
1188 .probe = if_sdio_probe, 1243 .probe = if_sdio_probe,
1189 .remove = if_sdio_remove, 1244 .remove = if_sdio_remove,
1245 .drv = {
1246 .pm = &if_sdio_pm_ops,
1247 },
1190}; 1248};
1191 1249
1192/*******************************************************************/ 1250/*******************************************************************/
diff --git a/drivers/net/wireless/libertas/if_usb.c b/drivers/net/wireless/libertas/if_usb.c
index f41594c7ac16..3678e532874f 100644
--- a/drivers/net/wireless/libertas/if_usb.c
+++ b/drivers/net/wireless/libertas/if_usb.c
@@ -613,16 +613,14 @@ static void if_usb_receive_fwload(struct urb *urb)
613 return; 613 return;
614 } 614 }
615 615
616 syncfwheader = kmalloc(sizeof(struct fwsyncheader), GFP_ATOMIC); 616 syncfwheader = kmemdup(skb->data + IPFIELD_ALIGN_OFFSET,
617 sizeof(struct fwsyncheader), GFP_ATOMIC);
617 if (!syncfwheader) { 618 if (!syncfwheader) {
618 lbs_deb_usbd(&cardp->udev->dev, "Failure to allocate syncfwheader\n"); 619 lbs_deb_usbd(&cardp->udev->dev, "Failure to allocate syncfwheader\n");
619 kfree_skb(skb); 620 kfree_skb(skb);
620 return; 621 return;
621 } 622 }
622 623
623 memcpy(syncfwheader, skb->data + IPFIELD_ALIGN_OFFSET,
624 sizeof(struct fwsyncheader));
625
626 if (!syncfwheader->cmd) { 624 if (!syncfwheader->cmd) {
627 lbs_deb_usb2(&cardp->udev->dev, "FW received Blk with correct CRC\n"); 625 lbs_deb_usb2(&cardp->udev->dev, "FW received Blk with correct CRC\n");
628 lbs_deb_usb2(&cardp->udev->dev, "FW received Blk seqnum = %d\n", 626 lbs_deb_usb2(&cardp->udev->dev, "FW received Blk seqnum = %d\n",
@@ -1043,6 +1041,12 @@ static int if_usb_suspend(struct usb_interface *intf, pm_message_t message)
1043 if (priv->psstate != PS_STATE_FULL_POWER) 1041 if (priv->psstate != PS_STATE_FULL_POWER)
1044 return -1; 1042 return -1;
1045 1043
1044 if (priv->wol_criteria == EHS_REMOVE_WAKEUP) {
1045 lbs_pr_info("Suspend attempt without "
1046 "configuring wake params!\n");
1047 return -ENOSYS;
1048 }
1049
1046 ret = lbs_suspend(priv); 1050 ret = lbs_suspend(priv);
1047 if (ret) 1051 if (ret)
1048 goto out; 1052 goto out;
diff --git a/drivers/net/wireless/libertas/main.c b/drivers/net/wireless/libertas/main.c
index d9b8ee130c45..abfecc4814b4 100644
--- a/drivers/net/wireless/libertas/main.c
+++ b/drivers/net/wireless/libertas/main.c
@@ -625,16 +625,13 @@ static int lbs_thread(void *data)
625 return 0; 625 return 0;
626} 626}
627 627
628static int lbs_suspend_callback(struct lbs_private *priv, unsigned long dummy, 628static int lbs_ret_host_sleep_activate(struct lbs_private *priv,
629 struct cmd_header *cmd) 629 unsigned long dummy,
630 struct cmd_header *cmd)
630{ 631{
631 lbs_deb_enter(LBS_DEB_FW); 632 lbs_deb_enter(LBS_DEB_FW);
632 633 priv->is_host_sleep_activated = 1;
633 netif_device_detach(priv->dev); 634 wake_up_interruptible(&priv->host_sleep_q);
634 if (priv->mesh_dev)
635 netif_device_detach(priv->mesh_dev);
636
637 priv->fw_ready = 0;
638 lbs_deb_leave(LBS_DEB_FW); 635 lbs_deb_leave(LBS_DEB_FW);
639 return 0; 636 return 0;
640} 637}
@@ -646,39 +643,65 @@ int lbs_suspend(struct lbs_private *priv)
646 643
647 lbs_deb_enter(LBS_DEB_FW); 644 lbs_deb_enter(LBS_DEB_FW);
648 645
649 if (priv->wol_criteria == 0xffffffff) { 646 if (priv->is_deep_sleep) {
650 lbs_pr_info("Suspend attempt without configuring wake params!\n"); 647 ret = lbs_set_deep_sleep(priv, 0);
651 return -EINVAL; 648 if (ret) {
649 lbs_pr_err("deep sleep cancellation failed: %d\n", ret);
650 return ret;
651 }
652 priv->deep_sleep_required = 1;
652 } 653 }
653 654
654 memset(&cmd, 0, sizeof(cmd)); 655 memset(&cmd, 0, sizeof(cmd));
656 ret = lbs_host_sleep_cfg(priv, priv->wol_criteria,
657 (struct wol_config *)NULL);
658 if (ret) {
659 lbs_pr_info("Host sleep configuration failed: %d\n", ret);
660 return ret;
661 }
662 if (priv->psstate == PS_STATE_FULL_POWER) {
663 ret = __lbs_cmd(priv, CMD_802_11_HOST_SLEEP_ACTIVATE, &cmd,
664 sizeof(cmd), lbs_ret_host_sleep_activate, 0);
665 if (ret)
666 lbs_pr_info("HOST_SLEEP_ACTIVATE failed: %d\n", ret);
667 }
655 668
656 ret = __lbs_cmd(priv, CMD_802_11_HOST_SLEEP_ACTIVATE, &cmd, 669 if (!wait_event_interruptible_timeout(priv->host_sleep_q,
657 sizeof(cmd), lbs_suspend_callback, 0); 670 priv->is_host_sleep_activated, (10 * HZ))) {
658 if (ret) 671 lbs_pr_err("host_sleep_q: timer expired\n");
659 lbs_pr_info("HOST_SLEEP_ACTIVATE failed: %d\n", ret); 672 ret = -1;
673 }
674 netif_device_detach(priv->dev);
675 if (priv->mesh_dev)
676 netif_device_detach(priv->mesh_dev);
660 677
661 lbs_deb_leave_args(LBS_DEB_FW, "ret %d", ret); 678 lbs_deb_leave_args(LBS_DEB_FW, "ret %d", ret);
662 return ret; 679 return ret;
663} 680}
664EXPORT_SYMBOL_GPL(lbs_suspend); 681EXPORT_SYMBOL_GPL(lbs_suspend);
665 682
666void lbs_resume(struct lbs_private *priv) 683int lbs_resume(struct lbs_private *priv)
667{ 684{
668 lbs_deb_enter(LBS_DEB_FW); 685 int ret;
686 uint32_t criteria = EHS_REMOVE_WAKEUP;
669 687
670 priv->fw_ready = 1; 688 lbs_deb_enter(LBS_DEB_FW);
671 689
672 /* Firmware doesn't seem to give us RX packets any more 690 ret = lbs_host_sleep_cfg(priv, criteria, (struct wol_config *)NULL);
673 until we send it some command. Might as well update */
674 lbs_prepare_and_send_command(priv, CMD_802_11_RSSI, 0,
675 0, 0, NULL);
676 691
677 netif_device_attach(priv->dev); 692 netif_device_attach(priv->dev);
678 if (priv->mesh_dev) 693 if (priv->mesh_dev)
679 netif_device_attach(priv->mesh_dev); 694 netif_device_attach(priv->mesh_dev);
680 695
681 lbs_deb_leave(LBS_DEB_FW); 696 if (priv->deep_sleep_required) {
697 priv->deep_sleep_required = 0;
698 ret = lbs_set_deep_sleep(priv, 1);
699 if (ret)
700 lbs_pr_err("deep sleep activation failed: %d\n", ret);
701 }
702
703 lbs_deb_leave_args(LBS_DEB_FW, "ret %d", ret);
704 return ret;
682} 705}
683EXPORT_SYMBOL_GPL(lbs_resume); 706EXPORT_SYMBOL_GPL(lbs_resume);
684 707
@@ -834,10 +857,13 @@ static int lbs_init_adapter(struct lbs_private *priv)
834 priv->psstate = PS_STATE_FULL_POWER; 857 priv->psstate = PS_STATE_FULL_POWER;
835 priv->is_deep_sleep = 0; 858 priv->is_deep_sleep = 0;
836 priv->is_auto_deep_sleep_enabled = 0; 859 priv->is_auto_deep_sleep_enabled = 0;
860 priv->deep_sleep_required = 0;
837 priv->wakeup_dev_required = 0; 861 priv->wakeup_dev_required = 0;
838 init_waitqueue_head(&priv->ds_awake_q); 862 init_waitqueue_head(&priv->ds_awake_q);
839 priv->authtype_auto = 1; 863 priv->authtype_auto = 1;
840 864 priv->is_host_sleep_configured = 0;
865 priv->is_host_sleep_activated = 0;
866 init_waitqueue_head(&priv->host_sleep_q);
841 mutex_init(&priv->lock); 867 mutex_init(&priv->lock);
842 868
843 setup_timer(&priv->command_timer, lbs_cmd_timeout_handler, 869 setup_timer(&priv->command_timer, lbs_cmd_timeout_handler,
@@ -976,6 +1002,7 @@ struct lbs_private *lbs_add_card(void *card, struct device *dmdev)
976 1002
977 priv->wol_criteria = 0xffffffff; 1003 priv->wol_criteria = 0xffffffff;
978 priv->wol_gpio = 0xff; 1004 priv->wol_gpio = 0xff;
1005 priv->wol_gap = 20;
979 1006
980 goto done; 1007 goto done;
981 1008
@@ -1031,6 +1058,10 @@ void lbs_remove_card(struct lbs_private *priv)
1031 wake_up_interruptible(&priv->ds_awake_q); 1058 wake_up_interruptible(&priv->ds_awake_q);
1032 } 1059 }
1033 1060
1061 priv->is_host_sleep_configured = 0;
1062 priv->is_host_sleep_activated = 0;
1063 wake_up_interruptible(&priv->host_sleep_q);
1064
1034 /* Stop the thread servicing the interrupts */ 1065 /* Stop the thread servicing the interrupts */
1035 priv->surpriseremoved = 1; 1066 priv->surpriseremoved = 1;
1036 kthread_stop(priv->main_thread); 1067 kthread_stop(priv->main_thread);
diff --git a/drivers/net/wireless/libertas/scan.c b/drivers/net/wireless/libertas/scan.c
index 24cd54b3a806..7d82f13bdf1d 100644
--- a/drivers/net/wireless/libertas/scan.c
+++ b/drivers/net/wireless/libertas/scan.c
@@ -666,7 +666,7 @@ void lbs_scan_worker(struct work_struct *work)
666/** 666/**
667 * @brief Interpret a BSS scan response returned from the firmware 667 * @brief Interpret a BSS scan response returned from the firmware
668 * 668 *
669 * Parse the various fixed fields and IEs passed back for a a BSS probe 669 * Parse the various fixed fields and IEs passed back for a BSS probe
670 * response or beacon from the scan command. Record information as needed 670 * response or beacon from the scan command. Record information as needed
671 * in the scan table struct bss_descriptor for that entry. 671 * in the scan table struct bss_descriptor for that entry.
672 * 672 *