diff options
Diffstat (limited to 'mm/highmem.c')
| -rw-r--r-- | mm/highmem.c | 48 | 
1 files changed, 20 insertions, 28 deletions
diff --git a/mm/highmem.c b/mm/highmem.c index 693394daa2e..b32b70cdaed 100644 --- a/mm/highmem.c +++ b/mm/highmem.c @@ -17,7 +17,7 @@   */  #include <linux/mm.h> -#include <linux/module.h> +#include <linux/export.h>  #include <linux/swap.h>  #include <linux/bio.h>  #include <linux/pagemap.h> @@ -94,6 +94,19 @@ static DECLARE_WAIT_QUEUE_HEAD(pkmap_map_wait);  		do { spin_unlock(&kmap_lock); (void)(flags); } while (0)  #endif +struct page *kmap_to_page(void *vaddr) +{ +	unsigned long addr = (unsigned long)vaddr; + +	if (addr >= PKMAP_ADDR(0) && addr < PKMAP_ADDR(LAST_PKMAP)) { +		int i = PKMAP_NR(addr); +		return pte_page(pkmap_page_table[i]); +	} + +	return virt_to_page(addr); +} +EXPORT_SYMBOL(kmap_to_page); +  static void flush_all_zero_pkmaps(void)  {  	int i; @@ -125,8 +138,7 @@ static void flush_all_zero_pkmaps(void)  		 * So no dangers, even with speculative execution.  		 */  		page = pte_page(pkmap_page_table[i]); -		pte_clear(&init_mm, (unsigned long)page_address(page), -			  &pkmap_page_table[i]); +		pte_clear(&init_mm, PKMAP_ADDR(i), &pkmap_page_table[i]);  		set_page_address(page, NULL);  		need_flush = 1; @@ -250,7 +262,7 @@ void *kmap_high_get(struct page *page)  #endif  /** - * kunmap_high - map a highmem page into memory + * kunmap_high - unmap a highmem page into memory   * @page: &struct page to unmap   *   * If ARCH_NEEDS_KMAP_HIGH_GET is not defined then this may be called @@ -312,11 +324,7 @@ struct page_address_map {  	struct list_head list;  }; -/* - * page_address_map freelist, allocated from page_address_maps. - */ -static struct list_head page_address_pool;	/* freelist */ -static spinlock_t pool_lock;			/* protects page_address_pool */ +static struct page_address_map page_address_maps[LAST_PKMAP];  /*   * Hash table bucket @@ -326,7 +334,7 @@ static struct page_address_slot {  	spinlock_t lock;			/* Protect this bucket's list */  } ____cacheline_aligned_in_smp page_address_htable[1<<PA_HASH_ORDER]; -static struct page_address_slot *page_slot(struct page *page) +static struct page_address_slot *page_slot(const struct page *page)  {  	return &page_address_htable[hash_ptr(page, PA_HASH_ORDER)];  } @@ -337,7 +345,7 @@ static struct page_address_slot *page_slot(struct page *page)   *   * Returns the page's virtual address.   */ -void *page_address(struct page *page) +void *page_address(const struct page *page)  {  	unsigned long flags;  	void *ret; @@ -381,14 +389,7 @@ void set_page_address(struct page *page, void *virtual)  	pas = page_slot(page);  	if (virtual) {		/* Add */ -		BUG_ON(list_empty(&page_address_pool)); - -		spin_lock_irqsave(&pool_lock, flags); -		pam = list_entry(page_address_pool.next, -				struct page_address_map, list); -		list_del(&pam->list); -		spin_unlock_irqrestore(&pool_lock, flags); - +		pam = &page_address_maps[PKMAP_NR((unsigned long)virtual)];  		pam->page = page;  		pam->virtual = virtual; @@ -401,9 +402,6 @@ void set_page_address(struct page *page, void *virtual)  			if (pam->page == page) {  				list_del(&pam->list);  				spin_unlock_irqrestore(&pas->lock, flags); -				spin_lock_irqsave(&pool_lock, flags); -				list_add_tail(&pam->list, &page_address_pool); -				spin_unlock_irqrestore(&pool_lock, flags);  				goto done;  			}  		} @@ -413,20 +411,14 @@ done:  	return;  } -static struct page_address_map page_address_maps[LAST_PKMAP]; -  void __init page_address_init(void)  {  	int i; -	INIT_LIST_HEAD(&page_address_pool); -	for (i = 0; i < ARRAY_SIZE(page_address_maps); i++) -		list_add(&page_address_maps[i].list, &page_address_pool);  	for (i = 0; i < ARRAY_SIZE(page_address_htable); i++) {  		INIT_LIST_HEAD(&page_address_htable[i].lh);  		spin_lock_init(&page_address_htable[i].lock);  	} -	spin_lock_init(&pool_lock);  }  #endif	/* defined(CONFIG_HIGHMEM) && !defined(WANT_PAGE_VIRTUAL) */  | 
