From 9a821f5d0fc36425e95f0f4ade4bbca8f0ebff4d Mon Sep 17 00:00:00 2001 From: Daniel Drake Date: Tue, 7 Jun 2011 18:15:57 +0100 Subject: libertas: add sd8686 reset_card support At http://dev.laptop.org/ticket/10748 we are seeing a case of the libertas firmware randomly stopping responding to commands after resume. Careful monitoring of communications indicates a firmware or hardware bug, which has been reported to Marvell. Work around this issue by adding a reset_card method; this is automatically called when command timeouts are detected and provides an instant recovery to this situation. Signed-off-by: Daniel Drake Signed-off-by: John W. Linville --- drivers/net/wireless/libertas/if_sdio.c | 34 +++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) (limited to 'drivers/net/wireless/libertas') diff --git a/drivers/net/wireless/libertas/if_sdio.c b/drivers/net/wireless/libertas/if_sdio.c index 224e9853c48..387786e1b39 100644 --- a/drivers/net/wireless/libertas/if_sdio.c +++ b/drivers/net/wireless/libertas/if_sdio.c @@ -892,6 +892,37 @@ static int if_sdio_reset_deep_sleep_wakeup(struct lbs_private *priv) } +static struct mmc_host *reset_host; + +static void if_sdio_reset_card_worker(struct work_struct *work) +{ + /* + * The actual reset operation must be run outside of lbs_thread. This + * is because mmc_remove_host() will cause the device to be instantly + * destroyed, and the libertas driver then needs to end lbs_thread, + * leading to a deadlock. + * + * We run it in a workqueue totally independent from the if_sdio_card + * instance for that reason. + */ + + pr_info("Resetting card..."); + mmc_remove_host(reset_host); + mmc_add_host(reset_host); +} +static DECLARE_WORK(card_reset_work, if_sdio_reset_card_worker); + +static void if_sdio_reset_card(struct lbs_private *priv) +{ + struct if_sdio_card *card = priv->card; + + if (work_pending(&card_reset_work)) + return; + + reset_host = card->func->card->host; + schedule_work(&card_reset_work); +} + /*******************************************************************/ /* SDIO callbacks */ /*******************************************************************/ @@ -1065,6 +1096,7 @@ static int if_sdio_probe(struct sdio_func *func, priv->enter_deep_sleep = if_sdio_enter_deep_sleep; priv->exit_deep_sleep = if_sdio_exit_deep_sleep; priv->reset_deep_sleep_wakeup = if_sdio_reset_deep_sleep_wakeup; + priv->reset_card = if_sdio_reset_card; sdio_claim_host(func); @@ -1301,6 +1333,8 @@ static void __exit if_sdio_exit_module(void) /* Set the flag as user is removing this module. */ user_rmmod = 1; + cancel_work_sync(&card_reset_work); + sdio_unregister_driver(&if_sdio_driver); lbs_deb_leave(LBS_DEB_SDIO); -- cgit v1.2.3 From 545a8aa793e04bee7a7e2aa8caa70bed94fd7a5c Mon Sep 17 00:00:00 2001 From: Nikanth Karthikesan Date: Tue, 14 Jun 2011 11:23:46 +0530 Subject: if_spi: Fix compilation warning - unused variable MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit if_spi: Fix compilation warning - unused variable 'spi' drivers/net/wireless/libertas/if_spi.c: In function ‘if_spi_init_card’: drivers/net/wireless/libertas/if_spi.c:1035: warning: unused variable ‘spi’ The variable is used only in a macro which uses the args only for DEBUG builds. Remove the 'spi' variable completely. Signed-off-by: Nikanth Karthikesan Acked-by: Dan Williams Signed-off-by: John W. Linville --- drivers/net/wireless/libertas/if_spi.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/net/wireless/libertas') diff --git a/drivers/net/wireless/libertas/if_spi.c b/drivers/net/wireless/libertas/if_spi.c index 463352c890d..d041bb2b577 100644 --- a/drivers/net/wireless/libertas/if_spi.c +++ b/drivers/net/wireless/libertas/if_spi.c @@ -1032,7 +1032,6 @@ static irqreturn_t if_spi_host_interrupt(int irq, void *dev_id) static int if_spi_init_card(struct if_spi_card *card) { struct lbs_private *priv = card->priv; - struct spi_device *spi = card->spi; int err, i; u32 scratch; const struct firmware *helper = NULL; @@ -1080,8 +1079,9 @@ static int if_spi_init_card(struct if_spi_card *card) "attached to SPI bus_num %d, chip_select %d. " "spi->max_speed_hz=%d\n", card->card_id, card->card_rev, - spi->master->bus_num, spi->chip_select, - spi->max_speed_hz); + card->spi->master->bus_num, + card->spi->chip_select, + card->spi->max_speed_hz); err = if_spi_prog_helper_firmware(card, helper); if (err) goto out; -- cgit v1.2.3