From ae63a33ec9b598b3454cf0d29077fa17b616c42a Mon Sep 17 00:00:00 2001 From: Deepak Saxena Date: Sun, 31 Oct 2010 13:40:33 +0000 Subject: libertas: EHS_REMOVE_WAKEUP is not always supported Certain firmware versions, particularly the 8388 found on the XO-1, do not support the EHS_REMOVE_WAKEUP command that is used to disable WOL. Sending this command to the card will return a failure that would get propagated up the stack and cause suspend to fail. Instead, fall back to an all-zero wakeup mask. This fixes http://dev.laptop.org/ticket/9967 Signed-off-by: Deepak Saxena Signed-off-by: Daniel Drake [includes fixups by Paul Fox] Signed-off-by: John W. Linville --- drivers/net/wireless/libertas/cmd.c | 8 ++++++++ drivers/net/wireless/libertas/dev.h | 1 + drivers/net/wireless/libertas/if_usb.c | 7 +++++++ drivers/net/wireless/libertas/main.c | 3 ++- 4 files changed, 18 insertions(+), 1 deletion(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/libertas/cmd.c b/drivers/net/wireless/libertas/cmd.c index 70745928f3f..78c4da150a7 100644 --- a/drivers/net/wireless/libertas/cmd.c +++ b/drivers/net/wireless/libertas/cmd.c @@ -177,6 +177,14 @@ int lbs_host_sleep_cfg(struct lbs_private *priv, uint32_t criteria, struct cmd_ds_host_sleep cmd_config; int ret; + /* + * Certain firmware versions do not support EHS_REMOVE_WAKEUP command + * and the card will return a failure. Since we need to be + * able to reset the mask, in those cases we set a 0 mask instead. + */ + if (criteria == EHS_REMOVE_WAKEUP && !priv->ehs_remove_supported) + criteria = 0; + cmd_config.hdr.size = cpu_to_le16(sizeof(cmd_config)); cmd_config.criteria = cpu_to_le32(criteria); cmd_config.gpio = priv->wol_gpio; diff --git a/drivers/net/wireless/libertas/dev.h b/drivers/net/wireless/libertas/dev.h index f062ed58390..f5a9851fc7e 100644 --- a/drivers/net/wireless/libertas/dev.h +++ b/drivers/net/wireless/libertas/dev.h @@ -137,6 +137,7 @@ struct lbs_private { uint32_t wol_criteria; uint8_t wol_gpio; uint8_t wol_gap; + bool ehs_remove_supported; /* Transmitting */ int tx_pending_len; /* -1 while building packet */ diff --git a/drivers/net/wireless/libertas/if_usb.c b/drivers/net/wireless/libertas/if_usb.c index 35931cf4d6d..6524c70363d 100644 --- a/drivers/net/wireless/libertas/if_usb.c +++ b/drivers/net/wireless/libertas/if_usb.c @@ -345,6 +345,13 @@ static int if_usb_probe(struct usb_interface *intf, if (device_create_file(&priv->dev->dev, &dev_attr_lbs_flash_boot2)) lbs_pr_err("cannot register lbs_flash_boot2 attribute\n"); + /* + * EHS_REMOVE_WAKEUP is not supported on all versions of the firmware. + */ + priv->wol_criteria = EHS_REMOVE_WAKEUP; + if (lbs_host_sleep_cfg(priv, priv->wol_criteria, NULL)) + priv->ehs_remove_supported = false; + return 0; err_start_card: diff --git a/drivers/net/wireless/libertas/main.c b/drivers/net/wireless/libertas/main.c index 47ce5a6ba12..6d7af91d52c 100644 --- a/drivers/net/wireless/libertas/main.c +++ b/drivers/net/wireless/libertas/main.c @@ -844,9 +844,10 @@ struct lbs_private *lbs_add_card(void *card, struct device *dmdev) priv->work_thread = create_singlethread_workqueue("lbs_worker"); INIT_WORK(&priv->mcast_work, lbs_set_mcast_worker); - priv->wol_criteria = 0xffffffff; + priv->wol_criteria = EHS_REMOVE_WAKEUP; priv->wol_gpio = 0xff; priv->wol_gap = 20; + priv->ehs_remove_supported = true; goto done; -- cgit v1.2.3-70-g09d2