mmc: sdhci: Move busy signal handling into sdhci_finish_cmd()
[cascardo/linux.git] / drivers / mmc / host / sdhci.c
index 44cdb6d..9ca4253 100644 (file)
@@ -45,7 +45,6 @@ static unsigned int debug_quirks2;
 
 static void sdhci_finish_data(struct sdhci_host *);
 
-static void sdhci_finish_command(struct sdhci_host *);
 static void sdhci_enable_preset_value(struct sdhci_host *host, bool enable);
 
 static void sdhci_dumpregs(struct sdhci_host *host)
@@ -1079,6 +1078,28 @@ static void sdhci_finish_command(struct sdhci_host *host)
                }
        }
 
+       /*
+        * The host can send and interrupt when the busy state has
+        * ended, allowing us to wait without wasting CPU cycles.
+        * The busy signal uses DAT0 so this is similar to waiting
+        * for data to complete.
+        *
+        * Note: The 1.0 specification is a bit ambiguous about this
+        *       feature so there might be some problems with older
+        *       controllers.
+        */
+       if (host->cmd->flags & MMC_RSP_BUSY) {
+               if (host->cmd->data) {
+                       DBG("Cannot wait for busy signal when also doing a data transfer");
+               } else if (!(host->quirks & SDHCI_QUIRK_NO_BUSY_IRQ) &&
+                          !host->busy_handle) {
+                       /* Mark that command complete before busy is ended */
+                       host->busy_handle = 1;
+                       host->cmd = NULL;
+                       return;
+               }
+       }
+
        /* Finished CMD23, now send actual command. */
        if (host->cmd == host->mrq->sbc) {
                host->cmd = NULL;
@@ -2295,33 +2316,10 @@ static void sdhci_cmd_irq(struct sdhci_host *host, u32 intmask, u32 *mask)
                return;
        }
 
-       /*
-        * The host can send and interrupt when the busy state has
-        * ended, allowing us to wait without wasting CPU cycles.
-        * Unfortunately this is overloaded on the "data complete"
-        * interrupt, so we need to take some care when handling
-        * it.
-        *
-        * Note: The 1.0 specification is a bit ambiguous about this
-        *       feature so there might be some problems with older
-        *       controllers.
-        */
-       if (host->cmd->flags & MMC_RSP_BUSY) {
-               if (host->cmd->data)
-                       DBG("Cannot wait for busy signal when also doing a data transfer");
-               else if (!(host->quirks & SDHCI_QUIRK_NO_BUSY_IRQ)
-                               && !host->busy_handle) {
-                       /* Mark that command complete before busy is ended */
-                       host->busy_handle = 1;
-                       return;
-               }
-
-               /* The controller does not support the end-of-busy IRQ,
-                * fall through and take the SDHCI_INT_RESPONSE */
-       } else if ((host->quirks2 & SDHCI_QUIRK2_STOP_WITH_TC) &&
-                  host->cmd->opcode == MMC_STOP_TRANSMISSION && !host->data) {
+       if ((host->quirks2 & SDHCI_QUIRK2_STOP_WITH_TC) &&
+           !(host->cmd->flags & MMC_RSP_BUSY) && !host->data &&
+           host->cmd->opcode == MMC_STOP_TRANSMISSION)
                *mask &= ~SDHCI_INT_DATA_END;
-       }
 
        if (intmask & SDHCI_INT_RESPONSE)
                sdhci_finish_command(host);
@@ -2395,7 +2393,7 @@ static void sdhci_data_irq(struct sdhci_host *host, u32 intmask)
                                 * sure we do things in the proper order.
                                 */
                                if (host->busy_handle)
-                                       sdhci_finish_command(host);
+                                       tasklet_schedule(&host->finish_tasklet);
                                else
                                        host->busy_handle = 1;
                                return;