diff options
Diffstat (limited to 'arch/powerpc/include/asm/pgalloc.h')
-rw-r--r-- | arch/powerpc/include/asm/pgalloc.h | 46 |
1 files changed, 34 insertions, 12 deletions
diff --git a/arch/powerpc/include/asm/pgalloc.h b/arch/powerpc/include/asm/pgalloc.h index 1730e5e298d6..f2e812de7c3c 100644 --- a/arch/powerpc/include/asm/pgalloc.h +++ b/arch/powerpc/include/asm/pgalloc.h | |||
@@ -4,6 +4,15 @@ | |||
4 | 4 | ||
5 | #include <linux/mm.h> | 5 | #include <linux/mm.h> |
6 | 6 | ||
7 | #ifdef CONFIG_PPC_BOOK3E | ||
8 | extern void tlb_flush_pgtable(struct mmu_gather *tlb, unsigned long address); | ||
9 | #else /* CONFIG_PPC_BOOK3E */ | ||
10 | static inline void tlb_flush_pgtable(struct mmu_gather *tlb, | ||
11 | unsigned long address) | ||
12 | { | ||
13 | } | ||
14 | #endif /* !CONFIG_PPC_BOOK3E */ | ||
15 | |||
7 | static inline void pte_free_kernel(struct mm_struct *mm, pte_t *pte) | 16 | static inline void pte_free_kernel(struct mm_struct *mm, pte_t *pte) |
8 | { | 17 | { |
9 | free_page((unsigned long)pte); | 18 | free_page((unsigned long)pte); |
@@ -19,7 +28,12 @@ typedef struct pgtable_free { | |||
19 | unsigned long val; | 28 | unsigned long val; |
20 | } pgtable_free_t; | 29 | } pgtable_free_t; |
21 | 30 | ||
22 | #define PGF_CACHENUM_MASK 0x7 | 31 | /* This needs to be big enough to allow for MMU_PAGE_COUNT + 2 to be stored |
32 | * and small enough to fit in the low bits of any naturally aligned page | ||
33 | * table cache entry. Arbitrarily set to 0x1f, that should give us some | ||
34 | * room to grow | ||
35 | */ | ||
36 | #define PGF_CACHENUM_MASK 0x1f | ||
23 | 37 | ||
24 | static inline pgtable_free_t pgtable_free_cache(void *p, int cachenum, | 38 | static inline pgtable_free_t pgtable_free_cache(void *p, int cachenum, |
25 | unsigned long mask) | 39 | unsigned long mask) |
@@ -35,19 +49,27 @@ static inline pgtable_free_t pgtable_free_cache(void *p, int cachenum, | |||
35 | #include <asm/pgalloc-32.h> | 49 | #include <asm/pgalloc-32.h> |
36 | #endif | 50 | #endif |
37 | 51 | ||
38 | extern void pgtable_free_tlb(struct mmu_gather *tlb, pgtable_free_t pgf); | ||
39 | |||
40 | #ifdef CONFIG_SMP | 52 | #ifdef CONFIG_SMP |
41 | #define __pte_free_tlb(tlb,ptepage,address) \ | 53 | extern void pgtable_free_tlb(struct mmu_gather *tlb, pgtable_free_t pgf); |
42 | do { \ | 54 | extern void pte_free_finish(void); |
43 | pgtable_page_dtor(ptepage); \ | 55 | #else /* CONFIG_SMP */ |
44 | pgtable_free_tlb(tlb, pgtable_free_cache(page_address(ptepage), \ | 56 | static inline void pgtable_free_tlb(struct mmu_gather *tlb, pgtable_free_t pgf) |
45 | PTE_NONCACHE_NUM, PTE_TABLE_SIZE-1)); \ | 57 | { |
46 | } while (0) | 58 | pgtable_free(pgf); |
47 | #else | 59 | } |
48 | #define __pte_free_tlb(tlb, pte, address) pte_free((tlb)->mm, (pte)) | 60 | static inline void pte_free_finish(void) { } |
49 | #endif | 61 | #endif /* !CONFIG_SMP */ |
50 | 62 | ||
63 | static inline void __pte_free_tlb(struct mmu_gather *tlb, struct page *ptepage, | ||
64 | unsigned long address) | ||
65 | { | ||
66 | pgtable_free_t pgf = pgtable_free_cache(page_address(ptepage), | ||
67 | PTE_NONCACHE_NUM, | ||
68 | PTE_TABLE_SIZE-1); | ||
69 | tlb_flush_pgtable(tlb, address); | ||
70 | pgtable_page_dtor(ptepage); | ||
71 | pgtable_free_tlb(tlb, pgf); | ||
72 | } | ||
51 | 73 | ||
52 | #endif /* __KERNEL__ */ | 74 | #endif /* __KERNEL__ */ |
53 | #endif /* _ASM_POWERPC_PGALLOC_H */ | 75 | #endif /* _ASM_POWERPC_PGALLOC_H */ |