summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLinux Build Service Account <lnxbuild@localhost>2017-03-04 10:12:54 -0800
committerGerrit - the friendly Code Review server <code-review@localhost>2017-03-04 10:12:54 -0800
commitd2499ee89d291515865fe8738b6be0c39693e53a (patch)
treeb6be609025cd3ffc45e588448b228aabbb1187cf
parent77610431cb72f691f94fdb4dd3cfcd83505ee77f (diff)
parente9cc73402e87bfa62f503c7f319094f6cbdfe469 (diff)
Merge "mmc: core: Retry claim host in mmc_sd_detect"
-rw-r--r--drivers/mmc/core/core.c32
-rw-r--r--drivers/mmc/core/sd.c12
-rw-r--r--include/linux/mmc/core.h1
3 files changed, 44 insertions, 1 deletions
diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
index f79e8377a2ee..5396e1d00178 100644
--- a/drivers/mmc/core/core.c
+++ b/drivers/mmc/core/core.c
@@ -2114,6 +2114,38 @@ int __mmc_claim_host(struct mmc_host *host, atomic_t *abort)
EXPORT_SYMBOL(__mmc_claim_host);
/**
+ * mmc_try_claim_host - try exclusively to claim a host
+ * and keep trying for given time, with a gap of 10ms
+ * @host: mmc host to claim
+ * @dealy_ms: delay in ms
+ *
+ * Returns %1 if the host is claimed, %0 otherwise.
+ */
+int mmc_try_claim_host(struct mmc_host *host, unsigned int delay_ms)
+{
+ int claimed_host = 0;
+ unsigned long flags;
+ int retry_cnt = delay_ms/10;
+
+ do {
+ spin_lock_irqsave(&host->lock, flags);
+ if (!host->claimed || host->claimer == current) {
+ host->claimed = 1;
+ host->claimer = current;
+ host->claim_cnt += 1;
+ claimed_host = 1;
+ }
+ spin_unlock_irqrestore(&host->lock, flags);
+ if (!claimed_host)
+ mmc_delay(10);
+ } while (!claimed_host && retry_cnt--);
+ if (host->ops->enable && claimed_host && host->claim_cnt == 1)
+ host->ops->enable(host);
+ return claimed_host;
+}
+EXPORT_SYMBOL(mmc_try_claim_host);
+
+/**
* mmc_release_host - release a host
* @host: mmc host to release
*
diff --git a/drivers/mmc/core/sd.c b/drivers/mmc/core/sd.c
index 7e7d7eb4da2a..ec5ce79e84e7 100644
--- a/drivers/mmc/core/sd.c
+++ b/drivers/mmc/core/sd.c
@@ -1147,7 +1147,17 @@ static void mmc_sd_detect(struct mmc_host *host)
BUG_ON(!host);
BUG_ON(!host->card);
- mmc_get_card(host->card);
+ /*
+ * Try to acquire claim host. If failed to get the lock in 2 sec,
+ * just return; This is to ensure that when this call is invoked
+ * due to pm_suspend, not to block suspend for longer duration.
+ */
+ pm_runtime_get_sync(&host->card->dev);
+ if (!mmc_try_claim_host(host, 2000)) {
+ pm_runtime_mark_last_busy(&host->card->dev);
+ pm_runtime_put_autosuspend(&host->card->dev);
+ return;
+ }
/*
* Just check if our card has been removed.
diff --git a/include/linux/mmc/core.h b/include/linux/mmc/core.h
index 55a30d685226..1068953943d8 100644
--- a/include/linux/mmc/core.h
+++ b/include/linux/mmc/core.h
@@ -203,6 +203,7 @@ extern unsigned int mmc_align_data_size(struct mmc_card *, unsigned int);
extern int __mmc_claim_host(struct mmc_host *host, atomic_t *abort);
extern void mmc_release_host(struct mmc_host *host);
+extern int mmc_try_claim_host(struct mmc_host *host, unsigned int delay);
extern void mmc_get_card(struct mmc_card *card);
extern void mmc_put_card(struct mmc_card *card);