summaryrefslogtreecommitdiff
path: root/drivers/mmc
diff options
context:
space:
mode:
authorUlf Hansson <ulf.hansson@linaro.org>2019-06-18 15:05:17 +0300
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2019-06-25 06:34:44 +0300
commitec959de3d3a45a24c9ffb2a4aaa6c3b5df61031f (patch)
treeee7cac91990a5f5740b4047a51b6902e23167f99 /drivers/mmc
parent55dc448847c9edaf128234bc6f14ac9d16c11e6c (diff)
downloadlinux-ec959de3d3a45a24c9ffb2a4aaa6c3b5df61031f.tar.xz
mmc: core: Prevent processing SDIO IRQs when the card is suspended
commit 83293386bc95cf5e9f0c0175794455835bd1cb4a upstream. Processing of SDIO IRQs must obviously be prevented while the card is system suspended, otherwise we may end up trying to communicate with an uninitialized SDIO card. Reports throughout the years shows that this is not only a theoretical problem, but a real issue. So, let's finally fix this problem, by keeping track of the state for the card and bail out before processing the SDIO IRQ, in case the card is suspended. Cc: stable@vger.kernel.org Reported-by: Douglas Anderson <dianders@chromium.org> Tested-by: Douglas Anderson <dianders@chromium.org> Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/mmc')
-rw-r--r--drivers/mmc/core/sdio.c13
-rw-r--r--drivers/mmc/core/sdio_irq.c4
2 files changed, 16 insertions, 1 deletions
diff --git a/drivers/mmc/core/sdio.c b/drivers/mmc/core/sdio.c
index 6718fc8bb40f..0f51e774183e 100644
--- a/drivers/mmc/core/sdio.c
+++ b/drivers/mmc/core/sdio.c
@@ -941,6 +941,10 @@ static int mmc_sdio_pre_suspend(struct mmc_host *host)
*/
static int mmc_sdio_suspend(struct mmc_host *host)
{
+ /* Prevent processing of SDIO IRQs in suspended state. */
+ mmc_card_set_suspended(host->card);
+ cancel_delayed_work_sync(&host->sdio_irq_work);
+
mmc_claim_host(host);
if (mmc_card_keep_power(host) && mmc_card_wake_sdio_irq(host))
@@ -989,13 +993,20 @@ static int mmc_sdio_resume(struct mmc_host *host)
err = sdio_enable_4bit_bus(host->card);
}
- if (!err && host->sdio_irqs) {
+ if (err)
+ goto out;
+
+ /* Allow SDIO IRQs to be processed again. */
+ mmc_card_clr_suspended(host->card);
+
+ if (host->sdio_irqs) {
if (!(host->caps2 & MMC_CAP2_SDIO_IRQ_NOTHREAD))
wake_up_process(host->sdio_irq_thread);
else if (host->caps & MMC_CAP_SDIO_IRQ)
host->ops->enable_sdio_irq(host, 1);
}
+out:
mmc_release_host(host);
host->pm_flags &= ~MMC_PM_KEEP_POWER;
diff --git a/drivers/mmc/core/sdio_irq.c b/drivers/mmc/core/sdio_irq.c
index 7ca7b99413f0..b299a24d33f9 100644
--- a/drivers/mmc/core/sdio_irq.c
+++ b/drivers/mmc/core/sdio_irq.c
@@ -38,6 +38,10 @@ static int process_sdio_pending_irqs(struct mmc_host *host)
unsigned char pending;
struct sdio_func *func;
+ /* Don't process SDIO IRQs if the card is suspended. */
+ if (mmc_card_suspended(card))
+ return 0;
+
/*
* Optimization, if there is only 1 function interrupt registered
* and we know an IRQ was signaled then call irq handler directly.