mmc: sdhci: Ensure all requests get errored out
authorAdrian Hunter <adrian.hunter@intel.com>
Wed, 29 Jun 2016 13:24:31 +0000 (16:24 +0300)
committerUlf Hansson <ulf.hansson@linaro.org>
Mon, 25 Jul 2016 08:34:42 +0000 (10:34 +0200)
In order to support commands during data transfer, there will have to be up
to two active requests (mrqs) at a time, instead of just one. That means
ensuring that all requests get errored out in the cases of card or driver
removal.

Signed-off-by: Adrian Hunter <adrian.hunter@intel.com>
Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
drivers/mmc/host/sdhci.c

index dce31b798180a6f70e055c155f109b3c364c2580..6e3b4d0e5b6725c9024a323e8bafdb54548956ac 100644 (file)
@@ -2137,6 +2137,24 @@ static void sdhci_pre_req(struct mmc_host *mmc, struct mmc_request *mrq,
                sdhci_pre_dma_transfer(host, mrq->data, COOKIE_PRE_MAPPED);
 }
 
+static inline bool sdhci_has_requests(struct sdhci_host *host)
+{
+       return host->cmd || host->data_cmd;
+}
+
+static void sdhci_error_out_mrqs(struct sdhci_host *host, int err)
+{
+       if (host->data_cmd) {
+               host->data_cmd->error = err;
+               sdhci_finish_mrq(host, host->data_cmd->mrq);
+       }
+
+       if (host->cmd) {
+               host->cmd->error = err;
+               sdhci_finish_mrq(host, host->cmd->mrq);
+       }
+}
+
 static void sdhci_card_event(struct mmc_host *mmc)
 {
        struct sdhci_host *host = mmc_priv(mmc);
@@ -2151,8 +2169,8 @@ static void sdhci_card_event(struct mmc_host *mmc)
 
        spin_lock_irqsave(&host->lock, flags);
 
-       /* Check host->mrq first in case we are runtime suspended */
-       if (host->mrq && !present) {
+       /* Check sdhci_has_requests() first in case we are runtime suspended */
+       if (sdhci_has_requests(host) && !present) {
                pr_err("%s: Card removed during transfer!\n",
                        mmc_hostname(host->mmc));
                pr_err("%s: Resetting controller.\n",
@@ -2161,8 +2179,7 @@ static void sdhci_card_event(struct mmc_host *mmc)
                sdhci_do_reset(host, SDHCI_RESET_CMD);
                sdhci_do_reset(host, SDHCI_RESET_DATA);
 
-               host->mrq->cmd->error = -ENOMEDIUM;
-               sdhci_finish_mrq(host, host->mrq);
+               sdhci_error_out_mrqs(host, -ENOMEDIUM);
        }
 
        spin_unlock_irqrestore(&host->lock, flags);
@@ -3496,12 +3513,10 @@ void sdhci_remove_host(struct sdhci_host *host, int dead)
 
                host->flags |= SDHCI_DEVICE_DEAD;
 
-               if (host->mrq) {
+               if (sdhci_has_requests(host)) {
                        pr_err("%s: Controller removed during "
                                " transfer!\n", mmc_hostname(mmc));
-
-                       host->mrq->cmd->error = -ENOMEDIUM;
-                       sdhci_finish_mrq(host, host->mrq);
+                       sdhci_error_out_mrqs(host, -ENOMEDIUM);
                }
 
                spin_unlock_irqrestore(&host->lock, flags);