Skip to content

Commit

Permalink
mmc: core: Prevent processing SDIO IRQs when the card is suspended
Browse files Browse the repository at this point in the history
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: [email protected]
Reported-by: Douglas Anderson <[email protected]>
Tested-by: Douglas Anderson <[email protected]>
Signed-off-by: Ulf Hansson <[email protected]>
  • Loading branch information
storulf committed Jun 18, 2019
1 parent 0f7b79a commit 8329338
Show file tree
Hide file tree
Showing 2 changed files with 16 additions and 1 deletion.
13 changes: 12 additions & 1 deletion drivers/mmc/core/sdio.c
Original file line number Diff line number Diff line change
Expand Up @@ -937,6 +937,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))
Expand Down Expand Up @@ -985,13 +989,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;
Expand Down
4 changes: 4 additions & 0 deletions drivers/mmc/core/sdio_irq.c
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,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.
Expand Down

0 comments on commit 8329338

Please sign in to comment.