aboutsummaryrefslogtreecommitdiffstats
path: root/arch/ia64/kernel
diff options
context:
space:
mode:
authorTony Luck <tony.luck@intel.com>2006-06-23 16:46:23 -0400
committerTony Luck <tony.luck@intel.com>2006-06-23 16:46:23 -0400
commit8cf60e04a131310199d5776e2f9e915f0c468899 (patch)
tree373a68e88e6737713a0a5723d552cdeefffff929 /arch/ia64/kernel
parent1323523f505606cfd24af6122369afddefc3b09d (diff)
parent95eaa5fa8eb2c345244acd5f65b200b115ae8c65 (diff)
Auto-update from upstream
Diffstat (limited to 'arch/ia64/kernel')
-rw-r--r--arch/ia64/kernel/acpi.c28
-rw-r--r--arch/ia64/kernel/entry.S2
-rw-r--r--arch/ia64/kernel/irq_ia64.c19
-rw-r--r--arch/ia64/kernel/perfmon.c10
-rw-r--r--arch/ia64/kernel/uncached.c200
5 files changed, 139 insertions, 120 deletions
diff --git a/arch/ia64/kernel/acpi.c b/arch/ia64/kernel/acpi.c
index 58c93a30348c..6ea642beaaee 100644
--- a/arch/ia64/kernel/acpi.c
+++ b/arch/ia64/kernel/acpi.c
@@ -68,8 +68,6 @@ EXPORT_SYMBOL(pm_power_off);
68unsigned char acpi_kbd_controller_present = 1; 68unsigned char acpi_kbd_controller_present = 1;
69unsigned char acpi_legacy_devices; 69unsigned char acpi_legacy_devices;
70 70
71static unsigned int __initdata acpi_madt_rev;
72
73unsigned int acpi_cpei_override; 71unsigned int acpi_cpei_override;
74unsigned int acpi_cpei_phys_cpuid; 72unsigned int acpi_cpei_phys_cpuid;
75 73
@@ -243,6 +241,8 @@ acpi_parse_iosapic(acpi_table_entry_header * header, const unsigned long end)
243 return iosapic_init(iosapic->address, iosapic->global_irq_base); 241 return iosapic_init(iosapic->address, iosapic->global_irq_base);
244} 242}
245 243
244static unsigned int __initdata acpi_madt_rev;
245
246static int __init 246static int __init
247acpi_parse_plat_int_src(acpi_table_entry_header * header, 247acpi_parse_plat_int_src(acpi_table_entry_header * header,
248 const unsigned long end) 248 const unsigned long end)
@@ -415,9 +415,6 @@ static int __initdata srat_num_cpus; /* number of cpus */
415static u32 __devinitdata pxm_flag[PXM_FLAG_LEN]; 415static u32 __devinitdata pxm_flag[PXM_FLAG_LEN];
416#define pxm_bit_set(bit) (set_bit(bit,(void *)pxm_flag)) 416#define pxm_bit_set(bit) (set_bit(bit,(void *)pxm_flag))
417#define pxm_bit_test(bit) (test_bit(bit,(void *)pxm_flag)) 417#define pxm_bit_test(bit) (test_bit(bit,(void *)pxm_flag))
418/* maps to convert between proximity domain and logical node ID */
419int __devinitdata pxm_to_nid_map[MAX_PXM_DOMAINS];
420int __initdata nid_to_pxm_map[MAX_NUMNODES];
421static struct acpi_table_slit __initdata *slit_table; 418static struct acpi_table_slit __initdata *slit_table;
422 419
423static int get_processor_proximity_domain(struct acpi_table_processor_affinity *pa) 420static int get_processor_proximity_domain(struct acpi_table_processor_affinity *pa)
@@ -533,22 +530,17 @@ void __init acpi_numa_arch_fixup(void)
533 * MCD - This can probably be dropped now. No need for pxm ID to node ID 530 * MCD - This can probably be dropped now. No need for pxm ID to node ID
534 * mapping with sparse node numbering iff MAX_PXM_DOMAINS <= MAX_NUMNODES. 531 * mapping with sparse node numbering iff MAX_PXM_DOMAINS <= MAX_NUMNODES.
535 */ 532 */
536 /* calculate total number of nodes in system from PXM bitmap */
537 memset(pxm_to_nid_map, -1, sizeof(pxm_to_nid_map));
538 memset(nid_to_pxm_map, -1, sizeof(nid_to_pxm_map));
539 nodes_clear(node_online_map); 533 nodes_clear(node_online_map);
540 for (i = 0; i < MAX_PXM_DOMAINS; i++) { 534 for (i = 0; i < MAX_PXM_DOMAINS; i++) {
541 if (pxm_bit_test(i)) { 535 if (pxm_bit_test(i)) {
542 int nid = num_online_nodes(); 536 int nid = acpi_map_pxm_to_node(i);
543 pxm_to_nid_map[i] = nid;
544 nid_to_pxm_map[nid] = i;
545 node_set_online(nid); 537 node_set_online(nid);
546 } 538 }
547 } 539 }
548 540
549 /* set logical node id in memory chunk structure */ 541 /* set logical node id in memory chunk structure */
550 for (i = 0; i < num_node_memblks; i++) 542 for (i = 0; i < num_node_memblks; i++)
551 node_memblk[i].nid = pxm_to_nid_map[node_memblk[i].nid]; 543 node_memblk[i].nid = pxm_to_node(node_memblk[i].nid);
552 544
553 /* assign memory bank numbers for each chunk on each node */ 545 /* assign memory bank numbers for each chunk on each node */
554 for_each_online_node(i) { 546 for_each_online_node(i) {
@@ -562,7 +554,7 @@ void __init acpi_numa_arch_fixup(void)
562 554
563 /* set logical node id in cpu structure */ 555 /* set logical node id in cpu structure */
564 for (i = 0; i < srat_num_cpus; i++) 556 for (i = 0; i < srat_num_cpus; i++)
565 node_cpuid[i].nid = pxm_to_nid_map[node_cpuid[i].nid]; 557 node_cpuid[i].nid = pxm_to_node(node_cpuid[i].nid);
566 558
567 printk(KERN_INFO "Number of logical nodes in system = %d\n", 559 printk(KERN_INFO "Number of logical nodes in system = %d\n",
568 num_online_nodes()); 560 num_online_nodes());
@@ -575,11 +567,11 @@ void __init acpi_numa_arch_fixup(void)
575 for (i = 0; i < slit_table->localities; i++) { 567 for (i = 0; i < slit_table->localities; i++) {
576 if (!pxm_bit_test(i)) 568 if (!pxm_bit_test(i))
577 continue; 569 continue;
578 node_from = pxm_to_nid_map[i]; 570 node_from = pxm_to_node(i);
579 for (j = 0; j < slit_table->localities; j++) { 571 for (j = 0; j < slit_table->localities; j++) {
580 if (!pxm_bit_test(j)) 572 if (!pxm_bit_test(j))
581 continue; 573 continue;
582 node_to = pxm_to_nid_map[j]; 574 node_to = pxm_to_node(j);
583 node_distance(node_from, node_to) = 575 node_distance(node_from, node_to) =
584 slit_table->entry[i * slit_table->localities + j]; 576 slit_table->entry[i * slit_table->localities + j];
585 } 577 }
@@ -785,9 +777,9 @@ int acpi_map_cpu2node(acpi_handle handle, int cpu, long physid)
785 777
786 /* 778 /*
787 * Assuming that the container driver would have set the proximity 779 * Assuming that the container driver would have set the proximity
788 * domain and would have initialized pxm_to_nid_map[pxm_id] && pxm_flag 780 * domain and would have initialized pxm_to_node(pxm_id) && pxm_flag
789 */ 781 */
790 node_cpuid[cpu].nid = (pxm_id < 0) ? 0 : pxm_to_nid_map[pxm_id]; 782 node_cpuid[cpu].nid = (pxm_id < 0) ? 0 : pxm_to_node(pxm_id);
791 783
792 node_cpuid[cpu].phys_id = physid; 784 node_cpuid[cpu].phys_id = physid;
793#endif 785#endif
@@ -966,7 +958,7 @@ acpi_map_iosapic(acpi_handle handle, u32 depth, void *context, void **ret)
966 if (pxm < 0) 958 if (pxm < 0)
967 return AE_OK; 959 return AE_OK;
968 960
969 node = pxm_to_nid_map[pxm]; 961 node = pxm_to_node(pxm);
970 962
971 if (node >= MAX_NUMNODES || !node_online(node) || 963 if (node >= MAX_NUMNODES || !node_online(node) ||
972 cpus_empty(node_to_cpumask(node))) 964 cpus_empty(node_to_cpumask(node)))
diff --git a/arch/ia64/kernel/entry.S b/arch/ia64/kernel/entry.S
index bcb80ca5cf40..32c999f58d12 100644
--- a/arch/ia64/kernel/entry.S
+++ b/arch/ia64/kernel/entry.S
@@ -1584,7 +1584,7 @@ sys_call_table:
1584 data8 sys_keyctl 1584 data8 sys_keyctl
1585 data8 sys_ioprio_set 1585 data8 sys_ioprio_set
1586 data8 sys_ioprio_get // 1275 1586 data8 sys_ioprio_get // 1275
1587 data8 sys_ni_syscall 1587 data8 sys_move_pages
1588 data8 sys_inotify_init 1588 data8 sys_inotify_init
1589 data8 sys_inotify_add_watch 1589 data8 sys_inotify_add_watch
1590 data8 sys_inotify_rm_watch 1590 data8 sys_inotify_rm_watch
diff --git a/arch/ia64/kernel/irq_ia64.c b/arch/ia64/kernel/irq_ia64.c
index 6c4d59fd0364..ef9a2b49307a 100644
--- a/arch/ia64/kernel/irq_ia64.c
+++ b/arch/ia64/kernel/irq_ia64.c
@@ -46,6 +46,10 @@
46 46
47#define IRQ_DEBUG 0 47#define IRQ_DEBUG 0
48 48
49/* These can be overridden in platform_irq_init */
50int ia64_first_device_vector = IA64_DEF_FIRST_DEVICE_VECTOR;
51int ia64_last_device_vector = IA64_DEF_LAST_DEVICE_VECTOR;
52
49/* default base addr of IPI table */ 53/* default base addr of IPI table */
50void __iomem *ipi_base_addr = ((void __iomem *) 54void __iomem *ipi_base_addr = ((void __iomem *)
51 (__IA64_UNCACHED_OFFSET | IA64_IPI_DEFAULT_BASE_ADDR)); 55 (__IA64_UNCACHED_OFFSET | IA64_IPI_DEFAULT_BASE_ADDR));
@@ -60,7 +64,7 @@ __u8 isa_irq_to_vector_map[16] = {
60}; 64};
61EXPORT_SYMBOL(isa_irq_to_vector_map); 65EXPORT_SYMBOL(isa_irq_to_vector_map);
62 66
63static unsigned long ia64_vector_mask[BITS_TO_LONGS(IA64_NUM_DEVICE_VECTORS)]; 67static unsigned long ia64_vector_mask[BITS_TO_LONGS(IA64_MAX_DEVICE_VECTORS)];
64 68
65int 69int
66assign_irq_vector (int irq) 70assign_irq_vector (int irq)
@@ -89,6 +93,19 @@ free_irq_vector (int vector)
89 printk(KERN_WARNING "%s: double free!\n", __FUNCTION__); 93 printk(KERN_WARNING "%s: double free!\n", __FUNCTION__);
90} 94}
91 95
96int
97reserve_irq_vector (int vector)
98{
99 int pos;
100
101 if (vector < IA64_FIRST_DEVICE_VECTOR ||
102 vector > IA64_LAST_DEVICE_VECTOR)
103 return -EINVAL;
104
105 pos = vector - IA64_FIRST_DEVICE_VECTOR;
106 return test_and_set_bit(pos, ia64_vector_mask);
107}
108
92#ifdef CONFIG_SMP 109#ifdef CONFIG_SMP
93# define IS_RESCHEDULE(vec) (vec == IA64_IPI_RESCHEDULE) 110# define IS_RESCHEDULE(vec) (vec == IA64_IPI_RESCHEDULE)
94#else 111#else
diff --git a/arch/ia64/kernel/perfmon.c b/arch/ia64/kernel/perfmon.c
index 077f21216b65..6d7bc8ff7b3a 100644
--- a/arch/ia64/kernel/perfmon.c
+++ b/arch/ia64/kernel/perfmon.c
@@ -532,7 +532,6 @@ static ctl_table pfm_sysctl_root[] = {
532static struct ctl_table_header *pfm_sysctl_header; 532static struct ctl_table_header *pfm_sysctl_header;
533 533
534static int pfm_context_unload(pfm_context_t *ctx, void *arg, int count, struct pt_regs *regs); 534static int pfm_context_unload(pfm_context_t *ctx, void *arg, int count, struct pt_regs *regs);
535static int pfm_flush(struct file *filp);
536 535
537#define pfm_get_cpu_var(v) __ia64_per_cpu_var(v) 536#define pfm_get_cpu_var(v) __ia64_per_cpu_var(v)
538#define pfm_get_cpu_data(a,b) per_cpu(a, b) 537#define pfm_get_cpu_data(a,b) per_cpu(a, b)
@@ -595,10 +594,11 @@ pfm_get_unmapped_area(struct file *file, unsigned long addr, unsigned long len,
595} 594}
596 595
597 596
598static struct super_block * 597static int
599pfmfs_get_sb(struct file_system_type *fs_type, int flags, const char *dev_name, void *data) 598pfmfs_get_sb(struct file_system_type *fs_type, int flags, const char *dev_name, void *data,
599 struct vfsmount *mnt)
600{ 600{
601 return get_sb_pseudo(fs_type, "pfm:", NULL, PFMFS_MAGIC); 601 return get_sb_pseudo(fs_type, "pfm:", NULL, PFMFS_MAGIC, mnt);
602} 602}
603 603
604static struct file_system_type pfm_fs_type = { 604static struct file_system_type pfm_fs_type = {
@@ -1773,7 +1773,7 @@ pfm_syswide_cleanup_other_cpu(pfm_context_t *ctx)
1773 * When caller is self-monitoring, the context is unloaded. 1773 * When caller is self-monitoring, the context is unloaded.
1774 */ 1774 */
1775static int 1775static int
1776pfm_flush(struct file *filp) 1776pfm_flush(struct file *filp, fl_owner_t id)
1777{ 1777{
1778 pfm_context_t *ctx; 1778 pfm_context_t *ctx;
1779 struct task_struct *task; 1779 struct task_struct *task;
diff --git a/arch/ia64/kernel/uncached.c b/arch/ia64/kernel/uncached.c
index fcd2bad0286f..5f03b9e524dd 100644
--- a/arch/ia64/kernel/uncached.c
+++ b/arch/ia64/kernel/uncached.c
@@ -1,5 +1,5 @@
1/* 1/*
2 * Copyright (C) 2001-2005 Silicon Graphics, Inc. All rights reserved. 2 * Copyright (C) 2001-2006 Silicon Graphics, Inc. All rights reserved.
3 * 3 *
4 * This program is free software; you can redistribute it and/or modify it 4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of version 2 of the GNU General Public License 5 * under the terms of version 2 of the GNU General Public License
@@ -29,15 +29,8 @@
29#include <asm/tlbflush.h> 29#include <asm/tlbflush.h>
30#include <asm/sn/arch.h> 30#include <asm/sn/arch.h>
31 31
32#define DEBUG 0
33 32
34#if DEBUG 33extern void __init efi_memmap_walk_uc(efi_freemem_callback_t, void *);
35#define dprintk printk
36#else
37#define dprintk(x...) do { } while (0)
38#endif
39
40void __init efi_memmap_walk_uc (efi_freemem_callback_t callback);
41 34
42#define MAX_UNCACHED_GRANULES 5 35#define MAX_UNCACHED_GRANULES 5
43static int allocated_granules; 36static int allocated_granules;
@@ -60,6 +53,7 @@ static void uncached_ipi_visibility(void *data)
60static void uncached_ipi_mc_drain(void *data) 53static void uncached_ipi_mc_drain(void *data)
61{ 54{
62 int status; 55 int status;
56
63 status = ia64_pal_mc_drain(); 57 status = ia64_pal_mc_drain();
64 if (status) 58 if (status)
65 printk(KERN_WARNING "ia64_pal_mc_drain() failed with %i on " 59 printk(KERN_WARNING "ia64_pal_mc_drain() failed with %i on "
@@ -67,30 +61,35 @@ static void uncached_ipi_mc_drain(void *data)
67} 61}
68 62
69 63
70static unsigned long 64/*
71uncached_get_new_chunk(struct gen_pool *poolp) 65 * Add a new chunk of uncached memory pages to the specified pool.
66 *
67 * @pool: pool to add new chunk of uncached memory to
68 * @nid: node id of node to allocate memory from, or -1
69 *
70 * This is accomplished by first allocating a granule of cached memory pages
71 * and then converting them to uncached memory pages.
72 */
73static int uncached_add_chunk(struct gen_pool *pool, int nid)
72{ 74{
73 struct page *page; 75 struct page *page;
74 void *tmp;
75 int status, i; 76 int status, i;
76 unsigned long addr, node; 77 unsigned long c_addr, uc_addr;
77 78
78 if (allocated_granules >= MAX_UNCACHED_GRANULES) 79 if (allocated_granules >= MAX_UNCACHED_GRANULES)
79 return 0; 80 return -1;
81
82 /* attempt to allocate a granule's worth of cached memory pages */
80 83
81 node = poolp->private; 84 page = alloc_pages_node(nid, GFP_KERNEL | __GFP_ZERO,
82 page = alloc_pages_node(node, GFP_KERNEL | __GFP_ZERO,
83 IA64_GRANULE_SHIFT-PAGE_SHIFT); 85 IA64_GRANULE_SHIFT-PAGE_SHIFT);
86 if (!page)
87 return -1;
84 88
85 dprintk(KERN_INFO "get_new_chunk page %p, addr %lx\n", 89 /* convert the memory pages from cached to uncached */
86 page, (unsigned long)(page-vmem_map) << PAGE_SHIFT);
87 90
88 /* 91 c_addr = (unsigned long)page_address(page);
89 * Do magic if no mem on local node! XXX 92 uc_addr = c_addr - PAGE_OFFSET + __IA64_UNCACHED_OFFSET;
90 */
91 if (!page)
92 return 0;
93 tmp = page_address(page);
94 93
95 /* 94 /*
96 * There's a small race here where it's possible for someone to 95 * There's a small race here where it's possible for someone to
@@ -100,76 +99,90 @@ uncached_get_new_chunk(struct gen_pool *poolp)
100 for (i = 0; i < (IA64_GRANULE_SIZE / PAGE_SIZE); i++) 99 for (i = 0; i < (IA64_GRANULE_SIZE / PAGE_SIZE); i++)
101 SetPageUncached(&page[i]); 100 SetPageUncached(&page[i]);
102 101
103 flush_tlb_kernel_range(tmp, tmp + IA64_GRANULE_SIZE); 102 flush_tlb_kernel_range(uc_addr, uc_adddr + IA64_GRANULE_SIZE);
104 103
105 status = ia64_pal_prefetch_visibility(PAL_VISIBILITY_PHYSICAL); 104 status = ia64_pal_prefetch_visibility(PAL_VISIBILITY_PHYSICAL);
106
107 dprintk(KERN_INFO "pal_prefetch_visibility() returns %i on cpu %i\n",
108 status, raw_smp_processor_id());
109
110 if (!status) { 105 if (!status) {
111 status = smp_call_function(uncached_ipi_visibility, NULL, 0, 1); 106 status = smp_call_function(uncached_ipi_visibility, NULL, 0, 1);
112 if (status) 107 if (status)
113 printk(KERN_WARNING "smp_call_function failed for " 108 goto failed;
114 "uncached_ipi_visibility! (%i)\n", status);
115 } 109 }
116 110
111 preempt_disable();
112
117 if (ia64_platform_is("sn2")) 113 if (ia64_platform_is("sn2"))
118 sn_flush_all_caches((unsigned long)tmp, IA64_GRANULE_SIZE); 114 sn_flush_all_caches(uc_addr, IA64_GRANULE_SIZE);
119 else 115 else
120 flush_icache_range((unsigned long)tmp, 116 flush_icache_range(uc_addr, uc_addr + IA64_GRANULE_SIZE);
121 (unsigned long)tmp+IA64_GRANULE_SIZE); 117
118 /* flush the just introduced uncached translation from the TLB */
119 local_flush_tlb_all();
120
121 preempt_enable();
122 122
123 ia64_pal_mc_drain(); 123 ia64_pal_mc_drain();
124 status = smp_call_function(uncached_ipi_mc_drain, NULL, 0, 1); 124 status = smp_call_function(uncached_ipi_mc_drain, NULL, 0, 1);
125 if (status) 125 if (status)
126 printk(KERN_WARNING "smp_call_function failed for " 126 goto failed;
127 "uncached_ipi_mc_drain! (%i)\n", status);
128 127
129 addr = (unsigned long)tmp - PAGE_OFFSET + __IA64_UNCACHED_OFFSET; 128 /*
129 * The chunk of memory pages has been converted to uncached so now we
130 * can add it to the pool.
131 */
132 status = gen_pool_add(pool, uc_addr, IA64_GRANULE_SIZE, nid);
133 if (status)
134 goto failed;
130 135
131 allocated_granules++; 136 allocated_granules++;
132 return addr; 137 return 0;
138
139 /* failed to convert or add the chunk so give it back to the kernel */
140failed:
141 for (i = 0; i < (IA64_GRANULE_SIZE / PAGE_SIZE); i++)
142 ClearPageUncached(&page[i]);
143
144 free_pages(c_addr, IA64_GRANULE_SHIFT-PAGE_SHIFT);
145 return -1;
133} 146}
134 147
135 148
136/* 149/*
137 * uncached_alloc_page 150 * uncached_alloc_page
138 * 151 *
152 * @starting_nid: node id of node to start with, or -1
153 *
139 * Allocate 1 uncached page. Allocates on the requested node. If no 154 * Allocate 1 uncached page. Allocates on the requested node. If no
140 * uncached pages are available on the requested node, roundrobin starting 155 * uncached pages are available on the requested node, roundrobin starting
141 * with higher nodes. 156 * with the next higher node.
142 */ 157 */
143unsigned long 158unsigned long uncached_alloc_page(int starting_nid)
144uncached_alloc_page(int nid)
145{ 159{
146 unsigned long maddr; 160 unsigned long uc_addr;
161 struct gen_pool *pool;
162 int nid;
147 163
148 maddr = gen_pool_alloc(uncached_pool[nid], PAGE_SIZE); 164 if (unlikely(starting_nid >= MAX_NUMNODES))
165 return 0;
149 166
150 dprintk(KERN_DEBUG "uncached_alloc_page returns %lx on node %i\n", 167 if (starting_nid < 0)
151 maddr, nid); 168 starting_nid = numa_node_id();
169 nid = starting_nid;
152 170
153 /* 171 do {
154 * If no memory is availble on our local node, try the 172 if (!node_online(nid))
155 * remaining nodes in the system. 173 continue;
156 */ 174 pool = uncached_pool[nid];
157 if (!maddr) { 175 if (pool == NULL)
158 int i; 176 continue;
159 177 do {
160 for (i = MAX_NUMNODES - 1; i >= 0; i--) { 178 uc_addr = gen_pool_alloc(pool, PAGE_SIZE);
161 if (i == nid || !node_online(i)) 179 if (uc_addr != 0)
162 continue; 180 return uc_addr;
163 maddr = gen_pool_alloc(uncached_pool[i], PAGE_SIZE); 181 } while (uncached_add_chunk(pool, nid) == 0);
164 dprintk(KERN_DEBUG "uncached_alloc_page alternate search " 182
165 "returns %lx on node %i\n", maddr, i); 183 } while ((nid = (nid + 1) % MAX_NUMNODES) != starting_nid);
166 if (maddr) {
167 break;
168 }
169 }
170 }
171 184
172 return maddr; 185 return 0;
173} 186}
174EXPORT_SYMBOL(uncached_alloc_page); 187EXPORT_SYMBOL(uncached_alloc_page);
175 188
@@ -177,21 +190,22 @@ EXPORT_SYMBOL(uncached_alloc_page);
177/* 190/*
178 * uncached_free_page 191 * uncached_free_page
179 * 192 *
193 * @uc_addr: uncached address of page to free
194 *
180 * Free a single uncached page. 195 * Free a single uncached page.
181 */ 196 */
182void 197void uncached_free_page(unsigned long uc_addr)
183uncached_free_page(unsigned long maddr)
184{ 198{
185 int node; 199 int nid = paddr_to_nid(uc_addr - __IA64_UNCACHED_OFFSET);
186 200 struct gen_pool *pool = uncached_pool[nid];
187 node = paddr_to_nid(maddr - __IA64_UNCACHED_OFFSET);
188 201
189 dprintk(KERN_DEBUG "uncached_free_page(%lx) on node %i\n", maddr, node); 202 if (unlikely(pool == NULL))
203 return;
190 204
191 if ((maddr & (0XFUL << 60)) != __IA64_UNCACHED_OFFSET) 205 if ((uc_addr & (0XFUL << 60)) != __IA64_UNCACHED_OFFSET)
192 panic("uncached_free_page invalid address %lx\n", maddr); 206 panic("uncached_free_page invalid address %lx\n", uc_addr);
193 207
194 gen_pool_free(uncached_pool[node], maddr, PAGE_SIZE); 208 gen_pool_free(pool, uc_addr, PAGE_SIZE);
195} 209}
196EXPORT_SYMBOL(uncached_free_page); 210EXPORT_SYMBOL(uncached_free_page);
197 211
@@ -199,43 +213,39 @@ EXPORT_SYMBOL(uncached_free_page);
199/* 213/*
200 * uncached_build_memmap, 214 * uncached_build_memmap,
201 * 215 *
216 * @uc_start: uncached starting address of a chunk of uncached memory
217 * @uc_end: uncached ending address of a chunk of uncached memory
218 * @arg: ignored, (NULL argument passed in on call to efi_memmap_walk_uc())
219 *
202 * Called at boot time to build a map of pages that can be used for 220 * Called at boot time to build a map of pages that can be used for
203 * memory special operations. 221 * memory special operations.
204 */ 222 */
205static int __init 223static int __init uncached_build_memmap(unsigned long uc_start,
206uncached_build_memmap(unsigned long start, unsigned long end, void *arg) 224 unsigned long uc_end, void *arg)
207{ 225{
208 long length = end - start; 226 int nid = paddr_to_nid(uc_start - __IA64_UNCACHED_OFFSET);
209 int node; 227 struct gen_pool *pool = uncached_pool[nid];
210 228 size_t size = uc_end - uc_start;
211 dprintk(KERN_ERR "uncached_build_memmap(%lx %lx)\n", start, end);
212 229
213 touch_softlockup_watchdog(); 230 touch_softlockup_watchdog();
214 memset((char *)start, 0, length);
215 231
216 node = paddr_to_nid(start - __IA64_UNCACHED_OFFSET); 232 if (pool != NULL) {
217 233 memset((char *)uc_start, 0, size);
218 for (; start < end ; start += PAGE_SIZE) { 234 (void) gen_pool_add(pool, uc_start, size, nid);
219 dprintk(KERN_INFO "sticking %lx into the pool!\n", start);
220 gen_pool_free(uncached_pool[node], start, PAGE_SIZE);
221 } 235 }
222
223 return 0; 236 return 0;
224} 237}
225 238
226 239
227static int __init uncached_init(void) { 240static int __init uncached_init(void)
228 int i; 241{
242 int nid;
229 243
230 for (i = 0; i < MAX_NUMNODES; i++) { 244 for_each_online_node(nid) {
231 if (!node_online(i)) 245 uncached_pool[nid] = gen_pool_create(PAGE_SHIFT, nid);
232 continue;
233 uncached_pool[i] = gen_pool_create(0, IA64_GRANULE_SHIFT,
234 &uncached_get_new_chunk, i);
235 } 246 }
236 247
237 efi_memmap_walk_uc(uncached_build_memmap); 248 efi_memmap_walk_uc(uncached_build_memmap, NULL);
238
239 return 0; 249 return 0;
240} 250}
241 251