Thanks Ralf for your patch, My target is MIPS 34Kc, and I check your patch , Since my target machine is on 2.6.35, so I need to do small modification, I am attaching my patch for reference. Modification done. 1. r4k_on_each_cpu(local_r4k_flush_kernel_vmap_range, &args); -> r4k_on_each_cpu(local_r4k_flush_kernel_vmap_range, &args,1); 2. My target is enabled with High mem, so I modify like below, if there is any problem with below code pls let me know. static inline void flush_kernel_dcache_page(struct page *page) { /* BUG_ON(cpu_has_dc_aliases && PageHighMem(page)); */ if(cpu_has_dc_aliases && !PageHighMem(page)) __flush_kernel_vmap_range((unsigned long)page_address(page), PAGE_SIZE); } with above modification this works fine for me. Regards Naveen On Fri, Jun 17, 2011 at 8:50 PM, Ralf Baechle <ralf@xxxxxxxxxxxxxx> wrote: > On Thu, Jun 16, 2011 at 08:02:50PM +0200, Christoph Hellwig wrote: > >> Ralf, >> >> I'll second that request. We'll really need this, right now embedded XFS >> users are hacking around it in horrible ways. > > Here's my shot at the problem. I don't have the time to setup a XFS > filesystem and tools for testing before the weekend so all I claim is this > patch builds for R4000-class CPUs but it should be pretty close to the > real thing. > > Naveen, can you give this patch a spin? Thanks! > > Ralf > > Signed-off-by: Ralf Baechle <ralf@xxxxxxxxxxxxxx> > > arch/mips/include/asm/cacheflush.h | 24 ++++++++++++++++++++++++ > arch/mips/mm/c-octeon.c | 6 ++++++ > arch/mips/mm/c-r3k.c | 7 +++++++ > arch/mips/mm/c-r4k.c | 35 +++++++++++++++++++++++++++++++++++ > arch/mips/mm/c-tx39.c | 7 +++++++ > arch/mips/mm/cache.c | 5 +++++ > 6 files changed, 84 insertions(+), 0 deletions(-) > > diff --git a/arch/mips/include/asm/cacheflush.h b/arch/mips/include/asm/cacheflush.h > index 40bb9fd..69468de 100644 > --- a/arch/mips/include/asm/cacheflush.h > +++ b/arch/mips/include/asm/cacheflush.h > @@ -114,4 +114,28 @@ unsigned long run_uncached(void *func); > extern void *kmap_coherent(struct page *page, unsigned long addr); > extern void kunmap_coherent(void); > > +#define ARCH_HAS_FLUSH_KERNEL_DCACHE_PAGE > +static inline void flush_kernel_dcache_page(struct page *page) > +{ > + BUG_ON(cpu_has_dc_aliases && PageHighMem(page)); > +} > + > +/* > + * For now flush_kernel_vmap_range and invalidate_kernel_vmap_range both do a > + * cache writeback and invalidate operation. > + */ > +extern void (*__flush_kernel_vmap_range)(unsigned long vaddr, int size); > + > +static inline void flush_kernel_vmap_range(void *vaddr, int size) > +{ > + if (cpu_has_dc_aliases) > + __flush_kernel_vmap_range((unsigned long) vaddr, size); > +} > + > +static inline void invalidate_kernel_vmap_range(void *vaddr, int size) > +{ > + if (cpu_has_dc_aliases) > + __flush_kernel_vmap_range((unsigned long) vaddr, size); > +} > + > #endif /* _ASM_CACHEFLUSH_H */ > diff --git a/arch/mips/mm/c-octeon.c b/arch/mips/mm/c-octeon.c > index 16c4d25..daa81f7 100644 > --- a/arch/mips/mm/c-octeon.c > +++ b/arch/mips/mm/c-octeon.c > @@ -169,6 +169,10 @@ static void octeon_flush_cache_page(struct vm_area_struct *vma, > octeon_flush_icache_all_cores(vma); > } > > +static void octeon_flush_kernel_vmap_range(unsigned long vaddr, int size) > +{ > + BUG(); > +} > > /** > * Probe Octeon's caches > @@ -273,6 +277,8 @@ void __cpuinit octeon_cache_init(void) > flush_icache_range = octeon_flush_icache_range; > local_flush_icache_range = local_octeon_flush_icache_range; > > + __flush_kernel_vmap_range = octeon_flush_kernel_vmap_range; > + > build_clear_page(); > build_copy_page(); > } > diff --git a/arch/mips/mm/c-r3k.c b/arch/mips/mm/c-r3k.c > index e6b0efd..0765583 100644 > --- a/arch/mips/mm/c-r3k.c > +++ b/arch/mips/mm/c-r3k.c > @@ -299,6 +299,11 @@ static void r3k_flush_cache_sigtramp(unsigned long addr) > write_c0_status(flags); > } > > +static void r3k_flush_kernel_vmap_range(unsigned long vaddr, int size) > +{ > + BUG(); > +} > + > static void r3k_dma_cache_wback_inv(unsigned long start, unsigned long size) > { > /* Catch bad driver code */ > @@ -323,6 +328,8 @@ void __cpuinit r3k_cache_init(void) > flush_icache_range = r3k_flush_icache_range; > local_flush_icache_range = r3k_flush_icache_range; > > + __flush_kernel_vmap_range = r3k_flush_kernel_vmap_range; > + > flush_cache_sigtramp = r3k_flush_cache_sigtramp; > local_flush_data_cache_page = local_r3k_flush_data_cache_page; > flush_data_cache_page = r3k_flush_data_cache_page; > diff --git a/arch/mips/mm/c-r4k.c b/arch/mips/mm/c-r4k.c > index eeb642e..38a593e 100644 > --- a/arch/mips/mm/c-r4k.c > +++ b/arch/mips/mm/c-r4k.c > @@ -718,6 +718,39 @@ static void r4k_flush_icache_all(void) > r4k_blast_icache(); > } > > +struct flush_kernel_vmap_range_args { > + unsigned long vaddr; > + int size; > +}; > + > +static inline void local_r4k_flush_kernel_vmap_range(void *args) > +{ > + struct flush_kernel_vmap_range_args *vmra = args; > + unsigned long vaddr = vmra->vaddr; > + int size = vmra->size; > + > + /* > + * Aliases only affect the primary caches so don't bother with > + * S-caches or T-caches. > + */ > + if (cpu_has_safe_index_cacheops && size >= dcache_size) > + r4k_blast_dcache(); > + else { > + R4600_HIT_CACHEOP_WAR_IMPL; > + blast_dcache_range(vaddr, vaddr + size); > + } > +} > + > +static void r4k_flush_kernel_vmap_range(unsigned long vaddr, int size) > +{ > + struct flush_kernel_vmap_range_args args; > + > + args.vaddr = (unsigned long) vaddr; > + args.size = size; > + > + r4k_on_each_cpu(local_r4k_flush_kernel_vmap_range, &args); > +} > + > static inline void rm7k_erratum31(void) > { > const unsigned long ic_lsize = 32; > @@ -1399,6 +1432,8 @@ void __cpuinit r4k_cache_init(void) > flush_cache_page = r4k_flush_cache_page; > flush_cache_range = r4k_flush_cache_range; > > + __flush_kernel_vmap_range = r4k_flush_kernel_vmap_range; > + > flush_cache_sigtramp = r4k_flush_cache_sigtramp; > flush_icache_all = r4k_flush_icache_all; > local_flush_data_cache_page = local_r4k_flush_data_cache_page; > diff --git a/arch/mips/mm/c-tx39.c b/arch/mips/mm/c-tx39.c > index d352fad..a43c197c 100644 > --- a/arch/mips/mm/c-tx39.c > +++ b/arch/mips/mm/c-tx39.c > @@ -253,6 +253,11 @@ static void tx39_flush_icache_range(unsigned long start, unsigned long end) > } > } > > +static void tx39_flush_kernel_vmap_range(unsigned long vaddr, int size) > +{ > + BUG(); > +} > + > static void tx39_dma_cache_wback_inv(unsigned long addr, unsigned long size) > { > unsigned long end; > @@ -394,6 +399,8 @@ void __cpuinit tx39_cache_init(void) > flush_icache_range = tx39_flush_icache_range; > local_flush_icache_range = tx39_flush_icache_range; > > + __flush_kernel_vmap_range = tx39_flush_kernel_vmap_range; > + > flush_cache_sigtramp = tx39_flush_cache_sigtramp; > local_flush_data_cache_page = local_tx39_flush_data_cache_page; > flush_data_cache_page = tx39_flush_data_cache_page; > diff --git a/arch/mips/mm/cache.c b/arch/mips/mm/cache.c > index 12af739..829320c 100644 > --- a/arch/mips/mm/cache.c > +++ b/arch/mips/mm/cache.c > @@ -35,6 +35,11 @@ void (*local_flush_icache_range)(unsigned long start, unsigned long end); > void (*__flush_cache_vmap)(void); > void (*__flush_cache_vunmap)(void); > > +void (*__flush_kernel_vmap_range)(unsigned long vaddr, int size); > +void (*__invalidate_kernel_vmap_range)(unsigned long vaddr, int size); > + > +EXPORT_SYMBOL_GPL(__flush_kernel_vmap_range); > + > /* MIPS specific cache operations */ > void (*flush_cache_sigtramp)(unsigned long addr); > void (*local_flush_data_cache_page)(void * addr); >
Attachment:
vmap_range.patch
Description: Binary data