
On 05/26/2016 05:58 PM, Paul Burton wrote:
The various cache maintenance routines perform a number of loops over cache lines. Rather than duplicate the code for performing such loops, abstract it out into a new cache_loop macro which performs an arbitrary number of cache ops on a range of addresses. This reduces duplication in the existing L1 cache maintenance code & will allow for not adding further duplication when introducing L2 cache support.
Signed-off-by: Paul Burton paul.burton@imgtec.com
arch/mips/lib/cache.c | 59 ++++++++++++++++----------------------------------- 1 file changed, 18 insertions(+), 41 deletions(-)
diff --git a/arch/mips/lib/cache.c b/arch/mips/lib/cache.c index 2bb91c6..320335c 100644 --- a/arch/mips/lib/cache.c +++ b/arch/mips/lib/cache.c @@ -37,82 +37,59 @@ static inline unsigned long dcache_line_size(void) return 2 << dl; }
+#define cache_loop(start, end, lsize, ops...) do { \
- const void *addr = (const void *)(start & ~(lsize - 1)); \
- const void *aend = (const void *)((end - 1) & ~(lsize - 1)); \
- const unsigned int cache_ops[] = { ops }; \
Can't you turn this into a function instead and pass some flags to select the ops instead ?
- unsigned int i; \
\
- for (; addr <= aend; addr += lsize) { \
for (i = 0; i < ARRAY_SIZE(cache_ops); i++) \
mips_cache(cache_ops[i], addr); \
- } \
+} while (0)
void flush_cache(ulong start_addr, ulong size) { unsigned long ilsize = icache_line_size(); unsigned long dlsize = dcache_line_size();
const void *addr, *aend;
/* aend will be miscalculated when size is zero, so we return here */ if (size == 0) return;
addr = (const void *)(start_addr & ~(dlsize - 1));
aend = (const void *)((start_addr + size - 1) & ~(dlsize - 1));
if (ilsize == dlsize) { /* flush I-cache & D-cache simultaneously */
while (1) {
mips_cache(HIT_WRITEBACK_INV_D, addr);
mips_cache(HIT_INVALIDATE_I, addr);
if (addr == aend)
break;
addr += dlsize;
}
cache_loop(start_addr, start_addr + size, ilsize,
HIT_WRITEBACK_INV_D, HIT_INVALIDATE_I);
return; }
/* flush D-cache */
- while (1) {
mips_cache(HIT_WRITEBACK_INV_D, addr);
if (addr == aend)
break;
addr += dlsize;
- }
cache_loop(start_addr, start_addr + size, dlsize, HIT_WRITEBACK_INV_D);
/* flush I-cache */
- addr = (const void *)(start_addr & ~(ilsize - 1));
- aend = (const void *)((start_addr + size - 1) & ~(ilsize - 1));
- while (1) {
mips_cache(HIT_INVALIDATE_I, addr);
if (addr == aend)
break;
addr += ilsize;
- }
- cache_loop(start_addr, start_addr + size, ilsize, HIT_INVALIDATE_I);
}
void flush_dcache_range(ulong start_addr, ulong stop) { unsigned long lsize = dcache_line_size();
const void *addr = (const void *)(start_addr & ~(lsize - 1));
const void *aend = (const void *)((stop - 1) & ~(lsize - 1));
/* aend will be miscalculated when size is zero, so we return here */ if (start_addr == stop) return;
while (1) {
mips_cache(HIT_WRITEBACK_INV_D, addr);
if (addr == aend)
break;
addr += lsize;
}
- cache_loop(start_addr, stop, lsize, HIT_WRITEBACK_INV_D);
}
void invalidate_dcache_range(ulong start_addr, ulong stop) { unsigned long lsize = dcache_line_size();
const void *addr = (const void *)(start_addr & ~(lsize - 1));
const void *aend = (const void *)((stop - 1) & ~(lsize - 1));
/* aend will be miscalculated when size is zero, so we return here */ if (start_addr == stop) return;
while (1) {
mips_cache(HIT_INVALIDATE_D, addr);
if (addr == aend)
break;
addr += lsize;
}
- cache_loop(start_addr, stop, lsize, HIT_INVALIDATE_I);
}