diff options
Diffstat (limited to 'arch/mips/mm/c-r4k.c')
-rw-r--r-- | arch/mips/mm/c-r4k.c | 74 |
1 files changed, 28 insertions, 46 deletions
diff --git a/arch/mips/mm/c-r4k.c b/arch/mips/mm/c-r4k.c index 738b89803a44..cf48371e5690 100644 --- a/arch/mips/mm/c-r4k.c +++ b/arch/mips/mm/c-r4k.c | |||
@@ -8,6 +8,7 @@ | |||
8 | * Copyright (C) 1999, 2000 Silicon Graphics, Inc. | 8 | * Copyright (C) 1999, 2000 Silicon Graphics, Inc. |
9 | */ | 9 | */ |
10 | #include <linux/init.h> | 10 | #include <linux/init.h> |
11 | #include <linux/highmem.h> | ||
11 | #include <linux/kernel.h> | 12 | #include <linux/kernel.h> |
12 | #include <linux/linkage.h> | 13 | #include <linux/linkage.h> |
13 | #include <linux/sched.h> | 14 | #include <linux/sched.h> |
@@ -318,23 +319,6 @@ static void __init r4k_blast_scache_setup(void) | |||
318 | r4k_blast_scache = blast_scache128; | 319 | r4k_blast_scache = blast_scache128; |
319 | } | 320 | } |
320 | 321 | ||
321 | /* | ||
322 | * This is former mm's flush_cache_all() which really should be | ||
323 | * flush_cache_vunmap these days ... | ||
324 | */ | ||
325 | static inline void local_r4k_flush_cache_all(void * args) | ||
326 | { | ||
327 | r4k_blast_dcache(); | ||
328 | } | ||
329 | |||
330 | static void r4k_flush_cache_all(void) | ||
331 | { | ||
332 | if (!cpu_has_dc_aliases) | ||
333 | return; | ||
334 | |||
335 | r4k_on_each_cpu(local_r4k_flush_cache_all, NULL, 1, 1); | ||
336 | } | ||
337 | |||
338 | static inline void local_r4k___flush_cache_all(void * args) | 322 | static inline void local_r4k___flush_cache_all(void * args) |
339 | { | 323 | { |
340 | #if defined(CONFIG_CPU_LOONGSON2) | 324 | #if defined(CONFIG_CPU_LOONGSON2) |
@@ -423,13 +407,14 @@ static inline void local_r4k_flush_cache_page(void *args) | |||
423 | struct flush_cache_page_args *fcp_args = args; | 407 | struct flush_cache_page_args *fcp_args = args; |
424 | struct vm_area_struct *vma = fcp_args->vma; | 408 | struct vm_area_struct *vma = fcp_args->vma; |
425 | unsigned long addr = fcp_args->addr; | 409 | unsigned long addr = fcp_args->addr; |
426 | unsigned long paddr = fcp_args->pfn << PAGE_SHIFT; | 410 | struct page *page = pfn_to_page(fcp_args->pfn); |
427 | int exec = vma->vm_flags & VM_EXEC; | 411 | int exec = vma->vm_flags & VM_EXEC; |
428 | struct mm_struct *mm = vma->vm_mm; | 412 | struct mm_struct *mm = vma->vm_mm; |
429 | pgd_t *pgdp; | 413 | pgd_t *pgdp; |
430 | pud_t *pudp; | 414 | pud_t *pudp; |
431 | pmd_t *pmdp; | 415 | pmd_t *pmdp; |
432 | pte_t *ptep; | 416 | pte_t *ptep; |
417 | void *vaddr; | ||
433 | 418 | ||
434 | /* | 419 | /* |
435 | * If ownes no valid ASID yet, cannot possibly have gotten | 420 | * If ownes no valid ASID yet, cannot possibly have gotten |
@@ -451,43 +436,40 @@ static inline void local_r4k_flush_cache_page(void *args) | |||
451 | if (!(pte_val(*ptep) & _PAGE_PRESENT)) | 436 | if (!(pte_val(*ptep) & _PAGE_PRESENT)) |
452 | return; | 437 | return; |
453 | 438 | ||
454 | /* | 439 | if ((mm == current->active_mm) && (pte_val(*ptep) & _PAGE_VALID)) |
455 | * Doing flushes for another ASID than the current one is | 440 | vaddr = NULL; |
456 | * too difficult since stupid R4k caches do a TLB translation | 441 | else { |
457 | * for every cache flush operation. So we do indexed flushes | 442 | /* |
458 | * in that case, which doesn't overly flush the cache too much. | 443 | * Use kmap_coherent or kmap_atomic to do flushes for |
459 | */ | 444 | * another ASID than the current one. |
460 | if ((mm == current->active_mm) && (pte_val(*ptep) & _PAGE_VALID)) { | 445 | */ |
461 | if (cpu_has_dc_aliases || (exec && !cpu_has_ic_fills_f_dc)) { | 446 | if (cpu_has_dc_aliases) |
462 | r4k_blast_dcache_page(addr); | 447 | vaddr = kmap_coherent(page, addr); |
463 | if (exec && !cpu_icache_snoops_remote_store) | 448 | else |
464 | r4k_blast_scache_page(addr); | 449 | vaddr = kmap_atomic(page, KM_USER0); |
465 | } | 450 | addr = (unsigned long)vaddr; |
466 | if (exec) | ||
467 | r4k_blast_icache_page(addr); | ||
468 | |||
469 | return; | ||
470 | } | 451 | } |
471 | 452 | ||
472 | /* | ||
473 | * Do indexed flush, too much work to get the (possible) TLB refills | ||
474 | * to work correctly. | ||
475 | */ | ||
476 | if (cpu_has_dc_aliases || (exec && !cpu_has_ic_fills_f_dc)) { | 453 | if (cpu_has_dc_aliases || (exec && !cpu_has_ic_fills_f_dc)) { |
477 | r4k_blast_dcache_page_indexed(cpu_has_pindexed_dcache ? | 454 | r4k_blast_dcache_page(addr); |
478 | paddr : addr); | 455 | if (exec && !cpu_icache_snoops_remote_store) |
479 | if (exec && !cpu_icache_snoops_remote_store) { | 456 | r4k_blast_scache_page(addr); |
480 | r4k_blast_scache_page_indexed(paddr); | ||
481 | } | ||
482 | } | 457 | } |
483 | if (exec) { | 458 | if (exec) { |
484 | if (cpu_has_vtag_icache && mm == current->active_mm) { | 459 | if (vaddr && cpu_has_vtag_icache && mm == current->active_mm) { |
485 | int cpu = smp_processor_id(); | 460 | int cpu = smp_processor_id(); |
486 | 461 | ||
487 | if (cpu_context(cpu, mm) != 0) | 462 | if (cpu_context(cpu, mm) != 0) |
488 | drop_mmu_context(mm, cpu); | 463 | drop_mmu_context(mm, cpu); |
489 | } else | 464 | } else |
490 | r4k_blast_icache_page_indexed(addr); | 465 | r4k_blast_icache_page(addr); |
466 | } | ||
467 | |||
468 | if (vaddr) { | ||
469 | if (cpu_has_dc_aliases) | ||
470 | kunmap_coherent(); | ||
471 | else | ||
472 | kunmap_atomic(vaddr, KM_USER0); | ||
491 | } | 473 | } |
492 | } | 474 | } |
493 | 475 | ||
@@ -1279,7 +1261,7 @@ void __init r4k_cache_init(void) | |||
1279 | PAGE_SIZE - 1); | 1261 | PAGE_SIZE - 1); |
1280 | else | 1262 | else |
1281 | shm_align_mask = PAGE_SIZE-1; | 1263 | shm_align_mask = PAGE_SIZE-1; |
1282 | flush_cache_all = r4k_flush_cache_all; | 1264 | flush_cache_all = cache_noop; |
1283 | __flush_cache_all = r4k___flush_cache_all; | 1265 | __flush_cache_all = r4k___flush_cache_all; |
1284 | flush_cache_mm = r4k_flush_cache_mm; | 1266 | flush_cache_mm = r4k_flush_cache_mm; |
1285 | flush_cache_page = r4k_flush_cache_page; | 1267 | flush_cache_page = r4k_flush_cache_page; |