]>
Commit | Line | Data |
---|---|---|
1aebfeb4 GKH |
1 | From 83293386bc95cf5e9f0c0175794455835bd1cb4a Mon Sep 17 00:00:00 2001 |
2 | From: Ulf Hansson <ulf.hansson@linaro.org> | |
3 | Date: Tue, 18 Jun 2019 14:05:17 +0200 | |
4 | Subject: mmc: core: Prevent processing SDIO IRQs when the card is suspended | |
5 | ||
6 | From: Ulf Hansson <ulf.hansson@linaro.org> | |
7 | ||
8 | commit 83293386bc95cf5e9f0c0175794455835bd1cb4a upstream. | |
9 | ||
10 | Processing of SDIO IRQs must obviously be prevented while the card is | |
11 | system suspended, otherwise we may end up trying to communicate with an | |
12 | uninitialized SDIO card. | |
13 | ||
14 | Reports throughout the years shows that this is not only a theoretical | |
15 | problem, but a real issue. So, let's finally fix this problem, by keeping | |
16 | track of the state for the card and bail out before processing the SDIO | |
17 | IRQ, in case the card is suspended. | |
18 | ||
19 | Cc: stable@vger.kernel.org | |
20 | Reported-by: Douglas Anderson <dianders@chromium.org> | |
21 | Tested-by: Douglas Anderson <dianders@chromium.org> | |
22 | Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org> | |
23 | Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> | |
24 | ||
25 | --- | |
26 | drivers/mmc/core/sdio.c | 13 ++++++++++++- | |
27 | drivers/mmc/core/sdio_irq.c | 4 ++++ | |
28 | 2 files changed, 16 insertions(+), 1 deletion(-) | |
29 | ||
30 | --- a/drivers/mmc/core/sdio.c | |
31 | +++ b/drivers/mmc/core/sdio.c | |
32 | @@ -907,6 +907,10 @@ static int mmc_sdio_pre_suspend(struct m | |
33 | */ | |
34 | static int mmc_sdio_suspend(struct mmc_host *host) | |
35 | { | |
36 | + /* Prevent processing of SDIO IRQs in suspended state. */ | |
37 | + mmc_card_set_suspended(host->card); | |
38 | + cancel_delayed_work_sync(&host->sdio_irq_work); | |
39 | + | |
40 | mmc_claim_host(host); | |
41 | ||
42 | if (mmc_card_keep_power(host) && mmc_card_wake_sdio_irq(host)) | |
43 | @@ -962,13 +966,20 @@ static int mmc_sdio_resume(struct mmc_ho | |
44 | err = sdio_enable_4bit_bus(host->card); | |
45 | } | |
46 | ||
47 | - if (!err && host->sdio_irqs) { | |
48 | + if (err) | |
49 | + goto out; | |
50 | + | |
51 | + /* Allow SDIO IRQs to be processed again. */ | |
52 | + mmc_card_clr_suspended(host->card); | |
53 | + | |
54 | + if (host->sdio_irqs) { | |
55 | if (!(host->caps2 & MMC_CAP2_SDIO_IRQ_NOTHREAD)) | |
56 | wake_up_process(host->sdio_irq_thread); | |
57 | else if (host->caps & MMC_CAP_SDIO_IRQ) | |
58 | host->ops->enable_sdio_irq(host, 1); | |
59 | } | |
60 | ||
61 | +out: | |
62 | mmc_release_host(host); | |
63 | ||
64 | host->pm_flags &= ~MMC_PM_KEEP_POWER; | |
65 | --- a/drivers/mmc/core/sdio_irq.c | |
66 | +++ b/drivers/mmc/core/sdio_irq.c | |
67 | @@ -38,6 +38,10 @@ static int process_sdio_pending_irqs(str | |
68 | unsigned char pending; | |
69 | struct sdio_func *func; | |
70 | ||
71 | + /* Don't process SDIO IRQs if the card is suspended. */ | |
72 | + if (mmc_card_suspended(card)) | |
73 | + return 0; | |
74 | + | |
75 | /* | |
76 | * Optimization, if there is only 1 function interrupt registered | |
77 | * and we know an IRQ was signaled then call irq handler directly. |