[MIPS] Fix WARNING: at kernel/smp.c:290
trap_init issues flush_icache_range(), which uses ipi functions to get icache flushing done on all cpus. But this is done before interrupts are enabled and caused WARN_ON messages. This changeset introduces a new local_flush_icache_range() and uses it before interrupts (and additional CPUs) are enabled to avoid this problem. Signed-off-by: Thomas Bogendoerfer <tsbogend@alpha.franken.de> Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
This commit is contained in:
committed by
Ralf Baechle
parent
0510617b85
commit
e0cee3eea7
@ -320,6 +320,7 @@ void __cpuinit r3k_cache_init(void)
|
||||
flush_cache_range = r3k_flush_cache_range;
|
||||
flush_cache_page = r3k_flush_cache_page;
|
||||
flush_icache_range = r3k_flush_icache_range;
|
||||
local_flush_icache_range = r3k_flush_icache_range;
|
||||
|
||||
flush_cache_sigtramp = r3k_flush_cache_sigtramp;
|
||||
local_flush_data_cache_page = local_r3k_flush_data_cache_page;
|
||||
|
@ -543,12 +543,8 @@ struct flush_icache_range_args {
|
||||
unsigned long end;
|
||||
};
|
||||
|
||||
static inline void local_r4k_flush_icache_range(void *args)
|
||||
static inline void local_r4k_flush_icache_range(unsigned long start, unsigned long end)
|
||||
{
|
||||
struct flush_icache_range_args *fir_args = args;
|
||||
unsigned long start = fir_args->start;
|
||||
unsigned long end = fir_args->end;
|
||||
|
||||
if (!cpu_has_ic_fills_f_dc) {
|
||||
if (end - start >= dcache_size) {
|
||||
r4k_blast_dcache();
|
||||
@ -564,6 +560,15 @@ static inline void local_r4k_flush_icache_range(void *args)
|
||||
protected_blast_icache_range(start, end);
|
||||
}
|
||||
|
||||
static inline void local_r4k_flush_icache_range_ipi(void *args)
|
||||
{
|
||||
struct flush_icache_range_args *fir_args = args;
|
||||
unsigned long start = fir_args->start;
|
||||
unsigned long end = fir_args->end;
|
||||
|
||||
local_r4k_flush_icache_range(start, end);
|
||||
}
|
||||
|
||||
static void r4k_flush_icache_range(unsigned long start, unsigned long end)
|
||||
{
|
||||
struct flush_icache_range_args args;
|
||||
@ -571,7 +576,7 @@ static void r4k_flush_icache_range(unsigned long start, unsigned long end)
|
||||
args.start = start;
|
||||
args.end = end;
|
||||
|
||||
r4k_on_each_cpu(local_r4k_flush_icache_range, &args, 1);
|
||||
r4k_on_each_cpu(local_r4k_flush_icache_range_ipi, &args, 1);
|
||||
instruction_hazard();
|
||||
}
|
||||
|
||||
@ -1375,6 +1380,7 @@ void __cpuinit r4k_cache_init(void)
|
||||
local_flush_data_cache_page = local_r4k_flush_data_cache_page;
|
||||
flush_data_cache_page = r4k_flush_data_cache_page;
|
||||
flush_icache_range = r4k_flush_icache_range;
|
||||
local_flush_icache_range = local_r4k_flush_icache_range;
|
||||
|
||||
#if defined(CONFIG_DMA_NONCOHERENT)
|
||||
if (coherentio) {
|
||||
|
@ -362,6 +362,7 @@ void __cpuinit tx39_cache_init(void)
|
||||
flush_cache_range = (void *) tx39h_flush_icache_all;
|
||||
flush_cache_page = (void *) tx39h_flush_icache_all;
|
||||
flush_icache_range = (void *) tx39h_flush_icache_all;
|
||||
local_flush_icache_range = (void *) tx39h_flush_icache_all;
|
||||
|
||||
flush_cache_sigtramp = (void *) tx39h_flush_icache_all;
|
||||
local_flush_data_cache_page = (void *) tx39h_flush_icache_all;
|
||||
|
@ -29,6 +29,7 @@ void (*flush_cache_range)(struct vm_area_struct *vma, unsigned long start,
|
||||
void (*flush_cache_page)(struct vm_area_struct *vma, unsigned long page,
|
||||
unsigned long pfn);
|
||||
void (*flush_icache_range)(unsigned long start, unsigned long end);
|
||||
void (*local_flush_icache_range)(unsigned long start, unsigned long end);
|
||||
|
||||
void (*__flush_cache_vmap)(void);
|
||||
void (*__flush_cache_vunmap)(void);
|
||||
|
@ -1273,10 +1273,10 @@ void __cpuinit build_tlb_refill_handler(void)
|
||||
|
||||
void __cpuinit flush_tlb_handlers(void)
|
||||
{
|
||||
flush_icache_range((unsigned long)handle_tlbl,
|
||||
local_flush_icache_range((unsigned long)handle_tlbl,
|
||||
(unsigned long)handle_tlbl + sizeof(handle_tlbl));
|
||||
flush_icache_range((unsigned long)handle_tlbs,
|
||||
local_flush_icache_range((unsigned long)handle_tlbs,
|
||||
(unsigned long)handle_tlbs + sizeof(handle_tlbs));
|
||||
flush_icache_range((unsigned long)handle_tlbm,
|
||||
local_flush_icache_range((unsigned long)handle_tlbm,
|
||||
(unsigned long)handle_tlbm + sizeof(handle_tlbm));
|
||||
}
|
||||
|
Reference in New Issue
Block a user