SD/MMC: multiple block read support
RFC PATCH 1/1 SD/MMC: multiple block read support
From: Jerry Huang <[email protected]>
Multiple block read support to improve performance (time it takes) to read larger amounts of data.
--- drivers/mmc/mmc.c | 71 +++++++++++++++++++++++++--------------------------- 1 files changed, 34 insertions(+), 37 deletions(-)
drivers/mmc/mmc.c +34 -37
@@ -1,5 +1,5 @@/* -* Copyright 2008, Freescale Semiconductor, Inc +* Copyright 2008-2010, Freescale Semiconductor, Inc * Andy Fleming * * Based vaguely on the Linux code
@@ -135,33 +135,51 @@ mmc_bwrite(int dev_num, ulong start, lbaint_t blkcnt, const void*src)return blkcnt; } -int mmc_read_block (struct mmc *mmc,void *dst,uint blocknum) +int mmc_read_block (struct mmc *mmc,void *dst,uint start,int blkcnt) {struct mmc_cmd cmd;struct mmc_data data; +int err, stoperr =0 ; - cmd.cmdidx =MMC_CMD_READ_SINGLE_BLOCK ; +if (blkcnt >1 ) + cmd.cmdidx =MMC_CMD_READ_MULTIPLE_BLOCK ; +else + cmd.cmdidx =MMC_CMD_READ_SINGLE_BLOCK ;if (mmc->high_capacity) - cmd.cmdarg = blocknum; + cmd.cmdarg = start;else - cmd.cmdarg = blocknum * mmc->read_bl_len; + cmd.cmdarg = start * mmc->read_bl_len; cmd.resp_type =MMC_RSP_R1 ; cmd.flags =0 ; data.dest = dst; - data.blocks =1 ; + data.blocks = blkcnt; data.blocksize = mmc->read_bl_len; data.flags =MMC_DATA_READ ; -return mmc_send_cmd (mmc, &cmd, &data); + err =mmc_send_cmd (mmc, &cmd, &data); + +if (blkcnt >1 ) { + cmd.cmdidx =MMC_CMD_STOP_TRANSMISSION ; + cmd.cmdarg =0 ; + cmd.resp_type = MMC_RSP_R1b; + cmd.flags =0 ; + stoperr =mmc_send_cmd (mmc, &cmd,NULL ); + } + +if (err) { +printf ("the read data have err %d\n" , err); +return err; + } + +return stoperr; }int mmc_read (struct mmc *mmc,u64 src,uchar *dst,int size) {char *buffer; -int i;int blklen = mmc->read_bl_len;int startblock =lldiv (src, mmc->read_bl_len);int endblock =lldiv (src + size -1 , mmc->read_bl_len);
@@ -181,28 +199,10 @@ int mmc_read(struct mmc *mmc, u64 src, uchar *dst, int size)if (err) goto free_buffer; -for (i = startblock; i <= endblock; i++) { -int segment_size; -int offset; - - err =mmc_read_block (mmc, buffer, i); - -if (err) - goto free_buffer; - -/* -* The first block may not be aligned, so we -* copy from the desired point in the block -*/ - offset = (src & (blklen -1 )); - segment_size =MIN (blklen - offset, size); - -memcpy (dst, buffer + offset, segment_size); - - dst += segment_size; - src += segment_size; - size -= segment_size; - } + err =mmc_read_block (mmc, buffer, startblock, endblock - startblock +1 ); +if (err) + goto free_buffer; +memcpy (dst, buffer, size); free_buffer:free (buffer);
@@ -213,7 +213,6 @@ free_buffer:static ulong mmc_bread (int dev_num,ulong start,lbaint_t blkcnt,void *dst) {int err; -int i;struct mmc *mmc =find_mmc_device (dev_num);if (!mmc)
@@ -226,13 +225,11 @@ static ulong mmc_bread(int dev_num, ulong start, lbaint_t blkcnt, void *dst)return 0 ; } -for (i = start; i < start + blkcnt; i++, dst += mmc->read_bl_len) { - err =mmc_read_block (mmc, dst, i); + err =mmc_read_block (mmc, dst, start, blkcnt); -if (err) { -printf ("block read failed: %d\n" , err); -return i - start; - } +if (err) { +printf ("block read failed: %d\n" , err); +return -start; }return blkcnt;
Signature · 1 line
1.6.0.6
RFC PATCH 1/1 SD/MMC: multiple block read support
Quoted 7 lines · Kumar Gala
From: Jerry Huang <[email protected]>
Multiple block read support to improve performance (time it takes) to read larger amounts of data.
Signed-off-by Jerry Huang <[email protected]>Signed-off-by Roy Zang <[email protected]>
How well has this been tested? I recall that there was some reason I did this, like the DMA wouldn't work to unaligned addresses. Or would show up in the middle of the buffer if you read from an unaligned address.
So has this been tested by trying to read a partial block? By trying to read multiple blocks that start and/or end at non-block-aligned addresses? I can't test this tonight, but will this weekend. I hope this didn't break it. :)
Andy