diff options
Diffstat (limited to 'arch/x86/kernel/mpparse.c')
-rw-r--r-- | arch/x86/kernel/mpparse.c | 847 |
1 files changed, 503 insertions, 344 deletions
diff --git a/arch/x86/kernel/mpparse.c b/arch/x86/kernel/mpparse.c index 404683b94e79..3b25e49380c6 100644 --- a/arch/x86/kernel/mpparse.c +++ b/arch/x86/kernel/mpparse.c | |||
@@ -25,6 +25,8 @@ | |||
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> | ||
28 | 30 | ||
29 | #include <mach_apic.h> | 31 | #include <mach_apic.h> |
30 | #ifdef CONFIG_X86_32 | 32 | #ifdef CONFIG_X86_32 |
@@ -32,28 +34,6 @@ | |||
32 | #include <mach_mpparse.h> | 34 | #include <mach_mpparse.h> |
33 | #endif | 35 | #endif |
34 | 36 | ||
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 | /* | 37 | /* |
58 | * Checksum an MP configuration block. | 38 | * Checksum an MP configuration block. |
59 | */ | 39 | */ |
@@ -69,15 +49,73 @@ static int __init mpf_checksum(unsigned char *mp, int len) | |||
69 | } | 49 | } |
70 | 50 | ||
71 | #ifdef CONFIG_X86_NUMAQ | 51 | #ifdef CONFIG_X86_NUMAQ |
52 | int found_numaq; | ||
72 | /* | 53 | /* |
73 | * Have to match translation table entries to main table entries by counter | 54 | * 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 | 55 | * hence the mpc_record variable .... can't see a less disgusting way of |
75 | * doing this .... | 56 | * doing this .... |
76 | */ | 57 | */ |
58 | struct mpc_config_translation { | ||
59 | unsigned char mpc_type; | ||
60 | unsigned char trans_len; | ||
61 | unsigned char trans_type; | ||
62 | unsigned char trans_quad; | ||
63 | unsigned char trans_global; | ||
64 | unsigned char trans_local; | ||
65 | unsigned short trans_reserved; | ||
66 | }; | ||
67 | |||
77 | 68 | ||
78 | static int mpc_record; | 69 | static int mpc_record; |
79 | static struct mpc_config_translation *translation_table[MAX_MPC_ENTRY] | 70 | static struct mpc_config_translation *translation_table[MAX_MPC_ENTRY] |
80 | __cpuinitdata; | 71 | __cpuinitdata; |
72 | |||
73 | static inline int generate_logical_apicid(int quad, int phys_apicid) | ||
74 | { | ||
75 | return (quad << 4) + (phys_apicid ? phys_apicid << 1 : 1); | ||
76 | } | ||
77 | |||
78 | |||
79 | static inline int mpc_apic_id(struct mpc_config_processor *m, | ||
80 | struct mpc_config_translation *translation_record) | ||
81 | { | ||
82 | int quad = translation_record->trans_quad; | ||
83 | int logical_apicid = generate_logical_apicid(quad, m->mpc_apicid); | ||
84 | |||
85 | printk(KERN_DEBUG "Processor #%d %u:%u APIC version %d (quad %d, apic %d)\n", | ||
86 | m->mpc_apicid, | ||
87 | (m->mpc_cpufeature & CPU_FAMILY_MASK) >> 8, | ||
88 | (m->mpc_cpufeature & CPU_MODEL_MASK) >> 4, | ||
89 | m->mpc_apicver, quad, logical_apicid); | ||
90 | return logical_apicid; | ||
91 | } | ||
92 | |||
93 | int mp_bus_id_to_node[MAX_MP_BUSSES]; | ||
94 | |||
95 | int mp_bus_id_to_local[MAX_MP_BUSSES]; | ||
96 | |||
97 | static void mpc_oem_bus_info(struct mpc_config_bus *m, char *name, | ||
98 | struct mpc_config_translation *translation) | ||
99 | { | ||
100 | int quad = translation->trans_quad; | ||
101 | int local = translation->trans_local; | ||
102 | |||
103 | mp_bus_id_to_node[m->mpc_busid] = quad; | ||
104 | mp_bus_id_to_local[m->mpc_busid] = local; | ||
105 | printk(KERN_INFO "Bus #%d is %s (node %d)\n", | ||
106 | m->mpc_busid, name, quad); | ||
107 | } | ||
108 | |||
109 | int quad_local_to_mp_bus_id [NR_CPUS/4][4]; | ||
110 | static void mpc_oem_pci_bus(struct mpc_config_bus *m, | ||
111 | struct mpc_config_translation *translation) | ||
112 | { | ||
113 | int quad = translation->trans_quad; | ||
114 | int local = translation->trans_local; | ||
115 | |||
116 | quad_local_to_mp_bus_id[quad][local] = m->mpc_busid; | ||
117 | } | ||
118 | |||
81 | #endif | 119 | #endif |
82 | 120 | ||
83 | static void __cpuinit MP_processor_info(struct mpc_config_processor *m) | 121 | static void __cpuinit MP_processor_info(struct mpc_config_processor *m) |
@@ -90,7 +128,10 @@ static void __cpuinit MP_processor_info(struct mpc_config_processor *m) | |||
90 | return; | 128 | return; |
91 | } | 129 | } |
92 | #ifdef CONFIG_X86_NUMAQ | 130 | #ifdef CONFIG_X86_NUMAQ |
93 | apicid = mpc_apic_id(m, translation_table[mpc_record]); | 131 | if (found_numaq) |
132 | apicid = mpc_apic_id(m, translation_table[mpc_record]); | ||
133 | else | ||
134 | apicid = m->mpc_apicid; | ||
94 | #else | 135 | #else |
95 | apicid = m->mpc_apicid; | 136 | apicid = m->mpc_apicid; |
96 | #endif | 137 | #endif |
@@ -103,17 +144,18 @@ static void __cpuinit MP_processor_info(struct mpc_config_processor *m) | |||
103 | generic_processor_info(apicid, m->mpc_apicver); | 144 | generic_processor_info(apicid, m->mpc_apicver); |
104 | } | 145 | } |
105 | 146 | ||
147 | #ifdef CONFIG_X86_IO_APIC | ||
106 | static void __init MP_bus_info(struct mpc_config_bus *m) | 148 | static void __init MP_bus_info(struct mpc_config_bus *m) |
107 | { | 149 | { |
108 | char str[7]; | 150 | char str[7]; |
109 | |||
110 | memcpy(str, m->mpc_bustype, 6); | 151 | memcpy(str, m->mpc_bustype, 6); |
111 | str[6] = 0; | 152 | str[6] = 0; |
112 | 153 | ||
113 | #ifdef CONFIG_X86_NUMAQ | 154 | #ifdef CONFIG_X86_NUMAQ |
114 | mpc_oem_bus_info(m, str, translation_table[mpc_record]); | 155 | if (found_numaq) |
156 | mpc_oem_bus_info(m, str, translation_table[mpc_record]); | ||
115 | #else | 157 | #else |
116 | Dprintk("Bus #%d is %s\n", m->mpc_busid, str); | 158 | printk(KERN_INFO "Bus #%d is %s\n", m->mpc_busid, str); |
117 | #endif | 159 | #endif |
118 | 160 | ||
119 | #if MAX_MP_BUSSES < 256 | 161 | #if MAX_MP_BUSSES < 256 |
@@ -132,11 +174,10 @@ static void __init MP_bus_info(struct mpc_config_bus *m) | |||
132 | #endif | 174 | #endif |
133 | } else if (strncmp(str, BUSTYPE_PCI, sizeof(BUSTYPE_PCI) - 1) == 0) { | 175 | } else if (strncmp(str, BUSTYPE_PCI, sizeof(BUSTYPE_PCI) - 1) == 0) { |
134 | #ifdef CONFIG_X86_NUMAQ | 176 | #ifdef CONFIG_X86_NUMAQ |
135 | mpc_oem_pci_bus(m, translation_table[mpc_record]); | 177 | if (found_numaq) |
178 | mpc_oem_pci_bus(m, translation_table[mpc_record]); | ||
136 | #endif | 179 | #endif |
137 | clear_bit(m->mpc_busid, mp_bus_not_pci); | 180 | 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) | 181 | #if defined(CONFIG_EISA) || defined (CONFIG_MCA) |
141 | mp_bus_id_to_type[m->mpc_busid] = MP_BUS_PCI; | 182 | mp_bus_id_to_type[m->mpc_busid] = MP_BUS_PCI; |
142 | } else if (strncmp(str, BUSTYPE_EISA, sizeof(BUSTYPE_EISA) - 1) == 0) { | 183 | } else if (strncmp(str, BUSTYPE_EISA, sizeof(BUSTYPE_EISA) - 1) == 0) { |
@@ -147,6 +188,7 @@ static void __init MP_bus_info(struct mpc_config_bus *m) | |||
147 | } else | 188 | } else |
148 | printk(KERN_WARNING "Unknown bustype %s - ignoring\n", str); | 189 | printk(KERN_WARNING "Unknown bustype %s - ignoring\n", str); |
149 | } | 190 | } |
191 | #endif | ||
150 | 192 | ||
151 | #ifdef CONFIG_X86_IO_APIC | 193 | #ifdef CONFIG_X86_IO_APIC |
152 | 194 | ||
@@ -176,18 +218,89 @@ static void __init MP_ioapic_info(struct mpc_config_ioapic *m) | |||
176 | if (bad_ioapic(m->mpc_apicaddr)) | 218 | if (bad_ioapic(m->mpc_apicaddr)) |
177 | return; | 219 | return; |
178 | 220 | ||
179 | mp_ioapics[nr_ioapics] = *m; | 221 | mp_ioapics[nr_ioapics].mp_apicaddr = m->mpc_apicaddr; |
222 | mp_ioapics[nr_ioapics].mp_apicid = m->mpc_apicid; | ||
223 | mp_ioapics[nr_ioapics].mp_type = m->mpc_type; | ||
224 | mp_ioapics[nr_ioapics].mp_apicver = m->mpc_apicver; | ||
225 | mp_ioapics[nr_ioapics].mp_flags = m->mpc_flags; | ||
180 | nr_ioapics++; | 226 | nr_ioapics++; |
181 | } | 227 | } |
182 | 228 | ||
183 | static void __init MP_intsrc_info(struct mpc_config_intsrc *m) | 229 | static void print_MP_intsrc_info(struct mpc_config_intsrc *m) |
184 | { | 230 | { |
185 | mp_irqs[mp_irq_entries] = *m; | 231 | 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", | 232 | " IRQ %02x, APIC ID %x, APIC INT %02x\n", |
188 | m->mpc_irqtype, m->mpc_irqflag & 3, | 233 | m->mpc_irqtype, m->mpc_irqflag & 3, |
189 | (m->mpc_irqflag >> 2) & 3, m->mpc_srcbus, | 234 | (m->mpc_irqflag >> 2) & 3, m->mpc_srcbus, |
190 | m->mpc_srcbusirq, m->mpc_dstapic, m->mpc_dstirq); | 235 | m->mpc_srcbusirq, m->mpc_dstapic, m->mpc_dstirq); |
236 | } | ||
237 | |||
238 | static void __init print_mp_irq_info(struct mp_config_intsrc *mp_irq) | ||
239 | { | ||
240 | printk(KERN_CONT "Int: type %d, pol %d, trig %d, bus %02x," | ||
241 | " IRQ %02x, APIC ID %x, APIC INT %02x\n", | ||
242 | mp_irq->mp_irqtype, mp_irq->mp_irqflag & 3, | ||
243 | (mp_irq->mp_irqflag >> 2) & 3, mp_irq->mp_srcbus, | ||
244 | mp_irq->mp_srcbusirq, mp_irq->mp_dstapic, mp_irq->mp_dstirq); | ||
245 | } | ||
246 | |||
247 | static void __init assign_to_mp_irq(struct mpc_config_intsrc *m, | ||
248 | struct mp_config_intsrc *mp_irq) | ||
249 | { | ||
250 | mp_irq->mp_dstapic = m->mpc_dstapic; | ||
251 | mp_irq->mp_type = m->mpc_type; | ||
252 | mp_irq->mp_irqtype = m->mpc_irqtype; | ||
253 | mp_irq->mp_irqflag = m->mpc_irqflag; | ||
254 | mp_irq->mp_srcbus = m->mpc_srcbus; | ||
255 | mp_irq->mp_srcbusirq = m->mpc_srcbusirq; | ||
256 | mp_irq->mp_dstirq = m->mpc_dstirq; | ||
257 | } | ||
258 | |||
259 | static void __init assign_to_mpc_intsrc(struct mp_config_intsrc *mp_irq, | ||
260 | struct mpc_config_intsrc *m) | ||
261 | { | ||
262 | m->mpc_dstapic = mp_irq->mp_dstapic; | ||
263 | m->mpc_type = mp_irq->mp_type; | ||
264 | m->mpc_irqtype = mp_irq->mp_irqtype; | ||
265 | m->mpc_irqflag = mp_irq->mp_irqflag; | ||
266 | m->mpc_srcbus = mp_irq->mp_srcbus; | ||
267 | m->mpc_srcbusirq = mp_irq->mp_srcbusirq; | ||
268 | m->mpc_dstirq = mp_irq->mp_dstirq; | ||
269 | } | ||
270 | |||
271 | static int __init mp_irq_mpc_intsrc_cmp(struct mp_config_intsrc *mp_irq, | ||
272 | struct mpc_config_intsrc *m) | ||
273 | { | ||
274 | if (mp_irq->mp_dstapic != m->mpc_dstapic) | ||
275 | return 1; | ||
276 | if (mp_irq->mp_type != m->mpc_type) | ||
277 | return 2; | ||
278 | if (mp_irq->mp_irqtype != m->mpc_irqtype) | ||
279 | return 3; | ||
280 | if (mp_irq->mp_irqflag != m->mpc_irqflag) | ||
281 | return 4; | ||
282 | if (mp_irq->mp_srcbus != m->mpc_srcbus) | ||
283 | return 5; | ||
284 | if (mp_irq->mp_srcbusirq != m->mpc_srcbusirq) | ||
285 | return 6; | ||
286 | if (mp_irq->mp_dstirq != m->mpc_dstirq) | ||
287 | return 7; | ||
288 | |||
289 | return 0; | ||
290 | } | ||
291 | |||
292 | static void __init MP_intsrc_info(struct mpc_config_intsrc *m) | ||
293 | { | ||
294 | int i; | ||
295 | |||
296 | print_MP_intsrc_info(m); | ||
297 | |||
298 | for (i = 0; i < mp_irq_entries; i++) { | ||
299 | if (!mp_irq_mpc_intsrc_cmp(&mp_irqs[i], m)) | ||
300 | return; | ||
301 | } | ||
302 | |||
303 | assign_to_mp_irq(m, &mp_irqs[mp_irq_entries]); | ||
191 | if (++mp_irq_entries == MAX_IRQ_SOURCES) | 304 | if (++mp_irq_entries == MAX_IRQ_SOURCES) |
192 | panic("Max # of irq sources exceeded!!\n"); | 305 | panic("Max # of irq sources exceeded!!\n"); |
193 | } | 306 | } |
@@ -196,7 +309,7 @@ static void __init MP_intsrc_info(struct mpc_config_intsrc *m) | |||
196 | 309 | ||
197 | static void __init MP_lintsrc_info(struct mpc_config_lintsrc *m) | 310 | static void __init MP_lintsrc_info(struct mpc_config_lintsrc *m) |
198 | { | 311 | { |
199 | Dprintk("Lint: type %d, pol %d, trig %d, bus %d," | 312 | printk(KERN_INFO "Lint: type %d, pol %d, trig %d, bus %02x," |
200 | " IRQ %02x, APIC ID %x, APIC LINT %02x\n", | 313 | " IRQ %02x, APIC ID %x, APIC LINT %02x\n", |
201 | m->mpc_irqtype, m->mpc_irqflag & 3, | 314 | m->mpc_irqtype, m->mpc_irqflag & 3, |
202 | (m->mpc_irqflag >> 2) & 3, m->mpc_srcbusid, | 315 | (m->mpc_irqflag >> 2) & 3, m->mpc_srcbusid, |
@@ -266,11 +379,14 @@ static void __init smp_read_mpc_oem(struct mp_config_oemtable *oemtable, | |||
266 | } | 379 | } |
267 | } | 380 | } |
268 | 381 | ||
269 | static inline void mps_oem_check(struct mp_config_table *mpc, char *oem, | 382 | void numaq_mps_oem_check(struct mp_config_table *mpc, char *oem, |
270 | char *productid) | 383 | char *productid) |
271 | { | 384 | { |
272 | if (strncmp(oem, "IBM NUMA", 8)) | 385 | if (strncmp(oem, "IBM NUMA", 8)) |
273 | printk("Warning! May not be a NUMA-Q system!\n"); | 386 | printk("Warning! Not a NUMA-Q system!\n"); |
387 | else | ||
388 | found_numaq = 1; | ||
389 | |||
274 | if (mpc->mpc_oemptr) | 390 | if (mpc->mpc_oemptr) |
275 | smp_read_mpc_oem((struct mp_config_oemtable *)mpc->mpc_oemptr, | 391 | smp_read_mpc_oem((struct mp_config_oemtable *)mpc->mpc_oemptr, |
276 | mpc->mpc_oemsize); | 392 | mpc->mpc_oemsize); |
@@ -281,12 +397,9 @@ static inline void mps_oem_check(struct mp_config_table *mpc, char *oem, | |||
281 | * Read/parse the MPC | 397 | * Read/parse the MPC |
282 | */ | 398 | */ |
283 | 399 | ||
284 | static int __init smp_read_mpc(struct mp_config_table *mpc, unsigned early) | 400 | static int __init smp_check_mpc(struct mp_config_table *mpc, char *oem, |
401 | char *str) | ||
285 | { | 402 | { |
286 | char str[16]; | ||
287 | char oem[10]; | ||
288 | int count = sizeof(*mpc); | ||
289 | unsigned char *mpt = ((unsigned char *)mpc) + count; | ||
290 | 403 | ||
291 | if (memcmp(mpc->mpc_signature, MPC_SIGNATURE, 4)) { | 404 | if (memcmp(mpc->mpc_signature, MPC_SIGNATURE, 4)) { |
292 | printk(KERN_ERR "MPTABLE: bad signature [%c%c%c%c]!\n", | 405 | printk(KERN_ERR "MPTABLE: bad signature [%c%c%c%c]!\n", |
@@ -309,19 +422,42 @@ static int __init smp_read_mpc(struct mp_config_table *mpc, unsigned early) | |||
309 | } | 422 | } |
310 | memcpy(oem, mpc->mpc_oem, 8); | 423 | memcpy(oem, mpc->mpc_oem, 8); |
311 | oem[8] = 0; | 424 | oem[8] = 0; |
312 | printk(KERN_INFO "MPTABLE: OEM ID: %s ", oem); | 425 | printk(KERN_INFO "MPTABLE: OEM ID: %s\n", oem); |
313 | 426 | ||
314 | memcpy(str, mpc->mpc_productid, 12); | 427 | memcpy(str, mpc->mpc_productid, 12); |
315 | str[12] = 0; | 428 | str[12] = 0; |
316 | printk("Product ID: %s ", str); | ||
317 | 429 | ||
318 | #ifdef CONFIG_X86_32 | 430 | 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 | 431 | ||
323 | printk(KERN_INFO "MPTABLE: APIC at: 0x%X\n", mpc->mpc_lapic); | 432 | printk(KERN_INFO "MPTABLE: APIC at: 0x%X\n", mpc->mpc_lapic); |
324 | 433 | ||
434 | return 1; | ||
435 | } | ||
436 | |||
437 | static int __init smp_read_mpc(struct mp_config_table *mpc, unsigned early) | ||
438 | { | ||
439 | char str[16]; | ||
440 | char oem[10]; | ||
441 | |||
442 | int count = sizeof(*mpc); | ||
443 | unsigned char *mpt = ((unsigned char *)mpc) + count; | ||
444 | |||
445 | if (!smp_check_mpc(mpc, oem, str)) | ||
446 | return 0; | ||
447 | |||
448 | #ifdef CONFIG_X86_32 | ||
449 | /* | ||
450 | * need to make sure summit and es7000's mps_oem_check is safe to be | ||
451 | * called early via genericarch 's mps_oem_check | ||
452 | */ | ||
453 | if (early) { | ||
454 | #ifdef CONFIG_X86_NUMAQ | ||
455 | numaq_mps_oem_check(mpc, oem, str); | ||
456 | #endif | ||
457 | } else | ||
458 | mps_oem_check(mpc, oem, str); | ||
459 | #endif | ||
460 | |||
325 | /* save the local APIC address, it might be non-default */ | 461 | /* save the local APIC address, it might be non-default */ |
326 | if (!acpi_lapic) | 462 | if (!acpi_lapic) |
327 | mp_lapic_addr = mpc->mpc_lapic; | 463 | mp_lapic_addr = mpc->mpc_lapic; |
@@ -352,7 +488,9 @@ static int __init smp_read_mpc(struct mp_config_table *mpc, unsigned early) | |||
352 | { | 488 | { |
353 | struct mpc_config_bus *m = | 489 | struct mpc_config_bus *m = |
354 | (struct mpc_config_bus *)mpt; | 490 | (struct mpc_config_bus *)mpt; |
491 | #ifdef CONFIG_X86_IO_APIC | ||
355 | MP_bus_info(m); | 492 | MP_bus_info(m); |
493 | #endif | ||
356 | mpt += sizeof(*m); | 494 | mpt += sizeof(*m); |
357 | count += sizeof(*m); | 495 | count += sizeof(*m); |
358 | break; | 496 | break; |
@@ -402,6 +540,11 @@ static int __init smp_read_mpc(struct mp_config_table *mpc, unsigned early) | |||
402 | ++mpc_record; | 540 | ++mpc_record; |
403 | #endif | 541 | #endif |
404 | } | 542 | } |
543 | |||
544 | #ifdef CONFIG_X86_GENERICARCH | ||
545 | generic_bigsmp_probe(); | ||
546 | #endif | ||
547 | |||
405 | setup_apic_routing(); | 548 | setup_apic_routing(); |
406 | if (!num_processors) | 549 | if (!num_processors) |
407 | printk(KERN_ERR "MPTABLE: no processors registered!\n"); | 550 | printk(KERN_ERR "MPTABLE: no processors registered!\n"); |
@@ -427,7 +570,7 @@ static void __init construct_default_ioirq_mptable(int mpc_default_type) | |||
427 | intsrc.mpc_type = MP_INTSRC; | 570 | intsrc.mpc_type = MP_INTSRC; |
428 | intsrc.mpc_irqflag = 0; /* conforming */ | 571 | intsrc.mpc_irqflag = 0; /* conforming */ |
429 | intsrc.mpc_srcbus = 0; | 572 | intsrc.mpc_srcbus = 0; |
430 | intsrc.mpc_dstapic = mp_ioapics[0].mpc_apicid; | 573 | intsrc.mpc_dstapic = mp_ioapics[0].mp_apicid; |
431 | 574 | ||
432 | intsrc.mpc_irqtype = mp_INT; | 575 | intsrc.mpc_irqtype = mp_INT; |
433 | 576 | ||
@@ -488,40 +631,11 @@ static void __init construct_default_ioirq_mptable(int mpc_default_type) | |||
488 | MP_intsrc_info(&intsrc); | 631 | MP_intsrc_info(&intsrc); |
489 | } | 632 | } |
490 | 633 | ||
491 | #endif | ||
492 | 634 | ||
493 | static inline void __init construct_default_ISA_mptable(int mpc_default_type) | 635 | static void construct_ioapic_table(int mpc_default_type) |
494 | { | 636 | { |
495 | struct mpc_config_processor processor; | ||
496 | struct mpc_config_bus bus; | ||
497 | #ifdef CONFIG_X86_IO_APIC | ||
498 | struct mpc_config_ioapic ioapic; | 637 | struct mpc_config_ioapic ioapic; |
499 | #endif | 638 | 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 | 639 | ||
526 | bus.mpc_type = MP_BUS; | 640 | bus.mpc_type = MP_BUS; |
527 | bus.mpc_busid = 0; | 641 | bus.mpc_busid = 0; |
@@ -550,7 +664,6 @@ static inline void __init construct_default_ISA_mptable(int mpc_default_type) | |||
550 | MP_bus_info(&bus); | 664 | MP_bus_info(&bus); |
551 | } | 665 | } |
552 | 666 | ||
553 | #ifdef CONFIG_X86_IO_APIC | ||
554 | ioapic.mpc_type = MP_IOAPIC; | 667 | ioapic.mpc_type = MP_IOAPIC; |
555 | ioapic.mpc_apicid = 2; | 668 | ioapic.mpc_apicid = 2; |
556 | ioapic.mpc_apicver = mpc_default_type > 4 ? 0x10 : 0x01; | 669 | ioapic.mpc_apicver = mpc_default_type > 4 ? 0x10 : 0x01; |
@@ -562,7 +675,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. | 675 | * We set up most of the low 16 IO-APIC pins according to MPS rules. |
563 | */ | 676 | */ |
564 | construct_default_ioirq_mptable(mpc_default_type); | 677 | construct_default_ioirq_mptable(mpc_default_type); |
678 | } | ||
679 | #else | ||
680 | static inline void construct_ioapic_table(int mpc_default_type) { } | ||
565 | #endif | 681 | #endif |
682 | |||
683 | static inline void __init construct_default_ISA_mptable(int mpc_default_type) | ||
684 | { | ||
685 | struct mpc_config_processor processor; | ||
686 | struct mpc_config_lintsrc lintsrc; | ||
687 | int linttypes[2] = { mp_ExtINT, mp_NMI }; | ||
688 | int i; | ||
689 | |||
690 | /* | ||
691 | * local APIC has default address | ||
692 | */ | ||
693 | mp_lapic_addr = APIC_DEFAULT_PHYS_BASE; | ||
694 | |||
695 | /* | ||
696 | * 2 CPUs, numbered 0 & 1. | ||
697 | */ | ||
698 | processor.mpc_type = MP_PROCESSOR; | ||
699 | /* Either an integrated APIC or a discrete 82489DX. */ | ||
700 | processor.mpc_apicver = mpc_default_type > 4 ? 0x10 : 0x01; | ||
701 | processor.mpc_cpuflag = CPU_ENABLED; | ||
702 | processor.mpc_cpufeature = (boot_cpu_data.x86 << 8) | | ||
703 | (boot_cpu_data.x86_model << 4) | boot_cpu_data.x86_mask; | ||
704 | processor.mpc_featureflag = boot_cpu_data.x86_capability[0]; | ||
705 | processor.mpc_reserved[0] = 0; | ||
706 | processor.mpc_reserved[1] = 0; | ||
707 | for (i = 0; i < 2; i++) { | ||
708 | processor.mpc_apicid = i; | ||
709 | MP_processor_info(&processor); | ||
710 | } | ||
711 | |||
712 | construct_ioapic_table(mpc_default_type); | ||
713 | |||
566 | lintsrc.mpc_type = MP_LINTSRC; | 714 | lintsrc.mpc_type = MP_LINTSRC; |
567 | lintsrc.mpc_irqflag = 0; /* conforming */ | 715 | lintsrc.mpc_irqflag = 0; /* conforming */ |
568 | lintsrc.mpc_srcbusid = 0; | 716 | lintsrc.mpc_srcbusid = 0; |
@@ -578,12 +726,22 @@ static inline void __init construct_default_ISA_mptable(int mpc_default_type) | |||
578 | static struct intel_mp_floating *mpf_found; | 726 | static struct intel_mp_floating *mpf_found; |
579 | 727 | ||
580 | /* | 728 | /* |
729 | * Machine specific quirk for finding the SMP config before other setup | ||
730 | * activities destroy the table: | ||
731 | */ | ||
732 | int (*mach_get_smp_config_quirk)(unsigned int early); | ||
733 | |||
734 | /* | ||
581 | * Scan the memory blocks for an SMP configuration block. | 735 | * Scan the memory blocks for an SMP configuration block. |
582 | */ | 736 | */ |
583 | static void __init __get_smp_config(unsigned early) | 737 | static void __init __get_smp_config(unsigned int early) |
584 | { | 738 | { |
585 | struct intel_mp_floating *mpf = mpf_found; | 739 | struct intel_mp_floating *mpf = mpf_found; |
586 | 740 | ||
741 | if (mach_get_smp_config_quirk) { | ||
742 | if (mach_get_smp_config_quirk(early)) | ||
743 | return; | ||
744 | } | ||
587 | if (acpi_lapic && early) | 745 | if (acpi_lapic && early) |
588 | return; | 746 | return; |
589 | /* | 747 | /* |
@@ -600,7 +758,7 @@ static void __init __get_smp_config(unsigned early) | |||
600 | 758 | ||
601 | printk(KERN_INFO "Intel MultiProcessor Specification v1.%d\n", | 759 | printk(KERN_INFO "Intel MultiProcessor Specification v1.%d\n", |
602 | mpf->mpf_specification); | 760 | mpf->mpf_specification); |
603 | #ifdef CONFIG_X86_32 | 761 | #if defined(CONFIG_X86_LOCAL_APIC) && defined(CONFIG_X86_32) |
604 | if (mpf->mpf_feature2 & (1 << 7)) { | 762 | if (mpf->mpf_feature2 & (1 << 7)) { |
605 | printk(KERN_INFO " IMCR and PIC compatibility mode.\n"); | 763 | printk(KERN_INFO " IMCR and PIC compatibility mode.\n"); |
606 | pic_mode = 1; | 764 | pic_mode = 1; |
@@ -632,7 +790,9 @@ static void __init __get_smp_config(unsigned early) | |||
632 | * override the defaults. | 790 | * override the defaults. |
633 | */ | 791 | */ |
634 | if (!smp_read_mpc(phys_to_virt(mpf->mpf_physptr), early)) { | 792 | if (!smp_read_mpc(phys_to_virt(mpf->mpf_physptr), early)) { |
793 | #ifdef CONFIG_X86_LOCAL_APIC | ||
635 | smp_found_config = 0; | 794 | smp_found_config = 0; |
795 | #endif | ||
636 | printk(KERN_ERR | 796 | printk(KERN_ERR |
637 | "BIOS bug, MP table errors detected!...\n"); | 797 | "BIOS bug, MP table errors detected!...\n"); |
638 | printk(KERN_ERR "... disabling SMP support. " | 798 | printk(KERN_ERR "... disabling SMP support. " |
@@ -689,7 +849,7 @@ static int __init smp_scan_config(unsigned long base, unsigned long length, | |||
689 | unsigned int *bp = phys_to_virt(base); | 849 | unsigned int *bp = phys_to_virt(base); |
690 | struct intel_mp_floating *mpf; | 850 | struct intel_mp_floating *mpf; |
691 | 851 | ||
692 | Dprintk("Scan SMP from %p for %ld bytes.\n", bp, length); | 852 | printk(KERN_DEBUG "Scan SMP from %p for %ld bytes.\n", bp, length); |
693 | BUILD_BUG_ON(sizeof(*mpf) != 16); | 853 | BUILD_BUG_ON(sizeof(*mpf) != 16); |
694 | 854 | ||
695 | while (length > 0) { | 855 | while (length > 0) { |
@@ -699,15 +859,21 @@ static int __init smp_scan_config(unsigned long base, unsigned long length, | |||
699 | !mpf_checksum((unsigned char *)bp, 16) && | 859 | !mpf_checksum((unsigned char *)bp, 16) && |
700 | ((mpf->mpf_specification == 1) | 860 | ((mpf->mpf_specification == 1) |
701 | || (mpf->mpf_specification == 4))) { | 861 | || (mpf->mpf_specification == 4))) { |
702 | 862 | #ifdef CONFIG_X86_LOCAL_APIC | |
703 | smp_found_config = 1; | 863 | smp_found_config = 1; |
864 | #endif | ||
704 | mpf_found = mpf; | 865 | mpf_found = mpf; |
705 | #ifdef CONFIG_X86_32 | 866 | |
706 | printk(KERN_INFO "found SMP MP-table at [%p] %08lx\n", | 867 | printk(KERN_INFO "found SMP MP-table at [%p] %08lx\n", |
707 | mpf, virt_to_phys(mpf)); | 868 | mpf, virt_to_phys(mpf)); |
708 | reserve_bootmem(virt_to_phys(mpf), PAGE_SIZE, | 869 | |
870 | if (!reserve) | ||
871 | return 1; | ||
872 | reserve_bootmem_generic(virt_to_phys(mpf), PAGE_SIZE, | ||
709 | BOOTMEM_DEFAULT); | 873 | BOOTMEM_DEFAULT); |
710 | if (mpf->mpf_physptr) { | 874 | if (mpf->mpf_physptr) { |
875 | unsigned long size = PAGE_SIZE; | ||
876 | #ifdef CONFIG_X86_32 | ||
711 | /* | 877 | /* |
712 | * We cannot access to MPC table to compute | 878 | * We cannot access to MPC table to compute |
713 | * table size yet, as only few megabytes from | 879 | * table size yet, as only few megabytes from |
@@ -717,24 +883,15 @@ static int __init smp_scan_config(unsigned long base, unsigned long length, | |||
717 | * PAGE_SIZE from mpg->mpf_physptr yields BUG() | 883 | * PAGE_SIZE from mpg->mpf_physptr yields BUG() |
718 | * in reserve_bootmem. | 884 | * in reserve_bootmem. |
719 | */ | 885 | */ |
720 | unsigned long size = PAGE_SIZE; | ||
721 | unsigned long end = max_low_pfn * PAGE_SIZE; | 886 | unsigned long end = max_low_pfn * PAGE_SIZE; |
722 | if (mpf->mpf_physptr + size > end) | 887 | if (mpf->mpf_physptr + size > end) |
723 | size = end - mpf->mpf_physptr; | 888 | size = end - mpf->mpf_physptr; |
724 | reserve_bootmem(mpf->mpf_physptr, size, | 889 | #endif |
890 | reserve_bootmem_generic(mpf->mpf_physptr, size, | ||
725 | BOOTMEM_DEFAULT); | 891 | BOOTMEM_DEFAULT); |
726 | } | 892 | } |
727 | 893 | ||
728 | #else | 894 | 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 | } | 895 | } |
739 | bp += 4; | 896 | bp += 4; |
740 | length -= 16; | 897 | length -= 16; |
@@ -742,10 +899,16 @@ static int __init smp_scan_config(unsigned long base, unsigned long length, | |||
742 | return 0; | 899 | return 0; |
743 | } | 900 | } |
744 | 901 | ||
745 | static void __init __find_smp_config(unsigned reserve) | 902 | int (*mach_find_smp_config_quirk)(unsigned int reserve); |
903 | |||
904 | static void __init __find_smp_config(unsigned int reserve) | ||
746 | { | 905 | { |
747 | unsigned int address; | 906 | unsigned int address; |
748 | 907 | ||
908 | if (mach_find_smp_config_quirk) { | ||
909 | if (mach_find_smp_config_quirk(reserve)) | ||
910 | return; | ||
911 | } | ||
749 | /* | 912 | /* |
750 | * FIXME: Linux assumes you have 640K of base ram.. | 913 | * FIXME: Linux assumes you have 640K of base ram.. |
751 | * this continues the error... | 914 | * this continues the error... |
@@ -790,298 +953,294 @@ void __init find_smp_config(void) | |||
790 | __find_smp_config(1); | 953 | __find_smp_config(1); |
791 | } | 954 | } |
792 | 955 | ||
793 | /* -------------------------------------------------------------------------- | 956 | #ifdef CONFIG_X86_IO_APIC |
794 | ACPI-based MP Configuration | 957 | static u8 __initdata irq_used[MAX_IRQ_SOURCES]; |
795 | -------------------------------------------------------------------------- */ | ||
796 | 958 | ||
797 | /* | 959 | static int __init get_MP_intsrc_index(struct mpc_config_intsrc *m) |
798 | * Keep this outside and initialized to 0, for !CONFIG_ACPI builds: | 960 | { |
799 | */ | 961 | int i; |
800 | int es7000_plat; | ||
801 | 962 | ||
802 | #ifdef CONFIG_ACPI | 963 | if (m->mpc_irqtype != mp_INT) |
964 | return 0; | ||
803 | 965 | ||
804 | #ifdef CONFIG_X86_IO_APIC | 966 | if (m->mpc_irqflag != 0x0f) |
967 | return 0; | ||
805 | 968 | ||
806 | #define MP_ISA_BUS 0 | 969 | /* not legacy */ |
807 | 970 | ||
808 | extern struct mp_ioapic_routing mp_ioapic_routing[MAX_IO_APICS]; | 971 | for (i = 0; i < mp_irq_entries; i++) { |
972 | if (mp_irqs[i].mp_irqtype != mp_INT) | ||
973 | continue; | ||
809 | 974 | ||
810 | static int mp_find_ioapic(int gsi) | 975 | if (mp_irqs[i].mp_irqflag != 0x0f) |
811 | { | 976 | continue; |
812 | int i = 0; | ||
813 | 977 | ||
814 | /* Find the IOAPIC that manages this GSI. */ | 978 | if (mp_irqs[i].mp_srcbus != m->mpc_srcbus) |
815 | for (i = 0; i < nr_ioapics; i++) { | 979 | continue; |
816 | if ((gsi >= mp_ioapic_routing[i].gsi_base) | 980 | if (mp_irqs[i].mp_srcbusirq != m->mpc_srcbusirq) |
817 | && (gsi <= mp_ioapic_routing[i].gsi_end)) | 981 | continue; |
818 | return i; | 982 | if (irq_used[i]) { |
983 | /* already claimed */ | ||
984 | return -2; | ||
985 | } | ||
986 | irq_used[i] = 1; | ||
987 | return i; | ||
819 | } | 988 | } |
820 | 989 | ||
821 | printk(KERN_ERR "ERROR: Unable to locate IOAPIC for GSI %d\n", gsi); | 990 | /* not found */ |
822 | return -1; | 991 | return -1; |
823 | } | 992 | } |
824 | 993 | ||
825 | static u8 __init uniq_ioapic_id(u8 id) | 994 | #define SPARE_SLOT_NUM 20 |
826 | { | 995 | |
827 | #ifdef CONFIG_X86_32 | 996 | 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 | 997 | #endif |
845 | } | ||
846 | 998 | ||
847 | void __init mp_register_ioapic(int id, u32 address, u32 gsi_base) | 999 | static int __init replace_intsrc_all(struct mp_config_table *mpc, |
1000 | unsigned long mpc_new_phys, | ||
1001 | unsigned long mpc_new_length) | ||
848 | { | 1002 | { |
849 | int idx = 0; | 1003 | #ifdef CONFIG_X86_IO_APIC |
850 | 1004 | int i; | |
851 | if (bad_ioapic(address)) | 1005 | int nr_m_spare = 0; |
852 | return; | 1006 | #endif |
853 | 1007 | ||
854 | idx = nr_ioapics; | 1008 | int count = sizeof(*mpc); |
1009 | unsigned char *mpt = ((unsigned char *)mpc) + count; | ||
855 | 1010 | ||
856 | mp_ioapics[idx].mpc_type = MP_IOAPIC; | 1011 | printk(KERN_INFO "mpc_length %x\n", mpc->mpc_length); |
857 | mp_ioapics[idx].mpc_flags = MPC_APIC_USABLE; | 1012 | while (count < mpc->mpc_length) { |
858 | mp_ioapics[idx].mpc_apicaddr = address; | 1013 | switch (*mpt) { |
1014 | case MP_PROCESSOR: | ||
1015 | { | ||
1016 | struct mpc_config_processor *m = | ||
1017 | (struct mpc_config_processor *)mpt; | ||
1018 | mpt += sizeof(*m); | ||
1019 | count += sizeof(*m); | ||
1020 | break; | ||
1021 | } | ||
1022 | case MP_BUS: | ||
1023 | { | ||
1024 | struct mpc_config_bus *m = | ||
1025 | (struct mpc_config_bus *)mpt; | ||
1026 | mpt += sizeof(*m); | ||
1027 | count += sizeof(*m); | ||
1028 | break; | ||
1029 | } | ||
1030 | case MP_IOAPIC: | ||
1031 | { | ||
1032 | mpt += sizeof(struct mpc_config_ioapic); | ||
1033 | count += sizeof(struct mpc_config_ioapic); | ||
1034 | break; | ||
1035 | } | ||
1036 | case MP_INTSRC: | ||
1037 | { | ||
1038 | #ifdef CONFIG_X86_IO_APIC | ||
1039 | struct mpc_config_intsrc *m = | ||
1040 | (struct mpc_config_intsrc *)mpt; | ||
859 | 1041 | ||
860 | set_fixmap_nocache(FIX_IO_APIC_BASE_0 + idx, address); | 1042 | printk(KERN_INFO "OLD "); |
861 | mp_ioapics[idx].mpc_apicid = uniq_ioapic_id(id); | 1043 | print_MP_intsrc_info(m); |
862 | #ifdef CONFIG_X86_32 | 1044 | i = get_MP_intsrc_index(m); |
863 | mp_ioapics[idx].mpc_apicver = io_apic_get_version(idx); | 1045 | if (i > 0) { |
864 | #else | 1046 | assign_to_mpc_intsrc(&mp_irqs[i], m); |
865 | mp_ioapics[idx].mpc_apicver = 0; | 1047 | printk(KERN_INFO "NEW "); |
1048 | print_mp_irq_info(&mp_irqs[i]); | ||
1049 | } else if (!i) { | ||
1050 | /* legacy, do nothing */ | ||
1051 | } else if (nr_m_spare < SPARE_SLOT_NUM) { | ||
1052 | /* | ||
1053 | * not found (-1), or duplicated (-2) | ||
1054 | * are invalid entries, | ||
1055 | * we need to use the slot later | ||
1056 | */ | ||
1057 | m_spare[nr_m_spare] = m; | ||
1058 | nr_m_spare++; | ||
1059 | } | ||
866 | #endif | 1060 | #endif |
867 | /* | 1061 | mpt += sizeof(struct mpc_config_intsrc); |
868 | * Build basic GSI lookup table to facilitate gsi->io_apic lookups | 1062 | count += sizeof(struct mpc_config_intsrc); |
869 | * and to prevent reprogramming of IOAPIC pins (PCI GSIs). | 1063 | break; |
870 | */ | 1064 | } |
871 | mp_ioapic_routing[idx].apic_id = mp_ioapics[idx].mpc_apicid; | 1065 | case MP_LINTSRC: |
872 | mp_ioapic_routing[idx].gsi_base = gsi_base; | 1066 | { |
873 | mp_ioapic_routing[idx].gsi_end = gsi_base + | 1067 | struct mpc_config_lintsrc *m = |
874 | io_apic_get_redir_entries(idx); | 1068 | (struct mpc_config_lintsrc *)mpt; |
875 | 1069 | mpt += sizeof(*m); | |
876 | printk(KERN_INFO "IOAPIC[%d]: apic_id %d, version %d, address 0x%x, " | 1070 | count += sizeof(*m); |
877 | "GSI %d-%d\n", idx, mp_ioapics[idx].mpc_apicid, | 1071 | break; |
878 | mp_ioapics[idx].mpc_apicver, mp_ioapics[idx].mpc_apicaddr, | 1072 | } |
879 | mp_ioapic_routing[idx].gsi_base, mp_ioapic_routing[idx].gsi_end); | 1073 | default: |
880 | 1074 | /* wrong mptable */ | |
881 | nr_ioapics++; | 1075 | printk(KERN_ERR "Your mptable is wrong, contact your HW vendor!\n"); |
882 | } | 1076 | printk(KERN_ERR "type %x\n", *mpt); |
1077 | print_hex_dump(KERN_ERR, " ", DUMP_PREFIX_ADDRESS, 16, | ||
1078 | 1, mpc, mpc->mpc_length, 1); | ||
1079 | goto out; | ||
1080 | } | ||
1081 | } | ||
883 | 1082 | ||
884 | void __init mp_override_legacy_irq(u8 bus_irq, u8 polarity, u8 trigger, u32 gsi) | 1083 | #ifdef CONFIG_X86_IO_APIC |
885 | { | 1084 | for (i = 0; i < mp_irq_entries; i++) { |
886 | struct mpc_config_intsrc intsrc; | 1085 | if (irq_used[i]) |
887 | int ioapic = -1; | 1086 | continue; |
888 | int pin = -1; | ||
889 | 1087 | ||
890 | /* | 1088 | if (mp_irqs[i].mp_irqtype != mp_INT) |
891 | * Convert 'gsi' to 'ioapic.pin'. | 1089 | continue; |
892 | */ | ||
893 | ioapic = mp_find_ioapic(gsi); | ||
894 | if (ioapic < 0) | ||
895 | return; | ||
896 | pin = gsi - mp_ioapic_routing[ioapic].gsi_base; | ||
897 | 1090 | ||
898 | /* | 1091 | if (mp_irqs[i].mp_irqflag != 0x0f) |
899 | * TBD: This check is for faulty timer entries, where the override | 1092 | 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 | 1093 | ||
906 | intsrc.mpc_type = MP_INTSRC; | 1094 | if (nr_m_spare > 0) { |
907 | intsrc.mpc_irqtype = mp_INT; | 1095 | printk(KERN_INFO "*NEW* found "); |
908 | intsrc.mpc_irqflag = (trigger << 2) | polarity; | 1096 | nr_m_spare--; |
909 | intsrc.mpc_srcbus = MP_ISA_BUS; | 1097 | assign_to_mpc_intsrc(&mp_irqs[i], m_spare[nr_m_spare]); |
910 | intsrc.mpc_srcbusirq = bus_irq; /* IRQ */ | 1098 | m_spare[nr_m_spare] = NULL; |
911 | intsrc.mpc_dstapic = mp_ioapics[ioapic].mpc_apicid; /* APIC ID */ | 1099 | } else { |
912 | intsrc.mpc_dstirq = pin; /* INTIN# */ | 1100 | struct mpc_config_intsrc *m = |
1101 | (struct mpc_config_intsrc *)mpt; | ||
1102 | count += sizeof(struct mpc_config_intsrc); | ||
1103 | if (!mpc_new_phys) { | ||
1104 | printk(KERN_INFO "No spare slots, try to append...take your risk, new mpc_length %x\n", count); | ||
1105 | } else { | ||
1106 | if (count <= mpc_new_length) | ||
1107 | printk(KERN_INFO "No spare slots, try to append..., new mpc_length %x\n", count); | ||
1108 | else { | ||
1109 | printk(KERN_ERR "mpc_new_length %lx is too small\n", mpc_new_length); | ||
1110 | goto out; | ||
1111 | } | ||
1112 | } | ||
1113 | assign_to_mpc_intsrc(&mp_irqs[i], m); | ||
1114 | mpc->mpc_length = count; | ||
1115 | mpt += sizeof(struct mpc_config_intsrc); | ||
1116 | } | ||
1117 | print_mp_irq_info(&mp_irqs[i]); | ||
1118 | } | ||
1119 | #endif | ||
1120 | out: | ||
1121 | /* update checksum */ | ||
1122 | mpc->mpc_checksum = 0; | ||
1123 | mpc->mpc_checksum -= mpf_checksum((unsigned char *)mpc, | ||
1124 | mpc->mpc_length); | ||
913 | 1125 | ||
914 | MP_intsrc_info(&intsrc); | 1126 | return 0; |
915 | } | 1127 | } |
916 | 1128 | ||
917 | void __init mp_config_acpi_legacy_irqs(void) | 1129 | static int __initdata enable_update_mptable; |
918 | { | ||
919 | struct mpc_config_intsrc intsrc; | ||
920 | int i = 0; | ||
921 | int ioapic = -1; | ||
922 | 1130 | ||
923 | #if defined (CONFIG_MCA) || defined (CONFIG_EISA) | 1131 | static int __init update_mptable_setup(char *str) |
924 | /* | 1132 | { |
925 | * Fabricate the legacy ISA bus (bus #31). | 1133 | enable_update_mptable = 1; |
926 | */ | 1134 | return 0; |
927 | mp_bus_id_to_type[MP_ISA_BUS] = MP_BUS_ISA; | 1135 | } |
928 | #endif | 1136 | 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 | 1137 | ||
932 | /* | 1138 | static unsigned long __initdata mpc_new_phys; |
933 | * Older generations of ES7000 have no legacy identity mappings | 1139 | static unsigned long mpc_new_length __initdata = 4096; |
934 | */ | ||
935 | if (es7000_plat == 1) | ||
936 | return; | ||
937 | 1140 | ||
938 | /* | 1141 | /* alloc_mptable or alloc_mptable=4k */ |
939 | * Locate the IOAPIC that manages the ISA IRQs (0-15). | 1142 | static int __initdata alloc_mptable; |
940 | */ | 1143 | static int __init parse_alloc_mptable_opt(char *p) |
941 | ioapic = mp_find_ioapic(0); | 1144 | { |
942 | if (ioapic < 0) | 1145 | enable_update_mptable = 1; |
943 | return; | 1146 | alloc_mptable = 1; |
1147 | if (!p) | ||
1148 | return 0; | ||
1149 | mpc_new_length = memparse(p, &p); | ||
1150 | return 0; | ||
1151 | } | ||
1152 | early_param("alloc_mptable", parse_alloc_mptable_opt); | ||
944 | 1153 | ||
945 | intsrc.mpc_type = MP_INTSRC; | 1154 | void __init early_reserve_e820_mpc_new(void) |
946 | intsrc.mpc_irqflag = 0; /* Conforming */ | 1155 | { |
947 | intsrc.mpc_srcbus = MP_ISA_BUS; | 1156 | if (enable_update_mptable && alloc_mptable) { |
948 | #ifdef CONFIG_X86_IO_APIC | 1157 | u64 startt = 0; |
949 | intsrc.mpc_dstapic = mp_ioapics[ioapic].mpc_apicid; | 1158 | #ifdef CONFIG_X86_TRAMPOLINE |
1159 | startt = TRAMPOLINE_BASE; | ||
950 | #endif | 1160 | #endif |
951 | /* | 1161 | 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 | } | 1162 | } |
983 | } | 1163 | } |
984 | 1164 | ||
985 | int mp_register_gsi(u32 gsi, int triggering, int polarity) | 1165 | static int __init update_mp_table(void) |
986 | { | 1166 | { |
987 | int ioapic; | 1167 | char str[16]; |
988 | int ioapic_pin; | 1168 | char oem[10]; |
989 | #ifdef CONFIG_X86_32 | 1169 | struct intel_mp_floating *mpf; |
990 | #define MAX_GSI_NUM 4096 | 1170 | struct mp_config_table *mpc; |
991 | #define IRQ_COMPRESSION_START 64 | 1171 | struct mp_config_table *mpc_new; |
1172 | |||
1173 | if (!enable_update_mptable) | ||
1174 | return 0; | ||
1175 | |||
1176 | mpf = mpf_found; | ||
1177 | if (!mpf) | ||
1178 | return 0; | ||
992 | 1179 | ||
993 | static int pci_irq = IRQ_COMPRESSION_START; | ||
994 | /* | 1180 | /* |
995 | * Mapping between Global System Interrupts, which | 1181 | * Now see if we need to go further. |
996 | * represent all possible interrupts, and IRQs | ||
997 | * assigned to actual devices. | ||
998 | */ | 1182 | */ |
999 | static int gsi_to_irq[MAX_GSI_NUM]; | 1183 | if (mpf->mpf_feature1 != 0) |
1000 | #else | 1184 | return 0; |
1001 | |||
1002 | if (acpi_irq_model != ACPI_IRQ_MODEL_IOAPIC) | ||
1003 | return gsi; | ||
1004 | #endif | ||
1005 | 1185 | ||
1006 | /* Don't set up the ACPI SCI because it's already set up */ | 1186 | if (!mpf->mpf_physptr) |
1007 | if (acpi_gbl_FADT.sci_interrupt == gsi) | 1187 | return 0; |
1008 | return gsi; | ||
1009 | 1188 | ||
1010 | ioapic = mp_find_ioapic(gsi); | 1189 | mpc = phys_to_virt(mpf->mpf_physptr); |
1011 | if (ioapic < 0) { | ||
1012 | printk(KERN_WARNING "No IOAPIC for GSI %u\n", gsi); | ||
1013 | return gsi; | ||
1014 | } | ||
1015 | 1190 | ||
1016 | ioapic_pin = gsi - mp_ioapic_routing[ioapic].gsi_base; | 1191 | if (!smp_check_mpc(mpc, oem, str)) |
1192 | return 0; | ||
1017 | 1193 | ||
1018 | #ifdef CONFIG_X86_32 | 1194 | printk(KERN_INFO "mpf: %lx\n", virt_to_phys(mpf)); |
1019 | if (ioapic_renumber_irq) | 1195 | printk(KERN_INFO "mpf_physptr: %x\n", mpf->mpf_physptr); |
1020 | gsi = ioapic_renumber_irq(ioapic, gsi); | ||
1021 | #endif | ||
1022 | 1196 | ||
1023 | /* | 1197 | if (mpc_new_phys && mpc->mpc_length > mpc_new_length) { |
1024 | * Avoid pin reprogramming. PRTs typically include entries | 1198 | mpc_new_phys = 0; |
1025 | * with redundant pin->gsi mappings (but unique PCI devices); | 1199 | printk(KERN_INFO "mpc_new_length is %ld, please use alloc_mptable=8k\n", |
1026 | * we only program the IOAPIC on the first. | 1200 | mpc_new_length); |
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 | } | 1201 | } |
1034 | if (test_bit(ioapic_pin, mp_ioapic_routing[ioapic].pin_programmed)) { | 1202 | |
1035 | Dprintk(KERN_DEBUG "Pin %d-%d already programmed\n", | 1203 | if (!mpc_new_phys) { |
1036 | mp_ioapic_routing[ioapic].apic_id, ioapic_pin); | 1204 | unsigned char old, new; |
1037 | #ifdef CONFIG_X86_32 | 1205 | /* check if we can change the postion */ |
1038 | return (gsi < IRQ_COMPRESSION_START ? gsi : gsi_to_irq[gsi]); | 1206 | mpc->mpc_checksum = 0; |
1039 | #else | 1207 | old = mpf_checksum((unsigned char *)mpc, mpc->mpc_length); |
1040 | return gsi; | 1208 | mpc->mpc_checksum = 0xff; |
1041 | #endif | 1209 | new = mpf_checksum((unsigned char *)mpc, mpc->mpc_length); |
1210 | if (old == new) { | ||
1211 | printk(KERN_INFO "mpc is readonly, please try alloc_mptable instead\n"); | ||
1212 | return 0; | ||
1213 | } | ||
1214 | printk(KERN_INFO "use in-positon replacing\n"); | ||
1215 | } else { | ||
1216 | mpf->mpf_physptr = mpc_new_phys; | ||
1217 | mpc_new = phys_to_virt(mpc_new_phys); | ||
1218 | memcpy(mpc_new, mpc, mpc->mpc_length); | ||
1219 | mpc = mpc_new; | ||
1220 | /* check if we can modify that */ | ||
1221 | if (mpc_new_phys - mpf->mpf_physptr) { | ||
1222 | struct intel_mp_floating *mpf_new; | ||
1223 | /* steal 16 bytes from [0, 1k) */ | ||
1224 | printk(KERN_INFO "mpf new: %x\n", 0x400 - 16); | ||
1225 | mpf_new = phys_to_virt(0x400 - 16); | ||
1226 | memcpy(mpf_new, mpf, 16); | ||
1227 | mpf = mpf_new; | ||
1228 | mpf->mpf_physptr = mpc_new_phys; | ||
1229 | } | ||
1230 | mpf->mpf_checksum = 0; | ||
1231 | mpf->mpf_checksum -= mpf_checksum((unsigned char *)mpf, 16); | ||
1232 | printk(KERN_INFO "mpf_physptr new: %x\n", mpf->mpf_physptr); | ||
1042 | } | 1233 | } |
1043 | 1234 | ||
1044 | set_bit(ioapic_pin, mp_ioapic_routing[ioapic].pin_programmed); | ||
1045 | #ifdef CONFIG_X86_32 | ||
1046 | /* | 1235 | /* |
1047 | * For GSI >= 64, use IRQ compression | 1236 | * only replace the one with mp_INT and |
1237 | * MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW, | ||
1238 | * already in mp_irqs , stored by ... and mp_config_acpi_gsi, | ||
1239 | * may need pci=routeirq for all coverage | ||
1048 | */ | 1240 | */ |
1049 | if ((gsi >= IRQ_COMPRESSION_START) | 1241 | replace_intsrc_all(mpc, mpc_new_phys, mpc_new_length); |
1050 | && (triggering == ACPI_LEVEL_SENSITIVE)) { | 1242 | |
1051 | /* | 1243 | 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 | } | 1244 | } |
1085 | 1245 | ||
1086 | #endif /* CONFIG_X86_IO_APIC */ | 1246 | late_initcall(update_mp_table); |
1087 | #endif /* CONFIG_ACPI */ | ||