
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; }