diff options
author | Tony Luck <tony.luck@intel.com> | 2006-06-23 16:46:23 -0400 |
---|---|---|
committer | Tony Luck <tony.luck@intel.com> | 2006-06-23 16:46:23 -0400 |
commit | 8cf60e04a131310199d5776e2f9e915f0c468899 (patch) | |
tree | 373a68e88e6737713a0a5723d552cdeefffff929 /arch/ia64/kernel | |
parent | 1323523f505606cfd24af6122369afddefc3b09d (diff) | |
parent | 95eaa5fa8eb2c345244acd5f65b200b115ae8c65 (diff) |
Auto-update from upstream
Diffstat (limited to 'arch/ia64/kernel')
-rw-r--r-- | arch/ia64/kernel/acpi.c | 28 | ||||
-rw-r--r-- | arch/ia64/kernel/entry.S | 2 | ||||
-rw-r--r-- | arch/ia64/kernel/irq_ia64.c | 19 | ||||
-rw-r--r-- | arch/ia64/kernel/perfmon.c | 10 | ||||
-rw-r--r-- | arch/ia64/kernel/uncached.c | 200 |
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); | |||
68 | unsigned char acpi_kbd_controller_present = 1; | 68 | unsigned char acpi_kbd_controller_present = 1; |
69 | unsigned char acpi_legacy_devices; | 69 | unsigned char acpi_legacy_devices; |
70 | 70 | ||
71 | static unsigned int __initdata acpi_madt_rev; | ||
72 | |||
73 | unsigned int acpi_cpei_override; | 71 | unsigned int acpi_cpei_override; |
74 | unsigned int acpi_cpei_phys_cpuid; | 72 | unsigned 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 | ||
244 | static unsigned int __initdata acpi_madt_rev; | ||
245 | |||
246 | static int __init | 246 | static int __init |
247 | acpi_parse_plat_int_src(acpi_table_entry_header * header, | 247 | acpi_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 */ | |||
415 | static u32 __devinitdata pxm_flag[PXM_FLAG_LEN]; | 415 | static 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 */ | ||
419 | int __devinitdata pxm_to_nid_map[MAX_PXM_DOMAINS]; | ||
420 | int __initdata nid_to_pxm_map[MAX_NUMNODES]; | ||
421 | static struct acpi_table_slit __initdata *slit_table; | 418 | static struct acpi_table_slit __initdata *slit_table; |
422 | 419 | ||
423 | static int get_processor_proximity_domain(struct acpi_table_processor_affinity *pa) | 420 | static 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 */ | ||
50 | int ia64_first_device_vector = IA64_DEF_FIRST_DEVICE_VECTOR; | ||
51 | int ia64_last_device_vector = IA64_DEF_LAST_DEVICE_VECTOR; | ||
52 | |||
49 | /* default base addr of IPI table */ | 53 | /* default base addr of IPI table */ |
50 | void __iomem *ipi_base_addr = ((void __iomem *) | 54 | void __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 | }; |
61 | EXPORT_SYMBOL(isa_irq_to_vector_map); | 65 | EXPORT_SYMBOL(isa_irq_to_vector_map); |
62 | 66 | ||
63 | static unsigned long ia64_vector_mask[BITS_TO_LONGS(IA64_NUM_DEVICE_VECTORS)]; | 67 | static unsigned long ia64_vector_mask[BITS_TO_LONGS(IA64_MAX_DEVICE_VECTORS)]; |
64 | 68 | ||
65 | int | 69 | int |
66 | assign_irq_vector (int irq) | 70 | assign_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 | ||
96 | int | ||
97 | reserve_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[] = { | |||
532 | static struct ctl_table_header *pfm_sysctl_header; | 532 | static struct ctl_table_header *pfm_sysctl_header; |
533 | 533 | ||
534 | static int pfm_context_unload(pfm_context_t *ctx, void *arg, int count, struct pt_regs *regs); | 534 | static int pfm_context_unload(pfm_context_t *ctx, void *arg, int count, struct pt_regs *regs); |
535 | static 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 | ||
598 | static struct super_block * | 597 | static int |
599 | pfmfs_get_sb(struct file_system_type *fs_type, int flags, const char *dev_name, void *data) | 598 | pfmfs_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 | ||
604 | static struct file_system_type pfm_fs_type = { | 604 | static 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 | */ |
1775 | static int | 1775 | static int |
1776 | pfm_flush(struct file *filp) | 1776 | pfm_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 | 33 | extern 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 | |||
40 | void __init efi_memmap_walk_uc (efi_freemem_callback_t callback); | ||
41 | 34 | ||
42 | #define MAX_UNCACHED_GRANULES 5 | 35 | #define MAX_UNCACHED_GRANULES 5 |
43 | static int allocated_granules; | 36 | static int allocated_granules; |
@@ -60,6 +53,7 @@ static void uncached_ipi_visibility(void *data) | |||
60 | static void uncached_ipi_mc_drain(void *data) | 53 | static 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 | ||
70 | static unsigned long | 64 | /* |
71 | uncached_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 | */ | ||
73 | static 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 */ | ||
140 | failed: | ||
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 | */ |
143 | unsigned long | 158 | unsigned long uncached_alloc_page(int starting_nid) |
144 | uncached_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 | } |
174 | EXPORT_SYMBOL(uncached_alloc_page); | 187 | EXPORT_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 | */ |
182 | void | 197 | void uncached_free_page(unsigned long uc_addr) |
183 | uncached_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 | } |
196 | EXPORT_SYMBOL(uncached_free_page); | 210 | EXPORT_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 | */ |
205 | static int __init | 223 | static int __init uncached_build_memmap(unsigned long uc_start, |
206 | uncached_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 | ||
227 | static int __init uncached_init(void) { | 240 | static 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 | ||