aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
Diffstat (limited to 'arch')
-rw-r--r--arch/x86/mm/k8topology_64.c144
1 files changed, 72 insertions, 72 deletions
diff --git a/arch/x86/mm/k8topology_64.c b/arch/x86/mm/k8topology_64.c
index 3695c9e8b9b6..32b963de9b8f 100644
--- a/arch/x86/mm/k8topology_64.c
+++ b/arch/x86/mm/k8topology_64.c
@@ -1,9 +1,9 @@
1/* 1/*
2 * AMD K8 NUMA support. 2 * AMD K8 NUMA support.
3 * Discover the memory map and associated nodes. 3 * Discover the memory map and associated nodes.
4 * 4 *
5 * This version reads it directly from the K8 northbridge. 5 * This version reads it directly from the K8 northbridge.
6 * 6 *
7 * Copyright 2002,2003 Andi Kleen, SuSE Labs. 7 * Copyright 2002,2003 Andi Kleen, SuSE Labs.
8 */ 8 */
9#include <linux/kernel.h> 9#include <linux/kernel.h>
@@ -22,26 +22,26 @@
22 22
23static __init int find_northbridge(void) 23static __init int find_northbridge(void)
24{ 24{
25 int num; 25 int num;
26 26
27 for (num = 0; num < 32; num++) { 27 for (num = 0; num < 32; num++) {
28 u32 header; 28 u32 header;
29 29
30 header = read_pci_config(0, num, 0, 0x00); 30 header = read_pci_config(0, num, 0, 0x00);
31 if (header != (PCI_VENDOR_ID_AMD | (0x1100<<16))) 31 if (header != (PCI_VENDOR_ID_AMD | (0x1100<<16)))
32 continue; 32 continue;
33 33
34 header = read_pci_config(0, num, 1, 0x00); 34 header = read_pci_config(0, num, 1, 0x00);
35 if (header != (PCI_VENDOR_ID_AMD | (0x1101<<16))) 35 if (header != (PCI_VENDOR_ID_AMD | (0x1101<<16)))
36 continue; 36 continue;
37 return num; 37 return num;
38 } 38 }
39 39
40 return -1; 40 return -1;
41} 41}
42 42
43int __init k8_scan_nodes(unsigned long start, unsigned long end) 43int __init k8_scan_nodes(unsigned long start, unsigned long end)
44{ 44{
45 unsigned long prevbase; 45 unsigned long prevbase;
46 struct bootnode nodes[8]; 46 struct bootnode nodes[8];
47 int nodeid, i, nb; 47 int nodeid, i, nb;
@@ -56,97 +56,97 @@ int __init k8_scan_nodes(unsigned long start, unsigned long end)
56 if (!early_pci_allowed()) 56 if (!early_pci_allowed())
57 return -1; 57 return -1;
58 58
59 nb = find_northbridge(); 59 nb = find_northbridge();
60 if (nb < 0) 60 if (nb < 0)
61 return nb; 61 return nb;
62 62
63 printk(KERN_INFO "Scanning NUMA topology in Northbridge %d\n", nb); 63 printk(KERN_INFO "Scanning NUMA topology in Northbridge %d\n", nb);
64 64
65 reg = read_pci_config(0, nb, 0, 0x60); 65 reg = read_pci_config(0, nb, 0, 0x60);
66 numnodes = ((reg >> 4) & 0xF) + 1; 66 numnodes = ((reg >> 4) & 0xF) + 1;
67 if (numnodes <= 1) 67 if (numnodes <= 1)
68 return -1; 68 return -1;
69 69
70 printk(KERN_INFO "Number of nodes %d\n", numnodes); 70 printk(KERN_INFO "Number of nodes %d\n", numnodes);
71 71
72 memset(&nodes,0,sizeof(nodes)); 72 memset(&nodes, 0, sizeof(nodes));
73 prevbase = 0; 73 prevbase = 0;
74 for (i = 0; i < 8; i++) { 74 for (i = 0; i < 8; i++) {
75 unsigned long base,limit; 75 unsigned long base, limit;
76 u32 nodeid; 76 u32 nodeid;
77 77
78 base = read_pci_config(0, nb, 1, 0x40 + i*8); 78 base = read_pci_config(0, nb, 1, 0x40 + i*8);
79 limit = read_pci_config(0, nb, 1, 0x44 + i*8); 79 limit = read_pci_config(0, nb, 1, 0x44 + i*8);
80 80
81 nodeid = limit & 7; 81 nodeid = limit & 7;
82 nodeids[i] = nodeid; 82 nodeids[i] = nodeid;
83 if ((base & 3) == 0) { 83 if ((base & 3) == 0) {
84 if (i < numnodes) 84 if (i < numnodes)
85 printk("Skipping disabled node %d\n", i); 85 printk("Skipping disabled node %d\n", i);
86 continue; 86 continue;
87 } 87 }
88 if (nodeid >= numnodes) { 88 if (nodeid >= numnodes) {
89 printk("Ignoring excess node %d (%lx:%lx)\n", nodeid, 89 printk("Ignoring excess node %d (%lx:%lx)\n", nodeid,
90 base, limit); 90 base, limit);
91 continue; 91 continue;
92 } 92 }
93 93
94 if (!limit) { 94 if (!limit) {
95 printk(KERN_INFO "Skipping node entry %d (base %lx)\n", i, 95 printk(KERN_INFO "Skipping node entry %d (base %lx)\n",
96 base); 96 i, base);
97 continue; 97 continue;
98 } 98 }
99 if ((base >> 8) & 3 || (limit >> 8) & 3) { 99 if ((base >> 8) & 3 || (limit >> 8) & 3) {
100 printk(KERN_ERR "Node %d using interleaving mode %lx/%lx\n", 100 printk(KERN_ERR "Node %d using interleaving mode %lx/%lx\n",
101 nodeid, (base>>8)&3, (limit>>8) & 3); 101 nodeid, (base>>8)&3, (limit>>8) & 3);
102 return -1; 102 return -1;
103 } 103 }
104 if (node_isset(nodeid, node_possible_map)) { 104 if (node_isset(nodeid, node_possible_map)) {
105 printk(KERN_INFO "Node %d already present. Skipping\n", 105 printk(KERN_INFO "Node %d already present. Skipping\n",
106 nodeid); 106 nodeid);
107 continue; 107 continue;
108 } 108 }
109 109
110 limit >>= 16; 110 limit >>= 16;
111 limit <<= 24; 111 limit <<= 24;
112 limit |= (1<<24)-1; 112 limit |= (1<<24)-1;
113 limit++; 113 limit++;
114 114
115 if (limit > end_pfn << PAGE_SHIFT) 115 if (limit > end_pfn << PAGE_SHIFT)
116 limit = end_pfn << PAGE_SHIFT; 116 limit = end_pfn << PAGE_SHIFT;
117 if (limit <= base) 117 if (limit <= base)
118 continue; 118 continue;
119 119
120 base >>= 16; 120 base >>= 16;
121 base <<= 24; 121 base <<= 24;
122 122
123 if (base < start) 123 if (base < start)
124 base = start; 124 base = start;
125 if (limit > end) 125 if (limit > end)
126 limit = end; 126 limit = end;
127 if (limit == base) { 127 if (limit == base) {
128 printk(KERN_ERR "Empty node %d\n", nodeid); 128 printk(KERN_ERR "Empty node %d\n", nodeid);
129 continue; 129 continue;
130 } 130 }
131 if (limit < base) { 131 if (limit < base) {
132 printk(KERN_ERR "Node %d bogus settings %lx-%lx.\n", 132 printk(KERN_ERR "Node %d bogus settings %lx-%lx.\n",
133 nodeid, base, limit); 133 nodeid, base, limit);
134 continue; 134 continue;
135 } 135 }
136 136
137 /* Could sort here, but pun for now. Should not happen anyroads. */ 137 /* Could sort here, but pun for now. Should not happen anyroads. */
138 if (prevbase > base) { 138 if (prevbase > base) {
139 printk(KERN_ERR "Node map not sorted %lx,%lx\n", 139 printk(KERN_ERR "Node map not sorted %lx,%lx\n",
140 prevbase,base); 140 prevbase, base);
141 return -1; 141 return -1;
142 } 142 }
143 143
144 printk(KERN_INFO "Node %d MemBase %016lx Limit %016lx\n", 144 printk(KERN_INFO "Node %d MemBase %016lx Limit %016lx\n",
145 nodeid, base, limit); 145 nodeid, base, limit);
146 146
147 found++; 147 found++;
148 148
149 nodes[nodeid].start = base; 149 nodes[nodeid].start = base;
150 nodes[nodeid].end = limit; 150 nodes[nodeid].end = limit;
151 e820_register_active_regions(nodeid, 151 e820_register_active_regions(nodeid,
152 nodes[nodeid].start >> PAGE_SHIFT, 152 nodes[nodeid].start >> PAGE_SHIFT,
@@ -155,31 +155,31 @@ int __init k8_scan_nodes(unsigned long start, unsigned long end)
155 prevbase = base; 155 prevbase = base;
156 156
157 node_set(nodeid, node_possible_map); 157 node_set(nodeid, node_possible_map);
158 } 158 }
159 159
160 if (!found) 160 if (!found)
161 return -1; 161 return -1;
162 162
163 memnode_shift = compute_hash_shift(nodes, 8); 163 memnode_shift = compute_hash_shift(nodes, 8);
164 if (memnode_shift < 0) { 164 if (memnode_shift < 0) {
165 printk(KERN_ERR "No NUMA node hash function found. Contact maintainer\n"); 165 printk(KERN_ERR "No NUMA node hash function found. Contact maintainer\n");
166 return -1; 166 return -1;
167 } 167 }
168 printk(KERN_INFO "Using node hash shift of %d\n", memnode_shift); 168 printk(KERN_INFO "Using node hash shift of %d\n", memnode_shift);
169 169
170 /* use the coreid bits from early_identify_cpu */ 170 /* use the coreid bits from early_identify_cpu */
171 bits = boot_cpu_data.x86_coreid_bits; 171 bits = boot_cpu_data.x86_coreid_bits;
172 cores = (1<<bits); 172 cores = (1<<bits);
173 173
174 for (i = 0; i < 8; i++) { 174 for (i = 0; i < 8; i++) {
175 if (nodes[i].start != nodes[i].end) { 175 if (nodes[i].start != nodes[i].end) {
176 nodeid = nodeids[i]; 176 nodeid = nodeids[i];
177 for (j = 0; j < cores; j++) 177 for (j = 0; j < cores; j++)
178 apicid_to_node[(nodeid << bits) + j] = i; 178 apicid_to_node[(nodeid << bits) + j] = i;
179 setup_node_bootmem(i, nodes[i].start, nodes[i].end); 179 setup_node_bootmem(i, nodes[i].start, nodes[i].end);
180 } 180 }
181 } 181 }
182 182
183 numa_init_array(); 183 numa_init_array();
184 return 0; 184 return 0;
185} 185}