[U-Boot] [PATCH] mmc:dcache: Cache line size aligned internal MMC buffers

Lukasz Majewski l.majewski at samsung.com
Fri Aug 19 11:25:13 CEST 2011


MMC operations are performed on cache line size aligned buffers.
In the current MMC implementation it is allowed to pass buffer 
with arbitrary alignment.
In this patch assumption has been made, that it is better to align the buffer
on the MMC framework boundary, than in a number of u-boot subsystems, which are
using MMC.

Signed-off-by: Lukasz Majewski <l.majewski at samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park at samsung.com>
CC: Andy Fleming <afleming at gmail.com>
CC: Albert ARIBAUD <albert.u.boot at aribaud.net>
---
 drivers/mmc/mmc.c |   30 +++++++++++++++++++++++++++---
 1 files changed, 27 insertions(+), 3 deletions(-)

diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c
index 5f79a17..47e94c8 100644
--- a/drivers/mmc/mmc.c
+++ b/drivers/mmc/mmc.c
@@ -263,6 +263,7 @@ mmc_write_blocks(struct mmc *mmc, ulong start, lbaint_t blkcnt, const void*src)
 	struct mmc_cmd cmd;
 	struct mmc_data data;
 	int timeout = 1000;
+	void *cache_align_buf;
 
 	if ((start + blkcnt) > mmc->block_dev.lba) {
 		printf("MMC: block number 0x%lx exceeds max(0x%lx)\n",
@@ -283,13 +284,22 @@ mmc_write_blocks(struct mmc *mmc, ulong start, lbaint_t blkcnt, const void*src)
 	cmd.resp_type = MMC_RSP_R1;
 	cmd.flags = 0;
 
-	data.src = src;
+	cache_align_buf = memalign(get_dcache_line_size(),
+				   mmc->write_bl_len * blkcnt);
+
+	if (!cache_align_buf)
+		return -ENOMEM;
+
+	memcpy(cache_align_buf, src, mmc->write_bl_len * blkcnt);
+
+	data.src = cache_align_buf;
 	data.blocks = blkcnt;
 	data.blocksize = mmc->write_bl_len;
 	data.flags = MMC_DATA_WRITE;
 
 	if (mmc_send_cmd(mmc, &cmd, &data)) {
 		printf("mmc write failed\n");
+		free(cache_align_buf);
 		return 0;
 	}
 
@@ -303,6 +313,7 @@ mmc_write_blocks(struct mmc *mmc, ulong start, lbaint_t blkcnt, const void*src)
 		cmd.flags = 0;
 		if (mmc_send_cmd(mmc, &cmd, NULL)) {
 			printf("mmc fail to send stop cmd\n");
+			free(cache_align_buf);
 			return 0;
 		}
 
@@ -310,6 +321,7 @@ mmc_write_blocks(struct mmc *mmc, ulong start, lbaint_t blkcnt, const void*src)
 		mmc_send_status(mmc, timeout);
 	}
 
+	free(cache_align_buf);
 	return blkcnt;
 }
 
@@ -342,6 +354,7 @@ int mmc_read_blocks(struct mmc *mmc, void *dst, ulong start, lbaint_t blkcnt)
 	struct mmc_cmd cmd;
 	struct mmc_data data;
 	int timeout = 1000;
+	void *cache_align_buf;
 
 	if (blkcnt > 1)
 		cmd.cmdidx = MMC_CMD_READ_MULTIPLE_BLOCK;
@@ -356,13 +369,21 @@ int mmc_read_blocks(struct mmc *mmc, void *dst, ulong start, lbaint_t blkcnt)
 	cmd.resp_type = MMC_RSP_R1;
 	cmd.flags = 0;
 
-	data.dest = dst;
+	cache_align_buf = memalign(get_dcache_line_size(),
+				   mmc->read_bl_len * blkcnt);
+
+	if (!cache_align_buf)
+		return -ENOMEM;
+
+	data.dest = cache_align_buf;
 	data.blocks = blkcnt;
 	data.blocksize = mmc->read_bl_len;
 	data.flags = MMC_DATA_READ;
 
-	if (mmc_send_cmd(mmc, &cmd, &data))
+	if (mmc_send_cmd(mmc, &cmd, &data)) {
+		free(cache_align_buf);
 		return 0;
+	}
 
 	if (blkcnt > 1) {
 		cmd.cmdidx = MMC_CMD_STOP_TRANSMISSION;
@@ -371,6 +392,7 @@ int mmc_read_blocks(struct mmc *mmc, void *dst, ulong start, lbaint_t blkcnt)
 		cmd.flags = 0;
 		if (mmc_send_cmd(mmc, &cmd, NULL)) {
 			printf("mmc fail to send stop cmd\n");
+			free(cache_align_buf);
 			return 0;
 		}
 
@@ -378,6 +400,8 @@ int mmc_read_blocks(struct mmc *mmc, void *dst, ulong start, lbaint_t blkcnt)
 		mmc_send_status(mmc, timeout);
 	}
 
+	memcpy(dst, cache_align_buf, mmc->read_bl_len * blkcnt);
+	free(cache_align_buf);
 	return blkcnt;
 }
 
-- 
1.7.2.3



More information about the U-Boot mailing list