提交 0cb403a2 编写于 作者: U Ulf Hansson 提交者: Chris Ball

mmc: core: Improve runtime PM support during suspend/resume for sd/mmc

The card device is considered as in-active after it has been suspended.
To prevent any further runtime PM requests in suspend state, we then
disable runtime PM.

After the card device has been resumed, we shall consider it as active,
like we also do after a probe sequence. When resumed, we can safely
enable runtime PM again.

This will make sure the PM core can request the card device to go to
in-active state after a resume has been completed. Previously we had to
wait for new pm_runtime_get->pm_runtime_put cycle to be executed.

Additionally, once a resume has been carried out, update the last busy
mark. At the moment this will have no effect but if the PM core will
respect autosuspend enabled devices, when it directly triggers a
runtime_suspend from a runtime_idle, it will mean the card device will
be scheduled for a delayed runtime_suspend instead of done immediately.
Signed-off-by: NUlf Hansson <ulf.hansson@linaro.org>
Signed-off-by: NChris Ball <cjb@laptop.org>
上级 0cc81a8c
...@@ -13,6 +13,7 @@ ...@@ -13,6 +13,7 @@
#include <linux/err.h> #include <linux/err.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/stat.h> #include <linux/stat.h>
#include <linux/pm_runtime.h>
#include <linux/mmc/host.h> #include <linux/mmc/host.h>
#include <linux/mmc/card.h> #include <linux/mmc/card.h>
...@@ -1510,20 +1511,26 @@ static int _mmc_suspend(struct mmc_host *host, bool is_suspend) ...@@ -1510,20 +1511,26 @@ static int _mmc_suspend(struct mmc_host *host, bool is_suspend)
} }
/* /*
* Suspend callback from host. * Suspend callback
*/ */
static int mmc_suspend(struct mmc_host *host) static int mmc_suspend(struct mmc_host *host)
{ {
return _mmc_suspend(host, true); int err;
err = _mmc_suspend(host, true);
if (!err) {
pm_runtime_disable(&host->card->dev);
pm_runtime_set_suspended(&host->card->dev);
}
return err;
} }
/* /*
* Resume callback from host.
*
* This function tries to determine if the same card is still present * This function tries to determine if the same card is still present
* and, if so, restore all state to it. * and, if so, restore all state to it.
*/ */
static int mmc_resume(struct mmc_host *host) static int _mmc_resume(struct mmc_host *host)
{ {
int err = 0; int err = 0;
...@@ -1557,7 +1564,7 @@ static int mmc_shutdown(struct mmc_host *host) ...@@ -1557,7 +1564,7 @@ static int mmc_shutdown(struct mmc_host *host)
*/ */
if (mmc_can_poweroff_notify(host->card) && if (mmc_can_poweroff_notify(host->card) &&
!(host->caps2 & MMC_CAP2_FULL_PWR_CYCLE)) !(host->caps2 & MMC_CAP2_FULL_PWR_CYCLE))
err = mmc_resume(host); err = _mmc_resume(host);
if (!err) if (!err)
err = _mmc_suspend(host, false); err = _mmc_suspend(host, false);
...@@ -1565,6 +1572,21 @@ static int mmc_shutdown(struct mmc_host *host) ...@@ -1565,6 +1572,21 @@ static int mmc_shutdown(struct mmc_host *host)
return err; return err;
} }
/*
* Callback for resume.
*/
static int mmc_resume(struct mmc_host *host)
{
int err;
err = _mmc_resume(host);
pm_runtime_set_active(&host->card->dev);
pm_runtime_mark_last_busy(&host->card->dev);
pm_runtime_enable(&host->card->dev);
return err;
}
/* /*
* Callback for runtime_suspend. * Callback for runtime_suspend.
*/ */
...@@ -1575,7 +1597,7 @@ static int mmc_runtime_suspend(struct mmc_host *host) ...@@ -1575,7 +1597,7 @@ static int mmc_runtime_suspend(struct mmc_host *host)
if (!(host->caps & MMC_CAP_AGGRESSIVE_PM)) if (!(host->caps & MMC_CAP_AGGRESSIVE_PM))
return 0; return 0;
err = mmc_suspend(host); err = _mmc_suspend(host, true);
if (err) if (err)
pr_err("%s: error %d doing aggessive suspend\n", pr_err("%s: error %d doing aggessive suspend\n",
mmc_hostname(host), err); mmc_hostname(host), err);
...@@ -1593,7 +1615,7 @@ static int mmc_runtime_resume(struct mmc_host *host) ...@@ -1593,7 +1615,7 @@ static int mmc_runtime_resume(struct mmc_host *host)
if (!(host->caps & MMC_CAP_AGGRESSIVE_PM)) if (!(host->caps & MMC_CAP_AGGRESSIVE_PM))
return 0; return 0;
err = mmc_resume(host); err = _mmc_resume(host);
if (err) if (err)
pr_err("%s: error %d doing aggessive resume\n", pr_err("%s: error %d doing aggessive resume\n",
mmc_hostname(host), err); mmc_hostname(host), err);
......
...@@ -13,6 +13,7 @@ ...@@ -13,6 +13,7 @@
#include <linux/err.h> #include <linux/err.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/stat.h> #include <linux/stat.h>
#include <linux/pm_runtime.h>
#include <linux/mmc/host.h> #include <linux/mmc/host.h>
#include <linux/mmc/card.h> #include <linux/mmc/card.h>
...@@ -1067,10 +1068,7 @@ static void mmc_sd_detect(struct mmc_host *host) ...@@ -1067,10 +1068,7 @@ static void mmc_sd_detect(struct mmc_host *host)
} }
} }
/* static int _mmc_sd_suspend(struct mmc_host *host)
* Suspend callback from host.
*/
static int mmc_sd_suspend(struct mmc_host *host)
{ {
int err = 0; int err = 0;
...@@ -1096,12 +1094,26 @@ static int mmc_sd_suspend(struct mmc_host *host) ...@@ -1096,12 +1094,26 @@ static int mmc_sd_suspend(struct mmc_host *host)
} }
/* /*
* Resume callback from host. * Callback for suspend
* */
static int mmc_sd_suspend(struct mmc_host *host)
{
int err;
err = _mmc_sd_suspend(host);
if (!err) {
pm_runtime_disable(&host->card->dev);
pm_runtime_set_suspended(&host->card->dev);
}
return err;
}
/*
* This function tries to determine if the same card is still present * This function tries to determine if the same card is still present
* and, if so, restore all state to it. * and, if so, restore all state to it.
*/ */
static int mmc_sd_resume(struct mmc_host *host) static int _mmc_sd_resume(struct mmc_host *host)
{ {
int err = 0; int err = 0;
...@@ -1122,6 +1134,21 @@ static int mmc_sd_resume(struct mmc_host *host) ...@@ -1122,6 +1134,21 @@ static int mmc_sd_resume(struct mmc_host *host)
return err; return err;
} }
/*
* Callback for resume
*/
static int mmc_sd_resume(struct mmc_host *host)
{
int err;
err = _mmc_sd_resume(host);
pm_runtime_set_active(&host->card->dev);
pm_runtime_mark_last_busy(&host->card->dev);
pm_runtime_enable(&host->card->dev);
return err;
}
/* /*
* Callback for runtime_suspend. * Callback for runtime_suspend.
*/ */
...@@ -1132,7 +1159,7 @@ static int mmc_sd_runtime_suspend(struct mmc_host *host) ...@@ -1132,7 +1159,7 @@ static int mmc_sd_runtime_suspend(struct mmc_host *host)
if (!(host->caps & MMC_CAP_AGGRESSIVE_PM)) if (!(host->caps & MMC_CAP_AGGRESSIVE_PM))
return 0; return 0;
err = mmc_sd_suspend(host); err = _mmc_sd_suspend(host);
if (err) if (err)
pr_err("%s: error %d doing aggessive suspend\n", pr_err("%s: error %d doing aggessive suspend\n",
mmc_hostname(host), err); mmc_hostname(host), err);
...@@ -1150,7 +1177,7 @@ static int mmc_sd_runtime_resume(struct mmc_host *host) ...@@ -1150,7 +1177,7 @@ static int mmc_sd_runtime_resume(struct mmc_host *host)
if (!(host->caps & MMC_CAP_AGGRESSIVE_PM)) if (!(host->caps & MMC_CAP_AGGRESSIVE_PM))
return 0; return 0;
err = mmc_sd_resume(host); err = _mmc_sd_resume(host);
if (err) if (err)
pr_err("%s: error %d doing aggessive resume\n", pr_err("%s: error %d doing aggessive resume\n",
mmc_hostname(host), err); mmc_hostname(host), err);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册