Hi, This patch adds support for DMA cache flushing for the R10000 processor on non-coherent systems (Indy and O2). Vivien. ================================================================================ --- linux/arch/mips64/mm/andes.c Mon Jul 8 22:26:10 2002 +++ linux.patch/arch/mips64/mm/andes.c Sun Jul 7 14:48:26 2002 @@ -11,13 +11,17 @@ #include <linux/kernel.h> #include <linux/sched.h> #include <linux/mm.h> +#include <asm/io.h> #include <asm/page.h> #include <asm/pgtable.h> -#include <asm/r10kcache.h> #include <asm/system.h> #include <asm/mmu_context.h> -static int scache_lsz64; +/* Secondary cache parameters. */ +static unsigned int scache_size, sc_lsize; /* Again, in bytes */ + +#include <asm/r10kcache.h> + /* * This version has been tuned on an Origin. For other machines the arguments @@ -98,7 +102,7 @@ */ static void andes_flush_cache_l2(void) { - switch (sc_lsize()) { + switch (sc_lsize) { case 64: blast_scache64(); break; @@ -111,13 +115,96 @@ } } +static void +andes_flush_cache_all(void) +{ + andes_flush_cache_l1(); + andes_flush_cache_l2(); +} + void andes_flush_icache_page(unsigned long page) { - if (scache_lsz64) - blast_scache64_page(page); - else - blast_scache128_page(page); + switch (sc_lsize) { + case 64: + blast_scache64_page(page); + break; + case 128: + blast_scache128_page(page); + break; + default: + printk(KERN_EMERG "Unknown L2 line size\n"); + while(1); + } +} + +/* + * Writeback and invalidate the cache before DMA. + */ + +static void andes_dma_cache_wback_inv(unsigned long addr, unsigned long size) +{ + unsigned long end, a; + + + if (size >= (unsigned long)dcache_size) { + flush_cache_l1(); + } else { + a = addr & ~((unsigned long)dc_lsize - 1); + end = (addr + size) & ~((unsigned long)dc_lsize - 1); + while (1) { + flush_dcache_line(a); /* Hit_Writeback_Inv_D */ + if (a == end) break; + a += dc_lsize; + } + } + + if (size >= (unsigned long)scache_size) { + flush_cache_l2(); + } else { + a = addr & ~((unsigned long) sc_lsize - 1); + end = (addr + size) & ~((unsigned long) sc_lsize - 1); + while (1) { + flush_scache_line(a); /* Hit_Writeback_Inv_S */ + if (a == end) break; + a += sc_lsize; + } + } +} + +static void andes_dma_cache_inv(unsigned long addr, unsigned long size) +{ + unsigned long end, a; + + + if (size >= (unsigned long)dcache_size) { + flush_cache_l1(); + } else { + a = addr & ~((unsigned long)dc_lsize - 1); + end = (addr + size) & ~((unsigned long)dc_lsize - 1); + while (1) { + flush_dcache_line(a); /* Hit_Writeback_Inv_D */ + if (a == end) break; + a += dc_lsize; + } + } + + if (size >= (unsigned long)scache_size) { + flush_cache_l2(); + } else { + a = addr & ~((unsigned long) sc_lsize - 1); + end = (addr + size) & ~((unsigned long) sc_lsize - 1); + while (1) { + flush_scache_line(a); /* Hit_Writeback_Inv_S */ + if (a == end) break; + a += sc_lsize; + } + } +} + +static void andes_dma_cache_wback(unsigned long addr, unsigned long size) +{ + panic("andes_dma_cache called - should not happen."); } static void @@ -176,11 +263,9 @@ } } -void local_flush_tlb_range(struct vm_area_struct *vma, unsigned long start, +void local_flush_tlb_range(struct mm_struct *mm, unsigned long start, unsigned long end) { - struct mm_struct *mm = vma->vm_mm; - if (CPU_CONTEXT(smp_processor_id(), mm) != 0) { unsigned long flags; int size; @@ -305,31 +390,28 @@ void __init ld_mmu_andes(void) { + /* get secondary cache parameters */ + scache_size = scache_size(); + sc_lsize = sc_lsize(); + printk("Primary instruction cache %dkb, linesize %d bytes\n", icache_size >> 10, ic_lsize); printk("Primary data cache %dkb, linesize %d bytes\n", dcache_size >> 10, dc_lsize); printk("Secondary cache sized at %ldK, linesize %ld\n", - scache_size() >> 10, sc_lsize()); + scache_size >> 10, sc_lsize); _clear_page = andes_clear_page; _copy_page = andes_copy_page; + _flush_cache_all = andes_flush_cache_all; _flush_cache_l1 = andes_flush_cache_l1; _flush_cache_l2 = andes_flush_cache_l2; _flush_cache_sigtramp = andes_flush_cache_sigtramp; - switch (sc_lsize()) { - case 64: - scache_lsz64 = 1; - break; - case 128: - scache_lsz64 = 0; - break; - default: - printk(KERN_EMERG "Unknown L2 line size\n"); - while(1); - } + _dma_cache_wback_inv = andes_dma_cache_wback_inv; + _dma_cache_wback = andes_dma_cache_wback; + _dma_cache_inv = andes_dma_cache_inv; update_mmu_cache = andes_update_mmu_cache;