Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

[IA64] allocate multiple contiguous pages via uncached allocator

Enable the uncached allocator to allocate multiple pages of contiguous
uncached memory.

Signed-off-by: Dean Nelson <dcn@sgi.com>
Signed-off-by: Tony Luck <tony.luck@intel.com>

authored by

Dean Nelson and committed by
Tony Luck
e4a064df e617fce6

+24 -21
+13 -10
arch/ia64/kernel/uncached.c
··· 1 1 /* 2 - * Copyright (C) 2001-2006 Silicon Graphics, Inc. All rights reserved. 2 + * Copyright (C) 2001-2008 Silicon Graphics, Inc. All rights reserved. 3 3 * 4 4 * This program is free software; you can redistribute it and/or modify it 5 5 * under the terms of version 2 of the GNU General Public License ··· 177 177 * uncached_alloc_page 178 178 * 179 179 * @starting_nid: node id of node to start with, or -1 180 + * @n_pages: number of contiguous pages to allocate 180 181 * 181 - * Allocate 1 uncached page. Allocates on the requested node. If no 182 - * uncached pages are available on the requested node, roundrobin starting 183 - * with the next higher node. 182 + * Allocate the specified number of contiguous uncached pages on the 183 + * the requested node. If not enough contiguous uncached pages are available 184 + * on the requested node, roundrobin starting with the next higher node. 184 185 */ 185 - unsigned long uncached_alloc_page(int starting_nid) 186 + unsigned long uncached_alloc_page(int starting_nid, int n_pages) 186 187 { 187 188 unsigned long uc_addr; 188 189 struct uncached_pool *uc_pool; ··· 203 202 if (uc_pool->pool == NULL) 204 203 continue; 205 204 do { 206 - uc_addr = gen_pool_alloc(uc_pool->pool, PAGE_SIZE); 205 + uc_addr = gen_pool_alloc(uc_pool->pool, 206 + n_pages * PAGE_SIZE); 207 207 if (uc_addr != 0) 208 208 return uc_addr; 209 209 } while (uncached_add_chunk(uc_pool, nid) == 0); ··· 219 217 /* 220 218 * uncached_free_page 221 219 * 222 - * @uc_addr: uncached address of page to free 220 + * @uc_addr: uncached address of first page to free 221 + * @n_pages: number of contiguous pages to free 223 222 * 224 - * Free a single uncached page. 223 + * Free the specified number of uncached pages. 225 224 */ 226 - void uncached_free_page(unsigned long uc_addr) 225 + void uncached_free_page(unsigned long uc_addr, int n_pages) 227 226 { 228 227 int nid = paddr_to_nid(uc_addr - __IA64_UNCACHED_OFFSET); 229 228 struct gen_pool *pool = uncached_pools[nid].pool; ··· 235 232 if ((uc_addr & (0XFUL << 60)) != __IA64_UNCACHED_OFFSET) 236 233 panic("uncached_free_page invalid address %lx\n", uc_addr); 237 234 238 - gen_pool_free(pool, uc_addr, PAGE_SIZE); 235 + gen_pool_free(pool, uc_addr, n_pages * PAGE_SIZE); 239 236 } 240 237 EXPORT_SYMBOL(uncached_free_page); 241 238
+6 -6
drivers/char/mspec.c
··· 180 180 my_page = vdata->maddr[index]; 181 181 vdata->maddr[index] = 0; 182 182 if (!mspec_zero_block(my_page, PAGE_SIZE)) 183 - uncached_free_page(my_page); 183 + uncached_free_page(my_page, 1); 184 184 else 185 185 printk(KERN_WARNING "mspec_close(): " 186 186 "failed to zero page %ld\n", my_page); ··· 209 209 index = (address - vdata->vm_start) >> PAGE_SHIFT; 210 210 maddr = (volatile unsigned long) vdata->maddr[index]; 211 211 if (maddr == 0) { 212 - maddr = uncached_alloc_page(numa_node_id()); 212 + maddr = uncached_alloc_page(numa_node_id(), 1); 213 213 if (maddr == 0) 214 214 return NOPFN_OOM; 215 215 ··· 218 218 vdata->count++; 219 219 vdata->maddr[index] = maddr; 220 220 } else { 221 - uncached_free_page(maddr); 221 + uncached_free_page(maddr, 1); 222 222 maddr = vdata->maddr[index]; 223 223 } 224 224 spin_unlock(&vdata->lock); ··· 367 367 int nasid; 368 368 unsigned long phys; 369 369 370 - scratch_page[nid] = uncached_alloc_page(nid); 370 + scratch_page[nid] = uncached_alloc_page(nid, 1); 371 371 if (scratch_page[nid] == 0) 372 372 goto free_scratch_pages; 373 373 phys = __pa(scratch_page[nid]); ··· 414 414 free_scratch_pages: 415 415 for_each_node(nid) { 416 416 if (scratch_page[nid] != 0) 417 - uncached_free_page(scratch_page[nid]); 417 + uncached_free_page(scratch_page[nid], 1); 418 418 } 419 419 return ret; 420 420 } ··· 431 431 432 432 for_each_node(nid) { 433 433 if (scratch_page[nid] != 0) 434 - uncached_free_page(scratch_page[nid]); 434 + uncached_free_page(scratch_page[nid], 1); 435 435 } 436 436 } 437 437 }
+2 -2
drivers/misc/sgi-xp/xpc_partition.c
··· 211 211 */ 212 212 amos_page = xpc_vars->amos_page; 213 213 if (amos_page == NULL) { 214 - amos_page = (AMO_t *)TO_AMO(uncached_alloc_page(0)); 214 + amos_page = (AMO_t *)TO_AMO(uncached_alloc_page(0, 1)); 215 215 if (amos_page == NULL) { 216 216 dev_err(xpc_part, "can't allocate page of AMOs\n"); 217 217 return NULL; ··· 230 230 dev_err(xpc_part, "can't change memory " 231 231 "protections\n"); 232 232 uncached_free_page(__IA64_UNCACHED_OFFSET | 233 - TO_PHYS((u64)amos_page)); 233 + TO_PHYS((u64)amos_page), 1); 234 234 return NULL; 235 235 } 236 236 }
+3 -3
include/asm-ia64/uncached.h
··· 1 1 /* 2 - * Copyright (C) 2001-2005 Silicon Graphics, Inc. All rights reserved. 2 + * Copyright (C) 2001-2008 Silicon Graphics, Inc. All rights reserved. 3 3 * 4 4 * This program is free software; you can redistribute it and/or modify it 5 5 * under the terms of version 2 of the GNU General Public License ··· 8 8 * Prototypes for the uncached page allocator 9 9 */ 10 10 11 - extern unsigned long uncached_alloc_page(int nid); 12 - extern void uncached_free_page(unsigned long); 11 + extern unsigned long uncached_alloc_page(int starting_nid, int n_pages); 12 + extern void uncached_free_page(unsigned long uc_addr, int n_pages);