f579e16a7f8f876e9d51c824713a7600ff49987e
[oweals/openwrt.git] /
1 From a32de68edab7b73ded850bcf76cdf6858e92a7e5 Mon Sep 17 00:00:00 2001
2 From: Dmitry Osipenko <digetx@gmail.com>
3 Date: Sun, 15 Dec 2019 21:42:24 +0300
4 Subject: [PATCH] brcmfmac: Keep OOB wake-interrupt disabled when it shouldn't
5  be enabled
6
7 NVIDIA Tegra SoCs do not like when OOB wake is enabled and WiFi interface
8 is in DOWN state during suspend. This results in a CPU hang on programming
9 OOB wake-up state of the GPIO controller during of system's suspend.
10
11 The solution is trivial: don't enable wake for the OOB interrupt when it
12 should be disabled.
13
14 This fixes hang on Tegra20 (Acer A500) and Tegra30 (Nexus 7) devices which
15 are using BCM4329 and BCM4330 WiFi chips respectively.
16
17 Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
18 Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
19 ---
20  .../net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c  | 10 +++++-----
21  .../net/wireless/broadcom/brcm80211/brcmfmac/sdio.h    |  1 -
22  2 files changed, 5 insertions(+), 6 deletions(-)
23
24 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c
25 +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c
26 @@ -120,7 +120,7 @@ int brcmf_sdiod_intr_register(struct brc
27                         brcmf_err("enable_irq_wake failed %d\n", ret);
28                         return ret;
29                 }
30 -               sdiodev->irq_wake = true;
31 +               disable_irq_wake(pdata->oob_irq_nr);
32  
33                 sdio_claim_host(sdiodev->func1);
34  
35 @@ -179,10 +179,6 @@ void brcmf_sdiod_intr_unregister(struct
36                 sdio_release_host(sdiodev->func1);
37  
38                 sdiodev->oob_irq_requested = false;
39 -               if (sdiodev->irq_wake) {
40 -                       disable_irq_wake(pdata->oob_irq_nr);
41 -                       sdiodev->irq_wake = false;
42 -               }
43                 free_irq(pdata->oob_irq_nr, &sdiodev->func1->dev);
44                 sdiodev->irq_en = false;
45                 sdiodev->oob_irq_requested = false;
46 @@ -1173,6 +1169,10 @@ static int brcmf_ops_sdio_resume(struct
47                 if (ret)
48                         brcmf_err("Failed to probe device on resume\n");
49         } else {
50 +               if (sdiodev->wowl_enabled &&
51 +                   sdiodev->settings->bus.sdio.oob_irq_supported)
52 +                       disable_irq_wake(sdiodev->settings->bus.sdio.oob_irq_nr);
53 +
54                 brcmf_sdiod_freezer_off(sdiodev);
55         }
56  
57 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.h
58 +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.h
59 @@ -178,7 +178,6 @@ struct brcmf_sdio_dev {
60         bool sd_irq_requested;
61         bool irq_en;                    /* irq enable flags */
62         spinlock_t irq_en_lock;
63 -       bool irq_wake;                  /* irq wake enable flags */
64         bool sg_support;
65         uint max_request_size;
66         ushort max_segment_count;