aboutsummaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorUlf Hansson <ulf.hansson@stericsson.com>2011-05-25 11:42:18 +0200
committersaid m bagheri <ebgheri@steludxu2848.(none)>2011-06-17 13:41:58 +0200
commit55f04adc712c9363ba288f6d38a5754d27c11906 (patch)
tree46c627a8bb75ca87fe5cb4500c0ab59606c890f4 /drivers
parentf46bf01fc1e7addbf351a9fd889cc420d4d89bdf (diff)
mmc: Fix hangs related to insert/remove of cards
In the error handling of mmc_attach(sd|mmc|sdio) functions, the bus can be detached. A detach triggered also a power_off, which was the key reason to the issue. If a power_off has been done, the framework must never send any new commands/requests to the host driver, without first doing a new power_up. This occured in the rescan sequence most likely triggering ANY host driver to hang. Moving power_off out of detach and instead handle power_off separate when it is actually needed, solves the issue. ST-Ericsson Linux next: - ST-Ericsson ID: 339637 ST-Ericsson FOSS-OUT ID: Trivial Change-Id: I9fefe95c4331b98b9f460b8309594ed32037cf2f Signed-off-by: Ulf Hansson <ulf.hansson@stericsson.com> Signed-off-by: Daniel Willerud <daniel.willerud@stericsson.com> Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/23841 Reviewed-by: Sebastian RASMUSSEN <sebastian.rasmussen@stericsson.com> Reviewed-by: Joakim AXELSSON <joakim.axelsson@stericsson.com> Reviewed-by: Jonas ABERG <jonas.aberg@stericsson.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/mmc/core/core.c18
-rw-r--r--drivers/mmc/core/core.h2
-rw-r--r--drivers/mmc/core/mmc.c4
-rw-r--r--drivers/mmc/core/sd.c4
-rw-r--r--drivers/mmc/core/sdio.c4
5 files changed, 22 insertions, 10 deletions
diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
index 69cda159113..6aee8313018 100644
--- a/drivers/mmc/core/core.c
+++ b/drivers/mmc/core/core.c
@@ -1091,8 +1091,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)
{
@@ -1109,8 +1108,6 @@ void mmc_detach_bus(struct mmc_host *host)
spin_unlock_irqrestore(&host->lock, flags);
- mmc_power_off(host);
-
mmc_bus_put(host);
}
@@ -1549,8 +1546,15 @@ void mmc_rescan(struct work_struct *work)
* still present
*/
if (host->bus_ops && host->bus_ops->detect && !host->bus_dead
- && !(host->caps & MMC_CAP_NONREMOVABLE))
- host->bus_ops->detect(host);
+ && !(host->caps & MMC_CAP_NONREMOVABLE)) {
+
+ if (host->bus_ops->detect(host)) {
+ /* power off if the card was not re-detected */
+ mmc_claim_host(host);
+ mmc_power_off(host);
+ mmc_release_host(host);
+ }
+ }
/*
* Let mmc_bus_put() free the bus/bus_ops if we've found that
@@ -1618,6 +1622,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;
@@ -1825,6 +1830,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 20b1c0831ea..ac43eeabf79 100644
--- a/drivers/mmc/core/core.h
+++ b/drivers/mmc/core/core.h
@@ -19,7 +19,7 @@ struct mmc_bus_ops {
int (*awake)(struct mmc_host *);
int (*sleep)(struct mmc_host *);
void (*remove)(struct mmc_host *);
- void (*detect)(struct mmc_host *);
+ int (*detect)(struct mmc_host *);
int (*suspend)(struct mmc_host *);
int (*resume)(struct mmc_host *);
int (*power_save)(struct mmc_host *);
diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c
index 14e95f39a7b..a78d57ebad4 100644
--- a/drivers/mmc/core/mmc.c
+++ b/drivers/mmc/core/mmc.c
@@ -701,7 +701,7 @@ static void mmc_remove(struct mmc_host *host)
/*
* Card detection callback from host.
*/
-static void mmc_detect(struct mmc_host *host)
+static int mmc_detect(struct mmc_host *host)
{
int err;
@@ -724,6 +724,8 @@ static void mmc_detect(struct mmc_host *host)
mmc_detach_bus(host);
mmc_release_host(host);
}
+
+ return err;
}
/*
diff --git a/drivers/mmc/core/sd.c b/drivers/mmc/core/sd.c
index 6dac89fe053..4752312cc3a 100644
--- a/drivers/mmc/core/sd.c
+++ b/drivers/mmc/core/sd.c
@@ -661,7 +661,7 @@ static void mmc_sd_remove(struct mmc_host *host)
/*
* Card detection callback from host.
*/
-static void mmc_sd_detect(struct mmc_host *host)
+static int mmc_sd_detect(struct mmc_host *host)
{
int err;
@@ -684,6 +684,8 @@ static void mmc_sd_detect(struct mmc_host *host)
mmc_detach_bus(host);
mmc_release_host(host);
}
+
+ return err;
}
/*
diff --git a/drivers/mmc/core/sdio.c b/drivers/mmc/core/sdio.c
index db0f0b44d68..8cdbbb4fc37 100644
--- a/drivers/mmc/core/sdio.c
+++ b/drivers/mmc/core/sdio.c
@@ -548,7 +548,7 @@ static void mmc_sdio_remove(struct mmc_host *host)
/*
* Card detection callback from host.
*/
-static void mmc_sdio_detect(struct mmc_host *host)
+static int mmc_sdio_detect(struct mmc_host *host)
{
int err;
@@ -593,6 +593,8 @@ out:
mmc_detach_bus(host);
mmc_release_host(host);
}
+
+ return err;
}
/*