aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mmc/core/core.c
diff options
context:
space:
mode:
authorUlf Hansson <ulf.hansson@stericsson.com>2011-09-21 14:08:13 -0400
committerChris Ball <cjb@laptop.org>2011-10-26 16:32:01 -0400
commit7f7e4129c23f0419257184dff6fec89d2d5a8964 (patch)
tree3840efd33b32d364451e9f52c575b857efbc771c /drivers/mmc/core/core.c
parentmmc: sdhci-spear: Don't set power gpio to 1 on probe (diff)
downloadlinux-dev-7f7e4129c23f0419257184dff6fec89d2d5a8964.tar.xz
linux-dev-7f7e4129c23f0419257184dff6fec89d2d5a8964.zip
mmc: core: Fix hangs related to insert/remove of cards
During a rescan operation mmc_attach(sd|mmc|sdio) functions are called. The error handling in these function can trigger a detach of the bus, which also meant a power off. This is not notified by the rescan operation which then continues to the next attach function. If a power off has been done, the framework must never send any new commands to the host driver, without first doing a new power up. This will most likely trigger any host driver to hang. Moving power off out of detach and instead handle power off separately when it is actually needed, solves the issue. Signed-off-by: Ulf Hansson <ulf.hansson@stericsson.com> Acked-by: Linus Walleij <linus.walleij@linaro.org> Cc: <stable@kernel.org> Signed-off-by: Chris Ball <cjb@laptop.org>
Diffstat (limited to 'drivers/mmc/core/core.c')
-rw-r--r--drivers/mmc/core/core.c10
1 files changed, 5 insertions, 5 deletions
diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
index 7289e999d1fc..5ae6b159dbea 100644
--- a/drivers/mmc/core/core.c
+++ b/drivers/mmc/core/core.c
@@ -1192,7 +1192,7 @@ static void mmc_power_up(struct mmc_host *host)
mmc_host_clk_release(host);
}
-static void mmc_power_off(struct mmc_host *host)
+void mmc_power_off(struct mmc_host *host)
{
mmc_host_clk_hold(host);
@@ -1289,8 +1289,7 @@ void mmc_attach_bus(struct mmc_host *host, const struct mmc_bus_ops *ops)
}
/*
- * Remove the current bus handler from a host. Assumes that there are
- * no interesting cards left, so the bus is powered down.
+ * Remove the current bus handler from a host.
*/
void mmc_detach_bus(struct mmc_host *host)
{
@@ -1307,8 +1306,6 @@ void mmc_detach_bus(struct mmc_host *host)
spin_unlock_irqrestore(&host->lock, flags);
- mmc_power_off(host);
-
mmc_bus_put(host);
}
@@ -1893,6 +1890,7 @@ void mmc_stop_host(struct mmc_host *host)
mmc_claim_host(host);
mmc_detach_bus(host);
+ mmc_power_off(host);
mmc_release_host(host);
mmc_bus_put(host);
return;
@@ -2022,6 +2020,7 @@ int mmc_suspend_host(struct mmc_host *host)
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;
@@ -2109,6 +2108,7 @@ int mmc_pm_notify(struct notifier_block *notify_block,
host->bus_ops->remove(host);
mmc_detach_bus(host);
+ mmc_power_off(host);
mmc_release_host(host);
host->pm_flags = 0;
break;