Commit 6ebebeab authored by Adrian Hunter's avatar Adrian Hunter Committed by Ulf Hansson

mmc: sdhci: Fix CMD line reset interfering with ongoing data transfer

CMD line reset during an ongoing data transfer can cause the data transfer
to hang.  Fix by delaying the reset until the data transfer is finished.
Signed-off-by: default avatarAdrian Hunter <adrian.hunter@intel.com>
Cc: stable@vger.kernel.org # v4.8+
Signed-off-by: default avatarUlf Hansson <ulf.hansson@linaro.org>
parent 3a667e3f
...@@ -2286,10 +2286,8 @@ static bool sdhci_request_done(struct sdhci_host *host) ...@@ -2286,10 +2286,8 @@ static bool sdhci_request_done(struct sdhci_host *host)
for (i = 0; i < SDHCI_MAX_MRQS; i++) { for (i = 0; i < SDHCI_MAX_MRQS; i++) {
mrq = host->mrqs_done[i]; mrq = host->mrqs_done[i];
if (mrq) { if (mrq)
host->mrqs_done[i] = NULL;
break; break;
}
} }
if (!mrq) { if (!mrq) {
...@@ -2320,6 +2318,17 @@ static bool sdhci_request_done(struct sdhci_host *host) ...@@ -2320,6 +2318,17 @@ static bool sdhci_request_done(struct sdhci_host *host)
* upon error conditions. * upon error conditions.
*/ */
if (sdhci_needs_reset(host, mrq)) { if (sdhci_needs_reset(host, mrq)) {
/*
* Do not finish until command and data lines are available for
* reset. Note there can only be one other mrq, so it cannot
* also be in mrqs_done, otherwise host->cmd and host->data_cmd
* would both be null.
*/
if (host->cmd || host->data_cmd) {
spin_unlock_irqrestore(&host->lock, flags);
return true;
}
/* Some controllers need this kick or reset won't work here */ /* Some controllers need this kick or reset won't work here */
if (host->quirks & SDHCI_QUIRK_CLOCK_BEFORE_RESET) if (host->quirks & SDHCI_QUIRK_CLOCK_BEFORE_RESET)
/* This is to force an update */ /* This is to force an update */
...@@ -2327,10 +2336,8 @@ static bool sdhci_request_done(struct sdhci_host *host) ...@@ -2327,10 +2336,8 @@ static bool sdhci_request_done(struct sdhci_host *host)
/* Spec says we should do both at the same time, but Ricoh /* Spec says we should do both at the same time, but Ricoh
controllers do not like that. */ controllers do not like that. */
if (!host->cmd) sdhci_do_reset(host, SDHCI_RESET_CMD);
sdhci_do_reset(host, SDHCI_RESET_CMD); sdhci_do_reset(host, SDHCI_RESET_DATA);
if (!host->data_cmd)
sdhci_do_reset(host, SDHCI_RESET_DATA);
host->pending_reset = false; host->pending_reset = false;
} }
...@@ -2338,6 +2345,8 @@ static bool sdhci_request_done(struct sdhci_host *host) ...@@ -2338,6 +2345,8 @@ static bool sdhci_request_done(struct sdhci_host *host)
if (!sdhci_has_requests(host)) if (!sdhci_has_requests(host))
sdhci_led_deactivate(host); sdhci_led_deactivate(host);
host->mrqs_done[i] = NULL;
mmiowb(); mmiowb();
spin_unlock_irqrestore(&host->lock, flags); spin_unlock_irqrestore(&host->lock, flags);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment