diff options
author | Andrew Morton <akpm@osdl.org> | 2008-01-30 07:30:47 -0500 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2008-01-30 07:30:47 -0500 |
commit | 022eb43419f896a3647f769cdc3b5e13a8fb8ee7 (patch) | |
tree | 5c8b716457b2bc12898a7d3a66ff3b6363f1b0a1 /arch/x86/mm | |
parent | 2c0b8a7578f7653e1e5312a5232e8ead563cf477 (diff) |
x86: kmap_atomic() debugging
[ mingo@elte.hu: cleanups and made dependent on CONFIG_DEBUG_HIGHMEM.
this caught a handful of bugs already, so lets apply it. If it gets
things wrong we'll disable it. ]
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Diffstat (limited to 'arch/x86/mm')
-rw-r--r-- | arch/x86/mm/highmem_32.c | 47 |
1 files changed, 46 insertions, 1 deletions
diff --git a/arch/x86/mm/highmem_32.c b/arch/x86/mm/highmem_32.c index 1c3bf95f7356..3d936f232704 100644 --- a/arch/x86/mm/highmem_32.c +++ b/arch/x86/mm/highmem_32.c | |||
@@ -18,6 +18,49 @@ void kunmap(struct page *page) | |||
18 | kunmap_high(page); | 18 | kunmap_high(page); |
19 | } | 19 | } |
20 | 20 | ||
21 | static void debug_kmap_atomic_prot(enum km_type type) | ||
22 | { | ||
23 | #ifdef CONFIG_DEBUG_HIGHMEM | ||
24 | static unsigned warn_count = 10; | ||
25 | |||
26 | if (unlikely(warn_count == 0)) | ||
27 | return; | ||
28 | |||
29 | if (unlikely(in_interrupt())) { | ||
30 | if (in_irq()) { | ||
31 | if (type != KM_IRQ0 && type != KM_IRQ1 && | ||
32 | type != KM_BIO_SRC_IRQ && type != KM_BIO_DST_IRQ && | ||
33 | type != KM_BOUNCE_READ) { | ||
34 | WARN_ON(1); | ||
35 | warn_count--; | ||
36 | } | ||
37 | } else if (!irqs_disabled()) { /* softirq */ | ||
38 | if (type != KM_IRQ0 && type != KM_IRQ1 && | ||
39 | type != KM_SOFTIRQ0 && type != KM_SOFTIRQ1 && | ||
40 | type != KM_SKB_SUNRPC_DATA && | ||
41 | type != KM_SKB_DATA_SOFTIRQ && | ||
42 | type != KM_BOUNCE_READ) { | ||
43 | WARN_ON(1); | ||
44 | warn_count--; | ||
45 | } | ||
46 | } | ||
47 | } | ||
48 | |||
49 | if (type == KM_IRQ0 || type == KM_IRQ1 || type == KM_BOUNCE_READ || | ||
50 | type == KM_BIO_SRC_IRQ || type == KM_BIO_DST_IRQ) { | ||
51 | if (!irqs_disabled()) { | ||
52 | WARN_ON(1); | ||
53 | warn_count--; | ||
54 | } | ||
55 | } else if (type == KM_SOFTIRQ0 || type == KM_SOFTIRQ1) { | ||
56 | if (irq_count() == 0 && !irqs_disabled()) { | ||
57 | WARN_ON(1); | ||
58 | warn_count--; | ||
59 | } | ||
60 | } | ||
61 | #endif | ||
62 | } | ||
63 | |||
21 | /* | 64 | /* |
22 | * kmap_atomic/kunmap_atomic is significantly faster than kmap/kunmap because | 65 | * kmap_atomic/kunmap_atomic is significantly faster than kmap/kunmap because |
23 | * no global lock is needed and because the kmap code must perform a global TLB | 66 | * no global lock is needed and because the kmap code must perform a global TLB |
@@ -30,8 +73,10 @@ void *kmap_atomic_prot(struct page *page, enum km_type type, pgprot_t prot) | |||
30 | { | 73 | { |
31 | enum fixed_addresses idx; | 74 | enum fixed_addresses idx; |
32 | unsigned long vaddr; | 75 | unsigned long vaddr; |
33 | |||
34 | /* even !CONFIG_PREEMPT needs this, for in_atomic in do_page_fault */ | 76 | /* even !CONFIG_PREEMPT needs this, for in_atomic in do_page_fault */ |
77 | |||
78 | debug_kmap_atomic_prot(type); | ||
79 | |||
35 | pagefault_disable(); | 80 | pagefault_disable(); |
36 | 81 | ||
37 | if (!PageHighMem(page)) | 82 | if (!PageHighMem(page)) |