diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c index 7c8e0a601cd4..b9febc75c64e 100644 --- a/drivers/mmc/card/block.c +++ b/drivers/mmc/card/block.c @@ -4056,6 +4056,10 @@ static int _mmc_blk_suspend(struct mmc_card *card) static void mmc_blk_shutdown(struct mmc_card *card) { _mmc_blk_suspend(card); + + /* send power off notification */ + if (mmc_card_mmc(card)) + mmc_send_pon(card); } #ifdef CONFIG_PM_SLEEP diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c index b0353f88f990..7ce9d3c01226 100644 --- a/drivers/mmc/core/mmc.c +++ b/drivers/mmc/core/mmc.c @@ -1431,10 +1431,7 @@ static int mmc_reboot_notify(struct notifier_block *notify_block, struct mmc_card *card = container_of( notify_block, struct mmc_card, reboot_notify); - if (event != SYS_RESTART) - card->issue_long_pon = true; - else - card->issue_long_pon = false; + card->pon_type = (event != SYS_RESTART) ? MMC_LONG_PON : MMC_SHRT_PON; return NOTIFY_OK; } @@ -2255,19 +2252,24 @@ static int mmc_poweroff_notify(struct mmc_card *card, unsigned int notify_type) return err; } -int mmc_send_long_pon(struct mmc_card *card) +int mmc_send_pon(struct mmc_card *card) { int err = 0; struct mmc_host *host = card->host; + if (!mmc_can_poweroff_notify(card)) + goto out; + mmc_claim_host(host); - if (card->issue_long_pon && mmc_can_poweroff_notify(card)) { + if (card->pon_type & MMC_LONG_PON) err = mmc_poweroff_notify(host->card, EXT_CSD_POWER_OFF_LONG); - if (err) - pr_warning("%s: error %d sending Long PON", - mmc_hostname(host), err); - } + else if (card->pon_type & MMC_SHRT_PON) + err = mmc_poweroff_notify(host->card, EXT_CSD_POWER_OFF_SHORT); + if (err) + pr_warn("%s: error %d sending PON type %u", + mmc_hostname(host), err, card->pon_type); mmc_release_host(host); +out: return err; } diff --git a/include/linux/mmc/card.h b/include/linux/mmc/card.h index 2430ba0e1182..c8faf8b146ee 100644 --- a/include/linux/mmc/card.h +++ b/include/linux/mmc/card.h @@ -324,6 +324,11 @@ struct mmc_bkops_info { bool needs_manual; }; +enum mmc_pon_type { + MMC_LONG_PON = 1, + MMC_SHRT_PON, +}; + /* * MMC device */ @@ -411,7 +416,7 @@ struct mmc_card { struct mmc_wr_pack_stats wr_pack_stats; /* packed commands stats*/ struct notifier_block reboot_notify; - bool issue_long_pon; + enum mmc_pon_type pon_type; u8 *cached_ext_csd; bool cmdq_init; struct mmc_bkops_info bkops; @@ -691,6 +696,6 @@ extern void mmc_fixup_device(struct mmc_card *card, extern struct mmc_wr_pack_stats *mmc_blk_get_packed_statistics( struct mmc_card *card); extern void mmc_blk_init_packed_statistics(struct mmc_card *card); -extern int mmc_send_long_pon(struct mmc_card *card); +extern int mmc_send_pon(struct mmc_card *card); extern void mmc_blk_cmdq_req_done(struct mmc_request *mrq); #endif /* LINUX_MMC_CARD_H */