add chaos_calmer branch
[15.05/openwrt.git] / package / kernel / mac80211 / patches / 360-brcmfmac-fix-sdio-suspend-and-resume.patch
1 From: Arend van Spriel <arend@broadcom.com>
2 Date: Tue, 14 Apr 2015 20:10:30 +0200
3 Subject: [PATCH] brcmfmac: fix sdio suspend and resume
4
5 commit 330b4e4be937 ("brcmfmac: Add wowl support for SDIO devices.")
6 changed the behaviour by removing the MMC_PM_KEEP_POWER flag for
7 non-wowl scenario, which needs to be restored. Another necessary
8 change is to mark the card as being non-removable. With this in place
9 the suspend resume test passes successfully doing:
10
11  # echo devices > /sys/power/pm_test
12  # echo mem > /sys/power/state
13
14 Note that power may still be switched off when system is going
15 in S3 state.
16
17 Reported-by: Fu, Zhonghui <<zhonghui.fu@linux.intel.com>
18 Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
19 Reviewed-by: Franky (Zhenhui) Lin <frankyl@broadcom.com>
20 Signed-off-by: Arend van Spriel <arend@broadcom.com>
21 ---
22
23 --- a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c
24 +++ b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c
25 @@ -1011,6 +1011,14 @@ static int brcmf_sdiod_remove(struct brc
26         return 0;
27  }
28  
29 +static void brcmf_sdiod_host_fixup(struct mmc_host *host)
30 +{
31 +       /* runtime-pm powers off the device */
32 +       pm_runtime_forbid(host->parent);
33 +       /* avoid removal detection upon resume */
34 +       host->caps |= MMC_CAP_NONREMOVABLE;
35 +}
36 +
37  static int brcmf_sdiod_probe(struct brcmf_sdio_dev *sdiodev)
38  {
39         struct sdio_func *func;
40 @@ -1076,7 +1084,7 @@ static int brcmf_sdiod_probe(struct brcm
41                 ret = -ENODEV;
42                 goto out;
43         }
44 -       pm_runtime_forbid(host->parent);
45 +       brcmf_sdiod_host_fixup(host);
46  out:
47         if (ret)
48                 brcmf_sdiod_remove(sdiodev);
49 @@ -1246,15 +1254,15 @@ static int brcmf_ops_sdio_suspend(struct
50         brcmf_sdiod_freezer_on(sdiodev);
51         brcmf_sdio_wd_timer(sdiodev->bus, 0);
52  
53 +       sdio_flags = MMC_PM_KEEP_POWER;
54         if (sdiodev->wowl_enabled) {
55 -               sdio_flags = MMC_PM_KEEP_POWER;
56                 if (sdiodev->pdata->oob_irq_supported)
57                         enable_irq_wake(sdiodev->pdata->oob_irq_nr);
58                 else
59 -                       sdio_flags = MMC_PM_WAKE_SDIO_IRQ;
60 -               if (sdio_set_host_pm_flags(sdiodev->func[1], sdio_flags))
61 -                       brcmf_err("Failed to set pm_flags %x\n", sdio_flags);
62 +                       sdio_flags |= MMC_PM_WAKE_SDIO_IRQ;
63         }
64 +       if (sdio_set_host_pm_flags(sdiodev->func[1], sdio_flags))
65 +               brcmf_err("Failed to set pm_flags %x\n", sdio_flags);
66         return 0;
67  }
68