mm: stack based kmap_atomic()
Keep the current interface but ignore the KM_type and use a stack based approach. The advantage is that we get rid of crappy code like: #define __KM_PTE \ (in_nmi() ? KM_NMI_PTE : \ in_irq() ? KM_IRQ_PTE : \ KM_PTE0) and in general can stop worrying about what context we're in and what kmap slots might be appropriate for that. The downside is that FRV kmap_atomic() gets more expensive. For now we use a CPP trick suggested by Andrew: #define kmap_atomic(page, args...) __kmap_atomic(page) to avoid having to touch all kmap_atomic() users in a single patch. [ not compiled on: - mn10300: the arch doesn't actually build with highmem to begin with ] [akpm@linux-foundation.org: coding-style fixes] [akpm@linux-foundation.org: fix up drivers/gpu/drm/i915/intel_overlay.c] Acked-by: Rik van Riel <riel@redhat.com> Signed-off-by: Peter Zijlstra <a.p.zijlstra@chello.nl> Acked-by: Chris Metcalf <cmetcalf@tilera.com> Cc: David Howells <dhowells@redhat.com> Cc: Hugh Dickins <hughd@google.com> Cc: Ingo Molnar <mingo@elte.hu> Cc: Thomas Gleixner <tglx@linutronix.de> Cc: "H. Peter Anvin" <hpa@zytor.com> Cc: Steven Rostedt <rostedt@goodmis.org> Cc: Russell King <rmk@arm.linux.org.uk> Cc: Ralf Baechle <ralf@linux-mips.org> Cc: David Miller <davem@davemloft.net> Cc: Paul Mackerras <paulus@samba.org> Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org> Cc: Dave Airlie <airlied@linux.ie> Cc: Li Zefan <lizf@cn.fujitsu.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
This commit is contained in:
parent
61ecdb801e
commit
3e4d3af501
28 changed files with 371 additions and 376 deletions
|
|
@ -28,18 +28,6 @@ static inline void invalidate_kernel_vmap_range(void *vaddr, int size)
|
|||
|
||||
#include <asm/kmap_types.h>
|
||||
|
||||
#ifdef CONFIG_DEBUG_HIGHMEM
|
||||
|
||||
void debug_kmap_atomic(enum km_type type);
|
||||
|
||||
#else
|
||||
|
||||
static inline void debug_kmap_atomic(enum km_type type)
|
||||
{
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_HIGHMEM
|
||||
#include <asm/highmem.h>
|
||||
|
||||
|
|
@ -49,6 +37,27 @@ extern unsigned long totalhigh_pages;
|
|||
|
||||
void kmap_flush_unused(void);
|
||||
|
||||
DECLARE_PER_CPU(int, __kmap_atomic_idx);
|
||||
|
||||
static inline int kmap_atomic_idx_push(void)
|
||||
{
|
||||
int idx = __get_cpu_var(__kmap_atomic_idx)++;
|
||||
#ifdef CONFIG_DEBUG_HIGHMEM
|
||||
WARN_ON_ONCE(in_irq() && !irqs_disabled());
|
||||
BUG_ON(idx > KM_TYPE_NR);
|
||||
#endif
|
||||
return idx;
|
||||
}
|
||||
|
||||
static inline int kmap_atomic_idx_pop(void)
|
||||
{
|
||||
int idx = --__get_cpu_var(__kmap_atomic_idx);
|
||||
#ifdef CONFIG_DEBUG_HIGHMEM
|
||||
BUG_ON(idx < 0);
|
||||
#endif
|
||||
return idx;
|
||||
}
|
||||
|
||||
#else /* CONFIG_HIGHMEM */
|
||||
|
||||
static inline unsigned int nr_free_highpages(void) { return 0; }
|
||||
|
|
@ -66,19 +75,19 @@ static inline void kunmap(struct page *page)
|
|||
{
|
||||
}
|
||||
|
||||
static inline void *kmap_atomic(struct page *page, enum km_type idx)
|
||||
static inline void *__kmap_atomic(struct page *page)
|
||||
{
|
||||
pagefault_disable();
|
||||
return page_address(page);
|
||||
}
|
||||
#define kmap_atomic_prot(page, idx, prot) kmap_atomic(page, idx)
|
||||
#define kmap_atomic_prot(page, prot) __kmap_atomic(page)
|
||||
|
||||
static inline void kunmap_atomic_notypecheck(void *addr, enum km_type idx)
|
||||
static inline void __kunmap_atomic(void *addr)
|
||||
{
|
||||
pagefault_enable();
|
||||
}
|
||||
|
||||
#define kmap_atomic_pfn(pfn, idx) kmap_atomic(pfn_to_page(pfn), (idx))
|
||||
#define kmap_atomic_pfn(pfn) kmap_atomic(pfn_to_page(pfn))
|
||||
#define kmap_atomic_to_page(ptr) virt_to_page(ptr)
|
||||
|
||||
#define kmap_flush_unused() do {} while(0)
|
||||
|
|
@ -86,12 +95,20 @@ static inline void kunmap_atomic_notypecheck(void *addr, enum km_type idx)
|
|||
|
||||
#endif /* CONFIG_HIGHMEM */
|
||||
|
||||
/* Prevent people trying to call kunmap_atomic() as if it were kunmap() */
|
||||
/* kunmap_atomic() should get the return value of kmap_atomic, not the page. */
|
||||
#define kunmap_atomic(addr, idx) do { \
|
||||
BUILD_BUG_ON(__same_type((addr), struct page *)); \
|
||||
kunmap_atomic_notypecheck((addr), (idx)); \
|
||||
} while (0)
|
||||
/*
|
||||
* Make both: kmap_atomic(page, idx) and kmap_atomic(page) work.
|
||||
*/
|
||||
#define kmap_atomic(page, args...) __kmap_atomic(page)
|
||||
|
||||
/*
|
||||
* Prevent people trying to call kunmap_atomic() as if it were kunmap()
|
||||
* kunmap_atomic() should get the return value of kmap_atomic, not the page.
|
||||
*/
|
||||
#define kunmap_atomic(addr, args...) \
|
||||
do { \
|
||||
BUILD_BUG_ON(__same_type((addr), struct page *)); \
|
||||
__kunmap_atomic(addr); \
|
||||
} while (0)
|
||||
|
||||
/* when CONFIG_HIGHMEM is not set these will be plain clear/copy_page */
|
||||
#ifndef clear_user_highpage
|
||||
|
|
|
|||
|
|
@ -81,8 +81,7 @@ io_mapping_free(struct io_mapping *mapping)
|
|||
/* Atomic map/unmap */
|
||||
static inline void __iomem *
|
||||
io_mapping_map_atomic_wc(struct io_mapping *mapping,
|
||||
unsigned long offset,
|
||||
int slot)
|
||||
unsigned long offset)
|
||||
{
|
||||
resource_size_t phys_addr;
|
||||
unsigned long pfn;
|
||||
|
|
@ -90,13 +89,13 @@ io_mapping_map_atomic_wc(struct io_mapping *mapping,
|
|||
BUG_ON(offset >= mapping->size);
|
||||
phys_addr = mapping->base + offset;
|
||||
pfn = (unsigned long) (phys_addr >> PAGE_SHIFT);
|
||||
return iomap_atomic_prot_pfn(pfn, slot, mapping->prot);
|
||||
return iomap_atomic_prot_pfn(pfn, mapping->prot);
|
||||
}
|
||||
|
||||
static inline void
|
||||
io_mapping_unmap_atomic(void __iomem *vaddr, int slot)
|
||||
io_mapping_unmap_atomic(void __iomem *vaddr)
|
||||
{
|
||||
iounmap_atomic(vaddr, slot);
|
||||
iounmap_atomic(vaddr);
|
||||
}
|
||||
|
||||
static inline void __iomem *
|
||||
|
|
@ -137,14 +136,13 @@ io_mapping_free(struct io_mapping *mapping)
|
|||
/* Atomic map/unmap */
|
||||
static inline void __iomem *
|
||||
io_mapping_map_atomic_wc(struct io_mapping *mapping,
|
||||
unsigned long offset,
|
||||
int slot)
|
||||
unsigned long offset)
|
||||
{
|
||||
return ((char __force __iomem *) mapping) + offset;
|
||||
}
|
||||
|
||||
static inline void
|
||||
io_mapping_unmap_atomic(void __iomem *vaddr, int slot)
|
||||
io_mapping_unmap_atomic(void __iomem *vaddr)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue