aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/include/asm/highmem.h
diff options
context:
space:
mode:
authorNicolas Pitre <nico@fluxnic.net>2011-01-25 15:35:38 -0500
committerRussell King <rmk+kernel@arm.linux.org.uk>2011-02-23 12:24:17 -0500
commitaaa50048f6ce44af66ce0389d4cc6a8348333271 (patch)
treea41e04a190420fb970981b8535db7cc9f6e583bd /arch/arm/include/asm/highmem.h
parentc191789c787f488fdb74de0ee55258f71a427704 (diff)
ARM: 6639/1: allow highmem on SMP platforms without h/w TLB ops broadcast
In commit e616c591405c168f6dc3dfd1221e105adfe49b8d, highmem support was deactivated for SMP platforms without hardware TLB ops broadcast because usage of kmap_high_get() requires that IRQs be disabled when kmap_lock is locked which is incompatible with the IPI mechanism used by the software TLB ops broadcast invoked through flush_all_zero_pkmaps(). The reason for kmap_high_get() is to ensure that the currently kmap'd page usage count does not decrease to zero while we're using its existing virtual mapping in an atomic context. With a VIVT cache this is essential to do due to cache coherency issues, but with a VIPT cache this is only an optimization so not to pay the price of establishing a second mapping if an existing one can be used. However, on VIPT platforms without hardware TLB maintenance we can give up on that optimization in order to be able to use highmem. From ARMv7 onwards the TLB ops are broadcasted in hardware, so let's disable ARCH_NEEDS_KMAP_HIGH_GET only when CONFIG_SMP and CONFIG_CPU_TLB_V6 are defined. Signed-off-by: Nicolas Pitre <nicolas.pitre@linaro.org> Tested-by: Saeed Bishara <saeed.bishara@gmail.com> Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
Diffstat (limited to 'arch/arm/include/asm/highmem.h')
-rw-r--r--arch/arm/include/asm/highmem.h29
1 files changed, 27 insertions, 2 deletions
diff --git a/arch/arm/include/asm/highmem.h b/arch/arm/include/asm/highmem.h
index 7080e2c8fa62..a4edd19dd3d6 100644
--- a/arch/arm/include/asm/highmem.h
+++ b/arch/arm/include/asm/highmem.h
@@ -19,11 +19,36 @@
19 19
20extern pte_t *pkmap_page_table; 20extern pte_t *pkmap_page_table;
21 21
22extern void *kmap_high(struct page *page);
23extern void kunmap_high(struct page *page);
24
25/*
26 * The reason for kmap_high_get() is to ensure that the currently kmap'd
27 * page usage count does not decrease to zero while we're using its
28 * existing virtual mapping in an atomic context. With a VIVT cache this
29 * is essential to do, but with a VIPT cache this is only an optimization
30 * so not to pay the price of establishing a second mapping if an existing
31 * one can be used. However, on platforms without hardware TLB maintenance
32 * broadcast, we simply cannot use ARCH_NEEDS_KMAP_HIGH_GET at all since
33 * the locking involved must also disable IRQs which is incompatible with
34 * the IPI mechanism used by global TLB operations.
35 */
22#define ARCH_NEEDS_KMAP_HIGH_GET 36#define ARCH_NEEDS_KMAP_HIGH_GET
37#if defined(CONFIG_SMP) && defined(CONFIG_CPU_TLB_V6)
38#undef ARCH_NEEDS_KMAP_HIGH_GET
39#if defined(CONFIG_HIGHMEM) && defined(CONFIG_CPU_CACHE_VIVT)
40#error "The sum of features in your kernel config cannot be supported together"
41#endif
42#endif
23 43
24extern void *kmap_high(struct page *page); 44#ifdef ARCH_NEEDS_KMAP_HIGH_GET
25extern void *kmap_high_get(struct page *page); 45extern void *kmap_high_get(struct page *page);
26extern void kunmap_high(struct page *page); 46#else
47static inline void *kmap_high_get(struct page *page)
48{
49 return NULL;
50}
51#endif
27 52
28/* 53/*
29 * The following functions are already defined by <linux/highmem.h> 54 * The following functions are already defined by <linux/highmem.h>