summaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c
diff options
context:
space:
mode:
authorArend van Spriel <arend@broadcom.com>2015-01-25 20:31:34 +0100
committerKalle Valo <kvalo@codeaurora.org>2015-01-29 09:59:00 +0200
commit8982cd40ace9b7f109ac8c63e6763409e39feb55 (patch)
treef598384aaded35074367ab1830b200e5b4afd17a /drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c
parent9b7a0ddc6073909bc61399ca3b8126ef886d5e8a (diff)
downloadlinux-stable-8982cd40ace9b7f109ac8c63e6763409e39feb55.tar.gz
linux-stable-8982cd40ace9b7f109ac8c63e6763409e39feb55.tar.bz2
linux-stable-8982cd40ace9b7f109ac8c63e6763409e39feb55.zip
brcmfmac: wait for driver to go idle during suspend
Before going in suspend state the watchdog thread needs to put the device in bus sleep state, which assures it can go in deep-sleep state during D3 state. Reviewed-by: Hante Meuleman <meuleman@broadcom.com> Reviewed-by: Daniel (Deognyoun) Kim <dekim@broadcom.com> Reviewed-by: Franky (Zhenhui) Lin <frankyl@broadcom.com> Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com> Signed-off-by: Arend van Spriel <arend@broadcom.com> Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
Diffstat (limited to 'drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c')
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c20
1 files changed, 15 insertions, 5 deletions
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c
index 8ba60f6f4915..9afaeb6d2af5 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c
@@ -1045,7 +1045,9 @@ static int brcmf_ops_sdio_probe(struct sdio_func *func,
bus_if->wowl_supported = true;
#endif
+ sdiodev->sleeping = false;
atomic_set(&sdiodev->suspend, false);
+ init_waitqueue_head(&sdiodev->idle_wait);
brcmf_dbg(SDIO, "F2 found, calling brcmf_sdiod_probe...\n");
err = brcmf_sdiod_probe(sdiodev);
@@ -1107,12 +1109,23 @@ void brcmf_sdio_wowl_config(struct device *dev, bool enabled)
#ifdef CONFIG_PM_SLEEP
static int brcmf_ops_sdio_suspend(struct device *dev)
{
- struct brcmf_bus *bus_if = dev_get_drvdata(dev);
- struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv.sdio;
+ struct brcmf_bus *bus_if;
+ struct brcmf_sdio_dev *sdiodev;
mmc_pm_flag_t sdio_flags;
brcmf_dbg(SDIO, "Enter\n");
+ bus_if = dev_get_drvdata(dev);
+ sdiodev = bus_if->bus_priv.sdio;
+
+ /* wait for watchdog to go idle */
+ if (wait_event_timeout(sdiodev->idle_wait, sdiodev->sleeping,
+ msecs_to_jiffies(3 * BRCMF_WD_POLL_MS)) == 0) {
+ brcmf_err("bus still active\n");
+ return -EBUSY;
+ }
+ /* disable watchdog */
+ brcmf_sdio_wd_timer(sdiodev->bus, 0);
atomic_set(&sdiodev->suspend, true);
if (sdiodev->wowl_enabled) {
@@ -1124,9 +1137,6 @@ static int brcmf_ops_sdio_suspend(struct device *dev)
if (sdio_set_host_pm_flags(sdiodev->func[1], sdio_flags))
brcmf_err("Failed to set pm_flags %x\n", sdio_flags);
}
-
- brcmf_sdio_wd_timer(sdiodev->bus, 0);
-
return 0;
}