mmc: core: Fix hangs related to cards initialization
authorChuanxiao Dong <chuanxiao.dong@intel.com>
Mon, 24 Oct 2011 02:34:14 +0000 (10:34 +0800)
committermgross <mark.gross@intel.com>
Wed, 9 Nov 2011 21:21:16 +0000 (13:21 -0800)
This patch is ported from upstream.
Actually we should understand this patch only can fix the hangs related
with cards initialization part. Insert/remove of cards can not only
cause cards initialization, but also some operation in mmc stack block
layer and host layer, which this patch cannot prevent can do nothing with.

Below is the original commint:
----------------------------------------------------------------
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>
---------------------------------------------------------------
Signed-off-by: Chuanxiao Dong <chuanxiao.dong@intel.com>
Change-Id: I7884d9bff2a9d9ef51e72ced03e4517560aedb0d
Reviewed-on: http://android.intel.com:8080/23124
Reviewed-by: Gross, Mark <mark.gross@intel.com>
Tested-by: Gross, Mark <mark.gross@intel.com>
drivers/mmc/core/core.c
drivers/mmc/core/core.h
drivers/mmc/core/mmc.c
drivers/mmc/core/sd.c
drivers/mmc/core/sdio.c

index 5b1c992..6cfa8d7 100644 (file)
@@ -1164,7 +1164,7 @@ static void mmc_power_up(struct mmc_host *host)
        mmc_host_clk_release(host);
 }
 
-static void mmc_power_off(struct mmc_host *host)
+void mmc_power_off(struct mmc_host *host)
 {
        mmc_host_clk_hold(host);
 
@@ -1284,8 +1284,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)
 {
@@ -1302,8 +1301,6 @@ void mmc_detach_bus(struct mmc_host *host)
 
        spin_unlock_irqrestore(&host->lock, flags);
 
-       mmc_power_off(host);
-
        mmc_bus_put(host);
 }
 
@@ -1974,6 +1971,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;
@@ -2105,6 +2103,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;
@@ -2200,6 +2199,7 @@ int mmc_pm_notify(struct notifier_block *notify_block,
 
                mmc_claim_host(host);
                mmc_detach_bus(host);
+               mmc_power_off(host);
                mmc_release_host(host);
                host->pm_flags = 0;
                break;
index d9411ed..14664f1 100644 (file)
@@ -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)
 {
index e090a87..82237c5 100644 (file)
@@ -893,6 +893,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);
        }
 }
index a6a43bf..fd9c48c 100644 (file)
@@ -1079,6 +1079,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);
        }
 }
index 7da522e..a2c1c4d 100644 (file)
@@ -617,6 +617,7 @@ out:
 
                mmc_claim_host(host);
                mmc_detach_bus(host);
+               mmc_power_off(host);
                mmc_release_host(host);
        }
 }