diff options
author | David S. Miller <davem@davemloft.net> | 2013-05-04 21:34:13 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2013-05-04 21:34:13 -0400 |
commit | 048c9acca90ca7da42b92745445fe008a48add88 (patch) | |
tree | e2e551a565a7dcdca0fc398aa659231745e5a901 /arch/sparc/mm/tlb.c | |
parent | 07df841877195765d958df146f614fc7bdedd5e3 (diff) | |
parent | ad348cc5349be4ef4abe08819afbb63386585413 (diff) |
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/sparc
Merge sparc bug fixes that didn't make it into v3.9 into
sparc-next.
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'arch/sparc/mm/tlb.c')
-rw-r--r-- | arch/sparc/mm/tlb.c | 39 |
1 files changed, 35 insertions, 4 deletions
diff --git a/arch/sparc/mm/tlb.c b/arch/sparc/mm/tlb.c index ba6ae7ffdc2c..83d89bcb44af 100644 --- a/arch/sparc/mm/tlb.c +++ b/arch/sparc/mm/tlb.c | |||
@@ -24,11 +24,17 @@ static DEFINE_PER_CPU(struct tlb_batch, tlb_batch); | |||
24 | void flush_tlb_pending(void) | 24 | void flush_tlb_pending(void) |
25 | { | 25 | { |
26 | struct tlb_batch *tb = &get_cpu_var(tlb_batch); | 26 | struct tlb_batch *tb = &get_cpu_var(tlb_batch); |
27 | struct mm_struct *mm = tb->mm; | ||
27 | 28 | ||
28 | if (tb->tlb_nr) { | 29 | if (!tb->tlb_nr) |
29 | flush_tsb_user(tb); | 30 | goto out; |
30 | 31 | ||
31 | if (CTX_VALID(tb->mm->context)) { | 32 | flush_tsb_user(tb); |
33 | |||
34 | if (CTX_VALID(mm->context)) { | ||
35 | if (tb->tlb_nr == 1) { | ||
36 | global_flush_tlb_page(mm, tb->vaddrs[0]); | ||
37 | } else { | ||
32 | #ifdef CONFIG_SMP | 38 | #ifdef CONFIG_SMP |
33 | smp_flush_tlb_pending(tb->mm, tb->tlb_nr, | 39 | smp_flush_tlb_pending(tb->mm, tb->tlb_nr, |
34 | &tb->vaddrs[0]); | 40 | &tb->vaddrs[0]); |
@@ -37,12 +43,30 @@ void flush_tlb_pending(void) | |||
37 | tb->tlb_nr, &tb->vaddrs[0]); | 43 | tb->tlb_nr, &tb->vaddrs[0]); |
38 | #endif | 44 | #endif |
39 | } | 45 | } |
40 | tb->tlb_nr = 0; | ||
41 | } | 46 | } |
42 | 47 | ||
48 | tb->tlb_nr = 0; | ||
49 | |||
50 | out: | ||
43 | put_cpu_var(tlb_batch); | 51 | put_cpu_var(tlb_batch); |
44 | } | 52 | } |
45 | 53 | ||
54 | void arch_enter_lazy_mmu_mode(void) | ||
55 | { | ||
56 | struct tlb_batch *tb = &__get_cpu_var(tlb_batch); | ||
57 | |||
58 | tb->active = 1; | ||
59 | } | ||
60 | |||
61 | void arch_leave_lazy_mmu_mode(void) | ||
62 | { | ||
63 | struct tlb_batch *tb = &__get_cpu_var(tlb_batch); | ||
64 | |||
65 | if (tb->tlb_nr) | ||
66 | flush_tlb_pending(); | ||
67 | tb->active = 0; | ||
68 | } | ||
69 | |||
46 | static void tlb_batch_add_one(struct mm_struct *mm, unsigned long vaddr, | 70 | static void tlb_batch_add_one(struct mm_struct *mm, unsigned long vaddr, |
47 | bool exec) | 71 | bool exec) |
48 | { | 72 | { |
@@ -60,6 +84,12 @@ static void tlb_batch_add_one(struct mm_struct *mm, unsigned long vaddr, | |||
60 | nr = 0; | 84 | nr = 0; |
61 | } | 85 | } |
62 | 86 | ||
87 | if (!tb->active) { | ||
88 | global_flush_tlb_page(mm, vaddr); | ||
89 | flush_tsb_user_page(mm, vaddr); | ||
90 | goto out; | ||
91 | } | ||
92 | |||
63 | if (nr == 0) | 93 | if (nr == 0) |
64 | tb->mm = mm; | 94 | tb->mm = mm; |
65 | 95 | ||
@@ -68,6 +98,7 @@ static void tlb_batch_add_one(struct mm_struct *mm, unsigned long vaddr, | |||
68 | if (nr >= TLB_BATCH_NR) | 98 | if (nr >= TLB_BATCH_NR) |
69 | flush_tlb_pending(); | 99 | flush_tlb_pending(); |
70 | 100 | ||
101 | out: | ||
71 | put_cpu_var(tlb_batch); | 102 | put_cpu_var(tlb_batch); |
72 | } | 103 | } |
73 | 104 | ||