summaryrefslogtreecommitdiffstats
path: root/drivers/mmc
diff options
context:
space:
mode:
authorAdrian Hunter <adrian.hunter@intel.com>2016-06-29 16:24:29 +0300
committerUlf Hansson <ulf.hansson@linaro.org>2016-07-25 10:34:41 +0200
commited1563de0bc90e09d9707a85cf8d0e958c6f6261 (patch)
treebc1221a33e862c4a7bdc0a2dbe186dec2cea61a0 /drivers/mmc
parent0cc563ce5436dca3119af86d0396412efec13a0f (diff)
downloadop-kernel-dev-ed1563de0bc90e09d9707a85cf8d0e958c6f6261.zip
op-kernel-dev-ed1563de0bc90e09d9707a85cf8d0e958c6f6261.tar.gz
mmc: sdhci: Track whether a reset is pending
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@intel.com> Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
Diffstat (limited to 'drivers/mmc')
-rw-r--r--drivers/mmc/host/sdhci.c20
-rw-r--r--drivers/mmc/host/sdhci.h1
2 files changed, 21 insertions, 0 deletions
diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
index b0a3200..320c294 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);
}
@@ -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);
diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h
index 13e0bd6..7301c90 100644
--- a/drivers/mmc/host/sdhci.h
+++ b/drivers/mmc/host/sdhci.h
@@ -463,6 +463,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 */
OpenPOWER on IntegriCloud