diff options
| -rw-r--r-- | arch/x86/kernel/mpparse.c | 261 |
1 files changed, 120 insertions, 141 deletions
diff --git a/arch/x86/kernel/mpparse.c b/arch/x86/kernel/mpparse.c index 47673e02ae58..58ddf6259afb 100644 --- a/arch/x86/kernel/mpparse.c +++ b/arch/x86/kernel/mpparse.c | |||
| @@ -109,9 +109,6 @@ static void __init MP_bus_info(struct mpc_bus *m) | |||
| 109 | } else | 109 | } else |
| 110 | printk(KERN_WARNING "Unknown bustype %s - ignoring\n", str); | 110 | printk(KERN_WARNING "Unknown bustype %s - ignoring\n", str); |
| 111 | } | 111 | } |
| 112 | #endif | ||
| 113 | |||
| 114 | #ifdef CONFIG_X86_IO_APIC | ||
| 115 | 112 | ||
| 116 | static int bad_ioapic(unsigned long address) | 113 | static int bad_ioapic(unsigned long address) |
| 117 | { | 114 | { |
| @@ -224,8 +221,12 @@ static void __init MP_intsrc_info(struct mpc_intsrc *m) | |||
| 224 | if (++mp_irq_entries == MAX_IRQ_SOURCES) | 221 | if (++mp_irq_entries == MAX_IRQ_SOURCES) |
| 225 | panic("Max # of irq sources exceeded!!\n"); | 222 | panic("Max # of irq sources exceeded!!\n"); |
| 226 | } | 223 | } |
| 224 | #else /* CONFIG_X86_IO_APIC */ | ||
| 225 | static inline void __init MP_bus_info(struct mpc_bus *m) {} | ||
| 226 | static inline void __init MP_ioapic_info(struct mpc_ioapic *m) {} | ||
| 227 | static inline void __init MP_intsrc_info(struct mpc_intsrc *m) {} | ||
| 228 | #endif /* CONFIG_X86_IO_APIC */ | ||
| 227 | 229 | ||
| 228 | #endif | ||
| 229 | 230 | ||
| 230 | static void __init MP_lintsrc_info(struct mpc_lintsrc *m) | 231 | static void __init MP_lintsrc_info(struct mpc_lintsrc *m) |
| 231 | { | 232 | { |
| @@ -275,6 +276,12 @@ static int __init smp_check_mpc(struct mpc_table *mpc, char *oem, char *str) | |||
| 275 | return 1; | 276 | return 1; |
| 276 | } | 277 | } |
| 277 | 278 | ||
| 279 | static void skip_entry(unsigned char **ptr, int *count, int size) | ||
| 280 | { | ||
| 281 | *ptr += size; | ||
| 282 | *count += size; | ||
| 283 | } | ||
| 284 | |||
| 278 | static int __init smp_read_mpc(struct mpc_table *mpc, unsigned early) | 285 | static int __init smp_read_mpc(struct mpc_table *mpc, unsigned early) |
| 279 | { | 286 | { |
| 280 | char str[16]; | 287 | char str[16]; |
| @@ -310,55 +317,27 @@ static int __init smp_read_mpc(struct mpc_table *mpc, unsigned early) | |||
| 310 | while (count < mpc->length) { | 317 | while (count < mpc->length) { |
| 311 | switch (*mpt) { | 318 | switch (*mpt) { |
| 312 | case MP_PROCESSOR: | 319 | case MP_PROCESSOR: |
| 313 | { | 320 | /* ACPI may have already provided this data */ |
| 314 | struct mpc_cpu *m = (struct mpc_cpu *)mpt; | 321 | if (!acpi_lapic) |
| 315 | /* ACPI may have already provided this data */ | 322 | MP_processor_info((struct mpc_cpu *)&mpt); |
| 316 | if (!acpi_lapic) | 323 | skip_entry(&mpt, &count, sizeof(struct mpc_cpu)); |
| 317 | MP_processor_info(m); | 324 | break; |
| 318 | mpt += sizeof(*m); | ||
| 319 | count += sizeof(*m); | ||
| 320 | break; | ||
| 321 | } | ||
| 322 | case MP_BUS: | 325 | case MP_BUS: |
| 323 | { | 326 | MP_bus_info((struct mpc_bus *)&mpt); |
| 324 | struct mpc_bus *m = (struct mpc_bus *)mpt; | 327 | skip_entry(&mpt, &count, sizeof(struct mpc_bus)); |
| 325 | #ifdef CONFIG_X86_IO_APIC | 328 | break; |
| 326 | MP_bus_info(m); | ||
| 327 | #endif | ||
| 328 | mpt += sizeof(*m); | ||
| 329 | count += sizeof(*m); | ||
| 330 | break; | ||
| 331 | } | ||
| 332 | case MP_IOAPIC: | 329 | case MP_IOAPIC: |
| 333 | { | 330 | MP_ioapic_info((struct mpc_ioapic *)&mpt); |
| 334 | #ifdef CONFIG_X86_IO_APIC | 331 | skip_entry(&mpt, &count, sizeof(struct mpc_ioapic)); |
| 335 | struct mpc_ioapic *m = (struct mpc_ioapic *)mpt; | 332 | break; |
| 336 | MP_ioapic_info(m); | ||
| 337 | #endif | ||
| 338 | mpt += sizeof(struct mpc_ioapic); | ||
| 339 | count += sizeof(struct mpc_ioapic); | ||
| 340 | break; | ||
| 341 | } | ||
| 342 | case MP_INTSRC: | 333 | case MP_INTSRC: |
| 343 | { | 334 | MP_intsrc_info((struct mpc_intsrc *)&mpt); |
| 344 | #ifdef CONFIG_X86_IO_APIC | 335 | skip_entry(&mpt, &count, sizeof(struct mpc_intsrc)); |
| 345 | struct mpc_intsrc *m = (struct mpc_intsrc *)mpt; | 336 | break; |
| 346 | |||
| 347 | MP_intsrc_info(m); | ||
| 348 | #endif | ||
| 349 | mpt += sizeof(struct mpc_intsrc); | ||
| 350 | count += sizeof(struct mpc_intsrc); | ||
| 351 | break; | ||
| 352 | } | ||
| 353 | case MP_LINTSRC: | 337 | case MP_LINTSRC: |
| 354 | { | 338 | MP_lintsrc_info((struct mpc_lintsrc *)&mpt); |
| 355 | struct mpc_lintsrc *m = | 339 | skip_entry(&mpt, &count, sizeof(struct mpc_lintsrc)); |
| 356 | (struct mpc_lintsrc *)mpt; | 340 | break; |
| 357 | MP_lintsrc_info(m); | ||
| 358 | mpt += sizeof(*m); | ||
| 359 | count += sizeof(*m); | ||
| 360 | break; | ||
| 361 | } | ||
| 362 | default: | 341 | default: |
| 363 | /* wrong mptable */ | 342 | /* wrong mptable */ |
| 364 | printk(KERN_ERR "Your mptable is wrong, contact your HW vendor!\n"); | 343 | printk(KERN_ERR "Your mptable is wrong, contact your HW vendor!\n"); |
| @@ -689,6 +668,31 @@ void __init get_smp_config(void) | |||
| 689 | __get_smp_config(0); | 668 | __get_smp_config(0); |
| 690 | } | 669 | } |
| 691 | 670 | ||
| 671 | static void smp_reserve_bootmem(struct mpf_intel *mpf) | ||
| 672 | { | ||
| 673 | unsigned long size = get_mpc_size(mpf->physptr); | ||
| 674 | #ifdef CONFIG_X86_32 | ||
| 675 | /* | ||
| 676 | * We cannot access to MPC table to compute table size yet, | ||
| 677 | * as only few megabytes from the bottom is mapped now. | ||
| 678 | * PC-9800's MPC table places on the very last of physical | ||
| 679 | * memory; so that simply reserving PAGE_SIZE from mpf->physptr | ||
| 680 | * yields BUG() in reserve_bootmem. | ||
| 681 | * also need to make sure physptr is below than max_low_pfn | ||
| 682 | * we don't need reserve the area above max_low_pfn | ||
| 683 | */ | ||
| 684 | unsigned long end = max_low_pfn * PAGE_SIZE; | ||
| 685 | |||
| 686 | if (mpf->physptr < end) { | ||
| 687 | if (mpf->physptr + size > end) | ||
| 688 | size = end - mpf->physptr; | ||
| 689 | reserve_bootmem_generic(mpf->physptr, size, BOOTMEM_DEFAULT); | ||
| 690 | } | ||
| 691 | #else | ||
| 692 | reserve_bootmem_generic(mpf->physptr, size, BOOTMEM_DEFAULT); | ||
| 693 | #endif | ||
| 694 | } | ||
| 695 | |||
| 692 | static int __init smp_scan_config(unsigned long base, unsigned long length, | 696 | static int __init smp_scan_config(unsigned long base, unsigned long length, |
| 693 | unsigned reserve) | 697 | unsigned reserve) |
| 694 | { | 698 | { |
| @@ -717,35 +721,9 @@ static int __init smp_scan_config(unsigned long base, unsigned long length, | |||
| 717 | if (!reserve) | 721 | if (!reserve) |
| 718 | return 1; | 722 | return 1; |
| 719 | reserve_bootmem_generic(virt_to_phys(mpf), sizeof(*mpf), | 723 | reserve_bootmem_generic(virt_to_phys(mpf), sizeof(*mpf), |
| 720 | BOOTMEM_DEFAULT); | ||
| 721 | if (mpf->physptr) { | ||
| 722 | unsigned long size = get_mpc_size(mpf->physptr); | ||
| 723 | #ifdef CONFIG_X86_32 | ||
| 724 | /* | ||
| 725 | * We cannot access to MPC table to compute | ||
| 726 | * table size yet, as only few megabytes from | ||
| 727 | * the bottom is mapped now. | ||
| 728 | * PC-9800's MPC table places on the very last | ||
| 729 | * of physical memory; so that simply reserving | ||
| 730 | * PAGE_SIZE from mpf->physptr yields BUG() | ||
| 731 | * in reserve_bootmem. | ||
| 732 | * also need to make sure physptr is below than | ||
| 733 | * max_low_pfn | ||
| 734 | * we don't need reserve the area above max_low_pfn | ||
| 735 | */ | ||
| 736 | unsigned long end = max_low_pfn * PAGE_SIZE; | ||
| 737 | |||
| 738 | if (mpf->physptr < end) { | ||
| 739 | if (mpf->physptr + size > end) | ||
| 740 | size = end - mpf->physptr; | ||
| 741 | reserve_bootmem_generic(mpf->physptr, size, | ||
| 742 | BOOTMEM_DEFAULT); | ||
| 743 | } | ||
| 744 | #else | ||
| 745 | reserve_bootmem_generic(mpf->physptr, size, | ||
| 746 | BOOTMEM_DEFAULT); | 724 | BOOTMEM_DEFAULT); |
| 747 | #endif | 725 | if (mpf->physptr) |
| 748 | } | 726 | smp_reserve_bootmem(mpf); |
| 749 | 727 | ||
| 750 | return 1; | 728 | return 1; |
| 751 | } | 729 | } |
| @@ -848,7 +826,57 @@ static int __init get_MP_intsrc_index(struct mpc_intsrc *m) | |||
| 848 | #define SPARE_SLOT_NUM 20 | 826 | #define SPARE_SLOT_NUM 20 |
| 849 | 827 | ||
| 850 | static struct mpc_intsrc __initdata *m_spare[SPARE_SLOT_NUM]; | 828 | static struct mpc_intsrc __initdata *m_spare[SPARE_SLOT_NUM]; |
| 851 | #endif | 829 | |
| 830 | static void check_irq_src(struct mpc_intsrc *m, int *nr_m_spare) | ||
| 831 | { | ||
| 832 | int i; | ||
| 833 | |||
| 834 | apic_printk(APIC_VERBOSE, "OLD "); | ||
| 835 | print_MP_intsrc_info(m); | ||
| 836 | |||
| 837 | i = get_MP_intsrc_index(m); | ||
| 838 | if (i > 0) { | ||
| 839 | assign_to_mpc_intsrc(&mp_irqs[i], m); | ||
| 840 | apic_printk(APIC_VERBOSE, "NEW "); | ||
| 841 | print_mp_irq_info(&mp_irqs[i]); | ||
| 842 | return; | ||
| 843 | } | ||
| 844 | if (!i) { | ||
| 845 | /* legacy, do nothing */ | ||
| 846 | return; | ||
| 847 | } | ||
| 848 | if (*nr_m_spare < SPARE_SLOT_NUM) { | ||
| 849 | /* | ||
| 850 | * not found (-1), or duplicated (-2) are invalid entries, | ||
| 851 | * we need to use the slot later | ||
| 852 | */ | ||
| 853 | m_spare[*nr_m_spare] = m; | ||
| 854 | *nr_m_spare += 1; | ||
| 855 | } | ||
| 856 | } | ||
| 857 | #else /* CONFIG_X86_IO_APIC */ | ||
| 858 | static inline void check_irq_src(struct mpc_intsrc *m, int *nr_m_spare) {} | ||
| 859 | #endif /* CONFIG_X86_IO_APIC */ | ||
| 860 | |||
| 861 | static int check_slot(unsigned long mpc_new_phys, unsigned long mpc_new_length, | ||
| 862 | int count) | ||
| 863 | { | ||
| 864 | if (!mpc_new_phys) { | ||
| 865 | pr_info("No spare slots, try to append...take your risk, " | ||
| 866 | "new mpc_length %x\n", count); | ||
| 867 | } else { | ||
| 868 | if (count <= mpc_new_length) | ||
| 869 | pr_info("No spare slots, try to append..., " | ||
| 870 | "new mpc_length %x\n", count); | ||
| 871 | else { | ||
| 872 | pr_err("mpc_new_length %lx is too small\n", | ||
| 873 | mpc_new_length); | ||
| 874 | return -1; | ||
| 875 | } | ||
| 876 | } | ||
| 877 | |||
| 878 | return 0; | ||
| 879 | } | ||
| 852 | 880 | ||
| 853 | static int __init replace_intsrc_all(struct mpc_table *mpc, | 881 | static int __init replace_intsrc_all(struct mpc_table *mpc, |
| 854 | unsigned long mpc_new_phys, | 882 | unsigned long mpc_new_phys, |
| @@ -856,71 +884,30 @@ static int __init replace_intsrc_all(struct mpc_table *mpc, | |||
| 856 | { | 884 | { |
| 857 | #ifdef CONFIG_X86_IO_APIC | 885 | #ifdef CONFIG_X86_IO_APIC |
| 858 | int i; | 886 | int i; |
| 859 | int nr_m_spare = 0; | ||
| 860 | #endif | 887 | #endif |
| 861 | |||
| 862 | int count = sizeof(*mpc); | 888 | int count = sizeof(*mpc); |
| 889 | int nr_m_spare = 0; | ||
| 863 | unsigned char *mpt = ((unsigned char *)mpc) + count; | 890 | unsigned char *mpt = ((unsigned char *)mpc) + count; |
| 864 | 891 | ||
| 865 | printk(KERN_INFO "mpc_length %x\n", mpc->length); | 892 | printk(KERN_INFO "mpc_length %x\n", mpc->length); |
| 866 | while (count < mpc->length) { | 893 | while (count < mpc->length) { |
| 867 | switch (*mpt) { | 894 | switch (*mpt) { |
| 868 | case MP_PROCESSOR: | 895 | case MP_PROCESSOR: |
| 869 | { | 896 | skip_entry(&mpt, &count, sizeof(struct mpc_cpu)); |
| 870 | struct mpc_cpu *m = (struct mpc_cpu *)mpt; | 897 | break; |
| 871 | mpt += sizeof(*m); | ||
| 872 | count += sizeof(*m); | ||
| 873 | break; | ||
| 874 | } | ||
| 875 | case MP_BUS: | 898 | case MP_BUS: |
| 876 | { | 899 | skip_entry(&mpt, &count, sizeof(struct mpc_bus)); |
| 877 | struct mpc_bus *m = (struct mpc_bus *)mpt; | 900 | break; |
| 878 | mpt += sizeof(*m); | ||
| 879 | count += sizeof(*m); | ||
| 880 | break; | ||
| 881 | } | ||
| 882 | case MP_IOAPIC: | 901 | case MP_IOAPIC: |
| 883 | { | 902 | skip_entry(&mpt, &count, sizeof(struct mpc_ioapic)); |
| 884 | mpt += sizeof(struct mpc_ioapic); | 903 | break; |
| 885 | count += sizeof(struct mpc_ioapic); | ||
| 886 | break; | ||
| 887 | } | ||
| 888 | case MP_INTSRC: | 904 | case MP_INTSRC: |
| 889 | { | 905 | check_irq_src((struct mpc_intsrc *)&mpt, &nr_m_spare); |
| 890 | #ifdef CONFIG_X86_IO_APIC | 906 | skip_entry(&mpt, &count, sizeof(struct mpc_intsrc)); |
| 891 | struct mpc_intsrc *m = (struct mpc_intsrc *)mpt; | 907 | break; |
| 892 | |||
| 893 | apic_printk(APIC_VERBOSE, "OLD "); | ||
| 894 | print_MP_intsrc_info(m); | ||
| 895 | i = get_MP_intsrc_index(m); | ||
| 896 | if (i > 0) { | ||
| 897 | assign_to_mpc_intsrc(&mp_irqs[i], m); | ||
| 898 | apic_printk(APIC_VERBOSE, "NEW "); | ||
| 899 | print_mp_irq_info(&mp_irqs[i]); | ||
| 900 | } else if (!i) { | ||
| 901 | /* legacy, do nothing */ | ||
| 902 | } else if (nr_m_spare < SPARE_SLOT_NUM) { | ||
| 903 | /* | ||
| 904 | * not found (-1), or duplicated (-2) | ||
| 905 | * are invalid entries, | ||
| 906 | * we need to use the slot later | ||
| 907 | */ | ||
| 908 | m_spare[nr_m_spare] = m; | ||
| 909 | nr_m_spare++; | ||
| 910 | } | ||
| 911 | #endif | ||
| 912 | mpt += sizeof(struct mpc_intsrc); | ||
| 913 | count += sizeof(struct mpc_intsrc); | ||
| 914 | break; | ||
| 915 | } | ||
| 916 | case MP_LINTSRC: | 908 | case MP_LINTSRC: |
| 917 | { | 909 | skip_entry(&mpt, &count, sizeof(struct mpc_lintsrc)); |
| 918 | struct mpc_lintsrc *m = | 910 | break; |
| 919 | (struct mpc_lintsrc *)mpt; | ||
| 920 | mpt += sizeof(*m); | ||
| 921 | count += sizeof(*m); | ||
| 922 | break; | ||
| 923 | } | ||
| 924 | default: | 911 | default: |
| 925 | /* wrong mptable */ | 912 | /* wrong mptable */ |
| 926 | printk(KERN_ERR "Your mptable is wrong, contact your HW vendor!\n"); | 913 | printk(KERN_ERR "Your mptable is wrong, contact your HW vendor!\n"); |
| @@ -950,16 +937,8 @@ static int __init replace_intsrc_all(struct mpc_table *mpc, | |||
| 950 | } else { | 937 | } else { |
| 951 | struct mpc_intsrc *m = (struct mpc_intsrc *)mpt; | 938 | struct mpc_intsrc *m = (struct mpc_intsrc *)mpt; |
| 952 | count += sizeof(struct mpc_intsrc); | 939 | count += sizeof(struct mpc_intsrc); |
| 953 | if (!mpc_new_phys) { | 940 | if (!check_slot(mpc_new_phys, mpc_new_length, count)) |
| 954 | printk(KERN_INFO "No spare slots, try to append...take your risk, new mpc_length %x\n", count); | 941 | goto out; |
| 955 | } else { | ||
| 956 | if (count <= mpc_new_length) | ||
| 957 | printk(KERN_INFO "No spare slots, try to append..., new mpc_length %x\n", count); | ||
| 958 | else { | ||
| 959 | printk(KERN_ERR "mpc_new_length %lx is too small\n", mpc_new_length); | ||
| 960 | goto out; | ||
| 961 | } | ||
| 962 | } | ||
| 963 | assign_to_mpc_intsrc(&mp_irqs[i], m); | 942 | assign_to_mpc_intsrc(&mp_irqs[i], m); |
| 964 | mpc->length = count; | 943 | mpc->length = count; |
| 965 | mpt += sizeof(struct mpc_intsrc); | 944 | mpt += sizeof(struct mpc_intsrc); |
