From: Ulf Hansson Date: Mon, 7 Apr 2025 15:27:52 +0000 (+0200) Subject: mmc: core: Further avoid re-storing power to the eMMC before a shutdown X-Git-Url: https://www.infradead.org/git/?a=commitdiff_plain;h=fa34c940e830e7af37b57f5fcdb17e2fc03dbf7f;p=users%2Fwilly%2Fxarray.git mmc: core: Further avoid re-storing power to the eMMC before a shutdown To manage a graceful power-off of the eMMC card during platform shutdown, the prioritized option is to use the poweroff-notification command, if the eMMC card supports it. During a suspend request we may decide to fall back to use the sleep command, instead of the poweroff-notification, unless the mmc host supports a complete power-cycle of the eMMC. For this reason, we may need to restore power and re-initialize the card, if it remains suspended when a shutdown request is received. However, the current condition to restore power and re-initialize the card doesn't take into account MMC_CAP2_FULL_PWR_CYCLE_IN_SUSPEND properly. This may lead to doing a re-initialization when it really isn't needed, as the eMMC may already have been powered-off using the poweroff-notification command. Let's fix the condition to avoid this. Tested-by: Wolfram Sang Signed-off-by: Ulf Hansson Link: https://lore.kernel.org/r/20250407152759.25160-3-ulf.hansson@linaro.org --- diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c index 3424bc9e20c5..ee65c5b85f95 100644 --- a/drivers/mmc/core/mmc.c +++ b/drivers/mmc/core/mmc.c @@ -2014,6 +2014,18 @@ static bool mmc_can_poweroff_notify(const struct mmc_card *card) (card->ext_csd.power_off_notification == EXT_CSD_POWER_ON); } +static bool mmc_host_can_poweroff_notify(const struct mmc_host *host, + bool is_suspend) +{ + if (host->caps2 & MMC_CAP2_FULL_PWR_CYCLE) + return true; + + if (host->caps2 & MMC_CAP2_FULL_PWR_CYCLE_IN_SUSPEND && is_suspend) + return true; + + return !is_suspend; +} + static int mmc_poweroff_notify(struct mmc_card *card, unsigned int notify_type) { unsigned int timeout = card->ext_csd.generic_cmd6_time; @@ -2124,8 +2136,7 @@ static int _mmc_suspend(struct mmc_host *host, bool is_suspend) goto out; if (mmc_can_poweroff_notify(host->card) && - ((host->caps2 & MMC_CAP2_FULL_PWR_CYCLE) || !is_suspend || - (host->caps2 & MMC_CAP2_FULL_PWR_CYCLE_IN_SUSPEND))) + mmc_host_can_poweroff_notify(host, is_suspend)) err = mmc_poweroff_notify(host->card, notify_type); else if (mmc_can_sleep(host->card)) err = mmc_sleep(host); @@ -2187,11 +2198,12 @@ 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 the card remains suspended at this point and it was done by using + * the sleep-cmd (CMD5), we may need to re-initialize it first, to allow + * us to send the preferred poweroff-notification cmd at shutdown. */ if (mmc_can_poweroff_notify(host->card) && - !(host->caps2 & MMC_CAP2_FULL_PWR_CYCLE)) + !mmc_host_can_poweroff_notify(host, true)) err = _mmc_resume(host); if (!err)