mmc: core: new discard feature support at eMMC v4.5
authorKyungmin Park <kyungmin.park@samsung.com>
Tue, 18 Oct 2011 00:34:04 +0000 (09:34 +0900)
committerChris Ball <cjb@laptop.org>
Wed, 26 Oct 2011 20:32:27 +0000 (16:32 -0400)
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>
drivers/mmc/card/block.c
drivers/mmc/core/core.c
drivers/mmc/core/mmc.c
include/linux/mmc/card.h
include/linux/mmc/core.h

index e85816e..3704727 100644 (file)
@@ -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;
index d9836e5..772de2c 100644 (file)
@@ -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)
index f8ea938..5408876 100644 (file)
@@ -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;
index 711c3f8..5513785 100644 (file)
@@ -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 {
index 9585835..e918120 100644 (file)
@@ -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,