2.4.21 from CVS is the first kernel to exhibit the problem. I tracked it down to the cache handling changes that went in between 2.4.20 and 2.4.21.
By (not very scientifically) removing flush_dcache_page() and re-instating flush_page_to_ram() I managed to get the 2.4.21 kernel stable (see attached patch). Applying a similiar patch to 2.4.23 (CVS HEAD) allows me to run 2.4.23 too.
I don't know how to track the problem any further - the kernel's cache handling is a bit out of my league.
Anyone got a clue stick they can point me in the right direction with ?
P.
diff -urN linux-2.4.21-xxx/arch/mips/mm/c-r4k.c linux-2.4.21/arch/mips/mm/c-r4k.c --- linux-2.4.21-xxx/arch/mips/mm/c-r4k.c Thu Dec 11 20:20:28 2003 +++ linux-2.4.21/arch/mips/mm/c-r4k.c Thu Dec 11 10:02:54 2003 @@ -1037,16 +1037,6 @@ return 1; } -static void r4k_flush_page_to_ram_d16(struct page *page) -{ - blast_dcache16_page((unsigned long)page_address(page)); -} - -static void r4k_flush_page_to_ram_d32(struct page *page) -{ - blast_dcache32_page((unsigned long)page_address(page)); -} - static void __init setup_noscache_funcs(void) { unsigned int prid; @@ -1059,7 +1049,6 @@ _clear_page = r4k_clear_page32_d16; _copy_page = r4k_copy_page_d16; - _flush_page_to_ram = r4k_flush_page_to_ram_d16; break; case 32: prid = read_c0_prid() & 0xfff0; @@ -1076,8 +1065,6 @@ _clear_page = r4k_clear_page32_d32; _copy_page = r4k_copy_page_d32; } - - _flush_page_to_ram = r4k_flush_page_to_ram_d32; break; } } diff -urN linux-2.4.21-xxx/arch/mips/mm/cache.c linux-2.4.21/arch/mips/mm/cache.c --- linux-2.4.21-xxx/arch/mips/mm/cache.c Thu Dec 11 20:15:37 2003 +++ linux-2.4.21/arch/mips/mm/cache.c Fri Jul 18 15:16:06 2003 @@ -20,8 +20,6 @@ return 0; } -#if 0 - void flush_dcache_page(struct page *page) { unsigned long addr; @@ -67,5 +65,3 @@ } EXPORT_SYMBOL(flush_dcache_page); - -#endif diff -urN linux-2.4.21-xxx/arch/mips/mm/loadmmu.c linux-2.4.21/arch/mips/mm/loadmmu.c --- linux-2.4.21-xxx/arch/mips/mm/loadmmu.c Thu Dec 11 20:25:23 2003 +++ linux-2.4.21/arch/mips/mm/loadmmu.c Thu Dec 11 10:02:54 2003 @@ -40,8 +40,6 @@ void (*_flush_data_cache_page)(unsigned long addr); void (*_flush_icache_all)(void); -void (*_flush_page_to_ram)(struct page * page); - #ifdef CONFIG_NONCOHERENT_IO /* DMA cache operations. */ diff -urN linux-2.4.21-xxx/include/asm-mips/cacheflush.h linux-2.4.21/include/asm-mips/cacheflush.h --- linux-2.4.21-xxx/include/asm-mips/cacheflush.h Thu Dec 11 20:22:51 2003 +++ linux-2.4.21/include/asm-mips/cacheflush.h Tue Apr 1 00:29:06 2003 @@ -46,16 +46,12 @@ extern void (*_flush_icache_all)(void); extern void (*_flush_data_cache_page)(unsigned long addr); -extern void (*_flush_page_to_ram)(struct page * page); - -#define flush_dcache_page(page) do { } while(0) - #define flush_cache_all() _flush_cache_all() #define __flush_cache_all() ___flush_cache_all() #define flush_cache_mm(mm) _flush_cache_mm(mm) #define flush_cache_range(mm,start,end) _flush_cache_range(mm,start,end) #define flush_cache_page(vma,page) _flush_cache_page(vma, page) -#define flush_page_to_ram(page) _flush_page_to_ram(page) +#define flush_page_to_ram(page) do { } while (0) #define flush_icache_range(start, end) _flush_icache_range(start,end) #define flush_icache_user_range(vma, page, addr, len) \ diff -urN linux-2.4.21-xxx/include/asm-mips/pgtable.h linux-2.4.21/include/asm-mips/pgtable.h --- linux-2.4.21-xxx/include/asm-mips/pgtable.h Thu Dec 11 20:36:56 2003 +++ linux-2.4.21/include/asm-mips/pgtable.h Thu Dec 11 10:04:27 2003 @@ -261,7 +261,7 @@ unsigned long address, pte_t pte) { __update_tlb(vma, address, pte); -// __update_cache(vma, address, pte); + __update_cache(vma, address, pte); } /* Swap entries must have VALID and GLOBAL bits cleared. */