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 <kyungmin.park@samsung.com>
Signed-off-by: Jaehoon Chung <jh80.chung@samsung.com>
Signed-off-by: Chris Ball <cjb@laptop.org>
Signed-off-by: Konstantin Dorfman <kdorfman@codeaurora.org>
diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c
index 6b03481..3d3ef78 100644
--- a/drivers/mmc/card/block.c
+++ b/drivers/mmc/card/block.c
@@ -764,7 +764,9 @@
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 74fd708..16a94ec 100644
--- a/drivers/mmc/core/core.c
+++ b/drivers/mmc/core/core.c
@@ -1721,10 +1721,24 @@
{
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 911175b..2d28c05 100644
--- a/drivers/mmc/core/mmc.c
+++ b/drivers/mmc/core/mmc.c
@@ -408,6 +408,10 @@
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 f91c1a2..0aca2cf 100644
--- a/include/linux/mmc/card.h
+++ b/include/linux/mmc/card.h
@@ -80,6 +80,9 @@
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 f625c9f..fcdc377 100644
--- a/include/linux/mmc/core.h
+++ b/include/linux/mmc/core.h
@@ -146,6 +146,7 @@
#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 @@
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,