mmc: MMC-4.5 Data Tag Support
authorSaugata Das <saugata.das@linaro.org>
Wed, 21 Dec 2011 07:39:17 +0000 (13:09 +0530)
committerChris Ball <cjb@laptop.org>
Sun, 25 Mar 2012 23:33:44 +0000 (19:33 -0400)
MMC-4.5 data tag feature will be used to store the file system meta-data
in the tagged region of eMMC. This will improve the write and subsequent
read transfer time for the meta data.

Signed-off-by: Saugata Das <saugata.das@linaro.org>
Tested-by: Venkatraman S <svenkatr@ti.com>
Signed-off-by: Chris Ball <cjb@laptop.org>
drivers/mmc/card/block.c
drivers/mmc/core/mmc.c
include/linux/mmc/card.h
include/linux/mmc/mmc.h

index e5a3c7b..f2020d3 100644 (file)
@@ -1080,6 +1080,7 @@ static void mmc_blk_rw_rq_prep(struct mmc_queue_req *mqrq,
        struct mmc_blk_request *brq = &mqrq->brq;
        struct request *req = mqrq->req;
        struct mmc_blk_data *md = mq->data;
+       bool do_data_tag;
 
        /*
         * Reliable writes are used to implement Forced Unit Access and
@@ -1156,6 +1157,16 @@ static void mmc_blk_rw_rq_prep(struct mmc_queue_req *mqrq,
                mmc_apply_rel_rw(brq, card, req);
 
        /*
+        * Data tag is used only during writing meta data to speed
+        * up write and any subsequent read of this meta data
+        */
+       do_data_tag = (card->ext_csd.data_tag_unit_size) &&
+               (req->cmd_flags & REQ_META) &&
+               (rq_data_dir(req) == WRITE) &&
+               ((brq->data.blocks * brq->data.blksz) >=
+                card->ext_csd.data_tag_unit_size);
+
+       /*
         * Pre-defined multi-block transfers are preferable to
         * open ended-ones (and necessary for reliable writes).
         * However, it is not sufficient to just send CMD23,
@@ -1173,13 +1184,13 @@ static void mmc_blk_rw_rq_prep(struct mmc_queue_req *mqrq,
         * We'll avoid using CMD23-bounded multiblock writes for
         * these, while retaining features like reliable writes.
         */
-
-       if ((md->flags & MMC_BLK_CMD23) &&
-           mmc_op_multi(brq->cmd.opcode) &&
-           (do_rel_wr || !(card->quirks & MMC_QUIRK_BLK_NO_CMD23))) {
+       if ((md->flags & MMC_BLK_CMD23) && mmc_op_multi(brq->cmd.opcode) &&
+           (do_rel_wr || !(card->quirks & MMC_QUIRK_BLK_NO_CMD23) ||
+            do_data_tag)) {
                brq->sbc.opcode = MMC_SET_BLOCK_COUNT;
                brq->sbc.arg = brq->data.blocks |
-                       (do_rel_wr ? (1 << 31) : 0);
+                       (do_rel_wr ? (1 << 31) : 0) |
+                       (do_data_tag ? (1 << 29) : 0);
                brq->sbc.flags = MMC_RSP_R1 | MMC_CMD_AC;
                brq->mrq.sbc = &brq->sbc;
        }
index 2b9ed14..6defddd 100644 (file)
@@ -519,6 +519,20 @@ static int mmc_read_ext_csd(struct mmc_card *card, u8 *ext_csd)
                        ext_csd[EXT_CSD_CACHE_SIZE + 1] << 8 |
                        ext_csd[EXT_CSD_CACHE_SIZE + 2] << 16 |
                        ext_csd[EXT_CSD_CACHE_SIZE + 3] << 24;
+
+               if (ext_csd[EXT_CSD_DATA_SECTOR_SIZE] == 1)
+                       card->ext_csd.data_sector_size = 4096;
+               else
+                       card->ext_csd.data_sector_size = 512;
+
+               if ((ext_csd[EXT_CSD_DATA_TAG_SUPPORT] & 1) &&
+                   (ext_csd[EXT_CSD_TAG_UNIT_SIZE] <= 8)) {
+                       card->ext_csd.data_tag_unit_size =
+                       ((unsigned int) 1 << ext_csd[EXT_CSD_TAG_UNIT_SIZE]) *
+                       (card->ext_csd.data_sector_size);
+               } else {
+                       card->ext_csd.data_tag_unit_size = 0;
+               }
        }
 
 out:
index 19a41d1..1a1ca71 100644 (file)
@@ -71,6 +71,8 @@ struct mmc_ext_csd {
        bool                    hpi_en;                 /* HPI enablebit */
        bool                    hpi;                    /* HPI support bit */
        unsigned int            hpi_cmd;                /* cmd used as HPI */
+       unsigned int            data_sector_size;       /* 512 bytes or 4KB */
+       unsigned int            data_tag_unit_size;     /* DATA TAG UNIT size */
        unsigned int            boot_ro_lock;           /* ro lock support */
        bool                    boot_ro_lockable;
        u8                      raw_partition_support;  /* 160 */
index fb9f6e1..b822a2c 100644 (file)
@@ -274,6 +274,7 @@ struct _mmc_csd {
 #define EXT_CSD_FLUSH_CACHE            32      /* W */
 #define EXT_CSD_CACHE_CTRL             33      /* R/W */
 #define EXT_CSD_POWER_OFF_NOTIFICATION 34      /* R/W */
+#define EXT_CSD_DATA_SECTOR_SIZE       61      /* R */
 #define EXT_CSD_GP_SIZE_MULT           143     /* R/W */
 #define EXT_CSD_PARTITION_ATTRIBUTE    156     /* R/W */
 #define EXT_CSD_PARTITION_SUPPORT      160     /* RO */
@@ -315,6 +316,8 @@ struct _mmc_csd {
 #define EXT_CSD_POWER_OFF_LONG_TIME    247     /* RO */
 #define EXT_CSD_GENERIC_CMD6_TIME      248     /* RO */
 #define EXT_CSD_CACHE_SIZE             249     /* RO, 4 bytes */
+#define EXT_CSD_TAG_UNIT_SIZE          498     /* RO */
+#define EXT_CSD_DATA_TAG_SUPPORT       499     /* RO */
 #define EXT_CSD_HPI_FEATURES           503     /* RO */
 
 /*