From 555c787abb033df7a678b3c4fdb2e51c4cf44d32 Mon Sep 17 00:00:00 2001 From: Andy Green Date: Fri, 25 Mar 2011 14:23:51 +0000 Subject: DRIVERS: WLAN: WL12XX provide driver runtime pm idle WL12XX fails to do power management in MMC layer when the last runtime_pm put is done and it calls runtime_pm_idle to indicate the device is not in use. The real reason seems to be to do with the .1 device, SDIO bluetooth, holding open the connection. This works around the problem by forcing power down in a local runtime_idle. Signed-off-by: Andy Green --- drivers/net/wireless/wl12xx/sdio.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/drivers/net/wireless/wl12xx/sdio.c b/drivers/net/wireless/wl12xx/sdio.c index 93cbb8d5aba..8c0eb433a35 100644 --- a/drivers/net/wireless/wl12xx/sdio.c +++ b/drivers/net/wireless/wl12xx/sdio.c @@ -28,6 +28,7 @@ #include #include #include +#include #include #include #include @@ -163,6 +164,11 @@ static int wl1271_sdio_power_on(struct wl1271 *wl) struct sdio_func *func = wl_to_func(wl); int ret; + /* + * defeat the runtime_idle OFF state + */ + mmc_power_restore_host(func->card->host); + /* Power up the card */ ret = pm_runtime_get_sync(&func->dev); if (ret < 0) @@ -302,9 +308,23 @@ static int wl1271_resume(struct device *dev) return 0; } +/* + * SDIO bus runtime idle gets precedence over this, but that just calls + * the generic version. The generic version will call our version if + * it exists, so we still get called. We need to allow it to power us + * off. + */ +static int wl1271_runtime_idle(struct device *dev) +{ + struct sdio_func *func = dev_to_sdio_func(dev); + + return mmc_power_save_host(func->card->host); +} + static const struct dev_pm_ops wl1271_sdio_pm_ops = { .suspend = wl1271_suspend, .resume = wl1271_resume, + .runtime_idle = wl1271_runtime_idle, }; static struct sdio_driver wl1271_sdio_driver = { -- cgit v1.2.3