diff options
Diffstat (limited to 'arch/sh/mm/pg-sh4.c')
-rw-r--r-- | arch/sh/mm/pg-sh4.c | 76 |
1 files changed, 35 insertions, 41 deletions
diff --git a/arch/sh/mm/pg-sh4.c b/arch/sh/mm/pg-sh4.c index df69da9ca69c..25f5c6f6821d 100644 --- a/arch/sh/mm/pg-sh4.c +++ b/arch/sh/mm/pg-sh4.c | |||
@@ -2,19 +2,45 @@ | |||
2 | * arch/sh/mm/pg-sh4.c | 2 | * arch/sh/mm/pg-sh4.c |
3 | * | 3 | * |
4 | * Copyright (C) 1999, 2000, 2002 Niibe Yutaka | 4 | * Copyright (C) 1999, 2000, 2002 Niibe Yutaka |
5 | * Copyright (C) 2002 - 2005 Paul Mundt | 5 | * Copyright (C) 2002 - 2007 Paul Mundt |
6 | * | 6 | * |
7 | * Released under the terms of the GNU GPL v2.0. | 7 | * Released under the terms of the GNU GPL v2.0. |
8 | */ | 8 | */ |
9 | #include <linux/mm.h> | 9 | #include <linux/mm.h> |
10 | #include <linux/mutex.h> | 10 | #include <linux/mutex.h> |
11 | #include <linux/fs.h> | ||
11 | #include <asm/mmu_context.h> | 12 | #include <asm/mmu_context.h> |
12 | #include <asm/cacheflush.h> | 13 | #include <asm/cacheflush.h> |
13 | 14 | ||
14 | extern struct mutex p3map_mutex[]; | ||
15 | |||
16 | #define CACHE_ALIAS (current_cpu_data.dcache.alias_mask) | 15 | #define CACHE_ALIAS (current_cpu_data.dcache.alias_mask) |
17 | 16 | ||
17 | static inline void *kmap_coherent(struct page *page, unsigned long addr) | ||
18 | { | ||
19 | enum fixed_addresses idx; | ||
20 | unsigned long vaddr, flags; | ||
21 | pte_t pte; | ||
22 | |||
23 | inc_preempt_count(); | ||
24 | |||
25 | idx = (addr & current_cpu_data.dcache.alias_mask) >> PAGE_SHIFT; | ||
26 | vaddr = __fix_to_virt(FIX_CMAP_END - idx); | ||
27 | pte = mk_pte(page, PAGE_KERNEL); | ||
28 | |||
29 | local_irq_save(flags); | ||
30 | flush_tlb_one(get_asid(), vaddr); | ||
31 | local_irq_restore(flags); | ||
32 | |||
33 | update_mmu_cache(NULL, vaddr, pte); | ||
34 | |||
35 | return (void *)vaddr; | ||
36 | } | ||
37 | |||
38 | static inline void kunmap_coherent(struct page *page) | ||
39 | { | ||
40 | dec_preempt_count(); | ||
41 | preempt_check_resched(); | ||
42 | } | ||
43 | |||
18 | /* | 44 | /* |
19 | * clear_user_page | 45 | * clear_user_page |
20 | * @to: P1 address | 46 | * @to: P1 address |
@@ -27,25 +53,9 @@ void clear_user_page(void *to, unsigned long address, struct page *page) | |||
27 | if (((address ^ (unsigned long)to) & CACHE_ALIAS) == 0) | 53 | if (((address ^ (unsigned long)to) & CACHE_ALIAS) == 0) |
28 | clear_page(to); | 54 | clear_page(to); |
29 | else { | 55 | else { |
30 | unsigned long phys_addr = PHYSADDR(to); | 56 | void *vto = kmap_coherent(page, address); |
31 | unsigned long p3_addr = P3SEG + (address & CACHE_ALIAS); | 57 | __clear_user_page(vto, to); |
32 | pgd_t *pgd = pgd_offset_k(p3_addr); | 58 | kunmap_coherent(vto); |
33 | pud_t *pud = pud_offset(pgd, p3_addr); | ||
34 | pmd_t *pmd = pmd_offset(pud, p3_addr); | ||
35 | pte_t *pte = pte_offset_kernel(pmd, p3_addr); | ||
36 | pte_t entry; | ||
37 | unsigned long flags; | ||
38 | |||
39 | entry = pfn_pte(phys_addr >> PAGE_SHIFT, PAGE_KERNEL); | ||
40 | mutex_lock(&p3map_mutex[(address & CACHE_ALIAS)>>12]); | ||
41 | set_pte(pte, entry); | ||
42 | local_irq_save(flags); | ||
43 | flush_tlb_one(get_asid(), p3_addr); | ||
44 | local_irq_restore(flags); | ||
45 | update_mmu_cache(NULL, p3_addr, entry); | ||
46 | __clear_user_page((void *)p3_addr, to); | ||
47 | pte_clear(&init_mm, p3_addr, pte); | ||
48 | mutex_unlock(&p3map_mutex[(address & CACHE_ALIAS)>>12]); | ||
49 | } | 59 | } |
50 | } | 60 | } |
51 | 61 | ||
@@ -63,25 +73,9 @@ void copy_user_page(void *to, void *from, unsigned long address, | |||
63 | if (((address ^ (unsigned long)to) & CACHE_ALIAS) == 0) | 73 | if (((address ^ (unsigned long)to) & CACHE_ALIAS) == 0) |
64 | copy_page(to, from); | 74 | copy_page(to, from); |
65 | else { | 75 | else { |
66 | unsigned long phys_addr = PHYSADDR(to); | 76 | void *vfrom = kmap_coherent(page, address); |
67 | unsigned long p3_addr = P3SEG + (address & CACHE_ALIAS); | 77 | __copy_user_page(vfrom, from, to); |
68 | pgd_t *pgd = pgd_offset_k(p3_addr); | 78 | kunmap_coherent(vfrom); |
69 | pud_t *pud = pud_offset(pgd, p3_addr); | ||
70 | pmd_t *pmd = pmd_offset(pud, p3_addr); | ||
71 | pte_t *pte = pte_offset_kernel(pmd, p3_addr); | ||
72 | pte_t entry; | ||
73 | unsigned long flags; | ||
74 | |||
75 | entry = pfn_pte(phys_addr >> PAGE_SHIFT, PAGE_KERNEL); | ||
76 | mutex_lock(&p3map_mutex[(address & CACHE_ALIAS)>>12]); | ||
77 | set_pte(pte, entry); | ||
78 | local_irq_save(flags); | ||
79 | flush_tlb_one(get_asid(), p3_addr); | ||
80 | local_irq_restore(flags); | ||
81 | update_mmu_cache(NULL, p3_addr, entry); | ||
82 | __copy_user_page((void *)p3_addr, from, to); | ||
83 | pte_clear(&init_mm, p3_addr, pte); | ||
84 | mutex_unlock(&p3map_mutex[(address & CACHE_ALIAS)>>12]); | ||
85 | } | 79 | } |
86 | } | 80 | } |
87 | 81 | ||