mmc: core: Remove bus vote after resume/suspend if no card is present

To remove bus vote we expect clk-gating to kick in. But when SDcard is not
inserted, we are never turning the clocks on and hence gating will never
kick in. Thus bus voting will be always put to true.

Fix this by notifying the sdhci_msm about the pm_status only when card
is present(if host->bus_ops is NOT NULL) and remove bus vote in case of
error in mmc_suspend_host/mmc_resume_host.

Change-Id: I1f244e312f0716f99cdc53c991d37b102d40b8bc
Signed-off-by: Sayali Lokhande <sayalil@codeaurora.org>
This commit is contained in:
Sayali Lokhande 2016-01-07 16:13:21 +05:30
parent b2b10e89a6
commit ce58571b65
2 changed files with 27 additions and 32 deletions

View File

@ -4045,6 +4045,7 @@ EXPORT_SYMBOL(mmc_flush_cache);
int mmc_suspend_host(struct mmc_host *host)
{
int err = 0;
bool remove_pm_vote = false;
ktime_t start = ktime_get();
if (mmc_bus_needs_resume(host))
@ -4052,6 +4053,8 @@ int mmc_suspend_host(struct mmc_host *host)
mmc_bus_get(host);
if (host->bus_ops && !host->bus_dead) {
if (host->ops->notify_pm_status)
host->ops->notify_pm_status(host, DEV_SUSPENDING);
/*
* Disable clock scaling before suspend and enable it after
* resume so as to avoid clock scaling decisions kicking in
@ -4073,17 +4076,23 @@ int mmc_suspend_host(struct mmc_host *host)
* causing deadlock.
*/
if (!(host->card && mmc_card_sdio(host->card)))
if (!mmc_try_claim_host(host))
if (!mmc_try_claim_host(host)) {
err = -EBUSY;
remove_pm_vote = true;
}
if (!err) {
if (host->bus_ops->suspend) {
if (host->card) {
err = mmc_stop_bkops(host->card);
if (err)
if (err) {
remove_pm_vote = true;
goto out;
}
}
err = host->bus_ops->suspend(host);
if (err)
remove_pm_vote = true;
if (host->card)
MMC_UPDATE_BKOPS_STATS_SUSPEND(host->
card->bkops_info.bkops_stats);
@ -4121,10 +4130,17 @@ int mmc_suspend_host(struct mmc_host *host)
mmc_init_clk_scaling(host);
trace_mmc_suspend_host(mmc_hostname(host), err,
ktime_to_us(ktime_sub(ktime_get(), start)));
if (host->ops->notify_pm_status)
host->ops->notify_pm_status(host,
remove_pm_vote ? DEV_ERROR : DEV_SUSPENDED);
return err;
out:
if (!(host->card && mmc_card_sdio(host->card)))
mmc_release_host(host);
if (host->ops->notify_pm_status)
host->ops->notify_pm_status(host,
remove_pm_vote ? DEV_ERROR : DEV_SUSPENDED);
return err;
}
@ -4138,6 +4154,7 @@ EXPORT_SYMBOL(mmc_suspend_host);
int mmc_resume_host(struct mmc_host *host)
{
int err = 0;
bool remove_pm_vote = false;
ktime_t start = ktime_get();
mmc_bus_get(host);
@ -4148,6 +4165,8 @@ int mmc_resume_host(struct mmc_host *host)
}
if (host->bus_ops && !host->bus_dead) {
if (host->ops->notify_pm_status)
host->ops->notify_pm_status(host, DEV_RESUMING);
if (!mmc_card_keep_power(host)) {
mmc_claim_host(host);
mmc_power_up(host);
@ -4172,6 +4191,7 @@ int mmc_resume_host(struct mmc_host *host)
pr_warning("%s: error %d during resume "
"(card was removed?)\n",
mmc_hostname(host), err);
remove_pm_vote = true;
err = 0;
}
}
@ -4180,6 +4200,10 @@ int mmc_resume_host(struct mmc_host *host)
trace_mmc_resume_host(mmc_hostname(host), err,
ktime_to_us(ktime_sub(ktime_get(), start)));
if (host->ops->notify_pm_status)
host->ops->notify_pm_status(host,
remove_pm_vote ? DEV_ERROR : DEV_RESUMED);
return err;
}
EXPORT_SYMBOL(mmc_resume_host);

View File

@ -4,7 +4,7 @@
* Copyright (C) 2003 Russell King, All Rights Reserved.
* Copyright (C) 2007-2008 Pierre Ossman
* Copyright (C) 2010 Linus Walleij
* Copyright (c) 2012-2015, The Linux Foundation. All rights reserved.
* Copyright (c) 2012-2016, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
@ -49,14 +49,10 @@ static int mmc_host_runtime_suspend(struct device *dev)
struct mmc_host *host = cls_dev_to_mmc_host(dev);
int ret = 0;
ktime_t start = ktime_get();
enum dev_state status = 0;
if (!mmc_use_core_runtime_pm(host))
return 0;
if (host->ops->notify_pm_status)
host->ops->notify_pm_status(host, DEV_SUSPENDING);
if (host->card && host->card->cmdq_init) {
BUG_ON(host->cmdq_ctx.active_reqs);
@ -108,10 +104,6 @@ static int mmc_host_runtime_suspend(struct device *dev)
if (ret == -ENOMEDIUM)
ret = 0;
out:
status = !ret ? DEV_SUSPENDED : DEV_ERROR;
if (host->ops->notify_pm_status)
host->ops->notify_pm_status(host, status);
trace_mmc_host_runtime_suspend(mmc_hostname(host), ret,
ktime_to_us(ktime_sub(ktime_get(), start)));
return ret;
@ -122,14 +114,10 @@ static int mmc_host_runtime_resume(struct device *dev)
struct mmc_host *host = cls_dev_to_mmc_host(dev);
int ret = 0;
ktime_t start = ktime_get();
enum dev_state status = 0;
if (!mmc_use_core_runtime_pm(host))
return 0;
if (host->ops->notify_pm_status)
host->ops->notify_pm_status(host, DEV_RESUMING);
ret = mmc_resume_host(host);
if (ret < 0) {
pr_err("%s: %s: resume host: failed: ret: %d\n",
@ -146,10 +134,6 @@ static int mmc_host_runtime_resume(struct device *dev)
mmc_card_clr_suspended(host->card);
}
status = !ret ? DEV_RESUMED : DEV_ERROR;
if (host->ops->notify_pm_status)
host->ops->notify_pm_status(host, status);
trace_mmc_host_runtime_resume(mmc_hostname(host), ret,
ktime_to_us(ktime_sub(ktime_get(), start)));
return ret;
@ -162,14 +146,10 @@ static int mmc_host_suspend(struct device *dev)
struct mmc_host *host = cls_dev_to_mmc_host(dev);
int ret = 0;
unsigned long flags;
enum dev_state status = 0;
if (!mmc_use_core_pm(host))
return 0;
if (host->ops->notify_pm_status)
host->ops->notify_pm_status(host, DEV_SUSPENDING);
spin_lock_irqsave(&host->clk_lock, flags);
/*
* let the driver know that suspend is in progress and must
@ -234,9 +214,6 @@ static int mmc_host_suspend(struct device *dev)
host->dev_status = DEV_SUSPENDED;
spin_unlock_irqrestore(&host->clk_lock, flags);
out:
status = !ret ? DEV_SUSPENDED : DEV_ERROR;
if (host->ops->notify_pm_status)
host->ops->notify_pm_status(host, status);
return ret;
}
@ -244,13 +221,10 @@ static int mmc_host_resume(struct device *dev)
{
struct mmc_host *host = cls_dev_to_mmc_host(dev);
int ret = 0;
enum dev_state status = 0;
if (!mmc_use_core_pm(host))
return 0;
if (host->ops->notify_pm_status)
host->ops->notify_pm_status(host, DEV_RESUMING);
if (!pm_runtime_suspended(dev)) {
ret = mmc_resume_host(host);
if (ret < 0) {
@ -266,9 +240,6 @@ static int mmc_host_resume(struct device *dev)
}
}
host->dev_status = DEV_RESUMED;
status = !ret ? DEV_RESUMED : DEV_ERROR;
if (host->ops->notify_pm_status)
host->ops->notify_pm_status(host, status);
return ret;
}