From 775a9362b5d7e006ff6bbec5cb9c9c9d5a751696 Mon Sep 17 00:00:00 2001 From: Maya Erez Date: Thu, 18 Apr 2013 15:41:55 +0300 Subject: mmc: card: Adding support for sanitize in eMMC 4.5 The sanitize support is added as a user-app ioctl call, and was removed from the block-device request, since its purpose is to be invoked not via File-System but by a user. This feature deletes the unmap memory region of the eMMC card, by writing to a specific register in the EXT_CSD. unmap region is the memory region that was previously deleted (by erase, trim or discard operation). In order to avoid timeout when sanitizing large-scale cards, the timeout for sanitize operation is 240 seconds. Signed-off-by: Yaniv Gardi Signed-off-by: Maya Erez Signed-off-by: Chris Ball --- drivers/mmc/core/mmc_ops.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/mmc/core/mmc_ops.c') diff --git a/drivers/mmc/core/mmc_ops.c b/drivers/mmc/core/mmc_ops.c index 49f04bc9d0e..124af5238d0 100644 --- a/drivers/mmc/core/mmc_ops.c +++ b/drivers/mmc/core/mmc_ops.c @@ -431,6 +431,8 @@ int __mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value, cmd.cmd_timeout_ms = timeout_ms; + if (index == EXT_CSD_SANITIZE_START) + cmd.sanitize_busy = true; err = mmc_wait_for_cmd(card->host, &cmd, MMC_CMD_RETRIES); if (err) -- cgit v1.2.3-70-g09d2 From 07a682160866e302d696f5c76d74024d575fb79d Mon Sep 17 00:00:00 2001 From: Ulf Hansson Date: Fri, 19 Apr 2013 15:12:11 +0200 Subject: mmc: core: Restructure and simplify code for mmc sleep|awake The mmc_card_sleep|awake APIs are not being used since the support is already properly encapsulated within the suspend sequence. Sleep|awake command is also specific for eMMC. We remove the sleep|awake bus_ops, the mmc_card_sleep|awake APIs and move the code into the mmc specific core instead. This also includes the mmc ops function, mmc_sleepawake. All releated functions have then become static and we have got far less code to maintain. Additionally this patch also simplifies the code from mmc_sleepawake, since it is only used to put the card to sleep and not awake. Signed-off-by: Ulf Hansson Signed-off-by: Chris Ball --- drivers/mmc/core/core.c | 46 --------------------------- drivers/mmc/core/core.h | 2 -- drivers/mmc/core/mmc.c | 77 ++++++++++++++++++++++++---------------------- drivers/mmc/core/mmc_ops.c | 34 -------------------- drivers/mmc/core/mmc_ops.h | 1 - include/linux/mmc/host.h | 4 --- 6 files changed, 41 insertions(+), 123 deletions(-) (limited to 'drivers/mmc/core/mmc_ops.c') diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c index 0f86144b0c5..e9a104b9e4d 100644 --- a/drivers/mmc/core/core.c +++ b/drivers/mmc/core/core.c @@ -2550,52 +2550,6 @@ int mmc_power_restore_host(struct mmc_host *host) } EXPORT_SYMBOL(mmc_power_restore_host); -int mmc_card_awake(struct mmc_host *host) -{ - int err = -ENOSYS; - - if (host->caps2 & MMC_CAP2_NO_SLEEP_CMD) - return 0; - - mmc_bus_get(host); - - if (host->bus_ops && !host->bus_dead && host->bus_ops->awake) - err = host->bus_ops->awake(host); - - mmc_bus_put(host); - - return err; -} -EXPORT_SYMBOL(mmc_card_awake); - -int mmc_card_sleep(struct mmc_host *host) -{ - int err = -ENOSYS; - - if (host->caps2 & MMC_CAP2_NO_SLEEP_CMD) - return 0; - - mmc_bus_get(host); - - if (host->bus_ops && !host->bus_dead && host->bus_ops->sleep) - err = host->bus_ops->sleep(host); - - mmc_bus_put(host); - - return err; -} -EXPORT_SYMBOL(mmc_card_sleep); - -int mmc_card_can_sleep(struct mmc_host *host) -{ - struct mmc_card *card = host->card; - - if (card && mmc_card_mmc(card) && card->ext_csd.rev >= 3) - return 1; - return 0; -} -EXPORT_SYMBOL(mmc_card_can_sleep); - /* * Flush the cache to the non-volatile storage. */ diff --git a/drivers/mmc/core/core.h b/drivers/mmc/core/core.h index 6242ffb789c..52a3650307a 100644 --- a/drivers/mmc/core/core.h +++ b/drivers/mmc/core/core.h @@ -16,8 +16,6 @@ #define MMC_CMD_RETRIES 3 struct mmc_bus_ops { - int (*awake)(struct mmc_host *); - int (*sleep)(struct mmc_host *); void (*remove)(struct mmc_host *); void (*detect)(struct mmc_host *); int (*suspend)(struct mmc_host *); diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c index 506f4ee84e1..dd6810eebd3 100644 --- a/drivers/mmc/core/mmc.c +++ b/drivers/mmc/core/mmc.c @@ -1321,6 +1321,45 @@ err: return err; } +static int mmc_can_sleep(struct mmc_card *card) +{ + return (card && card->ext_csd.rev >= 3); +} + +static int mmc_sleep(struct mmc_host *host) +{ + struct mmc_command cmd = {0}; + struct mmc_card *card = host->card; + int err; + + if (host->caps2 & MMC_CAP2_NO_SLEEP_CMD) + return 0; + + err = mmc_deselect_cards(host); + if (err) + return err; + + cmd.opcode = MMC_SLEEP_AWAKE; + cmd.arg = card->rca << 16; + cmd.arg |= 1 << 15; + + cmd.flags = MMC_RSP_R1B | MMC_CMD_AC; + err = mmc_wait_for_cmd(host, &cmd, 0); + if (err) + return err; + + /* + * If the host does not wait while the card signals busy, then we will + * will have to wait the sleep/awake timeout. Note, we cannot use the + * SEND_STATUS command to poll the status because that command (and most + * others) is invalid while the card sleeps. + */ + if (!(host->caps & MMC_CAP_WAIT_WHILE_BUSY)) + mmc_delay(DIV_ROUND_UP(card->ext_csd.sa_timeout, 10000)); + + return err; +} + static int mmc_can_poweroff_notify(const struct mmc_card *card) { return card && @@ -1423,8 +1462,8 @@ static int mmc_suspend(struct mmc_host *host) if (mmc_can_poweroff_notify(host->card)) err = mmc_poweroff_notify(host->card, EXT_CSD_POWER_OFF_SHORT); - else if (mmc_card_can_sleep(host)) - err = mmc_card_sleep(host); + else if (mmc_can_sleep(host->card)) + err = mmc_sleep(host); else if (!mmc_host_is_spi(host)) err = mmc_deselect_cards(host); host->card->state &= ~(MMC_STATE_HIGHSPEED | MMC_STATE_HIGHSPEED_200); @@ -1514,39 +1553,7 @@ static int mmc_power_restore(struct mmc_host *host) return ret; } -static int mmc_sleep(struct mmc_host *host) -{ - struct mmc_card *card = host->card; - int err = -ENOSYS; - - if (card && card->ext_csd.rev >= 3) { - err = mmc_card_sleepawake(host, 1); - if (err < 0) - pr_debug("%s: Error %d while putting card into sleep", - mmc_hostname(host), err); - } - - return err; -} - -static int mmc_awake(struct mmc_host *host) -{ - struct mmc_card *card = host->card; - int err = -ENOSYS; - - if (card && card->ext_csd.rev >= 3) { - err = mmc_card_sleepawake(host, 0); - if (err < 0) - pr_debug("%s: Error %d while awaking sleeping card", - mmc_hostname(host), err); - } - - return err; -} - static const struct mmc_bus_ops mmc_ops = { - .awake = mmc_awake, - .sleep = mmc_sleep, .remove = mmc_remove, .detect = mmc_detect, .suspend = NULL, @@ -1556,8 +1563,6 @@ static const struct mmc_bus_ops mmc_ops = { }; static const struct mmc_bus_ops mmc_ops_unsafe = { - .awake = mmc_awake, - .sleep = mmc_sleep, .remove = mmc_remove, .detect = mmc_detect, .suspend = mmc_suspend, diff --git a/drivers/mmc/core/mmc_ops.c b/drivers/mmc/core/mmc_ops.c index 124af5238d0..837fc7386e2 100644 --- a/drivers/mmc/core/mmc_ops.c +++ b/drivers/mmc/core/mmc_ops.c @@ -59,40 +59,6 @@ int mmc_deselect_cards(struct mmc_host *host) return _mmc_select_card(host, NULL); } -int mmc_card_sleepawake(struct mmc_host *host, int sleep) -{ - struct mmc_command cmd = {0}; - struct mmc_card *card = host->card; - int err; - - if (sleep) - mmc_deselect_cards(host); - - cmd.opcode = MMC_SLEEP_AWAKE; - cmd.arg = card->rca << 16; - if (sleep) - cmd.arg |= 1 << 15; - - cmd.flags = MMC_RSP_R1B | MMC_CMD_AC; - err = mmc_wait_for_cmd(host, &cmd, 0); - if (err) - return err; - - /* - * If the host does not wait while the card signals busy, then we will - * will have to wait the sleep/awake timeout. Note, we cannot use the - * SEND_STATUS command to poll the status because that command (and most - * others) is invalid while the card sleeps. - */ - if (!(host->caps & MMC_CAP_WAIT_WHILE_BUSY)) - mmc_delay(DIV_ROUND_UP(card->ext_csd.sa_timeout, 10000)); - - if (!sleep) - err = mmc_select_card(card); - - return err; -} - int mmc_go_idle(struct mmc_host *host) { int err; diff --git a/drivers/mmc/core/mmc_ops.h b/drivers/mmc/core/mmc_ops.h index 3dd8941c298..80ae9f4e029 100644 --- a/drivers/mmc/core/mmc_ops.h +++ b/drivers/mmc/core/mmc_ops.h @@ -24,7 +24,6 @@ int mmc_send_status(struct mmc_card *card, u32 *status); int mmc_send_cid(struct mmc_host *host, u32 *cid); int mmc_spi_read_ocr(struct mmc_host *host, int highcap, u32 *ocrp); int mmc_spi_set_crc(struct mmc_host *host, int use_crc); -int mmc_card_sleepawake(struct mmc_host *host, int sleep); int mmc_bus_test(struct mmc_card *card, u8 bus_width); int mmc_send_hpi_cmd(struct mmc_card *card, u32 *status); diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h index 374098bae83..2e34ee5cefc 100644 --- a/include/linux/mmc/host.h +++ b/include/linux/mmc/host.h @@ -425,10 +425,6 @@ static inline int mmc_regulator_get_supply(struct mmc_host *mmc) } #endif -int mmc_card_awake(struct mmc_host *host); -int mmc_card_sleep(struct mmc_host *host); -int mmc_card_can_sleep(struct mmc_host *host); - int mmc_pm_notify(struct notifier_block *notify_block, unsigned long, void *); /* Module parameter */ -- cgit v1.2.3-70-g09d2