diff options
Diffstat (limited to 'arch/x86/kernel/mpparse.c')
-rw-r--r-- | arch/x86/kernel/mpparse.c | 883 |
1 files changed, 443 insertions, 440 deletions
diff --git a/arch/x86/kernel/mpparse.c b/arch/x86/kernel/mpparse.c index 404683b94e79..6ae005ccaed8 100644 --- a/arch/x86/kernel/mpparse.c +++ b/arch/x86/kernel/mpparse.c | |||
@@ -25,6 +25,9 @@ | |||
25 | #include <asm/proto.h> | 25 | #include <asm/proto.h> |
26 | #include <asm/acpi.h> | 26 | #include <asm/acpi.h> |
27 | #include <asm/bios_ebda.h> | 27 | #include <asm/bios_ebda.h> |
28 | #include <asm/e820.h> | ||
29 | #include <asm/trampoline.h> | ||
30 | #include <asm/setup.h> | ||
28 | 31 | ||
29 | #include <mach_apic.h> | 32 | #include <mach_apic.h> |
30 | #ifdef CONFIG_X86_32 | 33 | #ifdef CONFIG_X86_32 |
@@ -32,28 +35,6 @@ | |||
32 | #include <mach_mpparse.h> | 35 | #include <mach_mpparse.h> |
33 | #endif | 36 | #endif |
34 | 37 | ||
35 | /* Have we found an MP table */ | ||
36 | int smp_found_config; | ||
37 | |||
38 | /* | ||
39 | * Various Linux-internal data structures created from the | ||
40 | * MP-table. | ||
41 | */ | ||
42 | #if defined (CONFIG_MCA) || defined (CONFIG_EISA) | ||
43 | int mp_bus_id_to_type[MAX_MP_BUSSES]; | ||
44 | #endif | ||
45 | |||
46 | DECLARE_BITMAP(mp_bus_not_pci, MAX_MP_BUSSES); | ||
47 | int mp_bus_id_to_pci_bus[MAX_MP_BUSSES] = {[0 ... MAX_MP_BUSSES - 1] = -1 }; | ||
48 | |||
49 | static int mp_current_pci_id; | ||
50 | |||
51 | int pic_mode; | ||
52 | |||
53 | /* | ||
54 | * Intel MP BIOS table parsing routines: | ||
55 | */ | ||
56 | |||
57 | /* | 38 | /* |
58 | * Checksum an MP configuration block. | 39 | * Checksum an MP configuration block. |
59 | */ | 40 | */ |
@@ -68,18 +49,6 @@ static int __init mpf_checksum(unsigned char *mp, int len) | |||
68 | return sum & 0xFF; | 49 | return sum & 0xFF; |
69 | } | 50 | } |
70 | 51 | ||
71 | #ifdef CONFIG_X86_NUMAQ | ||
72 | /* | ||
73 | * Have to match translation table entries to main table entries by counter | ||
74 | * hence the mpc_record variable .... can't see a less disgusting way of | ||
75 | * doing this .... | ||
76 | */ | ||
77 | |||
78 | static int mpc_record; | ||
79 | static struct mpc_config_translation *translation_table[MAX_MPC_ENTRY] | ||
80 | __cpuinitdata; | ||
81 | #endif | ||
82 | |||
83 | static void __cpuinit MP_processor_info(struct mpc_config_processor *m) | 52 | static void __cpuinit MP_processor_info(struct mpc_config_processor *m) |
84 | { | 53 | { |
85 | int apicid; | 54 | int apicid; |
@@ -89,11 +58,12 @@ static void __cpuinit MP_processor_info(struct mpc_config_processor *m) | |||
89 | disabled_cpus++; | 58 | disabled_cpus++; |
90 | return; | 59 | return; |
91 | } | 60 | } |
92 | #ifdef CONFIG_X86_NUMAQ | 61 | |
93 | apicid = mpc_apic_id(m, translation_table[mpc_record]); | 62 | if (x86_quirks->mpc_apic_id) |
94 | #else | 63 | apicid = x86_quirks->mpc_apic_id(m); |
95 | apicid = m->mpc_apicid; | 64 | else |
96 | #endif | 65 | apicid = m->mpc_apicid; |
66 | |||
97 | if (m->mpc_cpuflag & CPU_BOOTPROCESSOR) { | 67 | if (m->mpc_cpuflag & CPU_BOOTPROCESSOR) { |
98 | bootup_cpu = " (Bootup-CPU)"; | 68 | bootup_cpu = " (Bootup-CPU)"; |
99 | boot_cpu_physical_apicid = m->mpc_apicid; | 69 | boot_cpu_physical_apicid = m->mpc_apicid; |
@@ -103,18 +73,17 @@ static void __cpuinit MP_processor_info(struct mpc_config_processor *m) | |||
103 | generic_processor_info(apicid, m->mpc_apicver); | 73 | generic_processor_info(apicid, m->mpc_apicver); |
104 | } | 74 | } |
105 | 75 | ||
76 | #ifdef CONFIG_X86_IO_APIC | ||
106 | static void __init MP_bus_info(struct mpc_config_bus *m) | 77 | static void __init MP_bus_info(struct mpc_config_bus *m) |
107 | { | 78 | { |
108 | char str[7]; | 79 | char str[7]; |
109 | |||
110 | memcpy(str, m->mpc_bustype, 6); | 80 | memcpy(str, m->mpc_bustype, 6); |
111 | str[6] = 0; | 81 | str[6] = 0; |
112 | 82 | ||
113 | #ifdef CONFIG_X86_NUMAQ | 83 | if (x86_quirks->mpc_oem_bus_info) |
114 | mpc_oem_bus_info(m, str, translation_table[mpc_record]); | 84 | x86_quirks->mpc_oem_bus_info(m, str); |
115 | #else | 85 | else |
116 | Dprintk("Bus #%d is %s\n", m->mpc_busid, str); | 86 | printk(KERN_INFO "Bus #%d is %s\n", m->mpc_busid, str); |
117 | #endif | ||
118 | 87 | ||
119 | #if MAX_MP_BUSSES < 256 | 88 | #if MAX_MP_BUSSES < 256 |
120 | if (m->mpc_busid >= MAX_MP_BUSSES) { | 89 | if (m->mpc_busid >= MAX_MP_BUSSES) { |
@@ -131,12 +100,10 @@ static void __init MP_bus_info(struct mpc_config_bus *m) | |||
131 | mp_bus_id_to_type[m->mpc_busid] = MP_BUS_ISA; | 100 | mp_bus_id_to_type[m->mpc_busid] = MP_BUS_ISA; |
132 | #endif | 101 | #endif |
133 | } else if (strncmp(str, BUSTYPE_PCI, sizeof(BUSTYPE_PCI) - 1) == 0) { | 102 | } else if (strncmp(str, BUSTYPE_PCI, sizeof(BUSTYPE_PCI) - 1) == 0) { |
134 | #ifdef CONFIG_X86_NUMAQ | 103 | if (x86_quirks->mpc_oem_pci_bus) |
135 | mpc_oem_pci_bus(m, translation_table[mpc_record]); | 104 | x86_quirks->mpc_oem_pci_bus(m); |
136 | #endif | 105 | |
137 | clear_bit(m->mpc_busid, mp_bus_not_pci); | 106 | clear_bit(m->mpc_busid, mp_bus_not_pci); |
138 | mp_bus_id_to_pci_bus[m->mpc_busid] = mp_current_pci_id; | ||
139 | mp_current_pci_id++; | ||
140 | #if defined(CONFIG_EISA) || defined (CONFIG_MCA) | 107 | #if defined(CONFIG_EISA) || defined (CONFIG_MCA) |
141 | mp_bus_id_to_type[m->mpc_busid] = MP_BUS_PCI; | 108 | mp_bus_id_to_type[m->mpc_busid] = MP_BUS_PCI; |
142 | } else if (strncmp(str, BUSTYPE_EISA, sizeof(BUSTYPE_EISA) - 1) == 0) { | 109 | } else if (strncmp(str, BUSTYPE_EISA, sizeof(BUSTYPE_EISA) - 1) == 0) { |
@@ -147,6 +114,7 @@ static void __init MP_bus_info(struct mpc_config_bus *m) | |||
147 | } else | 114 | } else |
148 | printk(KERN_WARNING "Unknown bustype %s - ignoring\n", str); | 115 | printk(KERN_WARNING "Unknown bustype %s - ignoring\n", str); |
149 | } | 116 | } |
117 | #endif | ||
150 | 118 | ||
151 | #ifdef CONFIG_X86_IO_APIC | 119 | #ifdef CONFIG_X86_IO_APIC |
152 | 120 | ||
@@ -176,117 +144,111 @@ static void __init MP_ioapic_info(struct mpc_config_ioapic *m) | |||
176 | if (bad_ioapic(m->mpc_apicaddr)) | 144 | if (bad_ioapic(m->mpc_apicaddr)) |
177 | return; | 145 | return; |
178 | 146 | ||
179 | mp_ioapics[nr_ioapics] = *m; | 147 | mp_ioapics[nr_ioapics].mp_apicaddr = m->mpc_apicaddr; |
148 | mp_ioapics[nr_ioapics].mp_apicid = m->mpc_apicid; | ||
149 | mp_ioapics[nr_ioapics].mp_type = m->mpc_type; | ||
150 | mp_ioapics[nr_ioapics].mp_apicver = m->mpc_apicver; | ||
151 | mp_ioapics[nr_ioapics].mp_flags = m->mpc_flags; | ||
180 | nr_ioapics++; | 152 | nr_ioapics++; |
181 | } | 153 | } |
182 | 154 | ||
183 | static void __init MP_intsrc_info(struct mpc_config_intsrc *m) | 155 | static void print_MP_intsrc_info(struct mpc_config_intsrc *m) |
184 | { | 156 | { |
185 | mp_irqs[mp_irq_entries] = *m; | 157 | printk(KERN_CONT "Int: type %d, pol %d, trig %d, bus %02x," |
186 | Dprintk("Int: type %d, pol %d, trig %d, bus %d," | ||
187 | " IRQ %02x, APIC ID %x, APIC INT %02x\n", | 158 | " IRQ %02x, APIC ID %x, APIC INT %02x\n", |
188 | m->mpc_irqtype, m->mpc_irqflag & 3, | 159 | m->mpc_irqtype, m->mpc_irqflag & 3, |
189 | (m->mpc_irqflag >> 2) & 3, m->mpc_srcbus, | 160 | (m->mpc_irqflag >> 2) & 3, m->mpc_srcbus, |
190 | m->mpc_srcbusirq, m->mpc_dstapic, m->mpc_dstirq); | 161 | m->mpc_srcbusirq, m->mpc_dstapic, m->mpc_dstirq); |
191 | if (++mp_irq_entries == MAX_IRQ_SOURCES) | ||
192 | panic("Max # of irq sources exceeded!!\n"); | ||
193 | } | 162 | } |
194 | 163 | ||
195 | #endif | 164 | static void __init print_mp_irq_info(struct mp_config_intsrc *mp_irq) |
196 | |||
197 | static void __init MP_lintsrc_info(struct mpc_config_lintsrc *m) | ||
198 | { | 165 | { |
199 | Dprintk("Lint: type %d, pol %d, trig %d, bus %d," | 166 | printk(KERN_CONT "Int: type %d, pol %d, trig %d, bus %02x," |
200 | " IRQ %02x, APIC ID %x, APIC LINT %02x\n", | 167 | " IRQ %02x, APIC ID %x, APIC INT %02x\n", |
201 | m->mpc_irqtype, m->mpc_irqflag & 3, | 168 | mp_irq->mp_irqtype, mp_irq->mp_irqflag & 3, |
202 | (m->mpc_irqflag >> 2) & 3, m->mpc_srcbusid, | 169 | (mp_irq->mp_irqflag >> 2) & 3, mp_irq->mp_srcbus, |
203 | m->mpc_srcbusirq, m->mpc_destapic, m->mpc_destapiclint); | 170 | mp_irq->mp_srcbusirq, mp_irq->mp_dstapic, mp_irq->mp_dstirq); |
204 | } | 171 | } |
205 | 172 | ||
206 | #ifdef CONFIG_X86_NUMAQ | 173 | static void __init assign_to_mp_irq(struct mpc_config_intsrc *m, |
207 | static void __init MP_translation_info(struct mpc_config_translation *m) | 174 | struct mp_config_intsrc *mp_irq) |
208 | { | 175 | { |
209 | printk(KERN_INFO | 176 | mp_irq->mp_dstapic = m->mpc_dstapic; |
210 | "Translation: record %d, type %d, quad %d, global %d, local %d\n", | 177 | mp_irq->mp_type = m->mpc_type; |
211 | mpc_record, m->trans_type, m->trans_quad, m->trans_global, | 178 | mp_irq->mp_irqtype = m->mpc_irqtype; |
212 | m->trans_local); | 179 | mp_irq->mp_irqflag = m->mpc_irqflag; |
180 | mp_irq->mp_srcbus = m->mpc_srcbus; | ||
181 | mp_irq->mp_srcbusirq = m->mpc_srcbusirq; | ||
182 | mp_irq->mp_dstirq = m->mpc_dstirq; | ||
183 | } | ||
213 | 184 | ||
214 | if (mpc_record >= MAX_MPC_ENTRY) | 185 | static void __init assign_to_mpc_intsrc(struct mp_config_intsrc *mp_irq, |
215 | printk(KERN_ERR "MAX_MPC_ENTRY exceeded!\n"); | 186 | struct mpc_config_intsrc *m) |
216 | else | 187 | { |
217 | translation_table[mpc_record] = m; /* stash this for later */ | 188 | m->mpc_dstapic = mp_irq->mp_dstapic; |
218 | if (m->trans_quad < MAX_NUMNODES && !node_online(m->trans_quad)) | 189 | m->mpc_type = mp_irq->mp_type; |
219 | node_set_online(m->trans_quad); | 190 | m->mpc_irqtype = mp_irq->mp_irqtype; |
191 | m->mpc_irqflag = mp_irq->mp_irqflag; | ||
192 | m->mpc_srcbus = mp_irq->mp_srcbus; | ||
193 | m->mpc_srcbusirq = mp_irq->mp_srcbusirq; | ||
194 | m->mpc_dstirq = mp_irq->mp_dstirq; | ||
220 | } | 195 | } |
221 | 196 | ||
222 | /* | 197 | static int __init mp_irq_mpc_intsrc_cmp(struct mp_config_intsrc *mp_irq, |
223 | * Read/parse the MPC oem tables | 198 | struct mpc_config_intsrc *m) |
224 | */ | 199 | { |
200 | if (mp_irq->mp_dstapic != m->mpc_dstapic) | ||
201 | return 1; | ||
202 | if (mp_irq->mp_type != m->mpc_type) | ||
203 | return 2; | ||
204 | if (mp_irq->mp_irqtype != m->mpc_irqtype) | ||
205 | return 3; | ||
206 | if (mp_irq->mp_irqflag != m->mpc_irqflag) | ||
207 | return 4; | ||
208 | if (mp_irq->mp_srcbus != m->mpc_srcbus) | ||
209 | return 5; | ||
210 | if (mp_irq->mp_srcbusirq != m->mpc_srcbusirq) | ||
211 | return 6; | ||
212 | if (mp_irq->mp_dstirq != m->mpc_dstirq) | ||
213 | return 7; | ||
214 | |||
215 | return 0; | ||
216 | } | ||
225 | 217 | ||
226 | static void __init smp_read_mpc_oem(struct mp_config_oemtable *oemtable, | 218 | static void __init MP_intsrc_info(struct mpc_config_intsrc *m) |
227 | unsigned short oemsize) | ||
228 | { | 219 | { |
229 | int count = sizeof(*oemtable); /* the header size */ | 220 | int i; |
230 | unsigned char *oemptr = ((unsigned char *)oemtable) + count; | 221 | |
231 | 222 | print_MP_intsrc_info(m); | |
232 | mpc_record = 0; | 223 | |
233 | printk(KERN_INFO "Found an OEM MPC table at %8p - parsing it ... \n", | 224 | for (i = 0; i < mp_irq_entries; i++) { |
234 | oemtable); | 225 | if (!mp_irq_mpc_intsrc_cmp(&mp_irqs[i], m)) |
235 | if (memcmp(oemtable->oem_signature, MPC_OEM_SIGNATURE, 4)) { | 226 | return; |
236 | printk(KERN_WARNING | ||
237 | "SMP mpc oemtable: bad signature [%c%c%c%c]!\n", | ||
238 | oemtable->oem_signature[0], oemtable->oem_signature[1], | ||
239 | oemtable->oem_signature[2], oemtable->oem_signature[3]); | ||
240 | return; | ||
241 | } | ||
242 | if (mpf_checksum((unsigned char *)oemtable, oemtable->oem_length)) { | ||
243 | printk(KERN_WARNING "SMP oem mptable: checksum error!\n"); | ||
244 | return; | ||
245 | } | ||
246 | while (count < oemtable->oem_length) { | ||
247 | switch (*oemptr) { | ||
248 | case MP_TRANSLATION: | ||
249 | { | ||
250 | struct mpc_config_translation *m = | ||
251 | (struct mpc_config_translation *)oemptr; | ||
252 | MP_translation_info(m); | ||
253 | oemptr += sizeof(*m); | ||
254 | count += sizeof(*m); | ||
255 | ++mpc_record; | ||
256 | break; | ||
257 | } | ||
258 | default: | ||
259 | { | ||
260 | printk(KERN_WARNING | ||
261 | "Unrecognised OEM table entry type! - %d\n", | ||
262 | (int)*oemptr); | ||
263 | return; | ||
264 | } | ||
265 | } | ||
266 | } | 227 | } |
228 | |||
229 | assign_to_mp_irq(m, &mp_irqs[mp_irq_entries]); | ||
230 | if (++mp_irq_entries == MAX_IRQ_SOURCES) | ||
231 | panic("Max # of irq sources exceeded!!\n"); | ||
267 | } | 232 | } |
268 | 233 | ||
269 | static inline void mps_oem_check(struct mp_config_table *mpc, char *oem, | 234 | #endif |
270 | char *productid) | 235 | |
236 | static void __init MP_lintsrc_info(struct mpc_config_lintsrc *m) | ||
271 | { | 237 | { |
272 | if (strncmp(oem, "IBM NUMA", 8)) | 238 | printk(KERN_INFO "Lint: type %d, pol %d, trig %d, bus %02x," |
273 | printk("Warning! May not be a NUMA-Q system!\n"); | 239 | " IRQ %02x, APIC ID %x, APIC LINT %02x\n", |
274 | if (mpc->mpc_oemptr) | 240 | m->mpc_irqtype, m->mpc_irqflag & 3, |
275 | smp_read_mpc_oem((struct mp_config_oemtable *)mpc->mpc_oemptr, | 241 | (m->mpc_irqflag >> 2) & 3, m->mpc_srcbusid, |
276 | mpc->mpc_oemsize); | 242 | m->mpc_srcbusirq, m->mpc_destapic, m->mpc_destapiclint); |
277 | } | 243 | } |
278 | #endif /* CONFIG_X86_NUMAQ */ | ||
279 | 244 | ||
280 | /* | 245 | /* |
281 | * Read/parse the MPC | 246 | * Read/parse the MPC |
282 | */ | 247 | */ |
283 | 248 | ||
284 | static int __init smp_read_mpc(struct mp_config_table *mpc, unsigned early) | 249 | static int __init smp_check_mpc(struct mp_config_table *mpc, char *oem, |
250 | char *str) | ||
285 | { | 251 | { |
286 | char str[16]; | ||
287 | char oem[10]; | ||
288 | int count = sizeof(*mpc); | ||
289 | unsigned char *mpt = ((unsigned char *)mpc) + count; | ||
290 | 252 | ||
291 | if (memcmp(mpc->mpc_signature, MPC_SIGNATURE, 4)) { | 253 | if (memcmp(mpc->mpc_signature, MPC_SIGNATURE, 4)) { |
292 | printk(KERN_ERR "MPTABLE: bad signature [%c%c%c%c]!\n", | 254 | printk(KERN_ERR "MPTABLE: bad signature [%c%c%c%c]!\n", |
@@ -309,19 +271,41 @@ static int __init smp_read_mpc(struct mp_config_table *mpc, unsigned early) | |||
309 | } | 271 | } |
310 | memcpy(oem, mpc->mpc_oem, 8); | 272 | memcpy(oem, mpc->mpc_oem, 8); |
311 | oem[8] = 0; | 273 | oem[8] = 0; |
312 | printk(KERN_INFO "MPTABLE: OEM ID: %s ", oem); | 274 | printk(KERN_INFO "MPTABLE: OEM ID: %s\n", oem); |
313 | 275 | ||
314 | memcpy(str, mpc->mpc_productid, 12); | 276 | memcpy(str, mpc->mpc_productid, 12); |
315 | str[12] = 0; | 277 | str[12] = 0; |
316 | printk("Product ID: %s ", str); | ||
317 | 278 | ||
318 | #ifdef CONFIG_X86_32 | 279 | printk(KERN_INFO "MPTABLE: Product ID: %s\n", str); |
319 | mps_oem_check(mpc, oem, str); | ||
320 | #endif | ||
321 | printk(KERN_INFO "MPTABLE: Product ID: %s ", str); | ||
322 | 280 | ||
323 | printk(KERN_INFO "MPTABLE: APIC at: 0x%X\n", mpc->mpc_lapic); | 281 | printk(KERN_INFO "MPTABLE: APIC at: 0x%X\n", mpc->mpc_lapic); |
324 | 282 | ||
283 | return 1; | ||
284 | } | ||
285 | |||
286 | static int __init smp_read_mpc(struct mp_config_table *mpc, unsigned early) | ||
287 | { | ||
288 | char str[16]; | ||
289 | char oem[10]; | ||
290 | |||
291 | int count = sizeof(*mpc); | ||
292 | unsigned char *mpt = ((unsigned char *)mpc) + count; | ||
293 | |||
294 | if (!smp_check_mpc(mpc, oem, str)) | ||
295 | return 0; | ||
296 | |||
297 | #ifdef CONFIG_X86_32 | ||
298 | /* | ||
299 | * need to make sure summit and es7000's mps_oem_check is safe to be | ||
300 | * called early via genericarch 's mps_oem_check | ||
301 | */ | ||
302 | if (early) { | ||
303 | #ifdef CONFIG_X86_NUMAQ | ||
304 | numaq_mps_oem_check(mpc, oem, str); | ||
305 | #endif | ||
306 | } else | ||
307 | mps_oem_check(mpc, oem, str); | ||
308 | #endif | ||
325 | /* save the local APIC address, it might be non-default */ | 309 | /* save the local APIC address, it might be non-default */ |
326 | if (!acpi_lapic) | 310 | if (!acpi_lapic) |
327 | mp_lapic_addr = mpc->mpc_lapic; | 311 | mp_lapic_addr = mpc->mpc_lapic; |
@@ -329,12 +313,17 @@ static int __init smp_read_mpc(struct mp_config_table *mpc, unsigned early) | |||
329 | if (early) | 313 | if (early) |
330 | return 1; | 314 | return 1; |
331 | 315 | ||
316 | if (mpc->mpc_oemptr && x86_quirks->smp_read_mpc_oem) { | ||
317 | struct mp_config_oemtable *oem_table = (struct mp_config_oemtable *)(unsigned long)mpc->mpc_oemptr; | ||
318 | x86_quirks->smp_read_mpc_oem(oem_table, mpc->mpc_oemsize); | ||
319 | } | ||
320 | |||
332 | /* | 321 | /* |
333 | * Now process the configuration blocks. | 322 | * Now process the configuration blocks. |
334 | */ | 323 | */ |
335 | #ifdef CONFIG_X86_NUMAQ | 324 | if (x86_quirks->mpc_record) |
336 | mpc_record = 0; | 325 | *x86_quirks->mpc_record = 0; |
337 | #endif | 326 | |
338 | while (count < mpc->mpc_length) { | 327 | while (count < mpc->mpc_length) { |
339 | switch (*mpt) { | 328 | switch (*mpt) { |
340 | case MP_PROCESSOR: | 329 | case MP_PROCESSOR: |
@@ -352,7 +341,9 @@ static int __init smp_read_mpc(struct mp_config_table *mpc, unsigned early) | |||
352 | { | 341 | { |
353 | struct mpc_config_bus *m = | 342 | struct mpc_config_bus *m = |
354 | (struct mpc_config_bus *)mpt; | 343 | (struct mpc_config_bus *)mpt; |
344 | #ifdef CONFIG_X86_IO_APIC | ||
355 | MP_bus_info(m); | 345 | MP_bus_info(m); |
346 | #endif | ||
356 | mpt += sizeof(*m); | 347 | mpt += sizeof(*m); |
357 | count += sizeof(*m); | 348 | count += sizeof(*m); |
358 | break; | 349 | break; |
@@ -398,10 +389,14 @@ static int __init smp_read_mpc(struct mp_config_table *mpc, unsigned early) | |||
398 | count = mpc->mpc_length; | 389 | count = mpc->mpc_length; |
399 | break; | 390 | break; |
400 | } | 391 | } |
401 | #ifdef CONFIG_X86_NUMAQ | 392 | if (x86_quirks->mpc_record) |
402 | ++mpc_record; | 393 | (*x86_quirks->mpc_record)++; |
403 | #endif | ||
404 | } | 394 | } |
395 | |||
396 | #ifdef CONFIG_X86_GENERICARCH | ||
397 | generic_bigsmp_probe(); | ||
398 | #endif | ||
399 | |||
405 | setup_apic_routing(); | 400 | setup_apic_routing(); |
406 | if (!num_processors) | 401 | if (!num_processors) |
407 | printk(KERN_ERR "MPTABLE: no processors registered!\n"); | 402 | printk(KERN_ERR "MPTABLE: no processors registered!\n"); |
@@ -427,7 +422,7 @@ static void __init construct_default_ioirq_mptable(int mpc_default_type) | |||
427 | intsrc.mpc_type = MP_INTSRC; | 422 | intsrc.mpc_type = MP_INTSRC; |
428 | intsrc.mpc_irqflag = 0; /* conforming */ | 423 | intsrc.mpc_irqflag = 0; /* conforming */ |
429 | intsrc.mpc_srcbus = 0; | 424 | intsrc.mpc_srcbus = 0; |
430 | intsrc.mpc_dstapic = mp_ioapics[0].mpc_apicid; | 425 | intsrc.mpc_dstapic = mp_ioapics[0].mp_apicid; |
431 | 426 | ||
432 | intsrc.mpc_irqtype = mp_INT; | 427 | intsrc.mpc_irqtype = mp_INT; |
433 | 428 | ||
@@ -488,40 +483,11 @@ static void __init construct_default_ioirq_mptable(int mpc_default_type) | |||
488 | MP_intsrc_info(&intsrc); | 483 | MP_intsrc_info(&intsrc); |
489 | } | 484 | } |
490 | 485 | ||
491 | #endif | ||
492 | 486 | ||
493 | static inline void __init construct_default_ISA_mptable(int mpc_default_type) | 487 | static void construct_ioapic_table(int mpc_default_type) |
494 | { | 488 | { |
495 | struct mpc_config_processor processor; | ||
496 | struct mpc_config_bus bus; | ||
497 | #ifdef CONFIG_X86_IO_APIC | ||
498 | struct mpc_config_ioapic ioapic; | 489 | struct mpc_config_ioapic ioapic; |
499 | #endif | 490 | struct mpc_config_bus bus; |
500 | struct mpc_config_lintsrc lintsrc; | ||
501 | int linttypes[2] = { mp_ExtINT, mp_NMI }; | ||
502 | int i; | ||
503 | |||
504 | /* | ||
505 | * local APIC has default address | ||
506 | */ | ||
507 | mp_lapic_addr = APIC_DEFAULT_PHYS_BASE; | ||
508 | |||
509 | /* | ||
510 | * 2 CPUs, numbered 0 & 1. | ||
511 | */ | ||
512 | processor.mpc_type = MP_PROCESSOR; | ||
513 | /* Either an integrated APIC or a discrete 82489DX. */ | ||
514 | processor.mpc_apicver = mpc_default_type > 4 ? 0x10 : 0x01; | ||
515 | processor.mpc_cpuflag = CPU_ENABLED; | ||
516 | processor.mpc_cpufeature = (boot_cpu_data.x86 << 8) | | ||
517 | (boot_cpu_data.x86_model << 4) | boot_cpu_data.x86_mask; | ||
518 | processor.mpc_featureflag = boot_cpu_data.x86_capability[0]; | ||
519 | processor.mpc_reserved[0] = 0; | ||
520 | processor.mpc_reserved[1] = 0; | ||
521 | for (i = 0; i < 2; i++) { | ||
522 | processor.mpc_apicid = i; | ||
523 | MP_processor_info(&processor); | ||
524 | } | ||
525 | 491 | ||
526 | bus.mpc_type = MP_BUS; | 492 | bus.mpc_type = MP_BUS; |
527 | bus.mpc_busid = 0; | 493 | bus.mpc_busid = 0; |
@@ -550,7 +516,6 @@ static inline void __init construct_default_ISA_mptable(int mpc_default_type) | |||
550 | MP_bus_info(&bus); | 516 | MP_bus_info(&bus); |
551 | } | 517 | } |
552 | 518 | ||
553 | #ifdef CONFIG_X86_IO_APIC | ||
554 | ioapic.mpc_type = MP_IOAPIC; | 519 | ioapic.mpc_type = MP_IOAPIC; |
555 | ioapic.mpc_apicid = 2; | 520 | ioapic.mpc_apicid = 2; |
556 | ioapic.mpc_apicver = mpc_default_type > 4 ? 0x10 : 0x01; | 521 | ioapic.mpc_apicver = mpc_default_type > 4 ? 0x10 : 0x01; |
@@ -562,7 +527,42 @@ static inline void __init construct_default_ISA_mptable(int mpc_default_type) | |||
562 | * We set up most of the low 16 IO-APIC pins according to MPS rules. | 527 | * We set up most of the low 16 IO-APIC pins according to MPS rules. |
563 | */ | 528 | */ |
564 | construct_default_ioirq_mptable(mpc_default_type); | 529 | construct_default_ioirq_mptable(mpc_default_type); |
530 | } | ||
531 | #else | ||
532 | static inline void construct_ioapic_table(int mpc_default_type) { } | ||
565 | #endif | 533 | #endif |
534 | |||
535 | static inline void __init construct_default_ISA_mptable(int mpc_default_type) | ||
536 | { | ||
537 | struct mpc_config_processor processor; | ||
538 | struct mpc_config_lintsrc lintsrc; | ||
539 | int linttypes[2] = { mp_ExtINT, mp_NMI }; | ||
540 | int i; | ||
541 | |||
542 | /* | ||
543 | * local APIC has default address | ||
544 | */ | ||
545 | mp_lapic_addr = APIC_DEFAULT_PHYS_BASE; | ||
546 | |||
547 | /* | ||
548 | * 2 CPUs, numbered 0 & 1. | ||
549 | */ | ||
550 | processor.mpc_type = MP_PROCESSOR; | ||
551 | /* Either an integrated APIC or a discrete 82489DX. */ | ||
552 | processor.mpc_apicver = mpc_default_type > 4 ? 0x10 : 0x01; | ||
553 | processor.mpc_cpuflag = CPU_ENABLED; | ||
554 | processor.mpc_cpufeature = (boot_cpu_data.x86 << 8) | | ||
555 | (boot_cpu_data.x86_model << 4) | boot_cpu_data.x86_mask; | ||
556 | processor.mpc_featureflag = boot_cpu_data.x86_capability[0]; | ||
557 | processor.mpc_reserved[0] = 0; | ||
558 | processor.mpc_reserved[1] = 0; | ||
559 | for (i = 0; i < 2; i++) { | ||
560 | processor.mpc_apicid = i; | ||
561 | MP_processor_info(&processor); | ||
562 | } | ||
563 | |||
564 | construct_ioapic_table(mpc_default_type); | ||
565 | |||
566 | lintsrc.mpc_type = MP_LINTSRC; | 566 | lintsrc.mpc_type = MP_LINTSRC; |
567 | lintsrc.mpc_irqflag = 0; /* conforming */ | 567 | lintsrc.mpc_irqflag = 0; /* conforming */ |
568 | lintsrc.mpc_srcbusid = 0; | 568 | lintsrc.mpc_srcbusid = 0; |
@@ -580,10 +580,14 @@ static struct intel_mp_floating *mpf_found; | |||
580 | /* | 580 | /* |
581 | * Scan the memory blocks for an SMP configuration block. | 581 | * Scan the memory blocks for an SMP configuration block. |
582 | */ | 582 | */ |
583 | static void __init __get_smp_config(unsigned early) | 583 | static void __init __get_smp_config(unsigned int early) |
584 | { | 584 | { |
585 | struct intel_mp_floating *mpf = mpf_found; | 585 | struct intel_mp_floating *mpf = mpf_found; |
586 | 586 | ||
587 | if (x86_quirks->mach_get_smp_config) { | ||
588 | if (x86_quirks->mach_get_smp_config(early)) | ||
589 | return; | ||
590 | } | ||
587 | if (acpi_lapic && early) | 591 | if (acpi_lapic && early) |
588 | return; | 592 | return; |
589 | /* | 593 | /* |
@@ -600,7 +604,7 @@ static void __init __get_smp_config(unsigned early) | |||
600 | 604 | ||
601 | printk(KERN_INFO "Intel MultiProcessor Specification v1.%d\n", | 605 | printk(KERN_INFO "Intel MultiProcessor Specification v1.%d\n", |
602 | mpf->mpf_specification); | 606 | mpf->mpf_specification); |
603 | #ifdef CONFIG_X86_32 | 607 | #if defined(CONFIG_X86_LOCAL_APIC) && defined(CONFIG_X86_32) |
604 | if (mpf->mpf_feature2 & (1 << 7)) { | 608 | if (mpf->mpf_feature2 & (1 << 7)) { |
605 | printk(KERN_INFO " IMCR and PIC compatibility mode.\n"); | 609 | printk(KERN_INFO " IMCR and PIC compatibility mode.\n"); |
606 | pic_mode = 1; | 610 | pic_mode = 1; |
@@ -632,7 +636,9 @@ static void __init __get_smp_config(unsigned early) | |||
632 | * override the defaults. | 636 | * override the defaults. |
633 | */ | 637 | */ |
634 | if (!smp_read_mpc(phys_to_virt(mpf->mpf_physptr), early)) { | 638 | if (!smp_read_mpc(phys_to_virt(mpf->mpf_physptr), early)) { |
639 | #ifdef CONFIG_X86_LOCAL_APIC | ||
635 | smp_found_config = 0; | 640 | smp_found_config = 0; |
641 | #endif | ||
636 | printk(KERN_ERR | 642 | printk(KERN_ERR |
637 | "BIOS bug, MP table errors detected!...\n"); | 643 | "BIOS bug, MP table errors detected!...\n"); |
638 | printk(KERN_ERR "... disabling SMP support. " | 644 | printk(KERN_ERR "... disabling SMP support. " |
@@ -689,7 +695,7 @@ static int __init smp_scan_config(unsigned long base, unsigned long length, | |||
689 | unsigned int *bp = phys_to_virt(base); | 695 | unsigned int *bp = phys_to_virt(base); |
690 | struct intel_mp_floating *mpf; | 696 | struct intel_mp_floating *mpf; |
691 | 697 | ||
692 | Dprintk("Scan SMP from %p for %ld bytes.\n", bp, length); | 698 | printk(KERN_DEBUG "Scan SMP from %p for %ld bytes.\n", bp, length); |
693 | BUILD_BUG_ON(sizeof(*mpf) != 16); | 699 | BUILD_BUG_ON(sizeof(*mpf) != 16); |
694 | 700 | ||
695 | while (length > 0) { | 701 | while (length > 0) { |
@@ -699,15 +705,21 @@ static int __init smp_scan_config(unsigned long base, unsigned long length, | |||
699 | !mpf_checksum((unsigned char *)bp, 16) && | 705 | !mpf_checksum((unsigned char *)bp, 16) && |
700 | ((mpf->mpf_specification == 1) | 706 | ((mpf->mpf_specification == 1) |
701 | || (mpf->mpf_specification == 4))) { | 707 | || (mpf->mpf_specification == 4))) { |
702 | 708 | #ifdef CONFIG_X86_LOCAL_APIC | |
703 | smp_found_config = 1; | 709 | smp_found_config = 1; |
710 | #endif | ||
704 | mpf_found = mpf; | 711 | mpf_found = mpf; |
705 | #ifdef CONFIG_X86_32 | 712 | |
706 | printk(KERN_INFO "found SMP MP-table at [%p] %08lx\n", | 713 | printk(KERN_INFO "found SMP MP-table at [%p] %08lx\n", |
707 | mpf, virt_to_phys(mpf)); | 714 | mpf, virt_to_phys(mpf)); |
708 | reserve_bootmem(virt_to_phys(mpf), PAGE_SIZE, | 715 | |
716 | if (!reserve) | ||
717 | return 1; | ||
718 | reserve_bootmem_generic(virt_to_phys(mpf), PAGE_SIZE, | ||
709 | BOOTMEM_DEFAULT); | 719 | BOOTMEM_DEFAULT); |
710 | if (mpf->mpf_physptr) { | 720 | if (mpf->mpf_physptr) { |
721 | unsigned long size = PAGE_SIZE; | ||
722 | #ifdef CONFIG_X86_32 | ||
711 | /* | 723 | /* |
712 | * We cannot access to MPC table to compute | 724 | * We cannot access to MPC table to compute |
713 | * table size yet, as only few megabytes from | 725 | * table size yet, as only few megabytes from |
@@ -717,24 +729,15 @@ static int __init smp_scan_config(unsigned long base, unsigned long length, | |||
717 | * PAGE_SIZE from mpg->mpf_physptr yields BUG() | 729 | * PAGE_SIZE from mpg->mpf_physptr yields BUG() |
718 | * in reserve_bootmem. | 730 | * in reserve_bootmem. |
719 | */ | 731 | */ |
720 | unsigned long size = PAGE_SIZE; | ||
721 | unsigned long end = max_low_pfn * PAGE_SIZE; | 732 | unsigned long end = max_low_pfn * PAGE_SIZE; |
722 | if (mpf->mpf_physptr + size > end) | 733 | if (mpf->mpf_physptr + size > end) |
723 | size = end - mpf->mpf_physptr; | 734 | size = end - mpf->mpf_physptr; |
724 | reserve_bootmem(mpf->mpf_physptr, size, | 735 | #endif |
736 | reserve_bootmem_generic(mpf->mpf_physptr, size, | ||
725 | BOOTMEM_DEFAULT); | 737 | BOOTMEM_DEFAULT); |
726 | } | 738 | } |
727 | 739 | ||
728 | #else | 740 | return 1; |
729 | if (!reserve) | ||
730 | return 1; | ||
731 | |||
732 | reserve_bootmem_generic(virt_to_phys(mpf), PAGE_SIZE); | ||
733 | if (mpf->mpf_physptr) | ||
734 | reserve_bootmem_generic(mpf->mpf_physptr, | ||
735 | PAGE_SIZE); | ||
736 | #endif | ||
737 | return 1; | ||
738 | } | 741 | } |
739 | bp += 4; | 742 | bp += 4; |
740 | length -= 16; | 743 | length -= 16; |
@@ -742,10 +745,14 @@ static int __init smp_scan_config(unsigned long base, unsigned long length, | |||
742 | return 0; | 745 | return 0; |
743 | } | 746 | } |
744 | 747 | ||
745 | static void __init __find_smp_config(unsigned reserve) | 748 | static void __init __find_smp_config(unsigned int reserve) |
746 | { | 749 | { |
747 | unsigned int address; | 750 | unsigned int address; |
748 | 751 | ||
752 | if (x86_quirks->mach_find_smp_config) { | ||
753 | if (x86_quirks->mach_find_smp_config(reserve)) | ||
754 | return; | ||
755 | } | ||
749 | /* | 756 | /* |
750 | * FIXME: Linux assumes you have 640K of base ram.. | 757 | * FIXME: Linux assumes you have 640K of base ram.. |
751 | * this continues the error... | 758 | * this continues the error... |
@@ -790,298 +797,294 @@ void __init find_smp_config(void) | |||
790 | __find_smp_config(1); | 797 | __find_smp_config(1); |
791 | } | 798 | } |
792 | 799 | ||
793 | /* -------------------------------------------------------------------------- | 800 | #ifdef CONFIG_X86_IO_APIC |
794 | ACPI-based MP Configuration | 801 | static u8 __initdata irq_used[MAX_IRQ_SOURCES]; |
795 | -------------------------------------------------------------------------- */ | ||
796 | 802 | ||
797 | /* | 803 | static int __init get_MP_intsrc_index(struct mpc_config_intsrc *m) |
798 | * Keep this outside and initialized to 0, for !CONFIG_ACPI builds: | 804 | { |
799 | */ | 805 | int i; |
800 | int es7000_plat; | ||
801 | 806 | ||
802 | #ifdef CONFIG_ACPI | 807 | if (m->mpc_irqtype != mp_INT) |
808 | return 0; | ||
803 | 809 | ||
804 | #ifdef CONFIG_X86_IO_APIC | 810 | if (m->mpc_irqflag != 0x0f) |
811 | return 0; | ||
805 | 812 | ||
806 | #define MP_ISA_BUS 0 | 813 | /* not legacy */ |
807 | 814 | ||
808 | extern struct mp_ioapic_routing mp_ioapic_routing[MAX_IO_APICS]; | 815 | for (i = 0; i < mp_irq_entries; i++) { |
816 | if (mp_irqs[i].mp_irqtype != mp_INT) | ||
817 | continue; | ||
809 | 818 | ||
810 | static int mp_find_ioapic(int gsi) | 819 | if (mp_irqs[i].mp_irqflag != 0x0f) |
811 | { | 820 | continue; |
812 | int i = 0; | ||
813 | 821 | ||
814 | /* Find the IOAPIC that manages this GSI. */ | 822 | if (mp_irqs[i].mp_srcbus != m->mpc_srcbus) |
815 | for (i = 0; i < nr_ioapics; i++) { | 823 | continue; |
816 | if ((gsi >= mp_ioapic_routing[i].gsi_base) | 824 | if (mp_irqs[i].mp_srcbusirq != m->mpc_srcbusirq) |
817 | && (gsi <= mp_ioapic_routing[i].gsi_end)) | 825 | continue; |
818 | return i; | 826 | if (irq_used[i]) { |
827 | /* already claimed */ | ||
828 | return -2; | ||
829 | } | ||
830 | irq_used[i] = 1; | ||
831 | return i; | ||
819 | } | 832 | } |
820 | 833 | ||
821 | printk(KERN_ERR "ERROR: Unable to locate IOAPIC for GSI %d\n", gsi); | 834 | /* not found */ |
822 | return -1; | 835 | return -1; |
823 | } | 836 | } |
824 | 837 | ||
825 | static u8 __init uniq_ioapic_id(u8 id) | 838 | #define SPARE_SLOT_NUM 20 |
826 | { | 839 | |
827 | #ifdef CONFIG_X86_32 | 840 | static struct mpc_config_intsrc __initdata *m_spare[SPARE_SLOT_NUM]; |
828 | if ((boot_cpu_data.x86_vendor == X86_VENDOR_INTEL) && | ||
829 | !APIC_XAPIC(apic_version[boot_cpu_physical_apicid])) | ||
830 | return io_apic_get_unique_id(nr_ioapics, id); | ||
831 | else | ||
832 | return id; | ||
833 | #else | ||
834 | int i; | ||
835 | DECLARE_BITMAP(used, 256); | ||
836 | bitmap_zero(used, 256); | ||
837 | for (i = 0; i < nr_ioapics; i++) { | ||
838 | struct mpc_config_ioapic *ia = &mp_ioapics[i]; | ||
839 | __set_bit(ia->mpc_apicid, used); | ||
840 | } | ||
841 | if (!test_bit(id, used)) | ||
842 | return id; | ||
843 | return find_first_zero_bit(used, 256); | ||
844 | #endif | 841 | #endif |
845 | } | ||
846 | 842 | ||
847 | void __init mp_register_ioapic(int id, u32 address, u32 gsi_base) | 843 | static int __init replace_intsrc_all(struct mp_config_table *mpc, |
844 | unsigned long mpc_new_phys, | ||
845 | unsigned long mpc_new_length) | ||
848 | { | 846 | { |
849 | int idx = 0; | 847 | #ifdef CONFIG_X86_IO_APIC |
850 | 848 | int i; | |
851 | if (bad_ioapic(address)) | 849 | int nr_m_spare = 0; |
852 | return; | 850 | #endif |
853 | 851 | ||
854 | idx = nr_ioapics; | 852 | int count = sizeof(*mpc); |
853 | unsigned char *mpt = ((unsigned char *)mpc) + count; | ||
855 | 854 | ||
856 | mp_ioapics[idx].mpc_type = MP_IOAPIC; | 855 | printk(KERN_INFO "mpc_length %x\n", mpc->mpc_length); |
857 | mp_ioapics[idx].mpc_flags = MPC_APIC_USABLE; | 856 | while (count < mpc->mpc_length) { |
858 | mp_ioapics[idx].mpc_apicaddr = address; | 857 | switch (*mpt) { |
858 | case MP_PROCESSOR: | ||
859 | { | ||
860 | struct mpc_config_processor *m = | ||
861 | (struct mpc_config_processor *)mpt; | ||
862 | mpt += sizeof(*m); | ||
863 | count += sizeof(*m); | ||
864 | break; | ||
865 | } | ||
866 | case MP_BUS: | ||
867 | { | ||
868 | struct mpc_config_bus *m = | ||
869 | (struct mpc_config_bus *)mpt; | ||
870 | mpt += sizeof(*m); | ||
871 | count += sizeof(*m); | ||
872 | break; | ||
873 | } | ||
874 | case MP_IOAPIC: | ||
875 | { | ||
876 | mpt += sizeof(struct mpc_config_ioapic); | ||
877 | count += sizeof(struct mpc_config_ioapic); | ||
878 | break; | ||
879 | } | ||
880 | case MP_INTSRC: | ||
881 | { | ||
882 | #ifdef CONFIG_X86_IO_APIC | ||
883 | struct mpc_config_intsrc *m = | ||
884 | (struct mpc_config_intsrc *)mpt; | ||
859 | 885 | ||
860 | set_fixmap_nocache(FIX_IO_APIC_BASE_0 + idx, address); | 886 | printk(KERN_INFO "OLD "); |
861 | mp_ioapics[idx].mpc_apicid = uniq_ioapic_id(id); | 887 | print_MP_intsrc_info(m); |
862 | #ifdef CONFIG_X86_32 | 888 | i = get_MP_intsrc_index(m); |
863 | mp_ioapics[idx].mpc_apicver = io_apic_get_version(idx); | 889 | if (i > 0) { |
864 | #else | 890 | assign_to_mpc_intsrc(&mp_irqs[i], m); |
865 | mp_ioapics[idx].mpc_apicver = 0; | 891 | printk(KERN_INFO "NEW "); |
892 | print_mp_irq_info(&mp_irqs[i]); | ||
893 | } else if (!i) { | ||
894 | /* legacy, do nothing */ | ||
895 | } else if (nr_m_spare < SPARE_SLOT_NUM) { | ||
896 | /* | ||
897 | * not found (-1), or duplicated (-2) | ||
898 | * are invalid entries, | ||
899 | * we need to use the slot later | ||
900 | */ | ||
901 | m_spare[nr_m_spare] = m; | ||
902 | nr_m_spare++; | ||
903 | } | ||
866 | #endif | 904 | #endif |
867 | /* | 905 | mpt += sizeof(struct mpc_config_intsrc); |
868 | * Build basic GSI lookup table to facilitate gsi->io_apic lookups | 906 | count += sizeof(struct mpc_config_intsrc); |
869 | * and to prevent reprogramming of IOAPIC pins (PCI GSIs). | 907 | break; |
870 | */ | 908 | } |
871 | mp_ioapic_routing[idx].apic_id = mp_ioapics[idx].mpc_apicid; | 909 | case MP_LINTSRC: |
872 | mp_ioapic_routing[idx].gsi_base = gsi_base; | 910 | { |
873 | mp_ioapic_routing[idx].gsi_end = gsi_base + | 911 | struct mpc_config_lintsrc *m = |
874 | io_apic_get_redir_entries(idx); | 912 | (struct mpc_config_lintsrc *)mpt; |
875 | 913 | mpt += sizeof(*m); | |
876 | printk(KERN_INFO "IOAPIC[%d]: apic_id %d, version %d, address 0x%x, " | 914 | count += sizeof(*m); |
877 | "GSI %d-%d\n", idx, mp_ioapics[idx].mpc_apicid, | 915 | break; |
878 | mp_ioapics[idx].mpc_apicver, mp_ioapics[idx].mpc_apicaddr, | 916 | } |
879 | mp_ioapic_routing[idx].gsi_base, mp_ioapic_routing[idx].gsi_end); | 917 | default: |
880 | 918 | /* wrong mptable */ | |
881 | nr_ioapics++; | 919 | printk(KERN_ERR "Your mptable is wrong, contact your HW vendor!\n"); |
882 | } | 920 | printk(KERN_ERR "type %x\n", *mpt); |
921 | print_hex_dump(KERN_ERR, " ", DUMP_PREFIX_ADDRESS, 16, | ||
922 | 1, mpc, mpc->mpc_length, 1); | ||
923 | goto out; | ||
924 | } | ||
925 | } | ||
883 | 926 | ||
884 | void __init mp_override_legacy_irq(u8 bus_irq, u8 polarity, u8 trigger, u32 gsi) | 927 | #ifdef CONFIG_X86_IO_APIC |
885 | { | 928 | for (i = 0; i < mp_irq_entries; i++) { |
886 | struct mpc_config_intsrc intsrc; | 929 | if (irq_used[i]) |
887 | int ioapic = -1; | 930 | continue; |
888 | int pin = -1; | ||
889 | 931 | ||
890 | /* | 932 | if (mp_irqs[i].mp_irqtype != mp_INT) |
891 | * Convert 'gsi' to 'ioapic.pin'. | 933 | continue; |
892 | */ | ||
893 | ioapic = mp_find_ioapic(gsi); | ||
894 | if (ioapic < 0) | ||
895 | return; | ||
896 | pin = gsi - mp_ioapic_routing[ioapic].gsi_base; | ||
897 | 934 | ||
898 | /* | 935 | if (mp_irqs[i].mp_irqflag != 0x0f) |
899 | * TBD: This check is for faulty timer entries, where the override | 936 | continue; |
900 | * erroneously sets the trigger to level, resulting in a HUGE | ||
901 | * increase of timer interrupts! | ||
902 | */ | ||
903 | if ((bus_irq == 0) && (trigger == 3)) | ||
904 | trigger = 1; | ||
905 | 937 | ||
906 | intsrc.mpc_type = MP_INTSRC; | 938 | if (nr_m_spare > 0) { |
907 | intsrc.mpc_irqtype = mp_INT; | 939 | printk(KERN_INFO "*NEW* found "); |
908 | intsrc.mpc_irqflag = (trigger << 2) | polarity; | 940 | nr_m_spare--; |
909 | intsrc.mpc_srcbus = MP_ISA_BUS; | 941 | assign_to_mpc_intsrc(&mp_irqs[i], m_spare[nr_m_spare]); |
910 | intsrc.mpc_srcbusirq = bus_irq; /* IRQ */ | 942 | m_spare[nr_m_spare] = NULL; |
911 | intsrc.mpc_dstapic = mp_ioapics[ioapic].mpc_apicid; /* APIC ID */ | 943 | } else { |
912 | intsrc.mpc_dstirq = pin; /* INTIN# */ | 944 | struct mpc_config_intsrc *m = |
945 | (struct mpc_config_intsrc *)mpt; | ||
946 | count += sizeof(struct mpc_config_intsrc); | ||
947 | if (!mpc_new_phys) { | ||
948 | printk(KERN_INFO "No spare slots, try to append...take your risk, new mpc_length %x\n", count); | ||
949 | } else { | ||
950 | if (count <= mpc_new_length) | ||
951 | printk(KERN_INFO "No spare slots, try to append..., new mpc_length %x\n", count); | ||
952 | else { | ||
953 | printk(KERN_ERR "mpc_new_length %lx is too small\n", mpc_new_length); | ||
954 | goto out; | ||
955 | } | ||
956 | } | ||
957 | assign_to_mpc_intsrc(&mp_irqs[i], m); | ||
958 | mpc->mpc_length = count; | ||
959 | mpt += sizeof(struct mpc_config_intsrc); | ||
960 | } | ||
961 | print_mp_irq_info(&mp_irqs[i]); | ||
962 | } | ||
963 | #endif | ||
964 | out: | ||
965 | /* update checksum */ | ||
966 | mpc->mpc_checksum = 0; | ||
967 | mpc->mpc_checksum -= mpf_checksum((unsigned char *)mpc, | ||
968 | mpc->mpc_length); | ||
913 | 969 | ||
914 | MP_intsrc_info(&intsrc); | 970 | return 0; |
915 | } | 971 | } |
916 | 972 | ||
917 | void __init mp_config_acpi_legacy_irqs(void) | 973 | static int __initdata enable_update_mptable; |
918 | { | ||
919 | struct mpc_config_intsrc intsrc; | ||
920 | int i = 0; | ||
921 | int ioapic = -1; | ||
922 | 974 | ||
923 | #if defined (CONFIG_MCA) || defined (CONFIG_EISA) | 975 | static int __init update_mptable_setup(char *str) |
924 | /* | 976 | { |
925 | * Fabricate the legacy ISA bus (bus #31). | 977 | enable_update_mptable = 1; |
926 | */ | 978 | return 0; |
927 | mp_bus_id_to_type[MP_ISA_BUS] = MP_BUS_ISA; | 979 | } |
928 | #endif | 980 | early_param("update_mptable", update_mptable_setup); |
929 | set_bit(MP_ISA_BUS, mp_bus_not_pci); | ||
930 | Dprintk("Bus #%d is ISA\n", MP_ISA_BUS); | ||
931 | 981 | ||
932 | /* | 982 | static unsigned long __initdata mpc_new_phys; |
933 | * Older generations of ES7000 have no legacy identity mappings | 983 | static unsigned long mpc_new_length __initdata = 4096; |
934 | */ | ||
935 | if (es7000_plat == 1) | ||
936 | return; | ||
937 | 984 | ||
938 | /* | 985 | /* alloc_mptable or alloc_mptable=4k */ |
939 | * Locate the IOAPIC that manages the ISA IRQs (0-15). | 986 | static int __initdata alloc_mptable; |
940 | */ | 987 | static int __init parse_alloc_mptable_opt(char *p) |
941 | ioapic = mp_find_ioapic(0); | 988 | { |
942 | if (ioapic < 0) | 989 | enable_update_mptable = 1; |
943 | return; | 990 | alloc_mptable = 1; |
991 | if (!p) | ||
992 | return 0; | ||
993 | mpc_new_length = memparse(p, &p); | ||
994 | return 0; | ||
995 | } | ||
996 | early_param("alloc_mptable", parse_alloc_mptable_opt); | ||
944 | 997 | ||
945 | intsrc.mpc_type = MP_INTSRC; | 998 | void __init early_reserve_e820_mpc_new(void) |
946 | intsrc.mpc_irqflag = 0; /* Conforming */ | 999 | { |
947 | intsrc.mpc_srcbus = MP_ISA_BUS; | 1000 | if (enable_update_mptable && alloc_mptable) { |
948 | #ifdef CONFIG_X86_IO_APIC | 1001 | u64 startt = 0; |
949 | intsrc.mpc_dstapic = mp_ioapics[ioapic].mpc_apicid; | 1002 | #ifdef CONFIG_X86_TRAMPOLINE |
1003 | startt = TRAMPOLINE_BASE; | ||
950 | #endif | 1004 | #endif |
951 | /* | 1005 | mpc_new_phys = early_reserve_e820(startt, mpc_new_length, 4); |
952 | * Use the default configuration for the IRQs 0-15. Unless | ||
953 | * overridden by (MADT) interrupt source override entries. | ||
954 | */ | ||
955 | for (i = 0; i < 16; i++) { | ||
956 | int idx; | ||
957 | |||
958 | for (idx = 0; idx < mp_irq_entries; idx++) { | ||
959 | struct mpc_config_intsrc *irq = mp_irqs + idx; | ||
960 | |||
961 | /* Do we already have a mapping for this ISA IRQ? */ | ||
962 | if (irq->mpc_srcbus == MP_ISA_BUS | ||
963 | && irq->mpc_srcbusirq == i) | ||
964 | break; | ||
965 | |||
966 | /* Do we already have a mapping for this IOAPIC pin */ | ||
967 | if ((irq->mpc_dstapic == intsrc.mpc_dstapic) && | ||
968 | (irq->mpc_dstirq == i)) | ||
969 | break; | ||
970 | } | ||
971 | |||
972 | if (idx != mp_irq_entries) { | ||
973 | printk(KERN_DEBUG "ACPI: IRQ%d used by override.\n", i); | ||
974 | continue; /* IRQ already used */ | ||
975 | } | ||
976 | |||
977 | intsrc.mpc_irqtype = mp_INT; | ||
978 | intsrc.mpc_srcbusirq = i; /* Identity mapped */ | ||
979 | intsrc.mpc_dstirq = i; | ||
980 | |||
981 | MP_intsrc_info(&intsrc); | ||
982 | } | 1006 | } |
983 | } | 1007 | } |
984 | 1008 | ||
985 | int mp_register_gsi(u32 gsi, int triggering, int polarity) | 1009 | static int __init update_mp_table(void) |
986 | { | 1010 | { |
987 | int ioapic; | 1011 | char str[16]; |
988 | int ioapic_pin; | 1012 | char oem[10]; |
989 | #ifdef CONFIG_X86_32 | 1013 | struct intel_mp_floating *mpf; |
990 | #define MAX_GSI_NUM 4096 | 1014 | struct mp_config_table *mpc; |
991 | #define IRQ_COMPRESSION_START 64 | 1015 | struct mp_config_table *mpc_new; |
1016 | |||
1017 | if (!enable_update_mptable) | ||
1018 | return 0; | ||
1019 | |||
1020 | mpf = mpf_found; | ||
1021 | if (!mpf) | ||
1022 | return 0; | ||
992 | 1023 | ||
993 | static int pci_irq = IRQ_COMPRESSION_START; | ||
994 | /* | 1024 | /* |
995 | * Mapping between Global System Interrupts, which | 1025 | * Now see if we need to go further. |
996 | * represent all possible interrupts, and IRQs | ||
997 | * assigned to actual devices. | ||
998 | */ | 1026 | */ |
999 | static int gsi_to_irq[MAX_GSI_NUM]; | 1027 | if (mpf->mpf_feature1 != 0) |
1000 | #else | 1028 | return 0; |
1001 | 1029 | ||
1002 | if (acpi_irq_model != ACPI_IRQ_MODEL_IOAPIC) | 1030 | if (!mpf->mpf_physptr) |
1003 | return gsi; | 1031 | return 0; |
1004 | #endif | ||
1005 | 1032 | ||
1006 | /* Don't set up the ACPI SCI because it's already set up */ | 1033 | mpc = phys_to_virt(mpf->mpf_physptr); |
1007 | if (acpi_gbl_FADT.sci_interrupt == gsi) | ||
1008 | return gsi; | ||
1009 | 1034 | ||
1010 | ioapic = mp_find_ioapic(gsi); | 1035 | if (!smp_check_mpc(mpc, oem, str)) |
1011 | if (ioapic < 0) { | 1036 | return 0; |
1012 | printk(KERN_WARNING "No IOAPIC for GSI %u\n", gsi); | ||
1013 | return gsi; | ||
1014 | } | ||
1015 | 1037 | ||
1016 | ioapic_pin = gsi - mp_ioapic_routing[ioapic].gsi_base; | 1038 | printk(KERN_INFO "mpf: %lx\n", virt_to_phys(mpf)); |
1039 | printk(KERN_INFO "mpf_physptr: %x\n", mpf->mpf_physptr); | ||
1017 | 1040 | ||
1018 | #ifdef CONFIG_X86_32 | 1041 | if (mpc_new_phys && mpc->mpc_length > mpc_new_length) { |
1019 | if (ioapic_renumber_irq) | 1042 | mpc_new_phys = 0; |
1020 | gsi = ioapic_renumber_irq(ioapic, gsi); | 1043 | printk(KERN_INFO "mpc_new_length is %ld, please use alloc_mptable=8k\n", |
1021 | #endif | 1044 | mpc_new_length); |
1022 | |||
1023 | /* | ||
1024 | * Avoid pin reprogramming. PRTs typically include entries | ||
1025 | * with redundant pin->gsi mappings (but unique PCI devices); | ||
1026 | * we only program the IOAPIC on the first. | ||
1027 | */ | ||
1028 | if (ioapic_pin > MP_MAX_IOAPIC_PIN) { | ||
1029 | printk(KERN_ERR "Invalid reference to IOAPIC pin " | ||
1030 | "%d-%d\n", mp_ioapic_routing[ioapic].apic_id, | ||
1031 | ioapic_pin); | ||
1032 | return gsi; | ||
1033 | } | 1045 | } |
1034 | if (test_bit(ioapic_pin, mp_ioapic_routing[ioapic].pin_programmed)) { | 1046 | |
1035 | Dprintk(KERN_DEBUG "Pin %d-%d already programmed\n", | 1047 | if (!mpc_new_phys) { |
1036 | mp_ioapic_routing[ioapic].apic_id, ioapic_pin); | 1048 | unsigned char old, new; |
1037 | #ifdef CONFIG_X86_32 | 1049 | /* check if we can change the postion */ |
1038 | return (gsi < IRQ_COMPRESSION_START ? gsi : gsi_to_irq[gsi]); | 1050 | mpc->mpc_checksum = 0; |
1039 | #else | 1051 | old = mpf_checksum((unsigned char *)mpc, mpc->mpc_length); |
1040 | return gsi; | 1052 | mpc->mpc_checksum = 0xff; |
1041 | #endif | 1053 | new = mpf_checksum((unsigned char *)mpc, mpc->mpc_length); |
1054 | if (old == new) { | ||
1055 | printk(KERN_INFO "mpc is readonly, please try alloc_mptable instead\n"); | ||
1056 | return 0; | ||
1057 | } | ||
1058 | printk(KERN_INFO "use in-positon replacing\n"); | ||
1059 | } else { | ||
1060 | mpf->mpf_physptr = mpc_new_phys; | ||
1061 | mpc_new = phys_to_virt(mpc_new_phys); | ||
1062 | memcpy(mpc_new, mpc, mpc->mpc_length); | ||
1063 | mpc = mpc_new; | ||
1064 | /* check if we can modify that */ | ||
1065 | if (mpc_new_phys - mpf->mpf_physptr) { | ||
1066 | struct intel_mp_floating *mpf_new; | ||
1067 | /* steal 16 bytes from [0, 1k) */ | ||
1068 | printk(KERN_INFO "mpf new: %x\n", 0x400 - 16); | ||
1069 | mpf_new = phys_to_virt(0x400 - 16); | ||
1070 | memcpy(mpf_new, mpf, 16); | ||
1071 | mpf = mpf_new; | ||
1072 | mpf->mpf_physptr = mpc_new_phys; | ||
1073 | } | ||
1074 | mpf->mpf_checksum = 0; | ||
1075 | mpf->mpf_checksum -= mpf_checksum((unsigned char *)mpf, 16); | ||
1076 | printk(KERN_INFO "mpf_physptr new: %x\n", mpf->mpf_physptr); | ||
1042 | } | 1077 | } |
1043 | 1078 | ||
1044 | set_bit(ioapic_pin, mp_ioapic_routing[ioapic].pin_programmed); | ||
1045 | #ifdef CONFIG_X86_32 | ||
1046 | /* | 1079 | /* |
1047 | * For GSI >= 64, use IRQ compression | 1080 | * only replace the one with mp_INT and |
1081 | * MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW, | ||
1082 | * already in mp_irqs , stored by ... and mp_config_acpi_gsi, | ||
1083 | * may need pci=routeirq for all coverage | ||
1048 | */ | 1084 | */ |
1049 | if ((gsi >= IRQ_COMPRESSION_START) | 1085 | replace_intsrc_all(mpc, mpc_new_phys, mpc_new_length); |
1050 | && (triggering == ACPI_LEVEL_SENSITIVE)) { | 1086 | |
1051 | /* | 1087 | return 0; |
1052 | * For PCI devices assign IRQs in order, avoiding gaps | ||
1053 | * due to unused I/O APIC pins. | ||
1054 | */ | ||
1055 | int irq = gsi; | ||
1056 | if (gsi < MAX_GSI_NUM) { | ||
1057 | /* | ||
1058 | * Retain the VIA chipset work-around (gsi > 15), but | ||
1059 | * avoid a problem where the 8254 timer (IRQ0) is setup | ||
1060 | * via an override (so it's not on pin 0 of the ioapic), | ||
1061 | * and at the same time, the pin 0 interrupt is a PCI | ||
1062 | * type. The gsi > 15 test could cause these two pins | ||
1063 | * to be shared as IRQ0, and they are not shareable. | ||
1064 | * So test for this condition, and if necessary, avoid | ||
1065 | * the pin collision. | ||
1066 | */ | ||
1067 | gsi = pci_irq++; | ||
1068 | /* | ||
1069 | * Don't assign IRQ used by ACPI SCI | ||
1070 | */ | ||
1071 | if (gsi == acpi_gbl_FADT.sci_interrupt) | ||
1072 | gsi = pci_irq++; | ||
1073 | gsi_to_irq[irq] = gsi; | ||
1074 | } else { | ||
1075 | printk(KERN_ERR "GSI %u is too high\n", gsi); | ||
1076 | return gsi; | ||
1077 | } | ||
1078 | } | ||
1079 | #endif | ||
1080 | io_apic_set_pci_routing(ioapic, ioapic_pin, gsi, | ||
1081 | triggering == ACPI_EDGE_SENSITIVE ? 0 : 1, | ||
1082 | polarity == ACPI_ACTIVE_HIGH ? 0 : 1); | ||
1083 | return gsi; | ||
1084 | } | 1088 | } |
1085 | 1089 | ||
1086 | #endif /* CONFIG_X86_IO_APIC */ | 1090 | late_initcall(update_mp_table); |
1087 | #endif /* CONFIG_ACPI */ | ||