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

Lukasz Majewski
2011-08-19T09:25:13Z

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@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
CC: Andy Fleming <afleming@gmail.com>
CC: Albert ARIBAUD <albert.u.boot@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