From b3bf915308ca2b50f3beec6cc824083870f0f4b5 Mon Sep 17 00:00:00 2001 From: Kyungmin Park Date: Tue, 18 Oct 2011 09:34:04 +0900 Subject: [PATCH] mmc: core: new discard feature support at eMMC v4.5 MMC v4.5 supports the DISCARD feature (CMD38). It's different from trim and there's no check bit. Currently it's only supported at v4.5. Signed-off-by: Kyungmin Park Signed-off-by: Jaehoon Chung Signed-off-by: Chris Ball --- drivers/mmc/card/block.c | 4 +++- drivers/mmc/core/core.c | 14 ++++++++++++++ drivers/mmc/core/mmc.c | 4 ++++ include/linux/mmc/card.h | 3 +++ include/linux/mmc/core.h | 2 ++ 5 files changed, 26 insertions(+), 1 deletion(-) diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c index e85816e1634a..370472797fff 100644 --- a/drivers/mmc/card/block.c +++ b/drivers/mmc/card/block.c @@ -756,7 +756,9 @@ static int mmc_blk_issue_discard_rq(struct mmc_queue *mq, struct request *req) from = blk_rq_pos(req); nr = blk_rq_sectors(req); - if (mmc_can_trim(card)) + if (mmc_can_discard(card)) + arg = MMC_DISCARD_ARG; + else if (mmc_can_trim(card)) arg = MMC_TRIM_ARG; else arg = MMC_ERASE_ARG; diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c index d9836e5a4e59..772de2cdfd1d 100644 --- a/drivers/mmc/core/core.c +++ b/drivers/mmc/core/core.c @@ -1709,10 +1709,24 @@ int mmc_can_trim(struct mmc_card *card) { if (card->ext_csd.sec_feature_support & EXT_CSD_SEC_GB_CL_EN) return 1; + if (mmc_can_discard(card)) + return 1; return 0; } EXPORT_SYMBOL(mmc_can_trim); +int mmc_can_discard(struct mmc_card *card) +{ + /* + * As there's no way to detect the discard support bit at v4.5 + * use the s/w feature support filed. + */ + if (card->ext_csd.feature_support & MMC_DISCARD_FEATURE) + return 1; + return 0; +} +EXPORT_SYMBOL(mmc_can_discard); + int mmc_can_sanitize(struct mmc_card *card) { if (card->ext_csd.sec_feature_support & EXT_CSD_SEC_SANITIZE) diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c index f8ea9387d75c..54088768776c 100644 --- a/drivers/mmc/core/mmc.c +++ b/drivers/mmc/core/mmc.c @@ -452,6 +452,10 @@ static int mmc_read_ext_csd(struct mmc_card *card, u8 *ext_csd) card->ext_csd.rst_n_function = ext_csd[EXT_CSD_RST_N_FUNCTION]; } + /* eMMC v4.5 or later */ + if (card->ext_csd.rev >= 6) + card->ext_csd.feature_support |= MMC_DISCARD_FEATURE; + card->ext_csd.raw_erased_mem_count = ext_csd[EXT_CSD_ERASED_MEM_CONT]; if (ext_csd[EXT_CSD_ERASED_MEM_CONT]) card->erased_byte = 0xFF; diff --git a/include/linux/mmc/card.h b/include/linux/mmc/card.h index 711c3f8bfabd..551378508784 100644 --- a/include/linux/mmc/card.h +++ b/include/linux/mmc/card.h @@ -80,6 +80,9 @@ struct mmc_ext_csd { u8 raw_sec_feature_support;/* 231 */ u8 raw_trim_mult; /* 232 */ u8 raw_sectors[4]; /* 212 - 4 bytes */ + + unsigned int feature_support; +#define MMC_DISCARD_FEATURE BIT(0) /* CMD38 feature */ }; struct sd_scr { diff --git a/include/linux/mmc/core.h b/include/linux/mmc/core.h index 9585835cbc42..e918120235bd 100644 --- a/include/linux/mmc/core.h +++ b/include/linux/mmc/core.h @@ -146,6 +146,7 @@ extern int mmc_switch(struct mmc_card *, u8, u8, u8, unsigned int); #define MMC_ERASE_ARG 0x00000000 #define MMC_SECURE_ERASE_ARG 0x80000000 #define MMC_TRIM_ARG 0x00000001 +#define MMC_DISCARD_ARG 0x00000003 #define MMC_SECURE_TRIM1_ARG 0x80000001 #define MMC_SECURE_TRIM2_ARG 0x80008000 @@ -156,6 +157,7 @@ extern int mmc_erase(struct mmc_card *card, unsigned int from, unsigned int nr, unsigned int arg); extern int mmc_can_erase(struct mmc_card *card); extern int mmc_can_trim(struct mmc_card *card); +extern int mmc_can_discard(struct mmc_card *card); extern int mmc_can_sanitize(struct mmc_card *card); extern int mmc_can_secure_erase_trim(struct mmc_card *card); extern int mmc_erase_group_aligned(struct mmc_card *card, unsigned int from,