1
0
Fork 0
forked from len0rd/rockbox

rk27xx: Disable interrupts before invalidating cache.

If interrupts trigger during cache invalidation this could cause memory
corruption. This should be right fix for commit_discard_idcache in
contrast to 72ebcbf and c1ec1ec.

Change-Id: I141fb585004d4a1967b0a03bc37db3964d886564
Reviewed-on: http://gerrit.rockbox.org/345
Tested-by: Andrew Ryabinin <ryabinin.a.a@gmail.com>
Reviewed-by: Marcin Bukat <marcin.bukat@gmail.com>
This commit is contained in:
Andrew Ryabinin 2012-10-31 11:50:06 +04:00
parent 5cfcb8f48d
commit b19b250de7

View file

@ -200,14 +200,7 @@ void udelay(unsigned usecs)
); );
} }
/* Invalidating both cache lines from single function static void cache_invalidate_way(int way)
* gives sometimes strange data aborts.
* This version resembles how OF invalidates cache.
* noinline attribute is to guarantee that future
* gcc change will not decide to inline this call (although
* current arm-eabi version from our toolchain doesn't do that
*/
static void __attribute__((noinline)) cache_invalidate_way(int way)
{ {
/* Issue invalidata way command to the cache controler */ /* Issue invalidata way command to the cache controler */
CACHEOP = ((way<<31)|0x2); CACHEOP = ((way<<31)|0x2);
@ -218,15 +211,13 @@ static void __attribute__((noinline)) cache_invalidate_way(int way)
void commit_discard_idcache(void) void commit_discard_idcache(void)
{ {
DEVID &= ~(1<<31); /* disable cache */ int old_irq = disable_irq_save();
/* invalidate cache way 0 */
cache_invalidate_way(0); cache_invalidate_way(0);
/* invalidate cache way 1 */
cache_invalidate_way(1); cache_invalidate_way(1);
DEVID |= (1<<31); /* enable cache */ restore_irq(old_irq);
} }
void commit_discard_dcache (void) __attribute__((alias("commit_discard_idcache"))); void commit_discard_dcache (void) __attribute__((alias("commit_discard_idcache")));
@ -235,6 +226,8 @@ void commit_discard_dcache_range (const void *base, unsigned int size)
int cnt = size + ((unsigned long)base & 0x1f); int cnt = size + ((unsigned long)base & 0x1f);
unsigned long opcode = ((unsigned long)base & 0xffffffe0) | 0x01; unsigned long opcode = ((unsigned long)base & 0xffffffe0) | 0x01;
int old_irq = disable_irq_save();
while (cnt > 0) while (cnt > 0)
{ {
CACHEOP = opcode; CACHEOP = opcode;
@ -244,6 +237,8 @@ void commit_discard_dcache_range (const void *base, unsigned int size)
cnt -= 32; cnt -= 32;
opcode += 32; opcode += 32;
} }
restore_irq(old_irq);
} }
#ifdef HAVE_ADJUSTABLE_CPU_FREQ #ifdef HAVE_ADJUSTABLE_CPU_FREQ