diff options
Diffstat (limited to 'arch/x86/kernel/mpparse.c')
-rw-r--r-- | arch/x86/kernel/mpparse.c | 139 |
1 files changed, 23 insertions, 116 deletions
diff --git a/arch/x86/kernel/mpparse.c b/arch/x86/kernel/mpparse.c index d7b6f7fb4fec..9103b89c145a 100644 --- a/arch/x86/kernel/mpparse.c +++ b/arch/x86/kernel/mpparse.c | |||
@@ -11,6 +11,7 @@ | |||
11 | #include <linux/init.h> | 11 | #include <linux/init.h> |
12 | #include <linux/delay.h> | 12 | #include <linux/delay.h> |
13 | #include <linux/bootmem.h> | 13 | #include <linux/bootmem.h> |
14 | #include <linux/memblock.h> | ||
14 | #include <linux/kernel_stat.h> | 15 | #include <linux/kernel_stat.h> |
15 | #include <linux/mc146818rtc.h> | 16 | #include <linux/mc146818rtc.h> |
16 | #include <linux/bitops.h> | 17 | #include <linux/bitops.h> |
@@ -117,21 +118,8 @@ static void __init MP_bus_info(struct mpc_bus *m) | |||
117 | 118 | ||
118 | static void __init MP_ioapic_info(struct mpc_ioapic *m) | 119 | static void __init MP_ioapic_info(struct mpc_ioapic *m) |
119 | { | 120 | { |
120 | if (!(m->flags & MPC_APIC_USABLE)) | 121 | if (m->flags & MPC_APIC_USABLE) |
121 | return; | 122 | mp_register_ioapic(m->apicid, m->apicaddr, gsi_top); |
122 | |||
123 | printk(KERN_INFO "I/O APIC #%d Version %d at 0x%X.\n", | ||
124 | m->apicid, m->apicver, m->apicaddr); | ||
125 | |||
126 | mp_register_ioapic(m->apicid, m->apicaddr, gsi_top); | ||
127 | } | ||
128 | |||
129 | static void print_MP_intsrc_info(struct mpc_intsrc *m) | ||
130 | { | ||
131 | apic_printk(APIC_VERBOSE, "Int: type %d, pol %d, trig %d, bus %02x," | ||
132 | " IRQ %02x, APIC ID %x, APIC INT %02x\n", | ||
133 | m->irqtype, m->irqflag & 3, (m->irqflag >> 2) & 3, m->srcbus, | ||
134 | m->srcbusirq, m->dstapic, m->dstirq); | ||
135 | } | 123 | } |
136 | 124 | ||
137 | static void __init print_mp_irq_info(struct mpc_intsrc *mp_irq) | 125 | static void __init print_mp_irq_info(struct mpc_intsrc *mp_irq) |
@@ -143,73 +131,11 @@ static void __init print_mp_irq_info(struct mpc_intsrc *mp_irq) | |||
143 | mp_irq->srcbusirq, mp_irq->dstapic, mp_irq->dstirq); | 131 | mp_irq->srcbusirq, mp_irq->dstapic, mp_irq->dstirq); |
144 | } | 132 | } |
145 | 133 | ||
146 | static void __init assign_to_mp_irq(struct mpc_intsrc *m, | ||
147 | struct mpc_intsrc *mp_irq) | ||
148 | { | ||
149 | mp_irq->dstapic = m->dstapic; | ||
150 | mp_irq->type = m->type; | ||
151 | mp_irq->irqtype = m->irqtype; | ||
152 | mp_irq->irqflag = m->irqflag; | ||
153 | mp_irq->srcbus = m->srcbus; | ||
154 | mp_irq->srcbusirq = m->srcbusirq; | ||
155 | mp_irq->dstirq = m->dstirq; | ||
156 | } | ||
157 | |||
158 | static void __init assign_to_mpc_intsrc(struct mpc_intsrc *mp_irq, | ||
159 | struct mpc_intsrc *m) | ||
160 | { | ||
161 | m->dstapic = mp_irq->dstapic; | ||
162 | m->type = mp_irq->type; | ||
163 | m->irqtype = mp_irq->irqtype; | ||
164 | m->irqflag = mp_irq->irqflag; | ||
165 | m->srcbus = mp_irq->srcbus; | ||
166 | m->srcbusirq = mp_irq->srcbusirq; | ||
167 | m->dstirq = mp_irq->dstirq; | ||
168 | } | ||
169 | |||
170 | static int __init mp_irq_mpc_intsrc_cmp(struct mpc_intsrc *mp_irq, | ||
171 | struct mpc_intsrc *m) | ||
172 | { | ||
173 | if (mp_irq->dstapic != m->dstapic) | ||
174 | return 1; | ||
175 | if (mp_irq->type != m->type) | ||
176 | return 2; | ||
177 | if (mp_irq->irqtype != m->irqtype) | ||
178 | return 3; | ||
179 | if (mp_irq->irqflag != m->irqflag) | ||
180 | return 4; | ||
181 | if (mp_irq->srcbus != m->srcbus) | ||
182 | return 5; | ||
183 | if (mp_irq->srcbusirq != m->srcbusirq) | ||
184 | return 6; | ||
185 | if (mp_irq->dstirq != m->dstirq) | ||
186 | return 7; | ||
187 | |||
188 | return 0; | ||
189 | } | ||
190 | |||
191 | static void __init MP_intsrc_info(struct mpc_intsrc *m) | ||
192 | { | ||
193 | int i; | ||
194 | |||
195 | print_MP_intsrc_info(m); | ||
196 | |||
197 | for (i = 0; i < mp_irq_entries; i++) { | ||
198 | if (!mp_irq_mpc_intsrc_cmp(&mp_irqs[i], m)) | ||
199 | return; | ||
200 | } | ||
201 | |||
202 | assign_to_mp_irq(m, &mp_irqs[mp_irq_entries]); | ||
203 | if (++mp_irq_entries == MAX_IRQ_SOURCES) | ||
204 | panic("Max # of irq sources exceeded!!\n"); | ||
205 | } | ||
206 | #else /* CONFIG_X86_IO_APIC */ | 134 | #else /* CONFIG_X86_IO_APIC */ |
207 | static inline void __init MP_bus_info(struct mpc_bus *m) {} | 135 | static inline void __init MP_bus_info(struct mpc_bus *m) {} |
208 | static inline void __init MP_ioapic_info(struct mpc_ioapic *m) {} | 136 | static inline void __init MP_ioapic_info(struct mpc_ioapic *m) {} |
209 | static inline void __init MP_intsrc_info(struct mpc_intsrc *m) {} | ||
210 | #endif /* CONFIG_X86_IO_APIC */ | 137 | #endif /* CONFIG_X86_IO_APIC */ |
211 | 138 | ||
212 | |||
213 | static void __init MP_lintsrc_info(struct mpc_lintsrc *m) | 139 | static void __init MP_lintsrc_info(struct mpc_lintsrc *m) |
214 | { | 140 | { |
215 | apic_printk(APIC_VERBOSE, "Lint: type %d, pol %d, trig %d, bus %02x," | 141 | apic_printk(APIC_VERBOSE, "Lint: type %d, pol %d, trig %d, bus %02x," |
@@ -221,7 +147,6 @@ static void __init MP_lintsrc_info(struct mpc_lintsrc *m) | |||
221 | /* | 147 | /* |
222 | * Read/parse the MPC | 148 | * Read/parse the MPC |
223 | */ | 149 | */ |
224 | |||
225 | static int __init smp_check_mpc(struct mpc_table *mpc, char *oem, char *str) | 150 | static int __init smp_check_mpc(struct mpc_table *mpc, char *oem, char *str) |
226 | { | 151 | { |
227 | 152 | ||
@@ -274,18 +199,6 @@ static void __init smp_dump_mptable(struct mpc_table *mpc, unsigned char *mpt) | |||
274 | 199 | ||
275 | void __init default_smp_read_mpc_oem(struct mpc_table *mpc) { } | 200 | void __init default_smp_read_mpc_oem(struct mpc_table *mpc) { } |
276 | 201 | ||
277 | static void __init smp_register_lapic_address(unsigned long address) | ||
278 | { | ||
279 | mp_lapic_addr = address; | ||
280 | |||
281 | set_fixmap_nocache(FIX_APIC_BASE, address); | ||
282 | if (boot_cpu_physical_apicid == -1U) { | ||
283 | boot_cpu_physical_apicid = read_apic_id(); | ||
284 | apic_version[boot_cpu_physical_apicid] = | ||
285 | GET_APIC_VERSION(apic_read(APIC_LVR)); | ||
286 | } | ||
287 | } | ||
288 | |||
289 | static int __init smp_read_mpc(struct mpc_table *mpc, unsigned early) | 202 | static int __init smp_read_mpc(struct mpc_table *mpc, unsigned early) |
290 | { | 203 | { |
291 | char str[16]; | 204 | char str[16]; |
@@ -300,17 +213,13 @@ static int __init smp_read_mpc(struct mpc_table *mpc, unsigned early) | |||
300 | #ifdef CONFIG_X86_32 | 213 | #ifdef CONFIG_X86_32 |
301 | generic_mps_oem_check(mpc, oem, str); | 214 | generic_mps_oem_check(mpc, oem, str); |
302 | #endif | 215 | #endif |
303 | /* save the local APIC address, it might be non-default */ | 216 | /* Initialize the lapic mapping */ |
304 | if (!acpi_lapic) | 217 | if (!acpi_lapic) |
305 | mp_lapic_addr = mpc->lapic; | 218 | register_lapic_address(mpc->lapic); |
306 | 219 | ||
307 | if (early) | 220 | if (early) |
308 | return 1; | 221 | return 1; |
309 | 222 | ||
310 | /* Initialize the lapic mapping */ | ||
311 | if (!acpi_lapic) | ||
312 | smp_register_lapic_address(mpc->lapic); | ||
313 | |||
314 | if (mpc->oemptr) | 223 | if (mpc->oemptr) |
315 | x86_init.mpparse.smp_read_mpc_oem(mpc); | 224 | x86_init.mpparse.smp_read_mpc_oem(mpc); |
316 | 225 | ||
@@ -336,7 +245,7 @@ static int __init smp_read_mpc(struct mpc_table *mpc, unsigned early) | |||
336 | skip_entry(&mpt, &count, sizeof(struct mpc_ioapic)); | 245 | skip_entry(&mpt, &count, sizeof(struct mpc_ioapic)); |
337 | break; | 246 | break; |
338 | case MP_INTSRC: | 247 | case MP_INTSRC: |
339 | MP_intsrc_info((struct mpc_intsrc *)mpt); | 248 | mp_save_irq((struct mpc_intsrc *)mpt); |
340 | skip_entry(&mpt, &count, sizeof(struct mpc_intsrc)); | 249 | skip_entry(&mpt, &count, sizeof(struct mpc_intsrc)); |
341 | break; | 250 | break; |
342 | case MP_LINTSRC: | 251 | case MP_LINTSRC: |
@@ -376,7 +285,7 @@ static void __init construct_default_ioirq_mptable(int mpc_default_type) | |||
376 | intsrc.type = MP_INTSRC; | 285 | intsrc.type = MP_INTSRC; |
377 | intsrc.irqflag = 0; /* conforming */ | 286 | intsrc.irqflag = 0; /* conforming */ |
378 | intsrc.srcbus = 0; | 287 | intsrc.srcbus = 0; |
379 | intsrc.dstapic = mp_ioapics[0].apicid; | 288 | intsrc.dstapic = mpc_ioapic_id(0); |
380 | 289 | ||
381 | intsrc.irqtype = mp_INT; | 290 | intsrc.irqtype = mp_INT; |
382 | 291 | ||
@@ -428,13 +337,13 @@ static void __init construct_default_ioirq_mptable(int mpc_default_type) | |||
428 | 337 | ||
429 | intsrc.srcbusirq = i; | 338 | intsrc.srcbusirq = i; |
430 | intsrc.dstirq = i ? i : 2; /* IRQ0 to INTIN2 */ | 339 | intsrc.dstirq = i ? i : 2; /* IRQ0 to INTIN2 */ |
431 | MP_intsrc_info(&intsrc); | 340 | mp_save_irq(&intsrc); |
432 | } | 341 | } |
433 | 342 | ||
434 | intsrc.irqtype = mp_ExtINT; | 343 | intsrc.irqtype = mp_ExtINT; |
435 | intsrc.srcbusirq = 0; | 344 | intsrc.srcbusirq = 0; |
436 | intsrc.dstirq = 0; /* 8259A to INTIN0 */ | 345 | intsrc.dstirq = 0; /* 8259A to INTIN0 */ |
437 | MP_intsrc_info(&intsrc); | 346 | mp_save_irq(&intsrc); |
438 | } | 347 | } |
439 | 348 | ||
440 | 349 | ||
@@ -657,7 +566,7 @@ static void __init smp_reserve_memory(struct mpf_intel *mpf) | |||
657 | { | 566 | { |
658 | unsigned long size = get_mpc_size(mpf->physptr); | 567 | unsigned long size = get_mpc_size(mpf->physptr); |
659 | 568 | ||
660 | reserve_early_overlap_ok(mpf->physptr, mpf->physptr+size, "MP-table mpc"); | 569 | memblock_x86_reserve_range(mpf->physptr, mpf->physptr+size, "* MP-table mpc"); |
661 | } | 570 | } |
662 | 571 | ||
663 | static int __init smp_scan_config(unsigned long base, unsigned long length) | 572 | static int __init smp_scan_config(unsigned long base, unsigned long length) |
@@ -686,7 +595,7 @@ static int __init smp_scan_config(unsigned long base, unsigned long length) | |||
686 | mpf, (u64)virt_to_phys(mpf)); | 595 | mpf, (u64)virt_to_phys(mpf)); |
687 | 596 | ||
688 | mem = virt_to_phys(mpf); | 597 | mem = virt_to_phys(mpf); |
689 | reserve_early_overlap_ok(mem, mem + sizeof(*mpf), "MP-table mpf"); | 598 | memblock_x86_reserve_range(mem, mem + sizeof(*mpf), "* MP-table mpf"); |
690 | if (mpf->physptr) | 599 | if (mpf->physptr) |
691 | smp_reserve_memory(mpf); | 600 | smp_reserve_memory(mpf); |
692 | 601 | ||
@@ -783,11 +692,11 @@ static void __init check_irq_src(struct mpc_intsrc *m, int *nr_m_spare) | |||
783 | int i; | 692 | int i; |
784 | 693 | ||
785 | apic_printk(APIC_VERBOSE, "OLD "); | 694 | apic_printk(APIC_VERBOSE, "OLD "); |
786 | print_MP_intsrc_info(m); | 695 | print_mp_irq_info(m); |
787 | 696 | ||
788 | i = get_MP_intsrc_index(m); | 697 | i = get_MP_intsrc_index(m); |
789 | if (i > 0) { | 698 | if (i > 0) { |
790 | assign_to_mpc_intsrc(&mp_irqs[i], m); | 699 | memcpy(m, &mp_irqs[i], sizeof(*m)); |
791 | apic_printk(APIC_VERBOSE, "NEW "); | 700 | apic_printk(APIC_VERBOSE, "NEW "); |
792 | print_mp_irq_info(&mp_irqs[i]); | 701 | print_mp_irq_info(&mp_irqs[i]); |
793 | return; | 702 | return; |
@@ -805,23 +714,21 @@ static void __init check_irq_src(struct mpc_intsrc *m, int *nr_m_spare) | |||
805 | *nr_m_spare += 1; | 714 | *nr_m_spare += 1; |
806 | } | 715 | } |
807 | } | 716 | } |
808 | #else /* CONFIG_X86_IO_APIC */ | ||
809 | static | ||
810 | inline void __init check_irq_src(struct mpc_intsrc *m, int *nr_m_spare) {} | ||
811 | #endif /* CONFIG_X86_IO_APIC */ | ||
812 | 717 | ||
813 | static int | 718 | static int __init |
814 | check_slot(unsigned long mpc_new_phys, unsigned long mpc_new_length, int count) | 719 | check_slot(unsigned long mpc_new_phys, unsigned long mpc_new_length, int count) |
815 | { | 720 | { |
816 | int ret = 0; | ||
817 | |||
818 | if (!mpc_new_phys || count <= mpc_new_length) { | 721 | if (!mpc_new_phys || count <= mpc_new_length) { |
819 | WARN(1, "update_mptable: No spare slots (length: %x)\n", count); | 722 | WARN(1, "update_mptable: No spare slots (length: %x)\n", count); |
820 | return -1; | 723 | return -1; |
821 | } | 724 | } |
822 | 725 | ||
823 | return ret; | 726 | return 0; |
824 | } | 727 | } |
728 | #else /* CONFIG_X86_IO_APIC */ | ||
729 | static | ||
730 | inline void __init check_irq_src(struct mpc_intsrc *m, int *nr_m_spare) {} | ||
731 | #endif /* CONFIG_X86_IO_APIC */ | ||
825 | 732 | ||
826 | static int __init replace_intsrc_all(struct mpc_table *mpc, | 733 | static int __init replace_intsrc_all(struct mpc_table *mpc, |
827 | unsigned long mpc_new_phys, | 734 | unsigned long mpc_new_phys, |
@@ -874,14 +781,14 @@ static int __init replace_intsrc_all(struct mpc_table *mpc, | |||
874 | if (nr_m_spare > 0) { | 781 | if (nr_m_spare > 0) { |
875 | apic_printk(APIC_VERBOSE, "*NEW* found\n"); | 782 | apic_printk(APIC_VERBOSE, "*NEW* found\n"); |
876 | nr_m_spare--; | 783 | nr_m_spare--; |
877 | assign_to_mpc_intsrc(&mp_irqs[i], m_spare[nr_m_spare]); | 784 | memcpy(m_spare[nr_m_spare], &mp_irqs[i], sizeof(mp_irqs[i])); |
878 | m_spare[nr_m_spare] = NULL; | 785 | m_spare[nr_m_spare] = NULL; |
879 | } else { | 786 | } else { |
880 | struct mpc_intsrc *m = (struct mpc_intsrc *)mpt; | 787 | struct mpc_intsrc *m = (struct mpc_intsrc *)mpt; |
881 | count += sizeof(struct mpc_intsrc); | 788 | count += sizeof(struct mpc_intsrc); |
882 | if (check_slot(mpc_new_phys, mpc_new_length, count) < 0) | 789 | if (check_slot(mpc_new_phys, mpc_new_length, count) < 0) |
883 | goto out; | 790 | goto out; |
884 | assign_to_mpc_intsrc(&mp_irqs[i], m); | 791 | memcpy(m, &mp_irqs[i], sizeof(*m)); |
885 | mpc->length = count; | 792 | mpc->length = count; |
886 | mpt += sizeof(struct mpc_intsrc); | 793 | mpt += sizeof(struct mpc_intsrc); |
887 | } | 794 | } |
@@ -974,7 +881,7 @@ static int __init update_mp_table(void) | |||
974 | 881 | ||
975 | if (!mpc_new_phys) { | 882 | if (!mpc_new_phys) { |
976 | unsigned char old, new; | 883 | unsigned char old, new; |
977 | /* check if we can change the postion */ | 884 | /* check if we can change the position */ |
978 | mpc->checksum = 0; | 885 | mpc->checksum = 0; |
979 | old = mpf_checksum((unsigned char *)mpc, mpc->length); | 886 | old = mpf_checksum((unsigned char *)mpc, mpc->length); |
980 | mpc->checksum = 0xff; | 887 | mpc->checksum = 0xff; |
@@ -983,7 +890,7 @@ static int __init update_mp_table(void) | |||
983 | printk(KERN_INFO "mpc is readonly, please try alloc_mptable instead\n"); | 890 | printk(KERN_INFO "mpc is readonly, please try alloc_mptable instead\n"); |
984 | return 0; | 891 | return 0; |
985 | } | 892 | } |
986 | printk(KERN_INFO "use in-positon replacing\n"); | 893 | printk(KERN_INFO "use in-position replacing\n"); |
987 | } else { | 894 | } else { |
988 | mpf->physptr = mpc_new_phys; | 895 | mpf->physptr = mpc_new_phys; |
989 | mpc_new = phys_to_virt(mpc_new_phys); | 896 | mpc_new = phys_to_virt(mpc_new_phys); |