]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - arch/mips/mm/c-r4k.c
[MIPS] Fix AP/SP to work in the reality of modern kernels.
[linux-2.6-omap-h63xx.git] / arch / mips / mm / c-r4k.c
index 0b2da53750bd4220a30d1e97d7016d436a41ce6e..df04a315d8309d7303813338e9f6f46406288434 100644 (file)
@@ -323,7 +323,6 @@ static void __init r4k_blast_scache_setup(void)
 static inline void local_r4k_flush_cache_all(void * args)
 {
        r4k_blast_dcache();
-       r4k_blast_icache();
 }
 
 static void r4k_flush_cache_all(void)
@@ -359,21 +358,19 @@ static void r4k___flush_cache_all(void)
 static inline void local_r4k_flush_cache_range(void * args)
 {
        struct vm_area_struct *vma = args;
-       int exec;
 
        if (!(cpu_context(smp_processor_id(), vma->vm_mm)))
                return;
 
-       exec = vma->vm_flags & VM_EXEC;
-       if (cpu_has_dc_aliases || exec)
-               r4k_blast_dcache();
-       if (exec)
-               r4k_blast_icache();
+       r4k_blast_dcache();
 }
 
 static void r4k_flush_cache_range(struct vm_area_struct *vma,
        unsigned long start, unsigned long end)
 {
+       if (!cpu_has_dc_aliases)
+               return;
+
        r4k_on_each_cpu(local_r4k_flush_cache_range, vma, 1, 1);
 }
 
@@ -384,18 +381,21 @@ static inline void local_r4k_flush_cache_mm(void * args)
        if (!cpu_context(smp_processor_id(), mm))
                return;
 
-       r4k_blast_dcache();
-       r4k_blast_icache();
-
        /*
         * Kludge alert.  For obscure reasons R4000SC and R4400SC go nuts if we
         * only flush the primary caches but R10000 and R12000 behave sane ...
+        * R4000SC and R4400SC indexed S-cache ops also invalidate primary
+        * caches, so we can bail out early.
         */
        if (current_cpu_data.cputype == CPU_R4000SC ||
            current_cpu_data.cputype == CPU_R4000MC ||
            current_cpu_data.cputype == CPU_R4400SC ||
-           current_cpu_data.cputype == CPU_R4400MC)
+           current_cpu_data.cputype == CPU_R4400MC) {
                r4k_blast_scache();
+               return;
+       }
+
+       r4k_blast_dcache();
 }
 
 static void r4k_flush_cache_mm(struct mm_struct *mm)
@@ -551,82 +551,6 @@ static void r4k_flush_icache_range(unsigned long start, unsigned long end)
        instruction_hazard();
 }
 
-/*
- * Ok, this seriously sucks.  We use them to flush a user page but don't
- * know the virtual address, so we have to blast away the whole icache
- * which is significantly more expensive than the real thing.  Otoh we at
- * least know the kernel address of the page so we can flush it
- * selectivly.
- */
-
-struct flush_icache_page_args {
-       struct vm_area_struct *vma;
-       struct page *page;
-};
-
-static inline void local_r4k_flush_icache_page(void *args)
-{
-       struct flush_icache_page_args *fip_args = args;
-       struct vm_area_struct *vma = fip_args->vma;
-       struct page *page = fip_args->page;
-
-       /*
-        * Tricky ...  Because we don't know the virtual address we've got the
-        * choice of either invalidating the entire primary and secondary
-        * caches or invalidating the secondary caches also.  With the subset
-        * enforcment on R4000SC, R4400SC, R10000 and R12000 invalidating the
-        * secondary cache will result in any entries in the primary caches
-        * also getting invalidated which hopefully is a bit more economical.
-        */
-       if (cpu_has_inclusive_pcaches) {
-               unsigned long addr = (unsigned long) page_address(page);
-
-               r4k_blast_scache_page(addr);
-               ClearPageDcacheDirty(page);
-
-               return;
-       }
-
-       if (!cpu_has_ic_fills_f_dc) {
-               unsigned long addr = (unsigned long) page_address(page);
-               r4k_blast_dcache_page(addr);
-               if (!cpu_icache_snoops_remote_store)
-                       r4k_blast_scache_page(addr);
-               ClearPageDcacheDirty(page);
-       }
-
-       /*
-        * We're not sure of the virtual address(es) involved here, so
-        * we have to flush the entire I-cache.
-        */
-       if (cpu_has_vtag_icache && vma->vm_mm == current->active_mm) {
-               int cpu = smp_processor_id();
-
-               if (cpu_context(cpu, vma->vm_mm) != 0)
-                       drop_mmu_context(vma->vm_mm, cpu);
-       } else
-               r4k_blast_icache();
-}
-
-static void r4k_flush_icache_page(struct vm_area_struct *vma,
-       struct page *page)
-{
-       struct flush_icache_page_args args;
-
-       /*
-        * If there's no context yet, or the page isn't executable, no I-cache
-        * flush is needed.
-        */
-       if (!(vma->vm_flags & VM_EXEC))
-               return;
-
-       args.vma = vma;
-       args.page = page;
-
-       r4k_on_each_cpu(local_r4k_flush_icache_page, &args, 1, 1);
-}
-
-
 #ifdef CONFIG_DMA_NONCOHERENT
 
 static void r4k_dma_cache_wback_inv(unsigned long addr, unsigned long size)
@@ -1291,7 +1215,6 @@ void __init r4k_cache_init(void)
        __flush_cache_all       = r4k___flush_cache_all;
        flush_cache_mm          = r4k_flush_cache_mm;
        flush_cache_page        = r4k_flush_cache_page;
-       __flush_icache_page     = r4k_flush_icache_page;
        flush_cache_range       = r4k_flush_cache_range;
 
        flush_cache_sigtramp    = r4k_flush_cache_sigtramp;