diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c index 0f5d781d051b..9544076998ff 100644 --- a/drivers/mmc/core/core.c +++ b/drivers/mmc/core/core.c @@ -1644,6 +1644,47 @@ int __mmc_claim_host(struct mmc_host *host, struct mmc_ctx *ctx, } EXPORT_SYMBOL(__mmc_claim_host); +#if defined(CONFIG_SDC_QTI) +/** + * 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, struct mmc_ctx *ctx, + unsigned int delay_ms) +{ + int claimed_host = 0; + struct task_struct *task = ctx ? NULL : current; + unsigned long flags; + int retry_cnt = delay_ms/10; + bool pm = false; + + do { + spin_lock_irqsave(&host->lock, flags); + if (!host->claimed || mmc_ctx_matches(host, ctx, task)) { + host->claimed = 1; + mmc_ctx_set_claimer(host, ctx, task); + host->claim_cnt += 1; + claimed_host = 1; + if (host->claim_cnt == 1) + pm = true; + } + spin_unlock_irqrestore(&host->lock, flags); + if (!claimed_host) + mmc_delay(10); + } while (!claimed_host && retry_cnt--); + + if (pm) + pm_runtime_get_sync(mmc_dev(host)); + + return claimed_host; +} +EXPORT_SYMBOL(mmc_try_claim_host); +#endif + /** * mmc_release_host - release a host * @host: mmc host to release diff --git a/drivers/mmc/core/core.h b/drivers/mmc/core/core.h index 50ef5b5ecbc7..68c93b03b84f 100644 --- a/drivers/mmc/core/core.h +++ b/drivers/mmc/core/core.h @@ -143,6 +143,10 @@ int mmc_set_blocklen(struct mmc_card *card, unsigned int blocklen); int __mmc_claim_host(struct mmc_host *host, struct mmc_ctx *ctx, atomic_t *abort); +#if defined(CONFIG_SDC_QTI) +int mmc_try_claim_host(struct mmc_host *host, struct mmc_ctx *ctx, + unsigned int delay_ms); +#endif void mmc_release_host(struct mmc_host *host); void mmc_get_card(struct mmc_card *card, struct mmc_ctx *ctx); void mmc_put_card(struct mmc_card *card, struct mmc_ctx *ctx); diff --git a/drivers/mmc/core/sd.c b/drivers/mmc/core/sd.c index db361871de16..39d9ca53d27f 100644 --- a/drivers/mmc/core/sd.c +++ b/drivers/mmc/core/sd.c @@ -1206,7 +1206,21 @@ static void mmc_sd_detect(struct mmc_host *host) { int err; - mmc_get_card(host->card, NULL); +#if defined(CONFIG_SDC_QTI) + /* + * 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, NULL, 2000)) { + pm_runtime_mark_last_busy(&host->card->dev); + pm_runtime_put_autosuspend(&host->card->dev); + return; + } +#else + mmc_get_card(host->card, NULL); +#endif /* * Just check if our card has been removed.