diff options
author | Andrew Ryabinin <ryabinin.a.a@gmail.com> | 2012-10-31 11:50:06 +0400 |
---|---|---|
committer | Andrew Ryabinin <ryabinin.a.a@gmail.com> | 2012-10-31 09:30:10 +0100 |
commit | b19b250de70cc4ac5b4ecbeac714e7a4aaadf5fb (patch) | |
tree | f62bb573ee8a86ff9024bb387df23b711e208ca9 | |
parent | 5cfcb8f48db3da2c98aa1c9d81f2db69dd253191 (diff) | |
download | rockbox-b19b250de70cc4ac5b4ecbeac714e7a4aaadf5fb.tar.gz rockbox-b19b250de70cc4ac5b4ecbeac714e7a4aaadf5fb.zip |
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>
-rw-r--r-- | firmware/target/arm/rk27xx/system-rk27xx.c | 21 |
1 files changed, 8 insertions, 13 deletions
diff --git a/firmware/target/arm/rk27xx/system-rk27xx.c b/firmware/target/arm/rk27xx/system-rk27xx.c index 8e6773f816..d264476328 100644 --- a/firmware/target/arm/rk27xx/system-rk27xx.c +++ b/firmware/target/arm/rk27xx/system-rk27xx.c | |||
@@ -97,7 +97,7 @@ void irq_handler(void) | |||
97 | "sub sp, sp, #8 \n"); /* Reserve stack */ | 97 | "sub sp, sp, #8 \n"); /* Reserve stack */ |
98 | 98 | ||
99 | int irq_no = INTC_ISR & 0x1f; | 99 | int irq_no = INTC_ISR & 0x1f; |
100 | 100 | ||
101 | irqvector[irq_no](); | 101 | irqvector[irq_no](); |
102 | 102 | ||
103 | /* clear interrupt */ | 103 | /* clear interrupt */ |
@@ -200,14 +200,7 @@ void udelay(unsigned usecs) | |||
200 | ); | 200 | ); |
201 | } | 201 | } |
202 | 202 | ||
203 | /* Invalidating both cache lines from single function | 203 | static void cache_invalidate_way(int way) |
204 | * gives sometimes strange data aborts. | ||
205 | * This version resembles how OF invalidates cache. | ||
206 | * noinline attribute is to guarantee that future | ||
207 | * gcc change will not decide to inline this call (although | ||
208 | * current arm-eabi version from our toolchain doesn't do that | ||
209 | */ | ||
210 | static void __attribute__((noinline)) cache_invalidate_way(int way) | ||
211 | { | 204 | { |
212 | /* Issue invalidata way command to the cache controler */ | 205 | /* Issue invalidata way command to the cache controler */ |
213 | CACHEOP = ((way<<31)|0x2); | 206 | CACHEOP = ((way<<31)|0x2); |
@@ -218,15 +211,13 @@ static void __attribute__((noinline)) cache_invalidate_way(int way) | |||
218 | 211 | ||
219 | void commit_discard_idcache(void) | 212 | void commit_discard_idcache(void) |
220 | { | 213 | { |
221 | DEVID &= ~(1<<31); /* disable cache */ | 214 | int old_irq = disable_irq_save(); |
222 | 215 | ||
223 | /* invalidate cache way 0 */ | ||
224 | cache_invalidate_way(0); | 216 | cache_invalidate_way(0); |
225 | 217 | ||
226 | /* invalidate cache way 1 */ | ||
227 | cache_invalidate_way(1); | 218 | cache_invalidate_way(1); |
228 | 219 | ||
229 | DEVID |= (1<<31); /* enable cache */ | 220 | restore_irq(old_irq); |
230 | } | 221 | } |
231 | void commit_discard_dcache (void) __attribute__((alias("commit_discard_idcache"))); | 222 | void commit_discard_dcache (void) __attribute__((alias("commit_discard_idcache"))); |
232 | 223 | ||
@@ -235,6 +226,8 @@ void commit_discard_dcache_range (const void *base, unsigned int size) | |||
235 | int cnt = size + ((unsigned long)base & 0x1f); | 226 | int cnt = size + ((unsigned long)base & 0x1f); |
236 | unsigned long opcode = ((unsigned long)base & 0xffffffe0) | 0x01; | 227 | unsigned long opcode = ((unsigned long)base & 0xffffffe0) | 0x01; |
237 | 228 | ||
229 | int old_irq = disable_irq_save(); | ||
230 | |||
238 | while (cnt > 0) | 231 | while (cnt > 0) |
239 | { | 232 | { |
240 | CACHEOP = opcode; | 233 | CACHEOP = opcode; |
@@ -244,6 +237,8 @@ void commit_discard_dcache_range (const void *base, unsigned int size) | |||
244 | cnt -= 32; | 237 | cnt -= 32; |
245 | opcode += 32; | 238 | opcode += 32; |
246 | } | 239 | } |
240 | |||
241 | restore_irq(old_irq); | ||
247 | } | 242 | } |
248 | 243 | ||
249 | #ifdef HAVE_ADJUSTABLE_CPU_FREQ | 244 | #ifdef HAVE_ADJUSTABLE_CPU_FREQ |