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@linux-mips.org> 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@linux-mips.org>
>
> 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);
>
vmap_range.patch
Description: Binary data
|