aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/ti
diff options
context:
space:
mode:
authorTony Lindgren <tony@atomide.com>2018-05-17 11:29:50 -0700
committerKalle Valo <kvalo@codeaurora.org>2018-05-29 10:14:45 +0300
commit728a9dc61f132eb567f58c234e11ef80a3519cc0 (patch)
treec8655f5eaf32300560c29c45c3303f9a617b6f74 /drivers/net/wireless/ti
parentbrcmfmac: trigger memory dump on SDIO firmware halt message (diff)
downloadlinux-dev-728a9dc61f132eb567f58c234e11ef80a3519cc0.tar.xz
linux-dev-728a9dc61f132eb567f58c234e11ef80a3519cc0.zip
wlcore: sdio: Fix flakey SDIO runtime PM handling
We can have pm_runtime_get_sync() return 1, and we can have pm_runtime_put_sync() return -EBUSY. See rpm_suspend() and rpm_resume() for more information. Fix the issue by returning 0 from wl12xx_sdio_power_on() on success. And use pm_runtime_put() instead of pm_runtime_put_sync() for wl12xx_sdio_power_off(), then the MMC subsystem will idle the bus when suitable. Otherwise wlcore can sometimes get confused and may report bogus errors and WLAN connection can fail. Note that while wlcore checks the return value for wl1271_power_on(), the return value is ignored for wl1271_power_off(). Let's fix them both though to avoid further confusion in the future. Fixes: 60f36637bbbd ("wlcore: sdio: allow pm to handle sdio power") Signed-off-by: Tony Lindgren <tony@atomide.com> Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
Diffstat (limited to 'drivers/net/wireless/ti')
-rw-r--r--drivers/net/wireless/ti/wlcore/sdio.c16
1 files changed, 12 insertions, 4 deletions
diff --git a/drivers/net/wireless/ti/wlcore/sdio.c b/drivers/net/wireless/ti/wlcore/sdio.c
index 6dbe61d47dc3..15d5ac126061 100644
--- a/drivers/net/wireless/ti/wlcore/sdio.c
+++ b/drivers/net/wireless/ti/wlcore/sdio.c
@@ -159,28 +159,36 @@ static int wl12xx_sdio_power_on(struct wl12xx_sdio_glue *glue)
pm_runtime_put_noidle(&card->dev);
dev_err(glue->dev, "%s: failed to get_sync(%d)\n",
__func__, ret);
- goto out;
+
+ return ret;
}
sdio_claim_host(func);
sdio_enable_func(func);
sdio_release_host(func);
-out:
- return ret;
+ return 0;
}
static int wl12xx_sdio_power_off(struct wl12xx_sdio_glue *glue)
{
struct sdio_func *func = dev_to_sdio_func(glue->dev);
struct mmc_card *card = func->card;
+ int error;
sdio_claim_host(func);
sdio_disable_func(func);
sdio_release_host(func);
/* Let runtime PM know the card is powered off */
- return pm_runtime_put_sync(&card->dev);
+ error = pm_runtime_put(&card->dev);
+ if (error < 0 && error != -EBUSY) {
+ dev_err(&card->dev, "%s failed: %i\n", __func__, error);
+
+ return error;
+ }
+
+ return 0;
}
static int wl12xx_sdio_set_power(struct device *child, bool enable)