Skip to content

Commit

Permalink
mmc: core: Update PON based on the system state
Browse files Browse the repository at this point in the history
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.

Signed-off-by: Sahitya Tummala <[email protected]>
Signed-off-by: Pranav Vashi <[email protected]>
  • Loading branch information
Sahitya Tummala authored and neobuddy89 committed Feb 23, 2015
1 parent af53284 commit df43758
Show file tree
Hide file tree
Showing 3 changed files with 19 additions and 13 deletions.
2 changes: 1 addition & 1 deletion drivers/mmc/card/block.c
Original file line number Diff line number Diff line change
Expand Up @@ -3254,7 +3254,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;
Expand Down
22 changes: 12 additions & 10 deletions drivers/mmc/core/mmc.c
Original file line number Diff line number Diff line change
Expand Up @@ -1286,10 +1286,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;
}
Expand Down Expand Up @@ -1685,19 +1682,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;
}

Expand Down
8 changes: 6 additions & 2 deletions include/linux/mmc/card.h
Original file line number Diff line number Diff line change
Expand Up @@ -310,6 +310,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
*/
Expand Down Expand Up @@ -396,7 +400,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;
};

Expand Down Expand Up @@ -654,5 +658,5 @@ 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);
#endif /* LINUX_MMC_CARD_H */

0 comments on commit df43758

Please sign in to comment.