mmc: core: Update PON based on the system state

As per eMMC specification, the PON (Power Off Notification)
must be sent by host to the card before turning off the power.
This will allow card to prepare itself for the power off and
may even reduce the initialization of eMMC upon next boot-up.

Send long PON during system power off and send short PON during
system reboot to reduce the reboot latency.

Change-Id: If4188b8b80aaa0e6c4e00e1807aa9589d5e7efdb
Signed-off-by: Sahitya Tummala <stummala@codeaurora.org>
This commit is contained in:
Sahitya Tummala 2015-02-09 10:45:18 +05:30
parent 64bf9ca9a1
commit f295d19cc9
3 changed files with 19 additions and 13 deletions

View File

@ -4098,7 +4098,7 @@ static void mmc_blk_shutdown(struct mmc_card *card)
mmc_claim_host(card->host);
mmc_stop_bkops(card);
mmc_release_host(card->host);
mmc_send_long_pon(card);
mmc_send_pon(card);
mmc_rpm_release(card->host, &card->dev);
}
return;

View File

@ -1296,10 +1296,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;
}
@ -1802,19 +1799,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;
}

View File

@ -316,6 +316,10 @@ struct mmc_bkops_info {
#define BKOPS_SIZE_PERCENTAGE_TO_QUEUE_DELAYED_WORK 1 /* 1% */
};
enum mmc_pon_type {
MMC_LONG_PON = 1,
MMC_SHRT_PON,
};
/*
* MMC device
*/
@ -403,7 +407,7 @@ struct mmc_card {
struct device_attribute rpm_attrib;
unsigned int idle_timeout;
struct notifier_block reboot_notify;
bool issue_long_pon;
enum mmc_pon_type pon_type;
u8 *cached_ext_csd;
bool cmdq_init;
};
@ -686,6 +690,6 @@ 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 void mmc_blk_disable_wr_packing(struct mmc_queue *mq);
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 */