Skip to contentSkip to conversation

SD/MMC: multiple block read support

RFC PATCH New Kumar Gala 2 participants 2 messages Apr 7, 2010 – Apr 24, 2010 MMC, SD and SDIO

lore
Share & tools
lore

Kumar Gala

author
#0 lore raw

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
index cf4ea16..bb8b993 100644
@@ -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
#1 lore raw

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.

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