Commit 2bd62a40 authored by Christoph Lameter's avatar Christoph Lameter Committed by Tony Luck

[IA64] Quicklist support for IA64

IA64 is the origin of the quicklist implementation.  So cut out the pieces
that are now in core code and modify the functions called.
Signed-off-by: default avatarChristoph Lameter <clameter@sgi.com>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
Signed-off-by: default avatarTony Luck <tony.luck@intel.com>
parent cdc7dbdf
...@@ -31,6 +31,10 @@ config ZONE_DMA ...@@ -31,6 +31,10 @@ config ZONE_DMA
def_bool y def_bool y
depends on !IA64_SGI_SN2 depends on !IA64_SGI_SN2
config QUICKLIST
bool
default y
config MMU config MMU
bool bool
default y default y
......
...@@ -88,7 +88,7 @@ void show_mem(void) ...@@ -88,7 +88,7 @@ void show_mem(void)
printk(KERN_INFO "%d pages shared\n", total_shared); printk(KERN_INFO "%d pages shared\n", total_shared);
printk(KERN_INFO "%d pages swap cached\n", total_cached); printk(KERN_INFO "%d pages swap cached\n", total_cached);
printk(KERN_INFO "Total of %ld pages in page table cache\n", printk(KERN_INFO "Total of %ld pages in page table cache\n",
pgtable_quicklist_total_size()); quicklist_total_size());
printk(KERN_INFO "%d free buffer pages\n", nr_free_buffer_pages()); printk(KERN_INFO "%d free buffer pages\n", nr_free_buffer_pages());
} }
......
...@@ -561,7 +561,7 @@ void show_mem(void) ...@@ -561,7 +561,7 @@ void show_mem(void)
printk(KERN_INFO "%d pages shared\n", total_shared); printk(KERN_INFO "%d pages shared\n", total_shared);
printk(KERN_INFO "%d pages swap cached\n", total_cached); printk(KERN_INFO "%d pages swap cached\n", total_cached);
printk(KERN_INFO "Total of %ld pages in page table cache\n", printk(KERN_INFO "Total of %ld pages in page table cache\n",
pgtable_quicklist_total_size()); quicklist_total_size());
printk(KERN_INFO "%d free buffer pages\n", nr_free_buffer_pages()); printk(KERN_INFO "%d free buffer pages\n", nr_free_buffer_pages());
} }
......
...@@ -39,9 +39,6 @@ ...@@ -39,9 +39,6 @@
DEFINE_PER_CPU(struct mmu_gather, mmu_gathers); DEFINE_PER_CPU(struct mmu_gather, mmu_gathers);
DEFINE_PER_CPU(unsigned long *, __pgtable_quicklist);
DEFINE_PER_CPU(long, __pgtable_quicklist_size);
extern void ia64_tlb_init (void); extern void ia64_tlb_init (void);
unsigned long MAX_DMA_ADDRESS = PAGE_OFFSET + 0x100000000UL; unsigned long MAX_DMA_ADDRESS = PAGE_OFFSET + 0x100000000UL;
...@@ -56,54 +53,6 @@ EXPORT_SYMBOL(vmem_map); ...@@ -56,54 +53,6 @@ EXPORT_SYMBOL(vmem_map);
struct page *zero_page_memmap_ptr; /* map entry for zero page */ struct page *zero_page_memmap_ptr; /* map entry for zero page */
EXPORT_SYMBOL(zero_page_memmap_ptr); EXPORT_SYMBOL(zero_page_memmap_ptr);
#define MIN_PGT_PAGES 25UL
#define MAX_PGT_FREES_PER_PASS 16L
#define PGT_FRACTION_OF_NODE_MEM 16
static inline long
max_pgt_pages(void)
{
u64 node_free_pages, max_pgt_pages;
#ifndef CONFIG_NUMA
node_free_pages = nr_free_pages();
#else
node_free_pages = node_page_state(numa_node_id(), NR_FREE_PAGES);
#endif
max_pgt_pages = node_free_pages / PGT_FRACTION_OF_NODE_MEM;
max_pgt_pages = max(max_pgt_pages, MIN_PGT_PAGES);
return max_pgt_pages;
}
static inline long
min_pages_to_free(void)
{
long pages_to_free;
pages_to_free = pgtable_quicklist_size - max_pgt_pages();
pages_to_free = min(pages_to_free, MAX_PGT_FREES_PER_PASS);
return pages_to_free;
}
void
check_pgt_cache(void)
{
long pages_to_free;
if (unlikely(pgtable_quicklist_size <= MIN_PGT_PAGES))
return;
preempt_disable();
while (unlikely((pages_to_free = min_pages_to_free()) > 0)) {
while (pages_to_free--) {
free_page((unsigned long)pgtable_quicklist_alloc());
}
preempt_enable();
preempt_disable();
}
preempt_enable();
}
void void
lazy_mmu_prot_update (pte_t pte) lazy_mmu_prot_update (pte_t pte)
{ {
......
...@@ -18,71 +18,18 @@ ...@@ -18,71 +18,18 @@
#include <linux/mm.h> #include <linux/mm.h>
#include <linux/page-flags.h> #include <linux/page-flags.h>
#include <linux/threads.h> #include <linux/threads.h>
#include <linux/quicklist.h>
#include <asm/mmu_context.h> #include <asm/mmu_context.h>
DECLARE_PER_CPU(unsigned long *, __pgtable_quicklist);
#define pgtable_quicklist __ia64_per_cpu_var(__pgtable_quicklist)
DECLARE_PER_CPU(long, __pgtable_quicklist_size);
#define pgtable_quicklist_size __ia64_per_cpu_var(__pgtable_quicklist_size)
static inline long pgtable_quicklist_total_size(void)
{
long ql_size = 0;
int cpuid;
for_each_online_cpu(cpuid) {
ql_size += per_cpu(__pgtable_quicklist_size, cpuid);
}
return ql_size;
}
static inline void *pgtable_quicklist_alloc(void)
{
unsigned long *ret = NULL;
preempt_disable();
ret = pgtable_quicklist;
if (likely(ret != NULL)) {
pgtable_quicklist = (unsigned long *)(*ret);
ret[0] = 0;
--pgtable_quicklist_size;
preempt_enable();
} else {
preempt_enable();
ret = (unsigned long *)__get_free_page(GFP_KERNEL | __GFP_ZERO);
}
return ret;
}
static inline void pgtable_quicklist_free(void *pgtable_entry)
{
#ifdef CONFIG_NUMA
int nid = page_to_nid(virt_to_page(pgtable_entry));
if (unlikely(nid != numa_node_id())) {
free_page((unsigned long)pgtable_entry);
return;
}
#endif
preempt_disable();
*(unsigned long *)pgtable_entry = (unsigned long)pgtable_quicklist;
pgtable_quicklist = (unsigned long *)pgtable_entry;
++pgtable_quicklist_size;
preempt_enable();
}
static inline pgd_t *pgd_alloc(struct mm_struct *mm) static inline pgd_t *pgd_alloc(struct mm_struct *mm)
{ {
return pgtable_quicklist_alloc(); return quicklist_alloc(0, GFP_KERNEL, NULL);
} }
static inline void pgd_free(pgd_t * pgd) static inline void pgd_free(pgd_t * pgd)
{ {
pgtable_quicklist_free(pgd); quicklist_free(0, NULL, pgd);
} }
#ifdef CONFIG_PGTABLE_4 #ifdef CONFIG_PGTABLE_4
...@@ -94,12 +41,12 @@ pgd_populate(struct mm_struct *mm, pgd_t * pgd_entry, pud_t * pud) ...@@ -94,12 +41,12 @@ pgd_populate(struct mm_struct *mm, pgd_t * pgd_entry, pud_t * pud)
static inline pud_t *pud_alloc_one(struct mm_struct *mm, unsigned long addr) static inline pud_t *pud_alloc_one(struct mm_struct *mm, unsigned long addr)
{ {
return pgtable_quicklist_alloc(); return quicklist_alloc(0, GFP_KERNEL, NULL);
} }
static inline void pud_free(pud_t * pud) static inline void pud_free(pud_t * pud)
{ {
pgtable_quicklist_free(pud); quicklist_free(0, NULL, pud);
} }
#define __pud_free_tlb(tlb, pud) pud_free(pud) #define __pud_free_tlb(tlb, pud) pud_free(pud)
#endif /* CONFIG_PGTABLE_4 */ #endif /* CONFIG_PGTABLE_4 */
...@@ -112,12 +59,12 @@ pud_populate(struct mm_struct *mm, pud_t * pud_entry, pmd_t * pmd) ...@@ -112,12 +59,12 @@ pud_populate(struct mm_struct *mm, pud_t * pud_entry, pmd_t * pmd)
static inline pmd_t *pmd_alloc_one(struct mm_struct *mm, unsigned long addr) static inline pmd_t *pmd_alloc_one(struct mm_struct *mm, unsigned long addr)
{ {
return pgtable_quicklist_alloc(); return quicklist_alloc(0, GFP_KERNEL, NULL);
} }
static inline void pmd_free(pmd_t * pmd) static inline void pmd_free(pmd_t * pmd)
{ {
pgtable_quicklist_free(pmd); quicklist_free(0, NULL, pmd);
} }
#define __pmd_free_tlb(tlb, pmd) pmd_free(pmd) #define __pmd_free_tlb(tlb, pmd) pmd_free(pmd)
...@@ -137,28 +84,31 @@ pmd_populate_kernel(struct mm_struct *mm, pmd_t * pmd_entry, pte_t * pte) ...@@ -137,28 +84,31 @@ pmd_populate_kernel(struct mm_struct *mm, pmd_t * pmd_entry, pte_t * pte)
static inline struct page *pte_alloc_one(struct mm_struct *mm, static inline struct page *pte_alloc_one(struct mm_struct *mm,
unsigned long addr) unsigned long addr)
{ {
void *pg = pgtable_quicklist_alloc(); void *pg = quicklist_alloc(0, GFP_KERNEL, NULL);
return pg ? virt_to_page(pg) : NULL; return pg ? virt_to_page(pg) : NULL;
} }
static inline pte_t *pte_alloc_one_kernel(struct mm_struct *mm, static inline pte_t *pte_alloc_one_kernel(struct mm_struct *mm,
unsigned long addr) unsigned long addr)
{ {
return pgtable_quicklist_alloc(); return quicklist_alloc(0, GFP_KERNEL, NULL);
} }
static inline void pte_free(struct page *pte) static inline void pte_free(struct page *pte)
{ {
pgtable_quicklist_free(page_address(pte)); quicklist_free_page(0, NULL, pte);
} }
static inline void pte_free_kernel(pte_t * pte) static inline void pte_free_kernel(pte_t * pte)
{ {
pgtable_quicklist_free(pte); quicklist_free(0, NULL, pte);
} }
#define __pte_free_tlb(tlb, pte) pte_free(pte) static inline void check_pgt_cache(void)
{
quicklist_trim(0, NULL, 25, 16);
}
extern void check_pgt_cache(void); #define __pte_free_tlb(tlb, pte) pte_free(pte)
#endif /* _ASM_IA64_PGALLOC_H */ #endif /* _ASM_IA64_PGALLOC_H */
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