Re: [PATCH RESEND v7 3/3] mmc: core: Support packed read command foreMMC4.5 device

From: Namjae Jeon
Date: Mon Jun 18 2012 - 10:22:52 EST


2012/6/18 <merez@xxxxxxxxxxxxxx>:
> I would prefer that you didn't submit this.
> Let's wait with packed read until it is proven to be beneficial.
Hi. Merez.
I have reported packed read speed issue was because of firmware of mmc
card before.
And host can select packed read and write cmd by each performance.
mmc vendors willl be considering to improve packed read cmd.

Reviewed-by: Namjae Jeon <linkinjeon@xxxxxxxxx>

Thanks.
>
> Thanks,
> Maya
> On Sun, June 17, 2012 10:46 pm, Seungwon Jeon wrote:
>> Add the packed read command for issuing data. Unlike the
>> packed write, command header is handled separately.
>>
>> Signed-off-by: Seungwon Jeon <tgih.jun@xxxxxxxxxxx>
>> ---
>> Âdrivers/mmc/card/block.c | Â134
>> +++++++++++++++++++++++++++++++++++++++++++---
>> Âdrivers/mmc/card/queue.c | Â Â6 ++-
>> Âdrivers/mmc/card/queue.h | Â Â2 +
>> Â3 files changed, 133 insertions(+), 9 deletions(-)
>>
>> diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c
>> index eb99e35..25f42e8 100644
>> --- a/drivers/mmc/card/block.c
>> +++ b/drivers/mmc/card/block.c
>> @@ -62,6 +62,7 @@ MODULE_ALIAS("mmc:block");
>> Â Â Â Â Â Â Â Â Â Â Â (req->cmd_flags & REQ_META)) && \
>> Â Â Â Â Â Â Â Â Â Â Â (rq_data_dir(req) == WRITE))
>> Â#define PACKED_CMD_VER Â Â Â Â Â Â Â 0x01
>> +#define PACKED_CMD_RD Â Â Â Â Â Â Â Â0x01
>> Â#define PACKED_CMD_WR Â Â Â Â Â Â Â Â0x02
>>
>> Âstatic DEFINE_MUTEX(block_mutex);
>> @@ -104,6 +105,7 @@ struct mmc_blk_data {
>> Â#define MMC_BLK_WRITE Â Â Â Â Â Â Â ÂBIT(1)
>> Â#define MMC_BLK_DISCARD Â Â Â Â Â Â ÂBIT(2)
>> Â#define MMC_BLK_SECDISCARD Â BIT(3)
>> +#define MMC_BLK_WR_HDR Â Â Â Â Â Â Â BIT(4)
>>
>> Â Â Â /*
>> Â Â Â Â* Only set in main mmc_blk_data associated
>> @@ -1062,7 +1064,8 @@ static int mmc_blk_err_check(struct mmc_card *card,
>> Â Â Â Â* kind. ÂIf it was a write, we may have transitioned to
>> Â Â Â Â* program mode, which we have to wait for it to complete.
>> Â Â Â Â*/
>> - Â Â if (!mmc_host_is_spi(card->host) && rq_data_dir(req) != READ) {
>> + Â Â if ((!mmc_host_is_spi(card->host) && rq_data_dir(req) != READ) ||
>> + Â Â Â Â Â Â Â Â Â Â (mq_mrq->packed_cmd == MMC_PACKED_WR_HDR)) {
>> Â Â Â Â Â Â Â u32 status;
>> Â Â Â Â Â Â Â do {
>> Â Â Â Â Â Â Â Â Â Â Â int err = get_card_status(card, &status, 5);
>> @@ -1087,7 +1090,8 @@ static int mmc_blk_err_check(struct mmc_card *card,
>> Â Â Â Â Â Â Â Â Â Â Â(unsigned)blk_rq_sectors(req),
>> Â Â Â Â Â Â Â Â Â Â Âbrq->cmd.resp[0], brq->stop.resp[0]);
>>
>> - Â Â Â Â Â Â if (rq_data_dir(req) == READ) {
>> + Â Â Â Â Â Â if (rq_data_dir(req) == READ &&
>> + Â Â Â Â Â Â Â Â Â Â Â Â Â Â mq_mrq->packed_cmd != MMC_PACKED_WR_HDR) {
>> Â Â Â Â Â Â Â Â Â Â Â if (ecc_err)
>> Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â return MMC_BLK_ECC_ERR;
>> Â Â Â Â Â Â Â Â Â Â Â return MMC_BLK_DATA_ERR;
>> @@ -1330,6 +1334,9 @@ static u8 mmc_blk_prep_packed_list(struct mmc_queue
>> *mq, struct request *req)
>> Â Â Â if ((rq_data_dir(cur) == WRITE) &&
>> Â Â Â Â Â Â Â Â Â Â Â (card->host->caps2 & MMC_CAP2_PACKED_WR))
>> Â Â Â Â Â Â Â max_packed_rw = card->ext_csd.max_packed_writes;
>> + Â Â else if ((rq_data_dir(cur) == READ) &&
>> + Â Â Â Â Â Â Â Â Â Â (card->host->caps2 & MMC_CAP2_PACKED_RD))
>> + Â Â Â Â Â Â max_packed_rw = card->ext_csd.max_packed_reads;
>>
>> Â Â Â if (max_packed_rw == 0)
>> Â Â Â Â Â Â Â goto no_packed;
>> @@ -1426,13 +1433,16 @@ static void mmc_blk_packed_hdr_wrq_prep(struct
>> mmc_queue_req *mqrq,
>> Â Â Â u32 *packed_cmd_hdr = mqrq->packed_cmd_hdr;
>> Â Â Â u8 i = 1;
>>
>> - Â Â mqrq->packed_cmd = MMC_PACKED_WRITE;
>> + Â Â mqrq->packed_cmd = (rq_data_dir(req) == READ) ?
>> + Â Â Â Â Â Â MMC_PACKED_WR_HDR : MMC_PACKED_WRITE;
>> Â Â Â mqrq->packed_blocks = 0;
>> Â Â Â mqrq->packed_fail_idx = MMC_PACKED_N_IDX;
>>
>> Â Â Â memset(packed_cmd_hdr, 0, sizeof(mqrq->packed_cmd_hdr));
>> Â Â Â packed_cmd_hdr[0] = (mqrq->packed_num << 16) |
>> - Â Â Â Â Â Â (PACKED_CMD_WR << 8) | PACKED_CMD_VER;
>> + Â Â Â Â Â Â (((rq_data_dir(req) == READ) ?
>> + Â Â Â Â Â Â Â PACKED_CMD_RD : PACKED_CMD_WR) << 8) |
>> + Â Â Â Â Â Â PACKED_CMD_VER;
>>
>> Â Â Â /*
>> Â Â Â Â* Argument for each entry of packed group
>> @@ -1464,7 +1474,8 @@ static void mmc_blk_packed_hdr_wrq_prep(struct
>> mmc_queue_req *mqrq,
>> Â Â Â brq->mrq.stop = &brq->stop;
>>
>> Â Â Â brq->sbc.opcode = MMC_SET_BLOCK_COUNT;
>> - Â Â brq->sbc.arg = MMC_CMD23_ARG_PACKED | (mqrq->packed_blocks + 1);
>> + Â Â brq->sbc.arg = MMC_CMD23_ARG_PACKED |
>> + Â Â Â Â Â Â ((rq_data_dir(req) == READ) ? 1 : mqrq->packed_blocks + 1);
>> Â Â Â brq->sbc.flags = MMC_RSP_R1 | MMC_CMD_AC;
>>
>> Â Â Â brq->cmd.opcode = MMC_WRITE_MULTIPLE_BLOCK;
>> @@ -1474,7 +1485,12 @@ static void mmc_blk_packed_hdr_wrq_prep(struct
>> mmc_queue_req *mqrq,
>> Â Â Â brq->cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_ADTC;
>>
>> Â Â Â brq->data.blksz = 512;
>> - Â Â brq->data.blocks = mqrq->packed_blocks + 1;
>> + Â Â /*
>> + Â Â Â* Write separately the packd command header only for packed read.
>> + Â Â Â* In case of packed write, header is sent with blocks of data.
>> + Â Â Â*/
>> + Â Â brq->data.blocks = (rq_data_dir(req) == READ) ?
>> + Â Â Â Â Â Â 1 : mqrq->packed_blocks + 1;
>> Â Â Â brq->data.flags |= MMC_DATA_WRITE;
>>
>> Â Â Â brq->stop.opcode = MMC_STOP_TRANSMISSION;
>> @@ -1487,6 +1503,45 @@ static void mmc_blk_packed_hdr_wrq_prep(struct
>> mmc_queue_req *mqrq,
>> Â Â Â brq->data.sg_len = mmc_queue_map_sg(mq, mqrq);
>>
>> Â Â Â mqrq->mmc_active.mrq = &brq->mrq;
>> + Â Â mqrq->mmc_active.err_check = (rq_data_dir(req) == READ) ?
>> + Â Â Â Â Â Â mmc_blk_err_check : mmc_blk_packed_err_check;
>> +
>> + Â Â mmc_queue_bounce_pre(mqrq);
>> +}
>> +
>> +static void mmc_blk_packed_rrq_prep(struct mmc_queue_req *mqrq,
>> + Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â struct mmc_card *card,
>> + Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â struct mmc_queue *mq)
>> +{
>> + Â Â struct mmc_blk_request *brq = &mqrq->brq;
>> + Â Â struct request *req = mqrq->req;
>> +
>> + Â Â mqrq->packed_cmd = MMC_PACKED_READ;
>> +
>> + Â Â memset(brq, 0, sizeof(struct mmc_blk_request));
>> + Â Â brq->mrq.cmd = &brq->cmd;
>> + Â Â brq->mrq.data = &brq->data;
>> + Â Â brq->mrq.stop = &brq->stop;
>> +
>> + Â Â brq->cmd.opcode = MMC_READ_MULTIPLE_BLOCK;
>> + Â Â brq->cmd.arg = blk_rq_pos(req);
>> + Â Â if (!mmc_card_blockaddr(card))
>> + Â Â Â Â Â Â brq->cmd.arg <<= 9;
>> + Â Â brq->cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_ADTC;
>> + Â Â brq->data.blksz = 512;
>> + Â Â brq->data.blocks = mqrq->packed_blocks;
>> + Â Â brq->data.flags |= MMC_DATA_READ;
>> +
>> + Â Â brq->stop.opcode = MMC_STOP_TRANSMISSION;
>> + Â Â brq->stop.arg = 0;
>> + Â Â brq->stop.flags = MMC_RSP_SPI_R1B | MMC_RSP_R1B | MMC_CMD_AC;
>> +
>> + Â Â mmc_set_data_timeout(&brq->data, card);
>> +
>> + Â Â brq->data.sg = mqrq->sg;
>> + Â Â brq->data.sg_len = mmc_queue_map_sg(mq, mqrq);
>> +
>> + Â Â mqrq->mmc_active.mrq = &brq->mrq;
>> Â Â Â mqrq->mmc_active.err_check = mmc_blk_packed_err_check;
>>
>> Â Â Â mmc_queue_bounce_pre(mqrq);
>> @@ -1521,6 +1576,56 @@ static int mmc_blk_cmd_err(struct mmc_blk_data *md,
>> struct mmc_card *card,
>> Â Â Â return ret;
>> Â}
>>
>> +static int mmc_blk_chk_hdr_err(struct mmc_queue *mq, int status)
>> +{
>> + Â Â struct mmc_blk_data *md = mq->data;
>> + Â Â struct mmc_card *card = md->queue.card;
>> + Â Â int type = MMC_BLK_WR_HDR, err = 0;
>> +
>> + Â Â switch (status) {
>> + Â Â case MMC_BLK_PARTIAL:
>> + Â Â case MMC_BLK_RETRY:
>> + Â Â Â Â Â Â err = 0;
>> + Â Â Â Â Â Â break;
>> + Â Â case MMC_BLK_CMD_ERR:
>> + Â Â case MMC_BLK_ABORT:
>> + Â Â case MMC_BLK_DATA_ERR:
>> + Â Â case MMC_BLK_ECC_ERR:
>> + Â Â Â Â Â Â err = mmc_blk_reset(md, card->host, type);
>> + Â Â Â Â Â Â if (!err)
>> + Â Â Â Â Â Â Â Â Â Â mmc_blk_reset_success(md, type);
>> + Â Â Â Â Â Â break;
>> + Â Â }
>> +
>> + Â Â return err;
>> +}
>> +
>> +static int mmc_blk_issue_packed_rd(struct mmc_queue *mq,
>> + Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Âstruct mmc_queue_req *mq_rq)
>> +{
>> + Â Â struct mmc_blk_data *md = mq->data;
>> + Â Â struct mmc_card *card = md->queue.card;
>> + Â Â int status, ret, retry = 2;
>> +
>> + Â Â do {
>> + Â Â Â Â Â Â mmc_start_req(card->host, NULL, (int *) &status);
>> + Â Â Â Â Â Â if (status) {
>> + Â Â Â Â Â Â Â Â Â Â ret = mmc_blk_chk_hdr_err(mq, status);
>> + Â Â Â Â Â Â Â Â Â Â if (ret)
>> + Â Â Â Â Â Â Â Â Â Â Â Â Â Â break;
>> + Â Â Â Â Â Â Â Â Â Â mmc_blk_packed_hdr_wrq_prep(mq_rq, card, mq);
>> + Â Â Â Â Â Â Â Â Â Â mmc_start_req(card->host, &mq_rq->mmc_active, NULL);
>> + Â Â Â Â Â Â } else {
>> + Â Â Â Â Â Â Â Â Â Â mmc_blk_packed_rrq_prep(mq_rq, card, mq);
>> + Â Â Â Â Â Â Â Â Â Â mmc_start_req(card->host, &mq_rq->mmc_active, NULL);
>> + Â Â Â Â Â Â Â Â Â Â ret = 0;
>> + Â Â Â Â Â Â Â Â Â Â break;
>> + Â Â Â Â Â Â }
>> + Â Â } while (retry-- > 0);
>> +
>> + Â Â return ret;
>> +}
>> +
>> Âstatic int mmc_blk_end_packed_req(struct mmc_queue_req *mq_rq)
>> Â{
>> Â Â Â struct request *prq;
>> @@ -1626,8 +1731,12 @@ static int mmc_blk_issue_rw_rq(struct mmc_queue
>> *mq, struct request *rqc)
>> Â Â Â Â Â Â Â } else
>> Â Â Â Â Â Â Â Â Â Â Â areq = NULL;
>> Â Â Â Â Â Â Â areq = mmc_start_req(card->host, areq, (int *) &status);
>> - Â Â Â Â Â Â if (!areq)
>> - Â Â Â Â Â Â Â Â Â Â return 0;
>> + Â Â Â Â Â Â if (!areq) {
>> + Â Â Â Â Â Â Â Â Â Â if (mq->mqrq_cur->packed_cmd == MMC_PACKED_WR_HDR)
>> + Â Â Â Â Â Â Â Â Â Â Â Â Â Â goto snd_packed_rd;
>> + Â Â Â Â Â Â Â Â Â Â else
>> + Â Â Â Â Â Â Â Â Â Â Â Â Â Â return 0;
>> + Â Â Â Â Â Â }
>>
>> Â Â Â Â Â Â Â mq_rq = container_of(areq, struct mmc_queue_req, mmc_active);
>> Â Â Â Â Â Â Â brq = &mq_rq->brq;
>> @@ -1726,10 +1835,19 @@ static int mmc_blk_issue_rw_rq(struct mmc_queue
>> *mq, struct request *rqc)
>> Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â mmc_blk_packed_hdr_wrq_prep(mq_rq, card, mq);
>> Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â mmc_start_req(card->host,
>> Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â &mq_rq->mmc_active, NULL);
>> + Â Â Â Â Â Â Â Â Â Â Â Â Â Â if (mq_rq->packed_cmd == MMC_PACKED_WR_HDR) {
>> + Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â if (mmc_blk_issue_packed_rd(mq, mq_rq))
>> + Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â goto cmd_abort;
>> + Â Â Â Â Â Â Â Â Â Â Â Â Â Â }
>> Â Â Â Â Â Â Â Â Â Â Â }
>> Â Â Â Â Â Â Â }
>> Â Â Â } while (ret);
>>
>> +snd_packed_rd:
>> + Â Â if (mq->mqrq_cur->packed_cmd == MMC_PACKED_WR_HDR) {
>> + Â Â Â Â Â Â if (mmc_blk_issue_packed_rd(mq, mq->mqrq_cur))
>> + Â Â Â Â Â Â Â Â Â Â goto start_new_req;
>> + Â Â }
>> Â Â Â return 1;
>>
>> Â cmd_abort:
>> diff --git a/drivers/mmc/card/queue.c b/drivers/mmc/card/queue.c
>> index 165d85a..277905e 100644
>> --- a/drivers/mmc/card/queue.c
>> +++ b/drivers/mmc/card/queue.c
>> @@ -389,11 +389,15 @@ static unsigned int mmc_queue_packed_map_sg(struct
>> mmc_queue *mq,
>>
>> Â Â Â cmd = mqrq->packed_cmd;
>>
>> - Â Â if (cmd == MMC_PACKED_WRITE) {
>> + Â Â if (cmd == MMC_PACKED_WR_HDR || cmd == MMC_PACKED_WRITE) {
>> Â Â Â Â Â Â Â __sg = sg;
>> Â Â Â Â Â Â Â sg_set_buf(__sg, mqrq->packed_cmd_hdr,
>> Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â sizeof(mqrq->packed_cmd_hdr));
>> Â Â Â Â Â Â Â sg_len++;
>> + Â Â Â Â Â Â if (cmd == MMC_PACKED_WR_HDR) {
>> + Â Â Â Â Â Â Â Â Â Â sg_mark_end(__sg);
>> + Â Â Â Â Â Â Â Â Â Â return sg_len;
>> + Â Â Â Â Â Â }
>> Â Â Â Â Â Â Â __sg->page_link &= ~0x02;
>> Â Â Â }
>>
>> diff --git a/drivers/mmc/card/queue.h b/drivers/mmc/card/queue.h
>> index 5e04938..a8cad1f 100644
>> --- a/drivers/mmc/card/queue.h
>> +++ b/drivers/mmc/card/queue.h
>> @@ -14,7 +14,9 @@ struct mmc_blk_request {
>>
>> Âenum mmc_packed_cmd {
>> Â Â Â MMC_PACKED_NONE = 0,
>> + Â Â MMC_PACKED_WR_HDR,
>> Â Â Â MMC_PACKED_WRITE,
>> + Â Â MMC_PACKED_READ,
>> Â};
>>
>> Âstruct mmc_queue_req {
>> --
>> 1.7.0.4
>>
>>
>>
>
>
> --
> Sent by consultant of Qualcomm Innovation Center, Inc.
> Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum
>
> --
> 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-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/