summaryrefslogtreecommitdiff
path: root/drivers/mmc
diff options
context:
space:
mode:
authorUlf Hansson <ulf.hansson@stericsson.com>2011-05-25 11:42:18 +0200
committerUlf Hansson <ulf.hansson@stericsson.com>2011-09-19 16:07:33 +0200
commit3775861c930e459caa1ce6090138822a383bc51d (patch)
treeeef5adfa86d5e4ce729d8db785776fb6251fda90 /drivers/mmc
parent1c3f3cf0a6ea6c60b676938a04b3b090f89b0d42 (diff)
mmc: 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. ST-Ericsson Linux next: - ST-Ericsson ID: 339637 ST-Ericsson FOSS-OUT ID: Trivial Change-Id: Id808dc84625a953f4469855ad56e8d3b46b5434d Signed-off-by: Ulf Hansson <ulf.hansson@stericsson.com> Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/30814
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 6352e52b0e5..aeac7541b5d 100644
--- a/drivers/mmc/core/core.c
+++ b/drivers/mmc/core/core.c
@@ -1127,7 +1127,7 @@ static void mmc_power_up(struct mmc_host *host)
mmc_delay(10);
}
-static void mmc_power_off(struct mmc_host *host)
+void mmc_power_off(struct mmc_host *host)
{
host->ios.clock = 0;
host->ios.vdd = 0;
@@ -1243,8 +1243,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)
{
@@ -1261,8 +1260,6 @@ void mmc_detach_bus(struct mmc_host *host)
spin_unlock_irqrestore(&host->lock, flags);
- mmc_power_off(host);
-
mmc_bus_put(host);
}
@@ -1847,6 +1844,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;
@@ -1979,6 +1977,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;
@@ -2076,6 +2075,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;
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,
bool cmd11);
void mmc_set_timing(struct mmc_host *host, unsigned int timing);
void mmc_set_driver_type(struct mmc_host *host, unsigned int drv_type);
+void mmc_power_off(struct mmc_host *host);
static inline void mmc_delay(unsigned int ms)
{
diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c
index 5700b1cbdfe..59b5faa0072 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)
mmc_claim_host(host);
mmc_detach_bus(host);
+ mmc_power_off(host);
mmc_release_host(host);
}
}
diff --git a/drivers/mmc/core/sd.c b/drivers/mmc/core/sd.c
index 35fcc0ef5ca..c5f65609dc1 100644
--- a/drivers/mmc/core/sd.c
+++ b/drivers/mmc/core/sd.c
@@ -1058,6 +1058,7 @@ static void mmc_sd_detect(struct mmc_host *host)
mmc_claim_host(host);
mmc_detach_bus(host);
+ mmc_power_off(host);
mmc_release_host(host);
}
}
diff --git a/drivers/mmc/core/sdio.c b/drivers/mmc/core/sdio.c
index 7da522e958a..a2c1c4d8371 100644
--- a/drivers/mmc/core/sdio.c
+++ b/drivers/mmc/core/sdio.c
@@ -617,6 +617,7 @@ out:
mmc_claim_host(host);
mmc_detach_bus(host);
+ mmc_power_off(host);
mmc_release_host(host);
}
}