diff options
author | Andrew Ryabinin <ryabinin.a.a@gmail.com> | 2014-11-29 17:06:35 +0300 |
---|---|---|
committer | Andrew Ryabinin <ryabinin.a.a@gmail.com> | 2014-11-29 21:00:11 +0300 |
commit | 8618f2c227e7daed2d1dd566090c2c4588533470 (patch) | |
tree | 2225821258966d4076c00b1ee8afc9523f8c0d3e /firmware/target | |
parent | d1fcfe950a70ddbdd97164832cdb83ef2cc7f23a (diff) | |
download | rockbox-8618f2c227e7daed2d1dd566090c2c4588533470.tar.gz rockbox-8618f2c227e7daed2d1dd566090c2c4588533470.zip |
rk27xx: sd: properly align buffer used for DMA transfers.
Commit 7d1a47cf ("Rewrite filesystem code (WIP)") exposed
bug in rk27xx sd driver. Buffer passed to sd_read/write_sectors()
doesn't has to be cacheline aligned. DMA transfers on
unaligned buffers is quiet dangerous thing.
Make sure that the buffer is aligned to cacheline size,
If not use a temporary aligned buffer for DMA transfer.
Change-Id: I91420f2b8d58159c80c3f15f4b35e88ea0dfd14c
Diffstat (limited to 'firmware/target')
-rw-r--r-- | firmware/target/arm/rk27xx/sd-rk27xx.c | 27 | ||||
-rw-r--r-- | firmware/target/arm/rk27xx/system-target.h | 2 |
2 files changed, 25 insertions, 4 deletions
diff --git a/firmware/target/arm/rk27xx/sd-rk27xx.c b/firmware/target/arm/rk27xx/sd-rk27xx.c index 9d6821ee38..6eeff7bae5 100644 --- a/firmware/target/arm/rk27xx/sd-rk27xx.c +++ b/firmware/target/arm/rk27xx/sd-rk27xx.c | |||
@@ -58,6 +58,8 @@ static tCardInfo card_info; | |||
58 | static long last_disk_activity = -1; | 58 | static long last_disk_activity = -1; |
59 | 59 | ||
60 | static long sd_stack [(DEFAULT_STACK_SIZE*2 + 0x200)/sizeof(long)]; | 60 | static long sd_stack [(DEFAULT_STACK_SIZE*2 + 0x200)/sizeof(long)]; |
61 | static unsigned char aligned_buf[512] STORAGE_ALIGN_ATTR; | ||
62 | |||
61 | static const char sd_thread_name[] = "ata/sd"; | 63 | static const char sd_thread_name[] = "ata/sd"; |
62 | static struct mutex sd_mtx SHAREDBSS_ATTR; | 64 | static struct mutex sd_mtx SHAREDBSS_ATTR; |
63 | static struct event_queue sd_queue; | 65 | static struct event_queue sd_queue; |
@@ -460,9 +462,15 @@ int sd_init(void) | |||
460 | 462 | ||
461 | static inline void read_sd_data(unsigned char **dst) | 463 | static inline void read_sd_data(unsigned char **dst) |
462 | { | 464 | { |
463 | commit_discard_dcache_range((const void *)*dst, 512); | 465 | void *buf = *dst; |
466 | |||
467 | if (!IS_ALIGNED(((unsigned long)*dst), CACHEALIGN_SIZE)) | ||
468 | buf = aligned_buf; | ||
469 | |||
470 | commit_discard_dcache_range((const void *)buf, 512); | ||
464 | 471 | ||
465 | A2A_IDST0 = (unsigned long)*dst; | 472 | |
473 | A2A_IDST0 = (unsigned long)buf; | ||
466 | A2A_CON0 = (3<<9) | /* burst 16 */ | 474 | A2A_CON0 = (3<<9) | /* burst 16 */ |
467 | (1<<6) | /* fixed src */ | 475 | (1<<6) | /* fixed src */ |
468 | (1<<3) | /* DMA start */ | 476 | (1<<3) | /* DMA start */ |
@@ -472,14 +480,25 @@ static inline void read_sd_data(unsigned char **dst) | |||
472 | /* wait for DMA engine to finish transfer */ | 480 | /* wait for DMA engine to finish transfer */ |
473 | while (A2A_DMA_STS & 1); | 481 | while (A2A_DMA_STS & 1); |
474 | 482 | ||
483 | if (buf == aligned_buf) | ||
484 | memcpy(*dst, aligned_buf, 512); | ||
485 | |||
475 | *dst += 512; | 486 | *dst += 512; |
476 | } | 487 | } |
477 | 488 | ||
478 | static inline void write_sd_data(unsigned char **src) | 489 | static inline void write_sd_data(unsigned char **src) |
479 | { | 490 | { |
480 | commit_discard_dcache_range((const void *)*src, 512); | 491 | void *buf = *src; |
492 | |||
493 | if (!IS_ALIGNED(((unsigned long)*src), CACHEALIGN_SIZE)) | ||
494 | { | ||
495 | buf = aligned_buf; | ||
496 | memcpy(aligned_buf, *src, 512); | ||
497 | } | ||
498 | |||
499 | commit_discard_dcache_range((const void *)buf, 512); | ||
481 | 500 | ||
482 | A2A_ISRC1 = (unsigned long)*src; | 501 | A2A_ISRC1 = (unsigned long)buf; |
483 | A2A_CON1 = (3<<9) | /* burst 16 */ | 502 | A2A_CON1 = (3<<9) | /* burst 16 */ |
484 | (1<<5) | /* fixed dst */ | 503 | (1<<5) | /* fixed dst */ |
485 | (1<<3) | /* DMA start */ | 504 | (1<<3) | /* DMA start */ |
diff --git a/firmware/target/arm/rk27xx/system-target.h b/firmware/target/arm/rk27xx/system-target.h index 8a705dd77a..a5b27cc6b2 100644 --- a/firmware/target/arm/rk27xx/system-target.h +++ b/firmware/target/arm/rk27xx/system-target.h | |||
@@ -52,4 +52,6 @@ void commit_discard_idcache(void); | |||
52 | #define CPUFREQ_NORMAL 50000000 | 52 | #define CPUFREQ_NORMAL 50000000 |
53 | #define CPUFREQ_MAX 200000000 | 53 | #define CPUFREQ_MAX 200000000 |
54 | 54 | ||
55 | #define STORAGE_WANTS_ALIGN | ||
56 | |||
55 | #endif /* SYSTEM_TARGET_H */ | 57 | #endif /* SYSTEM_TARGET_H */ |