While trying to suspend the mmc host there could still be
ongoing requests that we need to wait for. At the same time
a device driver must respond to a suspend request rather quickly.

Instead of potentially wait "forever" by claiming the host we now
"try" to claim the host instead. If it fails, -EBUSY is returned.

Signed-off-by: Ulf Hansson <[email protected]>
---
 drivers/mmc/core/core.c |   42 +++++++++++++++++++++++++++---------------
 1 files changed, 27 insertions(+), 15 deletions(-)

diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
index 61d7730..b900932 100644
--- a/drivers/mmc/core/core.c
+++ b/drivers/mmc/core/core.c
@@ -2121,21 +2121,33 @@ int mmc_suspend_host(struct mmc_host *host)
 
        mmc_bus_get(host);
        if (host->bus_ops && !host->bus_dead) {
-               if (host->bus_ops->suspend)
-                       err = host->bus_ops->suspend(host);
-               if (err == -ENOSYS || !host->bus_ops->resume) {
-                       /*
-                        * We simply "remove" the card in this case.
-                        * It will be redetected on resume.
-                        */
-                       if (host->bus_ops->remove)
-                               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;
+
+               /*
+                * A long response time is not acceptable for device drivers
+                * when doing suspend. Prevent mmc_claim_host in the suspend
+                * sequence, to potentially wait "forever" by trying to
+                * pre-claim the host.
+                */
+               if (mmc_try_claim_host(host)) {
+                       if (host->bus_ops->suspend)
+                               err = host->bus_ops->suspend(host);
+                       if (err == -ENOSYS || !host->bus_ops->resume) {
+                               /*
+                                * We simply "remove" the card in this case.
+                                * It will be redetected on resume.
+                                */
+                               if (host->bus_ops->remove)
+                                       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;
+                       }
+                       mmc_do_release_host(host);
+               } else {
+                       err = -EBUSY;
                }
        }
        mmc_bus_put(host);
-- 
1.7.5.4

--
To unsubscribe from this list: send the line "unsubscribe linux-mmc" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to