aboutsummaryrefslogtreecommitdiffstats
path: root/package/kernel/mac80211/patches/360-brcmfmac-fix-sdio-suspend-and-resume.patch
diff options
context:
space:
mode:
Diffstat (limited to 'package/kernel/mac80211/patches/360-brcmfmac-fix-sdio-suspend-and-resume.patch')
-rw-r--r--package/kernel/mac80211/patches/360-brcmfmac-fix-sdio-suspend-and-resume.patch68
1 files changed, 68 insertions, 0 deletions
diff --git a/package/kernel/mac80211/patches/360-brcmfmac-fix-sdio-suspend-and-resume.patch b/package/kernel/mac80211/patches/360-brcmfmac-fix-sdio-suspend-and-resume.patch
new file mode 100644
index 0000000000..ac5584ec3c
--- /dev/null
+++ b/package/kernel/mac80211/patches/360-brcmfmac-fix-sdio-suspend-and-resume.patch
@@ -0,0 +1,68 @@
+From: Arend van Spriel <arend@broadcom.com>
+Date: Tue, 14 Apr 2015 20:10:30 +0200
+Subject: [PATCH] brcmfmac: fix sdio suspend and resume
+
+commit 330b4e4be937 ("brcmfmac: Add wowl support for SDIO devices.")
+changed the behaviour by removing the MMC_PM_KEEP_POWER flag for
+non-wowl scenario, which needs to be restored. Another necessary
+change is to mark the card as being non-removable. With this in place
+the suspend resume test passes successfully doing:
+
+ # echo devices > /sys/power/pm_test
+ # echo mem > /sys/power/state
+
+Note that power may still be switched off when system is going
+in S3 state.
+
+Reported-by: Fu, Zhonghui <<zhonghui.fu@linux.intel.com>
+Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
+Reviewed-by: Franky (Zhenhui) Lin <frankyl@broadcom.com>
+Signed-off-by: Arend van Spriel <arend@broadcom.com>
+---
+
+--- a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c
++++ b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c
+@@ -1011,6 +1011,14 @@ static int brcmf_sdiod_remove(struct brc
+ return 0;
+ }
+
++static void brcmf_sdiod_host_fixup(struct mmc_host *host)
++{
++ /* runtime-pm powers off the device */
++ pm_runtime_forbid(host->parent);
++ /* avoid removal detection upon resume */
++ host->caps |= MMC_CAP_NONREMOVABLE;
++}
++
+ static int brcmf_sdiod_probe(struct brcmf_sdio_dev *sdiodev)
+ {
+ struct sdio_func *func;
+@@ -1076,7 +1084,7 @@ static int brcmf_sdiod_probe(struct brcm
+ ret = -ENODEV;
+ goto out;
+ }
+- pm_runtime_forbid(host->parent);
++ brcmf_sdiod_host_fixup(host);
+ out:
+ if (ret)
+ brcmf_sdiod_remove(sdiodev);
+@@ -1246,15 +1254,15 @@ static int brcmf_ops_sdio_suspend(struct
+ brcmf_sdiod_freezer_on(sdiodev);
+ brcmf_sdio_wd_timer(sdiodev->bus, 0);
+
++ sdio_flags = MMC_PM_KEEP_POWER;
+ if (sdiodev->wowl_enabled) {
+- sdio_flags = MMC_PM_KEEP_POWER;
+ if (sdiodev->pdata->oob_irq_supported)
+ enable_irq_wake(sdiodev->pdata->oob_irq_nr);
+ else
+- sdio_flags = MMC_PM_WAKE_SDIO_IRQ;
+- if (sdio_set_host_pm_flags(sdiodev->func[1], sdio_flags))
+- brcmf_err("Failed to set pm_flags %x\n", sdio_flags);
++ sdio_flags |= MMC_PM_WAKE_SDIO_IRQ;
+ }
++ if (sdio_set_host_pm_flags(sdiodev->func[1], sdio_flags))
++ brcmf_err("Failed to set pm_flags %x\n", sdio_flags);
+ return 0;
+ }
+