diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c index a00cdd7fa65134f2d5370b101d4f02350f9bdb14..c9456bd603a97f8aa37701dbeeb90143c7139d21 100644 --- a/drivers/mmc/host/sdhci.c +++ b/drivers/mmc/host/sdhci.c @@ -929,6 +929,7 @@ static void sdhci_finish_data(struct sdhci_host *host) data = host->data; host->data = NULL; + host->data_cmd = NULL; if ((host->flags & (SDHCI_REQ_USE_DMA | SDHCI_USE_ADMA)) == (SDHCI_REQ_USE_DMA | SDHCI_USE_ADMA)) @@ -1014,6 +1015,10 @@ void sdhci_send_command(struct sdhci_host *host, struct mmc_command *cmd) host->cmd = cmd; host->busy_handle = 0; + if (cmd->data || cmd->flags & MMC_RSP_BUSY) { + WARN_ON(host->data_cmd); + host->data_cmd = cmd; + } sdhci_prepare_data(host, cmd); @@ -2224,6 +2229,7 @@ static void sdhci_tasklet_finish(unsigned long param) host->mrq = NULL; host->cmd = NULL; host->data = NULL; + host->data_cmd = NULL; sdhci_led_deactivate(host); @@ -2365,14 +2371,19 @@ static void sdhci_data_irq(struct sdhci_host *host, u32 intmask) } if (!host->data) { + struct mmc_command *data_cmd = host->data_cmd; + + if (data_cmd) + host->data_cmd = NULL; + /* * The "data complete" interrupt is also used to * indicate that a busy state has ended. See comment * above in sdhci_cmd_irq(). */ - if (host->cmd && (host->cmd->flags & MMC_RSP_BUSY)) { + if (data_cmd && (data_cmd->flags & MMC_RSP_BUSY)) { if (intmask & SDHCI_INT_DATA_TIMEOUT) { - host->cmd->error = -ETIMEDOUT; + data_cmd->error = -ETIMEDOUT; tasklet_schedule(&host->finish_tasklet); return; } @@ -2447,7 +2458,7 @@ static void sdhci_data_irq(struct sdhci_host *host, u32 intmask) } if (intmask & SDHCI_INT_DATA_END) { - if (host->cmd) { + if (host->cmd == host->data_cmd) { /* * Data managed to finish before the * command completed. Make sure we do diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h index e332e4a4082353d850b7fc0c789b78783a0b3bab..6e971709c9dffd1d905a48336606535e3cc1698f 100644 --- a/drivers/mmc/host/sdhci.h +++ b/drivers/mmc/host/sdhci.h @@ -466,6 +466,7 @@ struct sdhci_host { struct mmc_request *mrq; /* Current request */ struct mmc_command *cmd; /* Current command */ + struct mmc_command *data_cmd; /* Current data command */ struct mmc_data *data; /* Current data request */ unsigned int data_early:1; /* Data finished before cmd */ unsigned int busy_handle:1; /* Handling the order of Busy-end */