mmc: host: Notify LLD with mmc dev PM status

This adds support in mmc host layer to notify LLD
with mmc suspend/resume state.
This information is needed by LLD for optimizing
suspend/resume latency.

Change-Id: Ib8d8f63b4b228079f0e7ef79164e243a55eb2559
Signed-off-by: Ritesh Harjani <riteshh@codeaurora.org>
This commit is contained in:
Ritesh Harjani 2015-07-10 12:02:28 +05:30 committed by Gerrit - the friendly Code Review server
parent 139176ea57
commit f2ac898d2c
2 changed files with 44 additions and 8 deletions

View file

@ -49,10 +49,14 @@ 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 && mmc_card_cmdq(host->card)) {
BUG_ON(host->cmdq_ctx.active_reqs);
@ -61,7 +65,7 @@ static int mmc_host_runtime_suspend(struct device *dev)
if (ret) {
mmc_card_clr_suspended(host->card);
pr_err("%s: halt: failed: %d\n", __func__, ret);
return ret;
goto out;
}
mmc_host_clk_hold(host);
host->cmdq_ops->disable(host, true);
@ -91,6 +95,10 @@ 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)));
@ -102,10 +110,14 @@ 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",
@ -121,6 +133,11 @@ static int mmc_host_runtime_resume(struct device *dev)
else
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;
@ -133,9 +150,14 @@ 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
@ -152,7 +174,7 @@ static int mmc_host_suspend(struct device *dev)
if (ret) {
mmc_card_clr_suspended(host->card);
pr_err("%s: halt: failed: %d\n", __func__, ret);
return ret;
goto out;
}
mmc_host_clk_hold(host);
host->cmdq_ops->disable(host, true);
@ -179,6 +201,10 @@ static int mmc_host_suspend(struct device *dev)
spin_lock_irqsave(&host->clk_lock, flags);
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;
}
@ -186,10 +212,13 @@ 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) {
@ -205,6 +234,10 @@ 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;
}
#endif

View file

@ -91,6 +91,14 @@ enum mmc_load {
MMC_LOAD_LOW,
};
enum dev_state {
DEV_SUSPENDING = 1,
DEV_SUSPENDED,
DEV_RESUMING,
DEV_RESUMED,
DEV_ERROR,
};
struct mmc_cmdq_host_ops {
int (*enable)(struct mmc_host *host);
void (*disable)(struct mmc_host *host, bool soft);
@ -164,6 +172,7 @@ struct mmc_host_ops {
unsigned long (*get_max_frequency)(struct mmc_host *host);
unsigned long (*get_min_frequency)(struct mmc_host *host);
int (*notify_load)(struct mmc_host *, enum mmc_load);
void (*notify_pm_status)(struct mmc_host *, enum dev_state);
int (*stop_request)(struct mmc_host *host);
unsigned int (*get_xfer_remain)(struct mmc_host *host);
};
@ -281,12 +290,6 @@ struct mmc_supply {
struct regulator *vqmmc; /* Optional Vccq supply */
};
enum dev_state {
DEV_SUSPENDING = 1,
DEV_SUSPENDED,
DEV_RESUMED,
};
struct mmc_host {
struct device *parent;
struct device class_dev;