|
@@ -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);
|
|
|
}
|
|
|
|
|
@@ -2232,6 +2235,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;
|
|
@@ -2287,6 +2292,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);
|
|
@@ -2409,6 +2421,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);
|