mirror of
https://github.com/hardkernel/linux.git
synced 2026-04-14 09:30:40 +09:00
mmc: Don't force card to active state when entering suspend/shutdown
By adding a card state that records if it is suspended or resumed, we can accept asyncronus suspend/resume requests for the mmc and sd bus_ops. MMC_CAP_AGGRESSIVE_PM, will at request inactivity through the runtime bus_ops callbacks, execute a suspend of the the card. In the state were this has been done, we can receive a suspend request for the mmc bus, which for sd and mmc forced the card to active state by a pm_runtime_get_sync. In other words, the card was resumed and then immediately suspended again, completely unnecessary. Since the suspend/resume bus_ops callbacks for sd and mmc are now capable of handling asynchronous requests, we no longer need to force the card to active state before executing suspend. Evidently preventing the above sequence for MMC_CAP_AGGRESSIVE_PM. Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org> Signed-off-by: Chris Ball <cjb@laptop.org> Conflicts: drivers/mmc/core/mmc.c drivers/mmc/core/sd.c
This commit is contained in:
@@ -2461,7 +2461,6 @@ static int _mmc_blk_suspend(struct mmc_card *card)
|
||||
struct mmc_blk_data *md = mmc_get_drvdata(card);
|
||||
|
||||
if (md) {
|
||||
pm_runtime_get_sync(&card->dev);
|
||||
mmc_queue_suspend(&md->queue);
|
||||
list_for_each_entry(part_md, &md->part, part) {
|
||||
mmc_queue_suspend(&part_md->queue);
|
||||
@@ -2496,7 +2495,6 @@ static int mmc_blk_resume(struct mmc_card *card)
|
||||
list_for_each_entry(part_md, &md->part, part) {
|
||||
mmc_queue_resume(&part_md->queue);
|
||||
}
|
||||
pm_runtime_put(&card->dev);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1511,18 +1511,12 @@ out:
|
||||
*/
|
||||
static int mmc_suspend(struct mmc_host *host)
|
||||
{
|
||||
int err;
|
||||
|
||||
err = _mmc_suspend(host, true);
|
||||
if (!err) {
|
||||
pm_runtime_disable(&host->card->dev);
|
||||
pm_runtime_set_suspended(&host->card->dev);
|
||||
}
|
||||
|
||||
return err;
|
||||
return _mmc_suspend(host, true);
|
||||
}
|
||||
|
||||
/*
|
||||
* Resume callback from host.
|
||||
*
|
||||
* This function tries to determine if the same card is still present
|
||||
* and, if so, restore all state to it.
|
||||
*/
|
||||
@@ -1547,26 +1541,6 @@ out:
|
||||
return err;
|
||||
}
|
||||
|
||||
/*
|
||||
* Shutdown callback
|
||||
*/
|
||||
static int mmc_shutdown(struct mmc_host *host)
|
||||
{
|
||||
int err = 0;
|
||||
|
||||
/*
|
||||
* In a specific case for poweroff notify, we need to resume the card
|
||||
* before we can shutdown it properly.
|
||||
*/
|
||||
if (mmc_can_poweroff_notify(host->card) &&
|
||||
!(host->caps2 & MMC_CAP2_FULL_PWR_CYCLE))
|
||||
err = _mmc_resume(host);
|
||||
|
||||
if (!err)
|
||||
err = _mmc_suspend(host, false);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
/*
|
||||
* Callback for resume.
|
||||
@@ -1581,6 +1555,24 @@ static int mmc_resume(struct mmc_host *host)
|
||||
pm_runtime_mark_last_busy(&host->card->dev);
|
||||
}
|
||||
pm_runtime_enable(&host->card->dev);
|
||||
}
|
||||
/*
|
||||
* Shutdown callback
|
||||
*/
|
||||
static int mmc_shutdown(struct mmc_host *host)
|
||||
{
|
||||
int err = 0;
|
||||
|
||||
/*
|
||||
* In a specific case for poweroff notify, we need to resume the card
|
||||
* before we can shutdown it properly.
|
||||
*/
|
||||
if (mmc_can_poweroff_notify(host->card) &&
|
||||
!(host->caps2 & MMC_CAP2_FULL_PWR_CYCLE))
|
||||
err = mmc_resume(host);
|
||||
|
||||
if (!err)
|
||||
err = _mmc_suspend(host, false);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
@@ -1116,30 +1116,6 @@ static void mmc_sd_detect(struct mmc_host *host)
|
||||
}
|
||||
}
|
||||
|
||||
static int _mmc_sd_suspend(struct mmc_host *host)
|
||||
{
|
||||
int err = 0;
|
||||
|
||||
BUG_ON(!host);
|
||||
BUG_ON(!host->card);
|
||||
|
||||
mmc_claim_host(host);
|
||||
|
||||
if (mmc_card_suspended(host->card))
|
||||
goto out;
|
||||
|
||||
if (!mmc_host_is_spi(host))
|
||||
err = mmc_deselect_cards(host);
|
||||
host->card->state &= ~MMC_STATE_HIGHSPEED;
|
||||
if (!err) {
|
||||
mmc_power_off(host);
|
||||
mmc_card_set_suspended(host->card);
|
||||
}
|
||||
|
||||
out:
|
||||
mmc_release_host(host);
|
||||
return err;
|
||||
}
|
||||
|
||||
/*
|
||||
* Callback for suspend
|
||||
@@ -1148,13 +1124,25 @@ 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);
|
||||
}
|
||||
BUG_ON(!host);
|
||||
BUG_ON(!host->card);
|
||||
|
||||
mmc_claim_host(host);
|
||||
|
||||
if (mmc_card_suspended(host->card))
|
||||
goto out;
|
||||
if (!mmc_host_is_spi(host))
|
||||
err = mmc_deselect_cards(host);
|
||||
|
||||
host->card->state &= ~MMC_STATE_HIGHSPEED;
|
||||
if (!err) {
|
||||
mmc_power_off(host);
|
||||
mmc_card_set_suspended(host->card);
|
||||
}
|
||||
out:
|
||||
mmc_release_host(host);
|
||||
return err;
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1196,6 +1184,8 @@ static int mmc_sd_resume(struct mmc_host *host)
|
||||
}
|
||||
pm_runtime_enable(&host->card->dev);
|
||||
|
||||
out:
|
||||
mmc_release_host(host);
|
||||
return err;
|
||||
}
|
||||
|
||||
@@ -1209,7 +1199,7 @@ static int mmc_sd_runtime_suspend(struct mmc_host *host)
|
||||
if (!(host->caps & MMC_CAP_AGGRESSIVE_PM))
|
||||
return 0;
|
||||
|
||||
err = _mmc_sd_suspend(host);
|
||||
err = mmc_sd_suspend(host);
|
||||
if (err)
|
||||
pr_err("%s: error %d doing aggessive suspend\n",
|
||||
mmc_hostname(host), err);
|
||||
|
||||
Reference in New Issue
Block a user