From c9e9be9d3afa44d8775583c36fcab3c0bc552fe7 Mon Sep 17 00:00:00 2001 From: nbd Date: Sat, 13 Oct 2007 10:02:27 +0000 Subject: Finally fix the annoying BCM4704 segfault issues (#2035) - tested with WL-500gP Thanks to jhansen and Wolfram Joost for the fixes and to ryd for the test hardware. Seems like the user space segfaults actually came from this patch: http://lkml.org/lkml/2006/12/12/158 git-svn-id: svn://svn.openwrt.org/openwrt/trunk@9285 3c298f89-4303-0410-b956-a3cf2f4a3e73 --- .../brcm47xx/patches-2.6.23/150-cpu_fixes.patch | 344 ++------------------- 1 file changed, 31 insertions(+), 313 deletions(-) (limited to 'target/linux/brcm47xx/patches-2.6.23/150-cpu_fixes.patch') diff --git a/target/linux/brcm47xx/patches-2.6.23/150-cpu_fixes.patch b/target/linux/brcm47xx/patches-2.6.23/150-cpu_fixes.patch index fe759dc62..d19ba81fa 100644 --- a/target/linux/brcm47xx/patches-2.6.23/150-cpu_fixes.patch +++ b/target/linux/brcm47xx/patches-2.6.23/150-cpu_fixes.patch @@ -1,7 +1,7 @@ Index: linux-2.6.23/arch/mips/kernel/genex.S =================================================================== ---- linux-2.6.23.orig/arch/mips/kernel/genex.S 2007-10-09 22:31:38.000000000 +0200 -+++ linux-2.6.23/arch/mips/kernel/genex.S 2007-10-13 02:47:32.546043867 +0200 +--- linux-2.6.23.orig/arch/mips/kernel/genex.S 2007-10-13 11:29:46.219648163 +0200 ++++ linux-2.6.23/arch/mips/kernel/genex.S 2007-10-13 11:29:49.619841933 +0200 @@ -51,6 +51,10 @@ NESTED(except_vec3_generic, 0, sp) .set push @@ -15,8 +15,8 @@ Index: linux-2.6.23/arch/mips/kernel/genex.S #endif Index: linux-2.6.23/arch/mips/mm/c-r4k.c =================================================================== ---- linux-2.6.23.orig/arch/mips/mm/c-r4k.c 2007-10-13 02:47:02.792348301 +0200 -+++ linux-2.6.23/arch/mips/mm/c-r4k.c 2007-10-13 02:55:35.877587360 +0200 +--- linux-2.6.23.orig/arch/mips/mm/c-r4k.c 2007-10-13 11:29:46.227648623 +0200 ++++ linux-2.6.23/arch/mips/mm/c-r4k.c 2007-10-13 11:29:49.619841933 +0200 @@ -30,6 +30,9 @@ #include /* for run_uncached() */ @@ -27,19 +27,7 @@ Index: linux-2.6.23/arch/mips/mm/c-r4k.c /* * Special Variant of smp_call_function for use by cache functions: * -@@ -86,14 +89,21 @@ - - static inline void r4k_blast_dcache_page_dc32(unsigned long addr) - { -+ unsigned long flags; -+ -+ local_irq_save(flags); - R4600_HIT_CACHEOP_WAR_IMPL; - blast_dcache32_page(addr); -+ local_irq_restore(flags); - } - - static void __init r4k_blast_dcache_page_setup(void) +@@ -94,6 +97,9 @@ { unsigned long dc_lsize = cpu_dcache_line_size(); @@ -49,7 +37,7 @@ Index: linux-2.6.23/arch/mips/mm/c-r4k.c if (dc_lsize == 0) r4k_blast_dcache_page = (void *)cache_noop; else if (dc_lsize == 16) -@@ -108,6 +118,9 @@ +@@ -108,6 +114,9 @@ { unsigned long dc_lsize = cpu_dcache_line_size(); @@ -59,7 +47,7 @@ Index: linux-2.6.23/arch/mips/mm/c-r4k.c if (dc_lsize == 0) r4k_blast_dcache_page_indexed = (void *)cache_noop; else if (dc_lsize == 16) -@@ -122,6 +135,9 @@ +@@ -122,6 +131,9 @@ { unsigned long dc_lsize = cpu_dcache_line_size(); @@ -69,274 +57,16 @@ Index: linux-2.6.23/arch/mips/mm/c-r4k.c if (dc_lsize == 0) r4k_blast_dcache = (void *)cache_noop; else if (dc_lsize == 16) -@@ -203,8 +219,12 @@ - - static void (* r4k_blast_icache_page)(unsigned long addr); - -+static void r4k_flush_cache_all(void); - static void __init r4k_blast_icache_page_setup(void) - { -+#ifdef CONFIG_BCM947XX -+ r4k_blast_icache_page = (void *)r4k_flush_cache_all; -+#else - unsigned long ic_lsize = cpu_icache_line_size(); - - if (ic_lsize == 0) -@@ -215,6 +235,7 @@ - r4k_blast_icache_page = blast_icache32_page; - else if (ic_lsize == 64) - r4k_blast_icache_page = blast_icache64_page; -+#endif - } - - -@@ -222,6 +243,9 @@ - - static void __init r4k_blast_icache_page_indexed_setup(void) - { -+#ifdef CONFIG_BCM947XX -+ r4k_blast_icache_page_indexed = (void *)r4k_flush_cache_all; -+#else - unsigned long ic_lsize = cpu_icache_line_size(); - - if (ic_lsize == 0) -@@ -240,6 +264,7 @@ - blast_icache32_page_indexed; - } else if (ic_lsize == 64) - r4k_blast_icache_page_indexed = blast_icache64_page_indexed; -+#endif - } - - static void (* r4k_blast_icache)(void); -@@ -323,12 +348,17 @@ - */ - static inline void local_r4k_flush_cache_all(void * args) - { -+ unsigned long flags; -+ -+ local_irq_save(flags); - r4k_blast_dcache(); -+ r4k_blast_icache(); -+ local_irq_restore(flags); - } - - static void r4k_flush_cache_all(void) - { -- if (!cpu_has_dc_aliases) -+ if (!cpu_has_dc_aliases && cpu_use_kmap_coherent) - return; - - r4k_on_each_cpu(local_r4k_flush_cache_all, NULL, 1, 1); -@@ -336,6 +366,9 @@ - - static inline void local_r4k___flush_cache_all(void * args) - { -+ unsigned long flags; -+ -+ local_irq_save(flags); - #if defined(CONFIG_CPU_LOONGSON2) - r4k_blast_scache(); - return; -@@ -353,6 +386,7 @@ - case CPU_R14000: - r4k_blast_scache(); - } -+ local_irq_restore(flags); - } - - static void r4k___flush_cache_all(void) -@@ -363,17 +397,21 @@ - static inline void local_r4k_flush_cache_range(void * args) - { - struct vm_area_struct *vma = args; -+ unsigned long flags; - - if (!(cpu_context(smp_processor_id(), vma->vm_mm))) - return; - -+ local_irq_save(flags); - r4k_blast_dcache(); -+ r4k_blast_icache(); -+ local_irq_restore(flags); - } - - static void r4k_flush_cache_range(struct vm_area_struct *vma, - unsigned long start, unsigned long end) - { -- if (!cpu_has_dc_aliases) -+ if (!cpu_has_dc_aliases && cpu_use_kmap_coherent) - return; - - r4k_on_each_cpu(local_r4k_flush_cache_range, vma, 1, 1); -@@ -382,6 +420,7 @@ - static inline void local_r4k_flush_cache_mm(void * args) - { - struct mm_struct *mm = args; -+ unsigned long flags; - - if (!cpu_context(smp_processor_id(), mm)) - return; -@@ -400,12 +439,15 @@ - return; - } - -+ local_irq_save(flags); - r4k_blast_dcache(); -+ r4k_blast_icache(); -+ local_irq_restore(flags); - } - - static void r4k_flush_cache_mm(struct mm_struct *mm) - { -- if (!cpu_has_dc_aliases) -+ if (!cpu_has_dc_aliases && cpu_use_kmap_coherent) - return; - - r4k_on_each_cpu(local_r4k_flush_cache_mm, mm, 1, 1); -@@ -425,6 +467,7 @@ - unsigned long paddr = fcp_args->pfn << PAGE_SHIFT; - int exec = vma->vm_flags & VM_EXEC; - struct mm_struct *mm = vma->vm_mm; -+ unsigned long flags; - pgd_t *pgdp; - pud_t *pudp; - pmd_t *pmdp; -@@ -456,8 +499,9 @@ - * for every cache flush operation. So we do indexed flushes - * in that case, which doesn't overly flush the cache too much. - */ -+ local_irq_save(flags); - if ((mm == current->active_mm) && (pte_val(*ptep) & _PAGE_VALID)) { -- if (cpu_has_dc_aliases || (exec && !cpu_has_ic_fills_f_dc)) { -+ if (!cpu_use_kmap_coherent || cpu_has_dc_aliases || (exec && !cpu_has_ic_fills_f_dc)) { - r4k_blast_dcache_page(addr); - if (exec && !cpu_icache_snoops_remote_store) - r4k_blast_scache_page(addr); -@@ -465,14 +509,14 @@ - if (exec) - r4k_blast_icache_page(addr); - -- return; -+ goto done; - } - - /* - * Do indexed flush, too much work to get the (possible) TLB refills - * to work correctly. - */ -- if (cpu_has_dc_aliases || (exec && !cpu_has_ic_fills_f_dc)) { -+ if (!cpu_use_kmap_coherent || cpu_has_dc_aliases || (exec && !cpu_has_ic_fills_f_dc)) { - r4k_blast_dcache_page_indexed(cpu_has_pindexed_dcache ? - paddr : addr); - if (exec && !cpu_icache_snoops_remote_store) { -@@ -488,6 +532,8 @@ - } else - r4k_blast_icache_page_indexed(addr); - } -+done: -+ local_irq_restore(flags); - } - - static void r4k_flush_cache_page(struct vm_area_struct *vma, -@@ -504,7 +550,11 @@ - - static inline void local_r4k_flush_data_cache_page(void * addr) - { -+ unsigned long flags; -+ -+ local_irq_save(flags); - r4k_blast_dcache_page((unsigned long) addr); -+ local_irq_restore(flags); - } - - static void r4k_flush_data_cache_page(unsigned long addr) -@@ -547,6 +597,9 @@ - - static void r4k_flush_icache_range(unsigned long start, unsigned long end) - { -+#ifdef CONFIG_BCM947XX -+ r4k_flush_cache_all(); -+#else - struct flush_icache_range_args args; - - args.start = start; -@@ -554,12 +607,15 @@ - - r4k_on_each_cpu(local_r4k_flush_icache_range, &args, 1, 1); - instruction_hazard(); -+#endif - } - - #ifdef CONFIG_DMA_NONCOHERENT - - static void r4k_dma_cache_wback_inv(unsigned long addr, unsigned long size) - { -+ unsigned long flags; -+ - /* Catch bad driver code */ - BUG_ON(size == 0); - -@@ -576,18 +632,21 @@ - * subset property so we have to flush the primary caches - * explicitly - */ -+ local_irq_save(flags); - if (size >= dcache_size) { - r4k_blast_dcache(); - } else { - R4600_HIT_CACHEOP_WAR_IMPL; - blast_dcache_range(addr, addr + size); - } -- - bc_wback_inv(addr, size); -+ local_irq_restore(flags); - } - - static void r4k_dma_cache_inv(unsigned long addr, unsigned long size) - { -+ unsigned long flags; -+ - /* Catch bad driver code */ - BUG_ON(size == 0); - -@@ -599,6 +658,7 @@ - return; - } - -+ local_irq_save(flags); - if (size >= dcache_size) { - r4k_blast_dcache(); - } else { -@@ -607,6 +667,7 @@ - } - - bc_inv(addr, size); -+ local_irq_restore(flags); - } - #endif /* CONFIG_DMA_NONCOHERENT */ - -@@ -621,8 +682,12 @@ - unsigned long dc_lsize = cpu_dcache_line_size(); - unsigned long sc_lsize = cpu_scache_line_size(); +@@ -623,6 +635,8 @@ unsigned long addr = (unsigned long) arg; -+ unsigned long flags; -+ local_irq_save(flags); R4600_HIT_CACHEOP_WAR_IMPL; + BCM4710_PROTECTED_FILL_TLB(addr); + BCM4710_PROTECTED_FILL_TLB(addr + 4); if (dc_lsize) protected_writeback_dcache_line(addr & ~(dc_lsize - 1)); if (!cpu_icache_snoops_remote_store && scache_size) -@@ -649,6 +714,7 @@ - } - if (MIPS_CACHE_SYNC_WAR) - __asm__ __volatile__ ("sync"); -+ local_irq_restore(flags); - } - - static void r4k_flush_cache_sigtramp(unsigned long addr) -@@ -1198,6 +1264,17 @@ +@@ -1198,6 +1212,17 @@ * silly idea of putting something else there ... */ switch (current_cpu_data.cputype) { @@ -354,7 +84,7 @@ Index: linux-2.6.23/arch/mips/mm/c-r4k.c case CPU_R4000PC: case CPU_R4000SC: case CPU_R4000MC: -@@ -1228,6 +1305,15 @@ +@@ -1228,6 +1253,15 @@ /* Default cache error handler for R4000 and R5000 family */ set_uncached_handler (0x100, &except_vec2_generic, 0x80); @@ -370,7 +100,7 @@ Index: linux-2.6.23/arch/mips/mm/c-r4k.c probe_pcache(); setup_scache(); -@@ -1273,5 +1359,13 @@ +@@ -1273,5 +1307,13 @@ build_clear_page(); build_copy_page(); local_r4k___flush_cache_all(NULL); @@ -386,44 +116,32 @@ Index: linux-2.6.23/arch/mips/mm/c-r4k.c } Index: linux-2.6.23/arch/mips/mm/tlbex.c =================================================================== ---- linux-2.6.23.orig/arch/mips/mm/tlbex.c 2007-10-13 02:26:00.272401391 +0200 -+++ linux-2.6.23/arch/mips/mm/tlbex.c 2007-10-13 02:47:32.550044103 +0200 -@@ -1247,6 +1247,10 @@ - #endif - } - -+#ifdef CONFIG_BCM947XX -+extern int bcm4710; -+#endif -+ - static void __init build_r4000_tlb_refill_handler(void) - { - u32 *p = tlb_handler; -@@ -1261,6 +1265,10 @@ - memset(relocs, 0, sizeof(relocs)); - memset(final_handler, 0, sizeof(final_handler)); +--- linux-2.6.23.orig/arch/mips/mm/tlbex.c 2007-10-13 11:29:46.235649074 +0200 ++++ linux-2.6.23/arch/mips/mm/tlbex.c 2007-10-13 11:35:46.076155216 +0200 +@@ -1273,6 +1273,9 @@ + /* No need for i_nop */ + } +#ifdef CONFIG_BCM947XX + i_nop(&p); +#endif -+ - /* - * create the plain linear handler - */ -@@ -1756,6 +1764,9 @@ - memset(labels, 0, sizeof(labels)); - memset(relocs, 0, sizeof(relocs)); - + #ifdef CONFIG_64BIT + build_get_pmde64(&p, &l, &r, K0, K1); /* get pmd in K1 */ + #else +@@ -1708,6 +1711,9 @@ + struct reloc **r, unsigned int pte, + unsigned int ptr) + { +#ifdef CONFIG_BCM947XX -+ i_nop(&p); ++ i_nop(p); +#endif - if (bcm1250_m3_war()) { - i_MFC0(&p, K0, C0_BADVADDR); - i_MFC0(&p, K1, C0_ENTRYHI); + #ifdef CONFIG_64BIT + build_get_pmde64(p, l, r, pte, ptr); /* get pmd in ptr */ + #else Index: linux-2.6.23/include/asm-mips/r4kcache.h =================================================================== ---- linux-2.6.23.orig/include/asm-mips/r4kcache.h 2007-10-09 22:31:38.000000000 +0200 -+++ linux-2.6.23/include/asm-mips/r4kcache.h 2007-10-13 02:47:32.554044332 +0200 +--- linux-2.6.23.orig/include/asm-mips/r4kcache.h 2007-10-13 11:29:46.255650214 +0200 ++++ linux-2.6.23/include/asm-mips/r4kcache.h 2007-10-13 11:29:49.631842613 +0200 @@ -17,6 +17,20 @@ #include #include @@ -628,8 +346,8 @@ Index: linux-2.6.23/include/asm-mips/r4kcache.h #endif /* _ASM_R4KCACHE_H */ Index: linux-2.6.23/include/asm-mips/stackframe.h =================================================================== ---- linux-2.6.23.orig/include/asm-mips/stackframe.h 2007-10-09 22:31:38.000000000 +0200 -+++ linux-2.6.23/include/asm-mips/stackframe.h 2007-10-13 02:47:32.554044332 +0200 +--- linux-2.6.23.orig/include/asm-mips/stackframe.h 2007-10-13 11:29:46.263650671 +0200 ++++ linux-2.6.23/include/asm-mips/stackframe.h 2007-10-13 11:33:38.504885346 +0200 @@ -350,6 +350,10 @@ .macro RESTORE_SP_AND_RET LONG_L sp, PT_R29(sp) -- cgit v1.2.3