Commit 403acce5 authored by David S. Miller's avatar David S. Miller

[SPARC]: Uninline kmap atomic operations.

parent 0a60a8db
...@@ -23,6 +23,9 @@ ...@@ -23,6 +23,9 @@
#include <linux/pci.h> #include <linux/pci.h>
#endif #endif
#include <linux/pm.h> #include <linux/pm.h>
#ifdef CONFIG_HIGHMEM
#include <linux/highmem.h>
#endif
#include <asm/oplib.h> #include <asm/oplib.h>
#include <asm/delay.h> #include <asm/delay.h>
...@@ -199,6 +202,12 @@ EXPORT_SYMBOL(ioremap); ...@@ -199,6 +202,12 @@ EXPORT_SYMBOL(ioremap);
EXPORT_SYMBOL(iounmap); EXPORT_SYMBOL(iounmap);
#endif #endif
/* in arch/sparc/mm/highmem.c */
#ifdef CONFIG_HIGHMEM
EXPORT_SYMBOL(kmap_atomic);
EXPORT_SYMBOL(kunmap_atomic);
#endif
/* Solaris/SunOS binary compatibility */ /* Solaris/SunOS binary compatibility */
EXPORT_SYMBOL(svr4_setcontext); EXPORT_SYMBOL(svr4_setcontext);
EXPORT_SYMBOL(svr4_getcontext); EXPORT_SYMBOL(svr4_getcontext);
......
...@@ -12,6 +12,10 @@ else ...@@ -12,6 +12,10 @@ else
obj-y += srmmu.o iommu.o io-unit.o hypersparc.o viking.o tsunami.o swift.o obj-y += srmmu.o iommu.o io-unit.o hypersparc.o viking.o tsunami.o swift.o
endif endif
ifdef CONFIG_HIGHMEM
obj-y += highmem.o
endif
ifdef CONFIG_SMP ifdef CONFIG_SMP
obj-y += nosun4c.o obj-y += nosun4c.o
else else
......
...@@ -13,6 +13,8 @@ ...@@ -13,6 +13,8 @@
#include <asm/pgalloc.h> #include <asm/pgalloc.h>
#include <asm/pgtable.h> #include <asm/pgtable.h>
#include <asm/page.h> #include <asm/page.h>
#include <asm/cacheflush.h>
#include <asm/tlbflush.h>
static inline void forget_pte(pte_t page) static inline void forget_pte(pte_t page)
{ {
......
/*
* highmem.c: virtual kernel memory mappings for high memory
*
* Provides kernel-static versions of atomic kmap functions originally
* found as inlines in include/asm-sparc/highmem.h. These became
* needed as kmap_atomic() and kunmap_atomic() started getting
* called from within modules.
* -- Tomas Szepe <szepe@pinerecords.com>, September 2002
*
* But kmap_atomic() and kunmap_atomic() cannot be inlined in
* modules because they are loaded with btfixup-ped functions.
*/
/*
* The use of kmap_atomic/kunmap_atomic is discouraged - kmap/kunmap
* gives a more generic (and caching) interface. But kmap_atomic can
* be used in IRQ contexts, so in some (very limited) cases we need it.
*
* XXX This is an old text. Actually, it's good to use atomic kmaps,
* provided you remember that they are atomic and not try to sleep
* with a kmap taken, much like a spinlock. Non-atomic kmaps are
* shared by CPUs, and so precious, and establishing them requires IPI.
* Atomic kmaps are lightweight and we may have NCPUS more of them.
*/
#include <linux/mm.h>
#include <linux/highmem.h>
#include <asm/pgalloc.h>
#include <asm/cacheflush.h>
#include <asm/tlbflush.h>
void *kmap_atomic(struct page *page, enum km_type type)
{
unsigned long idx;
unsigned long vaddr;
inc_preempt_count();
if (page < highmem_start_page)
return page_address(page);
idx = type + KM_TYPE_NR*smp_processor_id();
vaddr = FIX_KMAP_BEGIN + idx * PAGE_SIZE;
/* XXX Fix - Anton */
#if 0
__flush_cache_one(vaddr);
#else
flush_cache_all();
#endif
#if HIGHMEM_DEBUG
if (!pte_none(*(kmap_pte+idx)))
BUG();
#endif
set_pte(kmap_pte+idx, mk_pte(page, kmap_prot));
/* XXX Fix - Anton */
#if 0
__flush_tlb_one(vaddr);
#else
flush_tlb_all();
#endif
return (void*) vaddr;
}
void kunmap_atomic(void *kvaddr, enum km_type type)
{
unsigned long vaddr = (unsigned long) kvaddr;
unsigned long idx = type + KM_TYPE_NR*smp_processor_id();
if (vaddr < FIX_KMAP_BEGIN) { // FIXME
dec_preempt_count();
return;
}
if (vaddr != FIX_KMAP_BEGIN + idx * PAGE_SIZE)
BUG();
/* XXX Fix - Anton */
#if 0
__flush_cache_one(vaddr);
#else
flush_cache_all();
#endif
#ifdef HIGHMEM_DEBUG
/*
* force other mappings to Oops if they'll try to access
* this pte without first remap it
*/
pte_clear(kmap_pte+idx);
/* XXX Fix - Anton */
#if 0
__flush_tlb_one(vaddr);
#else
flush_tlb_all();
#endif
#endif
dec_preempt_count();
}
...@@ -38,6 +38,8 @@ ...@@ -38,6 +38,8 @@
#include <asm/a.out.h> #include <asm/a.out.h>
#include <asm/mmu_context.h> #include <asm/mmu_context.h>
#include <asm/io-unit.h> #include <asm/io-unit.h>
#include <asm/cacheflush.h>
#include <asm/tlbflush.h>
/* Now the cpu specific definitions. */ /* Now the cpu specific definitions. */
#include <asm/viking.h> #include <asm/viking.h>
......
...@@ -20,13 +20,8 @@ ...@@ -20,13 +20,8 @@
#ifdef __KERNEL__ #ifdef __KERNEL__
#include <linux/init.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <asm/vaddrs.h>
#include <asm/kmap_types.h> #include <asm/kmap_types.h>
#include <asm/pgtable.h>
#include <asm/cacheflush.h>
#include <asm/tlbflush.h>
/* undef for production */ /* undef for production */
#define HIGHMEM_DEBUG 1 #define HIGHMEM_DEBUG 1
...@@ -72,81 +67,8 @@ static inline void kunmap(struct page *page) ...@@ -72,81 +67,8 @@ static inline void kunmap(struct page *page)
kunmap_high(page); kunmap_high(page);
} }
/* extern void *kmap_atomic(struct page *page, enum km_type type);
* The use of kmap_atomic/kunmap_atomic is discouraged - kmap/kunmap extern void kunmap_atomic(void *kvaddr, enum km_type type);
* gives a more generic (and caching) interface. But kmap_atomic can
* be used in IRQ contexts, so in some (very limited) cases we need
* it.
*/
static inline void *kmap_atomic(struct page *page, enum km_type type)
{
unsigned long idx;
unsigned long vaddr;
inc_preempt_count();
if (page < highmem_start_page)
return page_address(page);
idx = type + KM_TYPE_NR*smp_processor_id();
vaddr = FIX_KMAP_BEGIN + idx * PAGE_SIZE;
/* XXX Fix - Anton */
#if 0
__flush_cache_one(vaddr);
#else
flush_cache_all();
#endif
#if HIGHMEM_DEBUG
if (!pte_none(*(kmap_pte+idx)))
BUG();
#endif
set_pte(kmap_pte+idx, mk_pte(page, kmap_prot));
/* XXX Fix - Anton */
#if 0
__flush_tlb_one(vaddr);
#else
flush_tlb_all();
#endif
return (void*) vaddr;
}
static inline void kunmap_atomic(void *kvaddr, enum km_type type)
{
unsigned long vaddr = (unsigned long) kvaddr;
unsigned long idx = type + KM_TYPE_NR*smp_processor_id();
if (vaddr < FIX_KMAP_BEGIN) { // FIXME
dec_preempt_count();
return;
}
if (vaddr != FIX_KMAP_BEGIN + idx * PAGE_SIZE)
BUG();
/* XXX Fix - Anton */
#if 0
__flush_cache_one(vaddr);
#else
flush_cache_all();
#endif
#ifdef HIGHMEM_DEBUG
/*
* force other mappings to Oops if they'll try to access
* this pte without first remap it
*/
pte_clear(kmap_pte+idx);
/* XXX Fix - Anton */
#if 0
__flush_tlb_one(vaddr);
#else
flush_tlb_all();
#endif
#endif
dec_preempt_count();
}
static inline struct page *kmap_atomic_to_page(void *ptr) static inline struct page *kmap_atomic_to_page(void *ptr)
{ {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment