mirror of
https://github.com/Rockbox/rockbox.git
synced 2025-11-09 21:22:39 -05:00
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
This commit is contained in:
parent
d1fcfe950a
commit
8618f2c227
2 changed files with 25 additions and 4 deletions
|
|
@ -58,6 +58,8 @@ static tCardInfo card_info;
|
||||||
static long last_disk_activity = -1;
|
static long last_disk_activity = -1;
|
||||||
|
|
||||||
static long sd_stack [(DEFAULT_STACK_SIZE*2 + 0x200)/sizeof(long)];
|
static long sd_stack [(DEFAULT_STACK_SIZE*2 + 0x200)/sizeof(long)];
|
||||||
|
static unsigned char aligned_buf[512] STORAGE_ALIGN_ATTR;
|
||||||
|
|
||||||
static const char sd_thread_name[] = "ata/sd";
|
static const char sd_thread_name[] = "ata/sd";
|
||||||
static struct mutex sd_mtx SHAREDBSS_ATTR;
|
static struct mutex sd_mtx SHAREDBSS_ATTR;
|
||||||
static struct event_queue sd_queue;
|
static struct event_queue sd_queue;
|
||||||
|
|
@ -460,9 +462,15 @@ int sd_init(void)
|
||||||
|
|
||||||
static inline void read_sd_data(unsigned char **dst)
|
static inline void read_sd_data(unsigned char **dst)
|
||||||
{
|
{
|
||||||
commit_discard_dcache_range((const void *)*dst, 512);
|
void *buf = *dst;
|
||||||
|
|
||||||
A2A_IDST0 = (unsigned long)*dst;
|
if (!IS_ALIGNED(((unsigned long)*dst), CACHEALIGN_SIZE))
|
||||||
|
buf = aligned_buf;
|
||||||
|
|
||||||
|
commit_discard_dcache_range((const void *)buf, 512);
|
||||||
|
|
||||||
|
|
||||||
|
A2A_IDST0 = (unsigned long)buf;
|
||||||
A2A_CON0 = (3<<9) | /* burst 16 */
|
A2A_CON0 = (3<<9) | /* burst 16 */
|
||||||
(1<<6) | /* fixed src */
|
(1<<6) | /* fixed src */
|
||||||
(1<<3) | /* DMA start */
|
(1<<3) | /* DMA start */
|
||||||
|
|
@ -472,14 +480,25 @@ static inline void read_sd_data(unsigned char **dst)
|
||||||
/* wait for DMA engine to finish transfer */
|
/* wait for DMA engine to finish transfer */
|
||||||
while (A2A_DMA_STS & 1);
|
while (A2A_DMA_STS & 1);
|
||||||
|
|
||||||
|
if (buf == aligned_buf)
|
||||||
|
memcpy(*dst, aligned_buf, 512);
|
||||||
|
|
||||||
*dst += 512;
|
*dst += 512;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void write_sd_data(unsigned char **src)
|
static inline void write_sd_data(unsigned char **src)
|
||||||
{
|
{
|
||||||
commit_discard_dcache_range((const void *)*src, 512);
|
void *buf = *src;
|
||||||
|
|
||||||
A2A_ISRC1 = (unsigned long)*src;
|
if (!IS_ALIGNED(((unsigned long)*src), CACHEALIGN_SIZE))
|
||||||
|
{
|
||||||
|
buf = aligned_buf;
|
||||||
|
memcpy(aligned_buf, *src, 512);
|
||||||
|
}
|
||||||
|
|
||||||
|
commit_discard_dcache_range((const void *)buf, 512);
|
||||||
|
|
||||||
|
A2A_ISRC1 = (unsigned long)buf;
|
||||||
A2A_CON1 = (3<<9) | /* burst 16 */
|
A2A_CON1 = (3<<9) | /* burst 16 */
|
||||||
(1<<5) | /* fixed dst */
|
(1<<5) | /* fixed dst */
|
||||||
(1<<3) | /* DMA start */
|
(1<<3) | /* DMA start */
|
||||||
|
|
|
||||||
|
|
@ -52,4 +52,6 @@ void commit_discard_idcache(void);
|
||||||
#define CPUFREQ_NORMAL 50000000
|
#define CPUFREQ_NORMAL 50000000
|
||||||
#define CPUFREQ_MAX 200000000
|
#define CPUFREQ_MAX 200000000
|
||||||
|
|
||||||
|
#define STORAGE_WANTS_ALIGN
|
||||||
|
|
||||||
#endif /* SYSTEM_TARGET_H */
|
#endif /* SYSTEM_TARGET_H */
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue