diff options
author | Ulf Hansson <ulf.hansson@stericsson.com> | 2011-05-25 11:42:18 +0200 |
---|---|---|
committer | said m bagheri <ebgheri@steludxu2848.(none)> | 2011-06-17 13:41:58 +0200 |
commit | 55f04adc712c9363ba288f6d38a5754d27c11906 (patch) | |
tree | 46c627a8bb75ca87fe5cb4500c0ab59606c890f4 /drivers | |
parent | f46bf01fc1e7addbf351a9fd889cc420d4d89bdf (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.c | 18 | ||||
-rw-r--r-- | drivers/mmc/core/core.h | 2 | ||||
-rw-r--r-- | drivers/mmc/core/mmc.c | 4 | ||||
-rw-r--r-- | drivers/mmc/core/sd.c | 4 | ||||
-rw-r--r-- | drivers/mmc/core/sdio.c | 4 |
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; } /* |