Skip to content

Commit

Permalink
mmc: sdhci: Fix CMD line reset interfering with ongoing data transfer
Browse files Browse the repository at this point in the history
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: Adrian Hunter <[email protected]>
Cc: [email protected] # v4.8+
Signed-off-by: Ulf Hansson <[email protected]>
  • Loading branch information
ahunter6 authored and storulf committed Nov 7, 2016
1 parent 3a667e3 commit 6ebebea
Showing 1 changed file with 16 additions and 7 deletions.
23 changes: 16 additions & 7 deletions drivers/mmc/host/sdhci.c
Original file line number Diff line number Diff line change
Expand Up @@ -2286,10 +2286,8 @@ static bool sdhci_request_done(struct sdhci_host *host)

for (i = 0; i < SDHCI_MAX_MRQS; i++) {
mrq = host->mrqs_done[i];
if (mrq) {
host->mrqs_done[i] = NULL;
if (mrq)
break;
}
}

if (!mrq) {
Expand Down Expand Up @@ -2320,24 +2318,35 @@ static bool sdhci_request_done(struct sdhci_host *host)
* upon error conditions.
*/
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 */
if (host->quirks & SDHCI_QUIRK_CLOCK_BEFORE_RESET)
/* This is to force an update */
host->ops->set_clock(host, host->clock);

/* Spec says we should do both at the same time, but Ricoh
controllers do not like that. */
if (!host->cmd)
sdhci_do_reset(host, SDHCI_RESET_CMD);
if (!host->data_cmd)
sdhci_do_reset(host, SDHCI_RESET_DATA);
sdhci_do_reset(host, SDHCI_RESET_CMD);
sdhci_do_reset(host, SDHCI_RESET_DATA);

host->pending_reset = false;
}

if (!sdhci_has_requests(host))
sdhci_led_deactivate(host);

host->mrqs_done[i] = NULL;

mmiowb();
spin_unlock_irqrestore(&host->lock, flags);

Expand Down

0 comments on commit 6ebebea

Please sign in to comment.