SDHCI recovers from errors by resetting the cmd and data circuits. Until that is done, there very well might be more interrupts, so ignore them in that case. Signed-off-by: Adrian Hunter <adrian.hunter@xxxxxxxxx> --- drivers/mmc/host/sdhci.c | 20 ++++++++++++++++++++ drivers/mmc/host/sdhci.h | 1 + 2 files changed, 21 insertions(+) diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c index f75c226de7ff..a1afcd9dd228 100644 --- a/drivers/mmc/host/sdhci.c +++ b/drivers/mmc/host/sdhci.c @@ -935,6 +935,9 @@ static bool sdhci_needs_reset(struct sdhci_host *host, struct mmc_request *mrq) static void sdhci_finish_mrq(struct sdhci_host *host, struct mmc_request *mrq) { + if (sdhci_needs_reset(host, mrq)) + host->pending_reset = true; + tasklet_schedule(&host->finish_tasklet); } @@ -2226,6 +2229,8 @@ static void sdhci_tasklet_finish(unsigned long param) controllers do not like that. */ sdhci_do_reset(host, SDHCI_RESET_CMD); sdhci_do_reset(host, SDHCI_RESET_DATA); + + host->pending_reset = false; } host->mrq = NULL; @@ -2281,6 +2286,13 @@ static void sdhci_timeout_timer(unsigned long data) static void sdhci_cmd_irq(struct sdhci_host *host, u32 intmask, u32 *mask) { if (!host->cmd) { + /* + * SDHCI recovers from errors by resetting the cmd and data + * circuits. Until that is done, there very well might be more + * interrupts, so ignore them in that case. + */ + if (host->pending_reset) + return; pr_err("%s: Got command interrupt 0x%08x even though no command operation was in progress.\n", mmc_hostname(host->mmc), (unsigned)intmask); sdhci_dumpregs(host); @@ -2403,6 +2415,14 @@ static void sdhci_data_irq(struct sdhci_host *host, u32 intmask) } } + /* + * SDHCI recovers from errors by resetting the cmd and data + * circuits. Until that is done, there very well might be more + * interrupts, so ignore them in that case. + */ + if (host->pending_reset) + return; + pr_err("%s: Got data interrupt 0x%08x even though no data operation was in progress.\n", mmc_hostname(host->mmc), (unsigned)intmask); sdhci_dumpregs(host); diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h index d649dfd2f4d2..331a72b417ef 100644 --- a/drivers/mmc/host/sdhci.h +++ b/drivers/mmc/host/sdhci.h @@ -460,6 +460,7 @@ struct sdhci_host { bool runtime_suspended; /* Host is runtime suspended */ bool bus_on; /* Bus power prevents runtime suspend */ bool preset_enabled; /* Preset is enabled */ + bool pending_reset; /* Cmd/data reset is pending */ struct mmc_request *mrq; /* Current request */ struct mmc_command *cmd; /* Current command */ -- 1.9.1 -- To unsubscribe from this list: send the line "unsubscribe linux-mmc" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html