On 21 December 2011 17:01, Girish K S <girish.shivananjappa@xxxxxxxxxx> wrote: > On 21 December 2011 16:42, Saugata Das <saugata.das@xxxxxxxxxx> wrote: >> On 21 December 2011 16:23, Girish K S <girish.shivananjappa@xxxxxxxxxx> wrote: >>> On 21 December 2011 13:09, Saugata Das <saugata.das@xxxxxxxxxxxxxx> wrote: >>>> From: Saugata Das <saugata.das@xxxxxxxxxx> >>>> >>>> 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@xxxxxxxxxx> >>>> --- >>>> drivers/mmc/card/block.c | 17 +++++++++++++++-- >>>> drivers/mmc/core/mmc.c | 14 ++++++++++++++ >>>> include/linux/mmc/card.h | 2 ++ >>>> include/linux/mmc/mmc.h | 3 +++ >>>> 4 files changed, 34 insertions(+), 2 deletions(-) >>>> >>>> diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c >>>> index a1cb21f..af3b6c3 100644 >>>> --- a/drivers/mmc/card/block.c >>>> +++ b/drivers/mmc/card/block.c >>>> @@ -995,6 +995,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 >>>> @@ -1071,6 +1072,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, >>>> @@ -1091,10 +1102,12 @@ static void mmc_blk_rw_rq_prep(struct mmc_queue_req *mqrq, >>>> >>>> if ((md->flags & MMC_BLK_CMD23) && >>>> mmc_op_multi(brq->cmd.opcode) && >>>> - (do_rel_wr || !(card->quirks & MMC_QUIRK_BLK_NO_CMD23))) { >>>> + (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; >>>> } >>>> diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c >>>> index dbf421a..244049b 100644 >>>> --- a/drivers/mmc/core/mmc.c >>>> +++ b/drivers/mmc/core/mmc.c >>>> @@ -488,6 +488,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: >>>> diff --git a/include/linux/mmc/card.h b/include/linux/mmc/card.h >>>> index 415f2db..a55668d 100644 >>>> --- a/include/linux/mmc/card.h >>>> +++ b/include/linux/mmc/card.h >>>> @@ -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; /* 512Bytes or 4KB */ >>>> + unsigned int data_tag_unit_size; /* DATA TAG UNIT size */ >>>> u8 raw_partition_support; /* 160 */ >>>> u8 raw_erased_mem_count; /* 181 */ >>>> u8 raw_ext_csd_structure; /* 194 */ >>>> diff --git a/include/linux/mmc/mmc.h b/include/linux/mmc/mmc.h >>>> index 0e71356..e076f7f 100644 >>>> --- a/include/linux/mmc/mmc.h >>>> +++ b/include/linux/mmc/mmc.h >>>> @@ -273,6 +273,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 */ >>>> @@ -313,6 +314,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 */ >>>> >>>> /* >>> >>> TAG_RES_SIZE in the extended csd register mentions about the resource >>> size utilised by the device to keep data tag. >>> This can be used to avoid the data exhaustion case. >>> >> >> Once the tag resource is exhausted, the further tag data writes will >> be ignored by eMMC and those will be written to the non-tagged or >> default area of eMMC (ref to section 6.6.25 in 4.5 spec : "The data >> shall still be written to the device regardless of the resources >> exhaustion; however, it may not have the improved characteristics"). >> So, host driver need not do additional tracking of the amount of data >> written using tag option. > It also says > The host should manage the tag operation counting in order to avoid > resources exhaustion. If it happens > the host should executes operations having the final effect of freeing > some of the resources (for instance > by issuing a Trim command on some of the addresses containing System Data). > Trim will happen when some blocks are unmapped by file system and it will take care of the tagged region as well. We do not need to modify anything for this. Assume, host does the tracking of tagged writes. When it crosses TAG_RES_SIZE or when the SYSPOOL_EXHAUSTED event is received, it stops using tagged write and use default area instead for writing. This same objective is achieved by just letting eMMC to do the tracking of the tagged area usage which is simpler from host driver perspective. The specification does not say that using tagged flag when the tagged resource is exhausted is disallowed. >> >> >>>> -- >>>> 1.7.4.3 >>>> >>>> -- >>>> To unsubscribe from this list: send the line "unsubscribe linux-mmc" in >>>> the body of a message to majordomo@xxxxxxxxxxxxxxx >>>> More majordomo info at http://vger.kernel.org/majordomo-info.html >>> -- >>> To unsubscribe from this list: send the line "unsubscribe linux-mmc" in >>> the body of a message to majordomo@xxxxxxxxxxxxxxx >>> More majordomo info at http://vger.kernel.org/majordomo-info.html -- To unsubscribe from this list: send the line "unsubscribe linux-mmc" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html