summaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorAdrian Hunter <adrian.hunter@intel.com>2016-06-29 15:24:31 +0200
committerUlf Hansson <ulf.hansson@linaro.org>2016-07-25 10:34:42 +0200
commit5d0d11c51a599e6c074fdb2d55f6eba307936591 (patch)
tree840f06d02d2efb06e60595b834ddeed016a75468 /drivers
parentmmc: sdhci: Clear pointers when a request finishes (diff)
downloadlinux-5d0d11c51a599e6c074fdb2d55f6eba307936591.tar.xz
linux-5d0d11c51a599e6c074fdb2d55f6eba307936591.zip
mmc: sdhci: Ensure all requests get errored out
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>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/mmc/host/sdhci.c31
1 files changed, 23 insertions, 8 deletions
diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
index dce31b798180..6e3b4d0e5b67 100644
--- a/drivers/mmc/host/sdhci.c
+++ b/drivers/mmc/host/sdhci.c
@@ -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);