aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
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
parent46cbd56ad4a686c52eeab427faf7e28415bbf28f (diff)
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')
-rw-r--r--drivers/mmc/core/core.c10
-rw-r--r--drivers/mmc/core/core.h1
-rw-r--r--drivers/mmc/core/mmc.c1
-rw-r--r--drivers/mmc/core/sd.c1
-rw-r--r--drivers/mmc/core/sdio.c1
5 files changed, 9 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)
1192 mmc_host_clk_release(host); 1192 mmc_host_clk_release(host);
1193} 1193}
1194 1194
1195static void mmc_power_off(struct mmc_host *host) 1195void mmc_power_off(struct mmc_host *host)
1196{ 1196{
1197 mmc_host_clk_hold(host); 1197 mmc_host_clk_hold(host);
1198 1198
@@ -1289,8 +1289,7 @@ void mmc_attach_bus(struct mmc_host *host, const struct mmc_bus_ops *ops)
1289} 1289}
1290 1290
1291/* 1291/*
1292 * Remove the current bus handler from a host. Assumes that there are 1292 * Remove the current bus handler from a host.
1293 * no interesting cards left, so the bus is powered down.
1294 */ 1293 */
1295void mmc_detach_bus(struct mmc_host *host) 1294void mmc_detach_bus(struct mmc_host *host)
1296{ 1295{
@@ -1307,8 +1306,6 @@ void mmc_detach_bus(struct mmc_host *host)
1307 1306
1308 spin_unlock_irqrestore(&host->lock, flags); 1307 spin_unlock_irqrestore(&host->lock, flags);
1309 1308
1310 mmc_power_off(host);
1311
1312 mmc_bus_put(host); 1309 mmc_bus_put(host);
1313} 1310}
1314 1311
@@ -1893,6 +1890,7 @@ void mmc_stop_host(struct mmc_host *host)
1893 1890
1894 mmc_claim_host(host); 1891 mmc_claim_host(host);
1895 mmc_detach_bus(host); 1892 mmc_detach_bus(host);
1893 mmc_power_off(host);
1896 mmc_release_host(host); 1894 mmc_release_host(host);
1897 mmc_bus_put(host); 1895 mmc_bus_put(host);
1898 return; 1896 return;
@@ -2022,6 +2020,7 @@ int mmc_suspend_host(struct mmc_host *host)
2022 host->bus_ops->remove(host); 2020 host->bus_ops->remove(host);
2023 mmc_claim_host(host); 2021 mmc_claim_host(host);
2024 mmc_detach_bus(host); 2022 mmc_detach_bus(host);
2023 mmc_power_off(host);
2025 mmc_release_host(host); 2024 mmc_release_host(host);
2026 host->pm_flags = 0; 2025 host->pm_flags = 0;
2027 err = 0; 2026 err = 0;
@@ -2109,6 +2108,7 @@ int mmc_pm_notify(struct notifier_block *notify_block,
2109 host->bus_ops->remove(host); 2108 host->bus_ops->remove(host);
2110 2109
2111 mmc_detach_bus(host); 2110 mmc_detach_bus(host);
2111 mmc_power_off(host);
2112 mmc_release_host(host); 2112 mmc_release_host(host);
2113 host->pm_flags = 0; 2113 host->pm_flags = 0;
2114 break; 2114 break;
diff --git a/drivers/mmc/core/core.h b/drivers/mmc/core/core.h
index d9411ed2a39b..14664f1fb16f 100644
--- a/drivers/mmc/core/core.h
+++ b/drivers/mmc/core/core.h
@@ -43,6 +43,7 @@ int mmc_set_signal_voltage(struct mmc_host *host, int signal_voltage,
43 bool cmd11); 43 bool cmd11);
44void mmc_set_timing(struct mmc_host *host, unsigned int timing); 44void mmc_set_timing(struct mmc_host *host, unsigned int timing);
45void mmc_set_driver_type(struct mmc_host *host, unsigned int drv_type); 45void mmc_set_driver_type(struct mmc_host *host, unsigned int drv_type);
46void mmc_power_off(struct mmc_host *host);
46 47
47static inline void mmc_delay(unsigned int ms) 48static inline void mmc_delay(unsigned int ms)
48{ 49{
diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c
index f73fceea5dbd..3b7c069a4ea6 100644
--- a/drivers/mmc/core/mmc.c
+++ b/drivers/mmc/core/mmc.c
@@ -892,6 +892,7 @@ static void mmc_detect(struct mmc_host *host)
892 892
893 mmc_claim_host(host); 893 mmc_claim_host(host);
894 mmc_detach_bus(host); 894 mmc_detach_bus(host);
895 mmc_power_off(host);
895 mmc_release_host(host); 896 mmc_release_host(host);
896 } 897 }
897} 898}
diff --git a/drivers/mmc/core/sd.c b/drivers/mmc/core/sd.c
index 0370e03e3142..4c281a4bf058 100644
--- a/drivers/mmc/core/sd.c
+++ b/drivers/mmc/core/sd.c
@@ -1043,6 +1043,7 @@ static void mmc_sd_detect(struct mmc_host *host)
1043 1043
1044 mmc_claim_host(host); 1044 mmc_claim_host(host);
1045 mmc_detach_bus(host); 1045 mmc_detach_bus(host);
1046 mmc_power_off(host);
1046 mmc_release_host(host); 1047 mmc_release_host(host);
1047 } 1048 }
1048} 1049}
diff --git a/drivers/mmc/core/sdio.c b/drivers/mmc/core/sdio.c
index 262fff019177..ac492ac974e1 100644
--- a/drivers/mmc/core/sdio.c
+++ b/drivers/mmc/core/sdio.c
@@ -597,6 +597,7 @@ out:
597 597
598 mmc_claim_host(host); 598 mmc_claim_host(host);
599 mmc_detach_bus(host); 599 mmc_detach_bus(host);
600 mmc_power_off(host);
600 mmc_release_host(host); 601 mmc_release_host(host);
601 } 602 }
602} 603}