mmc: sdhci: Track whether a reset is pending
authorAdrian Hunter <adrian.hunter@intel.com>
Wed, 29 Jun 2016 13:24:29 +0000 (16:24 +0300)
committerUlf Hansson <ulf.hansson@linaro.org>
Mon, 25 Jul 2016 08:34:41 +0000 (10:34 +0200)
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>
drivers/mmc/host/sdhci.c
drivers/mmc/host/sdhci.h

index b0a320004e0ddda2d50db37b2dd70459bff803d0..320c294b9d73c482677dbfdc89b869309131c19d 100644 (file)
@@ -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);
index 13e0bd6cff5da364e528b808a9ae6b0928356e03..7301c90f85009fbac9c9453e4cb778b0af2d241d 100644 (file)
@@ -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 */