Skip to content

Commit

Permalink
[MIPS] Avoid indexed cacheops.
Browse files Browse the repository at this point in the history
On MP configurations it's highly dubious what this code will actually
affect since blasting away cachelines may or may not do the right
thing wrt. cache coherency.

Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
  • Loading branch information
Ralf Baechle committed Oct 11, 2007
1 parent e58d95a commit db813fe
Showing 1 changed file with 28 additions and 46 deletions.
74 changes: 28 additions & 46 deletions arch/mips/mm/c-r4k.c
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
* Copyright (C) 1999, 2000 Silicon Graphics, Inc.
*/
#include <linux/init.h>
#include <linux/highmem.h>
#include <linux/kernel.h>
#include <linux/linkage.h>
#include <linux/sched.h>
Expand Down Expand Up @@ -318,23 +319,6 @@ static void __init r4k_blast_scache_setup(void)
r4k_blast_scache = blast_scache128;
}

/*
* This is former mm's flush_cache_all() which really should be
* flush_cache_vunmap these days ...
*/
static inline void local_r4k_flush_cache_all(void * args)
{
r4k_blast_dcache();
}

static void r4k_flush_cache_all(void)
{
if (!cpu_has_dc_aliases)
return;

r4k_on_each_cpu(local_r4k_flush_cache_all, NULL, 1, 1);
}

static inline void local_r4k___flush_cache_all(void * args)
{
#if defined(CONFIG_CPU_LOONGSON2)
Expand Down Expand Up @@ -423,13 +407,14 @@ static inline void local_r4k_flush_cache_page(void *args)
struct flush_cache_page_args *fcp_args = args;
struct vm_area_struct *vma = fcp_args->vma;
unsigned long addr = fcp_args->addr;
unsigned long paddr = fcp_args->pfn << PAGE_SHIFT;
struct page *page = pfn_to_page(fcp_args->pfn);
int exec = vma->vm_flags & VM_EXEC;
struct mm_struct *mm = vma->vm_mm;
pgd_t *pgdp;
pud_t *pudp;
pmd_t *pmdp;
pte_t *ptep;
void *vaddr;

/*
* If ownes no valid ASID yet, cannot possibly have gotten
Expand All @@ -451,43 +436,40 @@ static inline void local_r4k_flush_cache_page(void *args)
if (!(pte_val(*ptep) & _PAGE_PRESENT))
return;

/*
* Doing flushes for another ASID than the current one is
* too difficult since stupid R4k caches do a TLB translation
* for every cache flush operation. So we do indexed flushes
* in that case, which doesn't overly flush the cache too much.
*/
if ((mm == current->active_mm) && (pte_val(*ptep) & _PAGE_VALID)) {
if (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);
}
if (exec)
r4k_blast_icache_page(addr);

return;
if ((mm == current->active_mm) && (pte_val(*ptep) & _PAGE_VALID))
vaddr = NULL;
else {
/*
* Use kmap_coherent or kmap_atomic to do flushes for
* another ASID than the current one.
*/
if (cpu_has_dc_aliases)
vaddr = kmap_coherent(page, addr);
else
vaddr = kmap_atomic(page, KM_USER0);
addr = (unsigned long)vaddr;
}

/*
* 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)) {
r4k_blast_dcache_page_indexed(cpu_has_pindexed_dcache ?
paddr : addr);
if (exec && !cpu_icache_snoops_remote_store) {
r4k_blast_scache_page_indexed(paddr);
}
r4k_blast_dcache_page(addr);
if (exec && !cpu_icache_snoops_remote_store)
r4k_blast_scache_page(addr);
}
if (exec) {
if (cpu_has_vtag_icache && mm == current->active_mm) {
if (vaddr && cpu_has_vtag_icache && mm == current->active_mm) {
int cpu = smp_processor_id();

if (cpu_context(cpu, mm) != 0)
drop_mmu_context(mm, cpu);
} else
r4k_blast_icache_page_indexed(addr);
r4k_blast_icache_page(addr);
}

if (vaddr) {
if (cpu_has_dc_aliases)
kunmap_coherent();
else
kunmap_atomic(vaddr, KM_USER0);
}
}

Expand Down Expand Up @@ -1279,7 +1261,7 @@ void __init r4k_cache_init(void)
PAGE_SIZE - 1);
else
shm_align_mask = PAGE_SIZE-1;
flush_cache_all = r4k_flush_cache_all;
flush_cache_all = cache_noop;
__flush_cache_all = r4k___flush_cache_all;
flush_cache_mm = r4k_flush_cache_mm;
flush_cache_page = r4k_flush_cache_page;
Expand Down

0 comments on commit db813fe

Please sign in to comment.