Skip to content

Commit

Permalink
mmc: core: Do not pre-claim host in suspend
Browse files Browse the repository at this point in the history
Since SDIO drivers may want to do some SDIO operations in their suspend
callback functions, we must not keep the host claimed when calling them.

Daniel Drake reported that libertas_sdio encountered a deadlock in its
suspend function.

Signed-off-by: Ulf Hansson <ulf.hansson@stericsson.com>
Tested-by: Daniel Drake <dsd@laptop.org>
[stable@: please apply to 3.2-stable and 3.3-stable]
Cc: stable <stable@vger.kernel.org>
Signed-off-by: Chris Ball <cjb@laptop.org>
  • Loading branch information
Ulf Hansson authored and Chris Ball committed Apr 21, 2012
1 parent e1631f9 commit 7c57091
Showing 1 changed file with 20 additions and 35 deletions.
55 changes: 20 additions & 35 deletions drivers/mmc/core/core.c
Original file line number Diff line number Diff line change
Expand Up @@ -2238,6 +2238,7 @@ int mmc_cache_ctrl(struct mmc_host *host, u8 enable)
mmc_card_is_removable(host))
return err;

mmc_claim_host(host);
if (card && mmc_card_mmc(card) &&
(card->ext_csd.cache_size > 0)) {
enable = !!enable;
Expand All @@ -2255,6 +2256,7 @@ int mmc_cache_ctrl(struct mmc_host *host, u8 enable)
card->ext_csd.cache_ctrl = enable;
}
}
mmc_release_host(host);

return err;
}
Expand All @@ -2272,49 +2274,32 @@ int mmc_suspend_host(struct mmc_host *host)

cancel_delayed_work(&host->detect);
mmc_flush_scheduled_work();
if (mmc_try_claim_host(host)) {
err = mmc_cache_ctrl(host, 0);
mmc_release_host(host);
} else {
err = -EBUSY;
}

err = mmc_cache_ctrl(host, 0);
if (err)
goto out;

mmc_bus_get(host);
if (host->bus_ops && !host->bus_dead) {

/*
* A long response time is not acceptable for device drivers
* when doing suspend. Prevent mmc_claim_host in the suspend
* sequence, to potentially wait "forever" by trying to
* pre-claim the host.
*/
if (mmc_try_claim_host(host)) {
if (host->bus_ops->suspend) {
err = host->bus_ops->suspend(host);
}
mmc_release_host(host);
if (host->bus_ops->suspend)
err = host->bus_ops->suspend(host);

if (err == -ENOSYS || !host->bus_ops->resume) {
/*
* We simply "remove" the card in this case.
* It will be redetected on resume. (Calling
* bus_ops->remove() with a claimed host can
* deadlock.)
*/
if (host->bus_ops->remove)
host->bus_ops->remove(host);
mmc_claim_host(host);
mmc_detach_bus(host);
mmc_power_off(host);
mmc_release_host(host);
host->pm_flags = 0;
err = 0;
}
} else {
err = -EBUSY;
if (err == -ENOSYS || !host->bus_ops->resume) {
/*
* We simply "remove" the card in this case.
* It will be redetected on resume. (Calling
* bus_ops->remove() with a claimed host can
* deadlock.)
*/
if (host->bus_ops->remove)
host->bus_ops->remove(host);
mmc_claim_host(host);
mmc_detach_bus(host);
mmc_power_off(host);
mmc_release_host(host);
host->pm_flags = 0;
err = 0;
}
}
mmc_bus_put(host);
Expand Down

0 comments on commit 7c57091

Please sign in to comment.