diff options
author | Max Filippov <jcmvbkbc@gmail.com> | 2014-07-16 21:04:49 -0400 |
---|---|---|
committer | Max Filippov <jcmvbkbc@gmail.com> | 2014-08-14 03:59:22 -0400 |
commit | 8504b503dfa86f698a38f9ee1fc2876ab012b776 (patch) | |
tree | 6cb668f177b82628fbb13de1d4207310294c4fdf | |
parent | 32544d9c10c42bac3be8b87d2fc95b0aef008795 (diff) |
xtensa: support aliasing cache in kmap
Define ARCH_PKMAP_COLORING and provide corresponding macro definitions
on cores with aliasing data cache.
Instead of single last_pkmap_nr maintain an array last_pkmap_nr_arr of
pkmap counters for each page color. Make sure that kmap maps physical
page at virtual address with color matching its physical address.
Signed-off-by: Max Filippov <jcmvbkbc@gmail.com>
-rw-r--r-- | arch/xtensa/include/asm/highmem.h | 40 | ||||
-rw-r--r-- | arch/xtensa/mm/highmem.c | 18 |
2 files changed, 56 insertions, 2 deletions
diff --git a/arch/xtensa/include/asm/highmem.h b/arch/xtensa/include/asm/highmem.h index 2653ef5d55f1..2c7901edffaf 100644 --- a/arch/xtensa/include/asm/highmem.h +++ b/arch/xtensa/include/asm/highmem.h | |||
@@ -12,19 +12,55 @@ | |||
12 | #ifndef _XTENSA_HIGHMEM_H | 12 | #ifndef _XTENSA_HIGHMEM_H |
13 | #define _XTENSA_HIGHMEM_H | 13 | #define _XTENSA_HIGHMEM_H |
14 | 14 | ||
15 | #include <linux/wait.h> | ||
15 | #include <asm/cacheflush.h> | 16 | #include <asm/cacheflush.h> |
16 | #include <asm/fixmap.h> | 17 | #include <asm/fixmap.h> |
17 | #include <asm/kmap_types.h> | 18 | #include <asm/kmap_types.h> |
18 | #include <asm/pgtable.h> | 19 | #include <asm/pgtable.h> |
19 | 20 | ||
20 | #define PKMAP_BASE (FIXADDR_START - PMD_SIZE) | 21 | #define PKMAP_BASE ((FIXADDR_START - \ |
21 | #define LAST_PKMAP PTRS_PER_PTE | 22 | (LAST_PKMAP + 1) * PAGE_SIZE) & PMD_MASK) |
23 | #define LAST_PKMAP (PTRS_PER_PTE * DCACHE_N_COLORS) | ||
22 | #define LAST_PKMAP_MASK (LAST_PKMAP - 1) | 24 | #define LAST_PKMAP_MASK (LAST_PKMAP - 1) |
23 | #define PKMAP_NR(virt) (((virt) - PKMAP_BASE) >> PAGE_SHIFT) | 25 | #define PKMAP_NR(virt) (((virt) - PKMAP_BASE) >> PAGE_SHIFT) |
24 | #define PKMAP_ADDR(nr) (PKMAP_BASE + ((nr) << PAGE_SHIFT)) | 26 | #define PKMAP_ADDR(nr) (PKMAP_BASE + ((nr) << PAGE_SHIFT)) |
25 | 27 | ||
26 | #define kmap_prot PAGE_KERNEL | 28 | #define kmap_prot PAGE_KERNEL |
27 | 29 | ||
30 | #if DCACHE_WAY_SIZE > PAGE_SIZE | ||
31 | #define get_pkmap_color get_pkmap_color | ||
32 | static inline int get_pkmap_color(struct page *page) | ||
33 | { | ||
34 | return DCACHE_ALIAS(page_to_phys(page)); | ||
35 | } | ||
36 | |||
37 | extern unsigned int last_pkmap_nr_arr[]; | ||
38 | |||
39 | static inline unsigned int get_next_pkmap_nr(unsigned int color) | ||
40 | { | ||
41 | last_pkmap_nr_arr[color] = | ||
42 | (last_pkmap_nr_arr[color] + DCACHE_N_COLORS) & LAST_PKMAP_MASK; | ||
43 | return last_pkmap_nr_arr[color] + color; | ||
44 | } | ||
45 | |||
46 | static inline int no_more_pkmaps(unsigned int pkmap_nr, unsigned int color) | ||
47 | { | ||
48 | return pkmap_nr < DCACHE_N_COLORS; | ||
49 | } | ||
50 | |||
51 | static inline int get_pkmap_entries_count(unsigned int color) | ||
52 | { | ||
53 | return LAST_PKMAP / DCACHE_N_COLORS; | ||
54 | } | ||
55 | |||
56 | extern wait_queue_head_t pkmap_map_wait_arr[]; | ||
57 | |||
58 | static inline wait_queue_head_t *get_pkmap_wait_queue_head(unsigned int color) | ||
59 | { | ||
60 | return pkmap_map_wait_arr + color; | ||
61 | } | ||
62 | #endif | ||
63 | |||
28 | extern pte_t *pkmap_page_table; | 64 | extern pte_t *pkmap_page_table; |
29 | 65 | ||
30 | void *kmap_high(struct page *page); | 66 | void *kmap_high(struct page *page); |
diff --git a/arch/xtensa/mm/highmem.c b/arch/xtensa/mm/highmem.c index 466abaed5382..8cfb71ec0937 100644 --- a/arch/xtensa/mm/highmem.c +++ b/arch/xtensa/mm/highmem.c | |||
@@ -14,6 +14,23 @@ | |||
14 | 14 | ||
15 | static pte_t *kmap_pte; | 15 | static pte_t *kmap_pte; |
16 | 16 | ||
17 | #if DCACHE_WAY_SIZE > PAGE_SIZE | ||
18 | unsigned int last_pkmap_nr_arr[DCACHE_N_COLORS]; | ||
19 | wait_queue_head_t pkmap_map_wait_arr[DCACHE_N_COLORS]; | ||
20 | |||
21 | static void __init kmap_waitqueues_init(void) | ||
22 | { | ||
23 | unsigned int i; | ||
24 | |||
25 | for (i = 0; i < ARRAY_SIZE(pkmap_map_wait_arr); ++i) | ||
26 | init_waitqueue_head(pkmap_map_wait_arr + i); | ||
27 | } | ||
28 | #else | ||
29 | static inline void kmap_waitqueues_init(void) | ||
30 | { | ||
31 | } | ||
32 | #endif | ||
33 | |||
17 | static inline enum fixed_addresses kmap_idx(int type, unsigned long color) | 34 | static inline enum fixed_addresses kmap_idx(int type, unsigned long color) |
18 | { | 35 | { |
19 | return (type + KM_TYPE_NR * smp_processor_id()) * DCACHE_N_COLORS + | 36 | return (type + KM_TYPE_NR * smp_processor_id()) * DCACHE_N_COLORS + |
@@ -72,4 +89,5 @@ void __init kmap_init(void) | |||
72 | /* cache the first kmap pte */ | 89 | /* cache the first kmap pte */ |
73 | kmap_vstart = __fix_to_virt(FIX_KMAP_BEGIN); | 90 | kmap_vstart = __fix_to_virt(FIX_KMAP_BEGIN); |
74 | kmap_pte = kmap_get_fixmap_pte(kmap_vstart); | 91 | kmap_pte = kmap_get_fixmap_pte(kmap_vstart); |
92 | kmap_waitqueues_init(); | ||
75 | } | 93 | } |