diff options
Diffstat (limited to 'arch/mips/mm')
-rw-r--r-- | arch/mips/mm/c-r4k.c | 33 | ||||
-rw-r--r-- | arch/mips/mm/init.c | 1 | ||||
-rw-r--r-- | arch/mips/mm/page.c | 10 | ||||
-rw-r--r-- | arch/mips/mm/tlbex.c | 3 |
4 files changed, 40 insertions, 7 deletions
diff --git a/arch/mips/mm/c-r4k.c b/arch/mips/mm/c-r4k.c index 643c8bcffff3..27096751ddce 100644 --- a/arch/mips/mm/c-r4k.c +++ b/arch/mips/mm/c-r4k.c @@ -446,6 +446,7 @@ static inline void local_r4k_flush_cache_page(void *args) struct page *page = pfn_to_page(fcp_args->pfn); int exec = vma->vm_flags & VM_EXEC; struct mm_struct *mm = vma->vm_mm; + int map_coherent = 0; pgd_t *pgdp; pud_t *pudp; pmd_t *pmdp; @@ -479,7 +480,9 @@ static inline void local_r4k_flush_cache_page(void *args) * Use kmap_coherent or kmap_atomic to do flushes for * another ASID than the current one. */ - if (cpu_has_dc_aliases) + map_coherent = (cpu_has_dc_aliases && + page_mapped(page) && !Page_dcache_dirty(page)); + if (map_coherent) vaddr = kmap_coherent(page, addr); else vaddr = kmap_atomic(page, KM_USER0); @@ -502,7 +505,7 @@ static inline void local_r4k_flush_cache_page(void *args) } if (vaddr) { - if (cpu_has_dc_aliases) + if (map_coherent) kunmap_coherent(); else kunmap_atomic(vaddr, KM_USER0); @@ -1226,6 +1229,28 @@ void au1x00_fixup_config_od(void) } } +/* CP0 hazard avoidance. */ +#define NXP_BARRIER() \ + __asm__ __volatile__( \ + ".set noreorder\n\t" \ + "nop; nop; nop; nop; nop; nop;\n\t" \ + ".set reorder\n\t") + +static void nxp_pr4450_fixup_config(void) +{ + unsigned long config0; + + config0 = read_c0_config(); + + /* clear all three cache coherency fields */ + config0 &= ~(0x7 | (7 << 25) | (7 << 28)); + config0 |= (((_page_cachable_default >> _CACHE_SHIFT) << 0) | + ((_page_cachable_default >> _CACHE_SHIFT) << 25) | + ((_page_cachable_default >> _CACHE_SHIFT) << 28)); + write_c0_config(config0); + NXP_BARRIER(); +} + static int __cpuinitdata cca = -1; static int __init cca_setup(char *str) @@ -1271,6 +1296,10 @@ static void __cpuinit coherency_setup(void) case CPU_AU1500: /* rev. AB */ au1x00_fixup_config_od(); break; + + case PRID_IMP_PR4450: + nxp_pr4450_fixup_config(); + break; } } diff --git a/arch/mips/mm/init.c b/arch/mips/mm/init.c index ecd562d2c348..137c14bafd6b 100644 --- a/arch/mips/mm/init.c +++ b/arch/mips/mm/init.c @@ -71,6 +71,7 @@ DEFINE_PER_CPU(struct mmu_gather, mmu_gathers); * don't have to care about aliases on other CPUs. */ unsigned long empty_zero_page, zero_page_mask; +EXPORT_SYMBOL_GPL(empty_zero_page); /* * Not static inline because used by IP27 special magic initialization code diff --git a/arch/mips/mm/page.c b/arch/mips/mm/page.c index d827d6144369..1edf0cbbeede 100644 --- a/arch/mips/mm/page.c +++ b/arch/mips/mm/page.c @@ -310,8 +310,8 @@ void __cpuinit build_clear_page(void) if (R4600_V2_HIT_CACHEOP_WAR && cpu_is_r4600_v2_x()) uasm_i_lui(&buf, AT, 0xa000); - off = min(8, pref_bias_clear_store / cache_line_size) * - cache_line_size; + off = cache_line_size ? min(8, pref_bias_clear_store / cache_line_size) + * cache_line_size : 0; while (off) { build_clear_pref(&buf, -off); off -= cache_line_size; @@ -454,12 +454,14 @@ void __cpuinit build_copy_page(void) if (R4600_V2_HIT_CACHEOP_WAR && cpu_is_r4600_v2_x()) uasm_i_lui(&buf, AT, 0xa000); - off = min(8, pref_bias_copy_load / cache_line_size) * cache_line_size; + off = cache_line_size ? min(8, pref_bias_copy_load / cache_line_size) * + cache_line_size : 0; while (off) { build_copy_load_pref(&buf, -off); off -= cache_line_size; } - off = min(8, pref_bias_copy_store / cache_line_size) * cache_line_size; + off = cache_line_size ? min(8, pref_bias_copy_store / cache_line_size) * + cache_line_size : 0; while (off) { build_copy_store_pref(&buf, -off); off -= cache_line_size; diff --git a/arch/mips/mm/tlbex.c b/arch/mips/mm/tlbex.c index 382738ca8a0b..76da73a5ab3c 100644 --- a/arch/mips/mm/tlbex.c +++ b/arch/mips/mm/tlbex.c @@ -224,8 +224,9 @@ static u32 final_handler[64] __cpuinitdata; static void __cpuinit __maybe_unused build_tlb_probe_entry(u32 **p) { switch (current_cpu_type()) { - /* Found by experiment: R4600 v2.0 needs this, too. */ + /* Found by experiment: R4600 v2.0/R4700 needs this, too. */ case CPU_R4600: + case CPU_R4700: case CPU_R5000: case CPU_R5000A: case CPU_NEVADA: |