aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mmc
diff options
context:
space:
mode:
authorUlf Hansson <ulf.hansson@stericsson.com>2011-09-21 14:08:13 -0400
committerHerton Ronaldo Krzesinski <herton.krzesinski@canonical.com>2011-11-21 12:54:52 -0500
commitccb10654fd75846cdc7114eddb7deceec26161ee (patch)
treeed9d2cae68ae6f54e8acf34beb6863c4078a2309 /drivers/mmc
parent64ffdad550d8dd8e9798c6c843f1ffd8a1cadff7 (diff)
mmc: core: Fix hangs related to insert/remove of cards
BugLink: http://bugs.launchpad.net/bugs/890952 commit 7f7e4129c23f0419257184dff6fec89d2d5a8964 upstream. 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> Signed-off-by: Chris Ball <cjb@laptop.org> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> Signed-off-by: Tim Gardner <tim.gardner@canonical.com>
Diffstat (limited to 'drivers/mmc')
-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 38089b25c57..75db30e6dcf 100644
--- a/drivers/mmc/core/core.c
+++ b/drivers/mmc/core/core.c
@@ -1057,7 +1057,7 @@ static void mmc_power_up(struct mmc_host *host)
1057 mmc_host_clk_release(host); 1057 mmc_host_clk_release(host);
1058} 1058}
1059 1059
1060static void mmc_power_off(struct mmc_host *host) 1060void mmc_power_off(struct mmc_host *host)
1061{ 1061{
1062 mmc_host_clk_hold(host); 1062 mmc_host_clk_hold(host);
1063 1063
@@ -1147,8 +1147,7 @@ void mmc_attach_bus(struct mmc_host *host, const struct mmc_bus_ops *ops)
1147} 1147}
1148 1148
1149/* 1149/*
1150 * Remove the current bus handler from a host. Assumes that there are 1150 * Remove the current bus handler from a host.
1151 * no interesting cards left, so the bus is powered down.
1152 */ 1151 */
1153void mmc_detach_bus(struct mmc_host *host) 1152void mmc_detach_bus(struct mmc_host *host)
1154{ 1153{
@@ -1165,8 +1164,6 @@ void mmc_detach_bus(struct mmc_host *host)
1165 1164
1166 spin_unlock_irqrestore(&host->lock, flags); 1165 spin_unlock_irqrestore(&host->lock, flags);
1167 1166
1168 mmc_power_off(host);
1169
1170 mmc_bus_put(host); 1167 mmc_bus_put(host);
1171} 1168}
1172 1169
@@ -1675,6 +1672,7 @@ void mmc_stop_host(struct mmc_host *host)
1675 1672
1676 mmc_claim_host(host); 1673 mmc_claim_host(host);
1677 mmc_detach_bus(host); 1674 mmc_detach_bus(host);
1675 mmc_power_off(host);
1678 mmc_release_host(host); 1676 mmc_release_host(host);
1679 mmc_bus_put(host); 1677 mmc_bus_put(host);
1680 return; 1678 return;
@@ -1796,6 +1794,7 @@ int mmc_suspend_host(struct mmc_host *host)
1796 host->bus_ops->remove(host); 1794 host->bus_ops->remove(host);
1797 mmc_claim_host(host); 1795 mmc_claim_host(host);
1798 mmc_detach_bus(host); 1796 mmc_detach_bus(host);
1797 mmc_power_off(host);
1799 mmc_release_host(host); 1798 mmc_release_host(host);
1800 host->pm_flags = 0; 1799 host->pm_flags = 0;
1801 err = 0; 1800 err = 0;
@@ -1883,6 +1882,7 @@ int mmc_pm_notify(struct notifier_block *notify_block,
1883 host->bus_ops->remove(host); 1882 host->bus_ops->remove(host);
1884 1883
1885 mmc_detach_bus(host); 1884 mmc_detach_bus(host);
1885 mmc_power_off(host);
1886 mmc_release_host(host); 1886 mmc_release_host(host);
1887 host->pm_flags = 0; 1887 host->pm_flags = 0;
1888 break; 1888 break;
diff --git a/drivers/mmc/core/core.h b/drivers/mmc/core/core.h
index d9411ed2a39..14664f1fb16 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 aa7d1d79b8c..6f5ee84ec71 100644
--- a/drivers/mmc/core/mmc.c
+++ b/drivers/mmc/core/mmc.c
@@ -891,6 +891,7 @@ static void mmc_detect(struct mmc_host *host)
891 891
892 mmc_claim_host(host); 892 mmc_claim_host(host);
893 mmc_detach_bus(host); 893 mmc_detach_bus(host);
894 mmc_power_off(host);
894 mmc_release_host(host); 895 mmc_release_host(host);
895 } 896 }
896} 897}
diff --git a/drivers/mmc/core/sd.c b/drivers/mmc/core/sd.c
index ff2774128aa..bd8805c9e8a 100644
--- a/drivers/mmc/core/sd.c
+++ b/drivers/mmc/core/sd.c
@@ -1008,6 +1008,7 @@ static void mmc_sd_detect(struct mmc_host *host)
1008 1008
1009 mmc_claim_host(host); 1009 mmc_claim_host(host);
1010 mmc_detach_bus(host); 1010 mmc_detach_bus(host);
1011 mmc_power_off(host);
1011 mmc_release_host(host); 1012 mmc_release_host(host);
1012 } 1013 }
1013} 1014}
diff --git a/drivers/mmc/core/sdio.c b/drivers/mmc/core/sdio.c
index 262fff01917..ac492ac974e 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}