diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2009-09-14 10:51:20 -0400 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2009-09-14 10:51:20 -0400 |
| commit | ffaf854b011bde97d63955a71232a20fe4382a38 (patch) | |
| tree | 7cd833505685b20bd11b065de1fd9b718b8b8b3f | |
| parent | 86d710146fb9975f04c505ec78caa43d227c1018 (diff) | |
| parent | eebc57f73d42095b778e899f6aa90ad050c72655 (diff) | |
Merge branch 'x86-apic-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip
* 'x86-apic-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip: (24 commits)
ACPI, x86: expose some IO-APIC routines when CONFIG_ACPI=n
x86, apic: Slim down stack usage in early_init_lapic_mapping()
x86, ioapic: Get rid of needless check and simplify ioapic_setup_resources()
x86, ioapic: Define IO_APIC_DEFAULT_PHYS_BASE constant
x86: Fix x86_model test in es7000_apic_is_cluster()
x86, apic: Move dmar_table_init() out of enable_IR()
x86, ioapic: Panic on irq-pin binding only if needed
x86/apic: Enable x2APIC without interrupt remapping under KVM
x86, apic: Drop redundant bit assignment
x86, ioapic: Throw BUG instead of NULL dereference
x86, ioapic: Introduce for_each_irq_pin() helper
x86: Remove superfluous NULL pointer check in destroy_irq()
x86/ioapic.c: unify ioapic_retrigger_irq()
x86/ioapic.c: convert __target_IO_APIC_irq to conventional for() loop
x86/ioapic.c: clean up replace_pin_at_irq_node logic and comments
x86/ioapic.c: convert replace_pin_at_irq_node to conventional for() loop
x86/ioapic.c: simplify add_pin_to_irq_node()
x86/ioapic.c: convert io_apic_level_ack_pending loop to normal for() loop
x86/ioapic.c: move lost comment to what seems like appropriate place
x86/ioapic.c: remove redundant declaration of irq_pin_list
...
| -rw-r--r-- | arch/x86/include/asm/apic.h | 7 | ||||
| -rw-r--r-- | arch/x86/include/asm/apicdef.h | 3 | ||||
| -rw-r--r-- | arch/x86/include/asm/io_apic.h | 13 | ||||
| -rw-r--r-- | arch/x86/kernel/acpi/boot.c | 105 | ||||
| -rw-r--r-- | arch/x86/kernel/apic/apic.c | 110 | ||||
| -rw-r--r-- | arch/x86/kernel/apic/es7000_32.c | 2 | ||||
| -rw-r--r-- | arch/x86/kernel/apic/io_apic.c | 324 | ||||
| -rw-r--r-- | arch/x86/kernel/apic/probe_64.c | 6 | ||||
| -rw-r--r-- | arch/x86/kernel/mpparse.c | 10 |
9 files changed, 269 insertions, 311 deletions
diff --git a/arch/x86/include/asm/apic.h b/arch/x86/include/asm/apic.h index bb7d47925847..586b7adb8e53 100644 --- a/arch/x86/include/asm/apic.h +++ b/arch/x86/include/asm/apic.h | |||
| @@ -183,6 +183,10 @@ static inline int x2apic_enabled(void) | |||
| 183 | } | 183 | } |
| 184 | 184 | ||
| 185 | #define x2apic_supported() (cpu_has_x2apic) | 185 | #define x2apic_supported() (cpu_has_x2apic) |
| 186 | static inline void x2apic_force_phys(void) | ||
| 187 | { | ||
| 188 | x2apic_phys = 1; | ||
| 189 | } | ||
| 186 | #else | 190 | #else |
| 187 | static inline void check_x2apic(void) | 191 | static inline void check_x2apic(void) |
| 188 | { | 192 | { |
| @@ -194,6 +198,9 @@ static inline int x2apic_enabled(void) | |||
| 194 | { | 198 | { |
| 195 | return 0; | 199 | return 0; |
| 196 | } | 200 | } |
| 201 | static inline void x2apic_force_phys(void) | ||
| 202 | { | ||
| 203 | } | ||
| 197 | 204 | ||
| 198 | #define x2apic_preenabled 0 | 205 | #define x2apic_preenabled 0 |
| 199 | #define x2apic_supported() 0 | 206 | #define x2apic_supported() 0 |
diff --git a/arch/x86/include/asm/apicdef.h b/arch/x86/include/asm/apicdef.h index 7ddb36ab933b..7386bfa4f4bc 100644 --- a/arch/x86/include/asm/apicdef.h +++ b/arch/x86/include/asm/apicdef.h | |||
| @@ -8,7 +8,8 @@ | |||
| 8 | * Ingo Molnar <mingo@redhat.com>, 1999, 2000 | 8 | * Ingo Molnar <mingo@redhat.com>, 1999, 2000 |
| 9 | */ | 9 | */ |
| 10 | 10 | ||
| 11 | #define APIC_DEFAULT_PHYS_BASE 0xfee00000 | 11 | #define IO_APIC_DEFAULT_PHYS_BASE 0xfec00000 |
| 12 | #define APIC_DEFAULT_PHYS_BASE 0xfee00000 | ||
| 12 | 13 | ||
| 13 | #define APIC_ID 0x20 | 14 | #define APIC_ID 0x20 |
| 14 | 15 | ||
diff --git a/arch/x86/include/asm/io_apic.h b/arch/x86/include/asm/io_apic.h index 330ee807f89e..85232d32fcb8 100644 --- a/arch/x86/include/asm/io_apic.h +++ b/arch/x86/include/asm/io_apic.h | |||
| @@ -150,11 +150,10 @@ extern int timer_through_8259; | |||
| 150 | #define io_apic_assign_pci_irqs \ | 150 | #define io_apic_assign_pci_irqs \ |
| 151 | (mp_irq_entries && !skip_ioapic_setup && io_apic_irqs) | 151 | (mp_irq_entries && !skip_ioapic_setup && io_apic_irqs) |
| 152 | 152 | ||
| 153 | #ifdef CONFIG_ACPI | 153 | extern u8 io_apic_unique_id(u8 id); |
| 154 | extern int io_apic_get_unique_id(int ioapic, int apic_id); | 154 | extern int io_apic_get_unique_id(int ioapic, int apic_id); |
| 155 | extern int io_apic_get_version(int ioapic); | 155 | extern int io_apic_get_version(int ioapic); |
| 156 | extern int io_apic_get_redir_entries(int ioapic); | 156 | extern int io_apic_get_redir_entries(int ioapic); |
| 157 | #endif /* CONFIG_ACPI */ | ||
| 158 | 157 | ||
| 159 | struct io_apic_irq_attr; | 158 | struct io_apic_irq_attr; |
| 160 | extern int io_apic_set_pci_routing(struct device *dev, int irq, | 159 | extern int io_apic_set_pci_routing(struct device *dev, int irq, |
| @@ -177,6 +176,16 @@ extern int setup_ioapic_entry(int apic, int irq, | |||
| 177 | int polarity, int vector, int pin); | 176 | int polarity, int vector, int pin); |
| 178 | extern void ioapic_write_entry(int apic, int pin, | 177 | extern void ioapic_write_entry(int apic, int pin, |
| 179 | struct IO_APIC_route_entry e); | 178 | struct IO_APIC_route_entry e); |
| 179 | |||
| 180 | struct mp_ioapic_gsi{ | ||
| 181 | int gsi_base; | ||
| 182 | int gsi_end; | ||
| 183 | }; | ||
| 184 | extern struct mp_ioapic_gsi mp_gsi_routing[]; | ||
| 185 | int mp_find_ioapic(int gsi); | ||
| 186 | int mp_find_ioapic_pin(int ioapic, int gsi); | ||
| 187 | void __init mp_register_ioapic(int id, u32 address, u32 gsi_base); | ||
| 188 | |||
| 180 | #else /* !CONFIG_X86_IO_APIC */ | 189 | #else /* !CONFIG_X86_IO_APIC */ |
| 181 | #define io_apic_assign_pci_irqs 0 | 190 | #define io_apic_assign_pci_irqs 0 |
| 182 | static const int timer_through_8259 = 0; | 191 | static const int timer_through_8259 = 0; |
diff --git a/arch/x86/kernel/acpi/boot.c b/arch/x86/kernel/acpi/boot.c index 6b8ca3a0285d..67e929b89875 100644 --- a/arch/x86/kernel/acpi/boot.c +++ b/arch/x86/kernel/acpi/boot.c | |||
| @@ -833,106 +833,6 @@ static int __init acpi_parse_madt_lapic_entries(void) | |||
| 833 | extern int es7000_plat; | 833 | extern int es7000_plat; |
| 834 | #endif | 834 | #endif |
| 835 | 835 | ||
| 836 | static struct { | ||
| 837 | int gsi_base; | ||
| 838 | int gsi_end; | ||
| 839 | } mp_ioapic_routing[MAX_IO_APICS]; | ||
| 840 | |||
| 841 | int mp_find_ioapic(int gsi) | ||
| 842 | { | ||
| 843 | int i = 0; | ||
| 844 | |||
| 845 | /* Find the IOAPIC that manages this GSI. */ | ||
| 846 | for (i = 0; i < nr_ioapics; i++) { | ||
| 847 | if ((gsi >= mp_ioapic_routing[i].gsi_base) | ||
| 848 | && (gsi <= mp_ioapic_routing[i].gsi_end)) | ||
| 849 | return i; | ||
| 850 | } | ||
| 851 | |||
| 852 | printk(KERN_ERR "ERROR: Unable to locate IOAPIC for GSI %d\n", gsi); | ||
| 853 | return -1; | ||
| 854 | } | ||
| 855 | |||
| 856 | int mp_find_ioapic_pin(int ioapic, int gsi) | ||
| 857 | { | ||
| 858 | if (WARN_ON(ioapic == -1)) | ||
| 859 | return -1; | ||
| 860 | if (WARN_ON(gsi > mp_ioapic_routing[ioapic].gsi_end)) | ||
| 861 | return -1; | ||
| 862 | |||
| 863 | return gsi - mp_ioapic_routing[ioapic].gsi_base; | ||
| 864 | } | ||
| 865 | |||
| 866 | static u8 __init uniq_ioapic_id(u8 id) | ||
| 867 | { | ||
| 868 | #ifdef CONFIG_X86_32 | ||
| 869 | if ((boot_cpu_data.x86_vendor == X86_VENDOR_INTEL) && | ||
| 870 | !APIC_XAPIC(apic_version[boot_cpu_physical_apicid])) | ||
| 871 | return io_apic_get_unique_id(nr_ioapics, id); | ||
| 872 | else | ||
| 873 | return id; | ||
| 874 | #else | ||
| 875 | int i; | ||
| 876 | DECLARE_BITMAP(used, 256); | ||
| 877 | bitmap_zero(used, 256); | ||
| 878 | for (i = 0; i < nr_ioapics; i++) { | ||
| 879 | struct mpc_ioapic *ia = &mp_ioapics[i]; | ||
| 880 | __set_bit(ia->apicid, used); | ||
| 881 | } | ||
| 882 | if (!test_bit(id, used)) | ||
| 883 | return id; | ||
| 884 | return find_first_zero_bit(used, 256); | ||
| 885 | #endif | ||
| 886 | } | ||
| 887 | |||
| 888 | static int bad_ioapic(unsigned long address) | ||
| 889 | { | ||
| 890 | if (nr_ioapics >= MAX_IO_APICS) { | ||
| 891 | printk(KERN_ERR "ERROR: Max # of I/O APICs (%d) exceeded " | ||
| 892 | "(found %d)\n", MAX_IO_APICS, nr_ioapics); | ||
| 893 | panic("Recompile kernel with bigger MAX_IO_APICS!\n"); | ||
| 894 | } | ||
| 895 | if (!address) { | ||
| 896 | printk(KERN_ERR "WARNING: Bogus (zero) I/O APIC address" | ||
| 897 | " found in table, skipping!\n"); | ||
| 898 | return 1; | ||
| 899 | } | ||
| 900 | return 0; | ||
| 901 | } | ||
| 902 | |||
| 903 | void __init mp_register_ioapic(int id, u32 address, u32 gsi_base) | ||
| 904 | { | ||
| 905 | int idx = 0; | ||
| 906 | |||
| 907 | if (bad_ioapic(address)) | ||
| 908 | return; | ||
| 909 | |||
| 910 | idx = nr_ioapics; | ||
| 911 | |||
| 912 | mp_ioapics[idx].type = MP_IOAPIC; | ||
| 913 | mp_ioapics[idx].flags = MPC_APIC_USABLE; | ||
| 914 | mp_ioapics[idx].apicaddr = address; | ||
| 915 | |||
| 916 | set_fixmap_nocache(FIX_IO_APIC_BASE_0 + idx, address); | ||
| 917 | mp_ioapics[idx].apicid = uniq_ioapic_id(id); | ||
| 918 | mp_ioapics[idx].apicver = io_apic_get_version(idx); | ||
| 919 | |||
| 920 | /* | ||
| 921 | * Build basic GSI lookup table to facilitate gsi->io_apic lookups | ||
| 922 | * and to prevent reprogramming of IOAPIC pins (PCI GSIs). | ||
| 923 | */ | ||
| 924 | mp_ioapic_routing[idx].gsi_base = gsi_base; | ||
| 925 | mp_ioapic_routing[idx].gsi_end = gsi_base + | ||
| 926 | io_apic_get_redir_entries(idx); | ||
| 927 | |||
| 928 | printk(KERN_INFO "IOAPIC[%d]: apic_id %d, version %d, address 0x%x, " | ||
| 929 | "GSI %d-%d\n", idx, mp_ioapics[idx].apicid, | ||
| 930 | mp_ioapics[idx].apicver, mp_ioapics[idx].apicaddr, | ||
| 931 | mp_ioapic_routing[idx].gsi_base, mp_ioapic_routing[idx].gsi_end); | ||
| 932 | |||
| 933 | nr_ioapics++; | ||
| 934 | } | ||
| 935 | |||
| 936 | int __init acpi_probe_gsi(void) | 836 | int __init acpi_probe_gsi(void) |
| 937 | { | 837 | { |
| 938 | int idx; | 838 | int idx; |
| @@ -947,7 +847,7 @@ int __init acpi_probe_gsi(void) | |||
| 947 | 847 | ||
| 948 | max_gsi = 0; | 848 | max_gsi = 0; |
| 949 | for (idx = 0; idx < nr_ioapics; idx++) { | 849 | for (idx = 0; idx < nr_ioapics; idx++) { |
| 950 | gsi = mp_ioapic_routing[idx].gsi_end; | 850 | gsi = mp_gsi_routing[idx].gsi_end; |
| 951 | 851 | ||
| 952 | if (gsi > max_gsi) | 852 | if (gsi > max_gsi) |
| 953 | max_gsi = gsi; | 853 | max_gsi = gsi; |
| @@ -1179,9 +1079,8 @@ static int __init acpi_parse_madt_ioapic_entries(void) | |||
| 1179 | * If MPS is present, it will handle them, | 1079 | * If MPS is present, it will handle them, |
| 1180 | * otherwise the system will stay in PIC mode | 1080 | * otherwise the system will stay in PIC mode |
| 1181 | */ | 1081 | */ |
| 1182 | if (acpi_disabled || acpi_noirq) { | 1082 | if (acpi_disabled || acpi_noirq) |
| 1183 | return -ENODEV; | 1083 | return -ENODEV; |
| 1184 | } | ||
| 1185 | 1084 | ||
| 1186 | if (!cpu_has_apic) | 1085 | if (!cpu_has_apic) |
| 1187 | return -ENODEV; | 1086 | return -ENODEV; |
diff --git a/arch/x86/kernel/apic/apic.c b/arch/x86/kernel/apic/apic.c index 0a1c2830ec66..159740decc41 100644 --- a/arch/x86/kernel/apic/apic.c +++ b/arch/x86/kernel/apic/apic.c | |||
| @@ -49,6 +49,7 @@ | |||
| 49 | #include <asm/mtrr.h> | 49 | #include <asm/mtrr.h> |
| 50 | #include <asm/smp.h> | 50 | #include <asm/smp.h> |
| 51 | #include <asm/mce.h> | 51 | #include <asm/mce.h> |
| 52 | #include <asm/kvm_para.h> | ||
| 52 | 53 | ||
| 53 | unsigned int num_processors; | 54 | unsigned int num_processors; |
| 54 | 55 | ||
| @@ -1361,52 +1362,80 @@ void enable_x2apic(void) | |||
| 1361 | } | 1362 | } |
| 1362 | #endif /* CONFIG_X86_X2APIC */ | 1363 | #endif /* CONFIG_X86_X2APIC */ |
| 1363 | 1364 | ||
| 1364 | void __init enable_IR_x2apic(void) | 1365 | int __init enable_IR(void) |
| 1365 | { | 1366 | { |
| 1366 | #ifdef CONFIG_INTR_REMAP | 1367 | #ifdef CONFIG_INTR_REMAP |
| 1367 | int ret; | ||
| 1368 | unsigned long flags; | ||
| 1369 | struct IO_APIC_route_entry **ioapic_entries = NULL; | ||
| 1370 | |||
| 1371 | ret = dmar_table_init(); | ||
| 1372 | if (ret) { | ||
| 1373 | pr_debug("dmar_table_init() failed with %d:\n", ret); | ||
| 1374 | goto ir_failed; | ||
| 1375 | } | ||
| 1376 | |||
| 1377 | if (!intr_remapping_supported()) { | 1368 | if (!intr_remapping_supported()) { |
| 1378 | pr_debug("intr-remapping not supported\n"); | 1369 | pr_debug("intr-remapping not supported\n"); |
| 1379 | goto ir_failed; | 1370 | return 0; |
| 1380 | } | 1371 | } |
| 1381 | 1372 | ||
| 1382 | |||
| 1383 | if (!x2apic_preenabled && skip_ioapic_setup) { | 1373 | if (!x2apic_preenabled && skip_ioapic_setup) { |
| 1384 | pr_info("Skipped enabling intr-remap because of skipping " | 1374 | pr_info("Skipped enabling intr-remap because of skipping " |
| 1385 | "io-apic setup\n"); | 1375 | "io-apic setup\n"); |
| 1386 | return; | 1376 | return 0; |
| 1387 | } | 1377 | } |
| 1388 | 1378 | ||
| 1379 | if (enable_intr_remapping(x2apic_supported())) | ||
| 1380 | return 0; | ||
| 1381 | |||
| 1382 | pr_info("Enabled Interrupt-remapping\n"); | ||
| 1383 | |||
| 1384 | return 1; | ||
| 1385 | |||
| 1386 | #endif | ||
| 1387 | return 0; | ||
| 1388 | } | ||
| 1389 | |||
| 1390 | void __init enable_IR_x2apic(void) | ||
| 1391 | { | ||
| 1392 | unsigned long flags; | ||
| 1393 | struct IO_APIC_route_entry **ioapic_entries = NULL; | ||
| 1394 | int ret, x2apic_enabled = 0; | ||
| 1395 | int dmar_table_init_ret = 0; | ||
| 1396 | |||
| 1397 | #ifdef CONFIG_INTR_REMAP | ||
| 1398 | dmar_table_init_ret = dmar_table_init(); | ||
| 1399 | if (dmar_table_init_ret) | ||
| 1400 | pr_debug("dmar_table_init() failed with %d:\n", | ||
| 1401 | dmar_table_init_ret); | ||
| 1402 | #endif | ||
| 1403 | |||
| 1389 | ioapic_entries = alloc_ioapic_entries(); | 1404 | ioapic_entries = alloc_ioapic_entries(); |
| 1390 | if (!ioapic_entries) { | 1405 | if (!ioapic_entries) { |
| 1391 | pr_info("Allocate ioapic_entries failed: %d\n", ret); | 1406 | pr_err("Allocate ioapic_entries failed\n"); |
| 1392 | goto end; | 1407 | goto out; |
| 1393 | } | 1408 | } |
| 1394 | 1409 | ||
| 1395 | ret = save_IO_APIC_setup(ioapic_entries); | 1410 | ret = save_IO_APIC_setup(ioapic_entries); |
| 1396 | if (ret) { | 1411 | if (ret) { |
| 1397 | pr_info("Saving IO-APIC state failed: %d\n", ret); | 1412 | pr_info("Saving IO-APIC state failed: %d\n", ret); |
| 1398 | goto end; | 1413 | goto out; |
| 1399 | } | 1414 | } |
| 1400 | 1415 | ||
| 1401 | local_irq_save(flags); | 1416 | local_irq_save(flags); |
| 1402 | mask_IO_APIC_setup(ioapic_entries); | ||
| 1403 | mask_8259A(); | 1417 | mask_8259A(); |
| 1418 | mask_IO_APIC_setup(ioapic_entries); | ||
| 1404 | 1419 | ||
| 1405 | ret = enable_intr_remapping(x2apic_supported()); | 1420 | if (dmar_table_init_ret) |
| 1406 | if (ret) | 1421 | ret = 0; |
| 1407 | goto end_restore; | 1422 | else |
| 1423 | ret = enable_IR(); | ||
| 1408 | 1424 | ||
| 1409 | pr_info("Enabled Interrupt-remapping\n"); | 1425 | if (!ret) { |
| 1426 | /* IR is required if there is APIC ID > 255 even when running | ||
| 1427 | * under KVM | ||
| 1428 | */ | ||
| 1429 | if (max_physical_apicid > 255 || !kvm_para_available()) | ||
| 1430 | goto nox2apic; | ||
| 1431 | /* | ||
| 1432 | * without IR all CPUs can be addressed by IOAPIC/MSI | ||
| 1433 | * only in physical mode | ||
| 1434 | */ | ||
| 1435 | x2apic_force_phys(); | ||
| 1436 | } | ||
| 1437 | |||
| 1438 | x2apic_enabled = 1; | ||
| 1410 | 1439 | ||
| 1411 | if (x2apic_supported() && !x2apic_mode) { | 1440 | if (x2apic_supported() && !x2apic_mode) { |
| 1412 | x2apic_mode = 1; | 1441 | x2apic_mode = 1; |
| @@ -1414,41 +1443,25 @@ void __init enable_IR_x2apic(void) | |||
| 1414 | pr_info("Enabled x2apic\n"); | 1443 | pr_info("Enabled x2apic\n"); |
| 1415 | } | 1444 | } |
| 1416 | 1445 | ||
| 1417 | end_restore: | 1446 | nox2apic: |
| 1418 | if (ret) | 1447 | if (!ret) /* IR enabling failed */ |
| 1419 | /* | ||
| 1420 | * IR enabling failed | ||
| 1421 | */ | ||
| 1422 | restore_IO_APIC_setup(ioapic_entries); | 1448 | restore_IO_APIC_setup(ioapic_entries); |
| 1423 | |||
| 1424 | unmask_8259A(); | 1449 | unmask_8259A(); |
| 1425 | local_irq_restore(flags); | 1450 | local_irq_restore(flags); |
| 1426 | 1451 | ||
| 1427 | end: | 1452 | out: |
| 1428 | if (ioapic_entries) | 1453 | if (ioapic_entries) |
| 1429 | free_ioapic_entries(ioapic_entries); | 1454 | free_ioapic_entries(ioapic_entries); |
| 1430 | 1455 | ||
| 1431 | if (!ret) | 1456 | if (x2apic_enabled) |
| 1432 | return; | 1457 | return; |
| 1433 | 1458 | ||
| 1434 | ir_failed: | ||
| 1435 | if (x2apic_preenabled) | 1459 | if (x2apic_preenabled) |
| 1436 | panic("x2apic enabled by bios. But IR enabling failed"); | 1460 | panic("x2apic: enabled by BIOS but kernel init failed."); |
| 1437 | else if (cpu_has_x2apic) | 1461 | else if (cpu_has_x2apic) |
| 1438 | pr_info("Not enabling x2apic,Intr-remapping\n"); | 1462 | pr_info("Not enabling x2apic, Intr-remapping init failed.\n"); |
| 1439 | #else | ||
| 1440 | if (!cpu_has_x2apic) | ||
| 1441 | return; | ||
| 1442 | |||
| 1443 | if (x2apic_preenabled) | ||
| 1444 | panic("x2apic enabled prior OS handover," | ||
| 1445 | " enable CONFIG_X86_X2APIC, CONFIG_INTR_REMAP"); | ||
| 1446 | #endif | ||
| 1447 | |||
| 1448 | return; | ||
| 1449 | } | 1463 | } |
| 1450 | 1464 | ||
| 1451 | |||
| 1452 | #ifdef CONFIG_X86_64 | 1465 | #ifdef CONFIG_X86_64 |
| 1453 | /* | 1466 | /* |
| 1454 | * Detect and enable local APICs on non-SMP boards. | 1467 | * Detect and enable local APICs on non-SMP boards. |
| @@ -1549,8 +1562,6 @@ no_apic: | |||
| 1549 | #ifdef CONFIG_X86_64 | 1562 | #ifdef CONFIG_X86_64 |
| 1550 | void __init early_init_lapic_mapping(void) | 1563 | void __init early_init_lapic_mapping(void) |
| 1551 | { | 1564 | { |
| 1552 | unsigned long phys_addr; | ||
| 1553 | |||
| 1554 | /* | 1565 | /* |
| 1555 | * If no local APIC can be found then go out | 1566 | * If no local APIC can be found then go out |
| 1556 | * : it means there is no mpatable and MADT | 1567 | * : it means there is no mpatable and MADT |
| @@ -1558,11 +1569,9 @@ void __init early_init_lapic_mapping(void) | |||
| 1558 | if (!smp_found_config) | 1569 | if (!smp_found_config) |
| 1559 | return; | 1570 | return; |
| 1560 | 1571 | ||
| 1561 | phys_addr = mp_lapic_addr; | 1572 | set_fixmap_nocache(FIX_APIC_BASE, mp_lapic_addr); |
| 1562 | |||
| 1563 | set_fixmap_nocache(FIX_APIC_BASE, phys_addr); | ||
| 1564 | apic_printk(APIC_VERBOSE, "mapped APIC to %16lx (%16lx)\n", | 1573 | apic_printk(APIC_VERBOSE, "mapped APIC to %16lx (%16lx)\n", |
| 1565 | APIC_BASE, phys_addr); | 1574 | APIC_BASE, mp_lapic_addr); |
| 1566 | 1575 | ||
| 1567 | /* | 1576 | /* |
| 1568 | * Fetch the APIC ID of the BSP in case we have a | 1577 | * Fetch the APIC ID of the BSP in case we have a |
| @@ -1651,7 +1660,6 @@ int __init APIC_init_uniprocessor(void) | |||
| 1651 | APIC_INTEGRATED(apic_version[boot_cpu_physical_apicid])) { | 1660 | APIC_INTEGRATED(apic_version[boot_cpu_physical_apicid])) { |
| 1652 | pr_err("BIOS bug, local APIC 0x%x not detected!...\n", | 1661 | pr_err("BIOS bug, local APIC 0x%x not detected!...\n", |
| 1653 | boot_cpu_physical_apicid); | 1662 | boot_cpu_physical_apicid); |
| 1654 | clear_cpu_cap(&boot_cpu_data, X86_FEATURE_APIC); | ||
| 1655 | return -1; | 1663 | return -1; |
| 1656 | } | 1664 | } |
| 1657 | #endif | 1665 | #endif |
diff --git a/arch/x86/kernel/apic/es7000_32.c b/arch/x86/kernel/apic/es7000_32.c index 8952a5890281..89174f847b49 100644 --- a/arch/x86/kernel/apic/es7000_32.c +++ b/arch/x86/kernel/apic/es7000_32.c | |||
| @@ -167,7 +167,7 @@ static int es7000_apic_is_cluster(void) | |||
| 167 | { | 167 | { |
| 168 | /* MPENTIUMIII */ | 168 | /* MPENTIUMIII */ |
| 169 | if (boot_cpu_data.x86 == 6 && | 169 | if (boot_cpu_data.x86 == 6 && |
| 170 | (boot_cpu_data.x86_model >= 7 || boot_cpu_data.x86_model <= 11)) | 170 | (boot_cpu_data.x86_model >= 7 && boot_cpu_data.x86_model <= 11)) |
| 171 | return 1; | 171 | return 1; |
| 172 | 172 | ||
| 173 | return 0; | 173 | return 0; |
diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c index d2ed6c5ddc80..3c8f9e75d038 100644 --- a/arch/x86/kernel/apic/io_apic.c +++ b/arch/x86/kernel/apic/io_apic.c | |||
| @@ -66,6 +66,8 @@ | |||
| 66 | #include <asm/apic.h> | 66 | #include <asm/apic.h> |
| 67 | 67 | ||
| 68 | #define __apicdebuginit(type) static type __init | 68 | #define __apicdebuginit(type) static type __init |
| 69 | #define for_each_irq_pin(entry, head) \ | ||
| 70 | for (entry = head; entry; entry = entry->next) | ||
| 69 | 71 | ||
| 70 | /* | 72 | /* |
| 71 | * Is the SiS APIC rmw bug present ? | 73 | * Is the SiS APIC rmw bug present ? |
| @@ -85,6 +87,9 @@ int nr_ioapic_registers[MAX_IO_APICS]; | |||
| 85 | struct mpc_ioapic mp_ioapics[MAX_IO_APICS]; | 87 | struct mpc_ioapic mp_ioapics[MAX_IO_APICS]; |
| 86 | int nr_ioapics; | 88 | int nr_ioapics; |
| 87 | 89 | ||
| 90 | /* IO APIC gsi routing info */ | ||
| 91 | struct mp_ioapic_gsi mp_gsi_routing[MAX_IO_APICS]; | ||
| 92 | |||
| 88 | /* MP IRQ source entries */ | 93 | /* MP IRQ source entries */ |
| 89 | struct mpc_intsrc mp_irqs[MAX_IRQ_SOURCES]; | 94 | struct mpc_intsrc mp_irqs[MAX_IRQ_SOURCES]; |
| 90 | 95 | ||
| @@ -116,15 +121,6 @@ static int __init parse_noapic(char *str) | |||
| 116 | } | 121 | } |
| 117 | early_param("noapic", parse_noapic); | 122 | early_param("noapic", parse_noapic); |
| 118 | 123 | ||
| 119 | struct irq_pin_list; | ||
| 120 | |||
| 121 | /* | ||
| 122 | * This is performance-critical, we want to do it O(1) | ||
| 123 | * | ||
| 124 | * the indexing order of this array favors 1:1 mappings | ||
| 125 | * between pins and IRQs. | ||
| 126 | */ | ||
| 127 | |||
| 128 | struct irq_pin_list { | 124 | struct irq_pin_list { |
| 129 | int apic, pin; | 125 | int apic, pin; |
| 130 | struct irq_pin_list *next; | 126 | struct irq_pin_list *next; |
| @@ -139,6 +135,11 @@ static struct irq_pin_list *get_one_free_irq_2_pin(int node) | |||
| 139 | return pin; | 135 | return pin; |
| 140 | } | 136 | } |
| 141 | 137 | ||
| 138 | /* | ||
| 139 | * This is performance-critical, we want to do it O(1) | ||
| 140 | * | ||
| 141 | * Most irqs are mapped 1:1 with pins. | ||
| 142 | */ | ||
| 142 | struct irq_cfg { | 143 | struct irq_cfg { |
| 143 | struct irq_pin_list *irq_2_pin; | 144 | struct irq_pin_list *irq_2_pin; |
| 144 | cpumask_var_t domain; | 145 | cpumask_var_t domain; |
| @@ -414,13 +415,10 @@ static bool io_apic_level_ack_pending(struct irq_cfg *cfg) | |||
| 414 | unsigned long flags; | 415 | unsigned long flags; |
| 415 | 416 | ||
| 416 | spin_lock_irqsave(&ioapic_lock, flags); | 417 | spin_lock_irqsave(&ioapic_lock, flags); |
| 417 | entry = cfg->irq_2_pin; | 418 | for_each_irq_pin(entry, cfg->irq_2_pin) { |
| 418 | for (;;) { | ||
| 419 | unsigned int reg; | 419 | unsigned int reg; |
| 420 | int pin; | 420 | int pin; |
| 421 | 421 | ||
| 422 | if (!entry) | ||
| 423 | break; | ||
| 424 | pin = entry->pin; | 422 | pin = entry->pin; |
| 425 | reg = io_apic_read(entry->apic, 0x10 + pin*2); | 423 | reg = io_apic_read(entry->apic, 0x10 + pin*2); |
| 426 | /* Is the remote IRR bit set? */ | 424 | /* Is the remote IRR bit set? */ |
| @@ -428,9 +426,6 @@ static bool io_apic_level_ack_pending(struct irq_cfg *cfg) | |||
| 428 | spin_unlock_irqrestore(&ioapic_lock, flags); | 426 | spin_unlock_irqrestore(&ioapic_lock, flags); |
| 429 | return true; | 427 | return true; |
| 430 | } | 428 | } |
| 431 | if (!entry->next) | ||
| 432 | break; | ||
| 433 | entry = entry->next; | ||
| 434 | } | 429 | } |
| 435 | spin_unlock_irqrestore(&ioapic_lock, flags); | 430 | spin_unlock_irqrestore(&ioapic_lock, flags); |
| 436 | 431 | ||
| @@ -498,72 +493,68 @@ static void ioapic_mask_entry(int apic, int pin) | |||
| 498 | * shared ISA-space IRQs, so we have to support them. We are super | 493 | * shared ISA-space IRQs, so we have to support them. We are super |
| 499 | * fast in the common case, and fast for shared ISA-space IRQs. | 494 | * fast in the common case, and fast for shared ISA-space IRQs. |
| 500 | */ | 495 | */ |
| 501 | static void add_pin_to_irq_node(struct irq_cfg *cfg, int node, int apic, int pin) | 496 | static int |
| 497 | add_pin_to_irq_node_nopanic(struct irq_cfg *cfg, int node, int apic, int pin) | ||
| 502 | { | 498 | { |
| 503 | struct irq_pin_list *entry; | 499 | struct irq_pin_list **last, *entry; |
| 504 | 500 | ||
| 505 | entry = cfg->irq_2_pin; | 501 | /* don't allow duplicates */ |
| 506 | if (!entry) { | 502 | last = &cfg->irq_2_pin; |
| 507 | entry = get_one_free_irq_2_pin(node); | 503 | for_each_irq_pin(entry, cfg->irq_2_pin) { |
| 508 | if (!entry) { | ||
| 509 | printk(KERN_ERR "can not alloc irq_2_pin to add %d - %d\n", | ||
| 510 | apic, pin); | ||
| 511 | return; | ||
| 512 | } | ||
| 513 | cfg->irq_2_pin = entry; | ||
| 514 | entry->apic = apic; | ||
| 515 | entry->pin = pin; | ||
| 516 | return; | ||
| 517 | } | ||
| 518 | |||
| 519 | while (entry->next) { | ||
| 520 | /* not again, please */ | ||
| 521 | if (entry->apic == apic && entry->pin == pin) | 504 | if (entry->apic == apic && entry->pin == pin) |
| 522 | return; | 505 | return 0; |
| 523 | 506 | last = &entry->next; | |
| 524 | entry = entry->next; | ||
| 525 | } | 507 | } |
| 526 | 508 | ||
| 527 | entry->next = get_one_free_irq_2_pin(node); | 509 | entry = get_one_free_irq_2_pin(node); |
| 528 | entry = entry->next; | 510 | if (!entry) { |
| 511 | printk(KERN_ERR "can not alloc irq_pin_list (%d,%d,%d)\n", | ||
| 512 | node, apic, pin); | ||
| 513 | return -ENOMEM; | ||
| 514 | } | ||
| 529 | entry->apic = apic; | 515 | entry->apic = apic; |
| 530 | entry->pin = pin; | 516 | entry->pin = pin; |
| 517 | |||
| 518 | *last = entry; | ||
| 519 | return 0; | ||
| 520 | } | ||
| 521 | |||
| 522 | static void add_pin_to_irq_node(struct irq_cfg *cfg, int node, int apic, int pin) | ||
| 523 | { | ||
| 524 | if (add_pin_to_irq_node_nopanic(cfg, node, apic, pin)) | ||
| 525 | panic("IO-APIC: failed to add irq-pin. Can not proceed\n"); | ||
| 531 | } | 526 | } |
| 532 | 527 | ||
| 533 | /* | 528 | /* |
| 534 | * Reroute an IRQ to a different pin. | 529 | * Reroute an IRQ to a different pin. |
| 535 | */ | 530 | */ |
| 536 | static void __init replace_pin_at_irq_node(struct irq_cfg *cfg, int node, | 531 | static void __init replace_pin_at_irq_node(struct irq_cfg *cfg, int node, |
| 537 | int oldapic, int oldpin, | 532 | int oldapic, int oldpin, |
| 538 | int newapic, int newpin) | 533 | int newapic, int newpin) |
| 539 | { | 534 | { |
| 540 | struct irq_pin_list *entry = cfg->irq_2_pin; | 535 | struct irq_pin_list *entry; |
| 541 | int replaced = 0; | ||
| 542 | 536 | ||
| 543 | while (entry) { | 537 | for_each_irq_pin(entry, cfg->irq_2_pin) { |
| 544 | if (entry->apic == oldapic && entry->pin == oldpin) { | 538 | if (entry->apic == oldapic && entry->pin == oldpin) { |
| 545 | entry->apic = newapic; | 539 | entry->apic = newapic; |
| 546 | entry->pin = newpin; | 540 | entry->pin = newpin; |
| 547 | replaced = 1; | ||
| 548 | /* every one is different, right? */ | 541 | /* every one is different, right? */ |
| 549 | break; | 542 | return; |
| 550 | } | 543 | } |
| 551 | entry = entry->next; | ||
| 552 | } | 544 | } |
| 553 | 545 | ||
| 554 | /* why? call replace before add? */ | 546 | /* old apic/pin didn't exist, so just add new ones */ |
| 555 | if (!replaced) | 547 | add_pin_to_irq_node(cfg, node, newapic, newpin); |
| 556 | add_pin_to_irq_node(cfg, node, newapic, newpin); | ||
| 557 | } | 548 | } |
| 558 | 549 | ||
| 559 | static inline void io_apic_modify_irq(struct irq_cfg *cfg, | 550 | static void io_apic_modify_irq(struct irq_cfg *cfg, |
| 560 | int mask_and, int mask_or, | 551 | int mask_and, int mask_or, |
| 561 | void (*final)(struct irq_pin_list *entry)) | 552 | void (*final)(struct irq_pin_list *entry)) |
| 562 | { | 553 | { |
| 563 | int pin; | 554 | int pin; |
| 564 | struct irq_pin_list *entry; | 555 | struct irq_pin_list *entry; |
| 565 | 556 | ||
| 566 | for (entry = cfg->irq_2_pin; entry != NULL; entry = entry->next) { | 557 | for_each_irq_pin(entry, cfg->irq_2_pin) { |
| 567 | unsigned int reg; | 558 | unsigned int reg; |
| 568 | pin = entry->pin; | 559 | pin = entry->pin; |
| 569 | reg = io_apic_read(entry->apic, 0x10 + pin * 2); | 560 | reg = io_apic_read(entry->apic, 0x10 + pin * 2); |
| @@ -580,7 +571,6 @@ static void __unmask_IO_APIC_irq(struct irq_cfg *cfg) | |||
| 580 | io_apic_modify_irq(cfg, ~IO_APIC_REDIR_MASKED, 0, NULL); | 571 | io_apic_modify_irq(cfg, ~IO_APIC_REDIR_MASKED, 0, NULL); |
| 581 | } | 572 | } |
| 582 | 573 | ||
| 583 | #ifdef CONFIG_X86_64 | ||
| 584 | static void io_apic_sync(struct irq_pin_list *entry) | 574 | static void io_apic_sync(struct irq_pin_list *entry) |
| 585 | { | 575 | { |
| 586 | /* | 576 | /* |
| @@ -596,11 +586,6 @@ static void __mask_IO_APIC_irq(struct irq_cfg *cfg) | |||
| 596 | { | 586 | { |
| 597 | io_apic_modify_irq(cfg, ~0, IO_APIC_REDIR_MASKED, &io_apic_sync); | 587 | io_apic_modify_irq(cfg, ~0, IO_APIC_REDIR_MASKED, &io_apic_sync); |
| 598 | } | 588 | } |
| 599 | #else /* CONFIG_X86_32 */ | ||
| 600 | static void __mask_IO_APIC_irq(struct irq_cfg *cfg) | ||
| 601 | { | ||
| 602 | io_apic_modify_irq(cfg, ~0, IO_APIC_REDIR_MASKED, NULL); | ||
| 603 | } | ||
| 604 | 589 | ||
| 605 | static void __mask_and_edge_IO_APIC_irq(struct irq_cfg *cfg) | 590 | static void __mask_and_edge_IO_APIC_irq(struct irq_cfg *cfg) |
| 606 | { | 591 | { |
| @@ -613,7 +598,6 @@ static void __unmask_and_level_IO_APIC_irq(struct irq_cfg *cfg) | |||
| 613 | io_apic_modify_irq(cfg, ~IO_APIC_REDIR_MASKED, | 598 | io_apic_modify_irq(cfg, ~IO_APIC_REDIR_MASKED, |
| 614 | IO_APIC_REDIR_LEVEL_TRIGGER, NULL); | 599 | IO_APIC_REDIR_LEVEL_TRIGGER, NULL); |
| 615 | } | 600 | } |
| 616 | #endif /* CONFIG_X86_32 */ | ||
| 617 | 601 | ||
| 618 | static void mask_IO_APIC_irq_desc(struct irq_desc *desc) | 602 | static void mask_IO_APIC_irq_desc(struct irq_desc *desc) |
| 619 | { | 603 | { |
| @@ -1702,12 +1686,8 @@ __apicdebuginit(void) print_IO_APIC(void) | |||
| 1702 | if (!entry) | 1686 | if (!entry) |
| 1703 | continue; | 1687 | continue; |
| 1704 | printk(KERN_DEBUG "IRQ%d ", irq); | 1688 | printk(KERN_DEBUG "IRQ%d ", irq); |
| 1705 | for (;;) { | 1689 | for_each_irq_pin(entry, cfg->irq_2_pin) |
| 1706 | printk("-> %d:%d", entry->apic, entry->pin); | 1690 | printk("-> %d:%d", entry->apic, entry->pin); |
| 1707 | if (!entry->next) | ||
| 1708 | break; | ||
| 1709 | entry = entry->next; | ||
| 1710 | } | ||
| 1711 | printk("\n"); | 1691 | printk("\n"); |
| 1712 | } | 1692 | } |
| 1713 | 1693 | ||
| @@ -2211,7 +2191,6 @@ static unsigned int startup_ioapic_irq(unsigned int irq) | |||
| 2211 | return was_pending; | 2191 | return was_pending; |
| 2212 | } | 2192 | } |
| 2213 | 2193 | ||
| 2214 | #ifdef CONFIG_X86_64 | ||
| 2215 | static int ioapic_retrigger_irq(unsigned int irq) | 2194 | static int ioapic_retrigger_irq(unsigned int irq) |
| 2216 | { | 2195 | { |
| 2217 | 2196 | ||
| @@ -2224,14 +2203,6 @@ static int ioapic_retrigger_irq(unsigned int irq) | |||
| 2224 | 2203 | ||
| 2225 | return 1; | 2204 | return 1; |
| 2226 | } | 2205 | } |
| 2227 | #else | ||
| 2228 | static int ioapic_retrigger_irq(unsigned int irq) | ||
| 2229 | { | ||
| 2230 | apic->send_IPI_self(irq_cfg(irq)->vector); | ||
| 2231 | |||
| 2232 | return 1; | ||
| 2233 | } | ||
| 2234 | #endif | ||
| 2235 | 2206 | ||
| 2236 | /* | 2207 | /* |
| 2237 | * Level and edge triggered IO-APIC interrupts need different handling, | 2208 | * Level and edge triggered IO-APIC interrupts need different handling, |
| @@ -2269,13 +2240,9 @@ static void __target_IO_APIC_irq(unsigned int irq, unsigned int dest, struct irq | |||
| 2269 | struct irq_pin_list *entry; | 2240 | struct irq_pin_list *entry; |
| 2270 | u8 vector = cfg->vector; | 2241 | u8 vector = cfg->vector; |
| 2271 | 2242 | ||
| 2272 | entry = cfg->irq_2_pin; | 2243 | for_each_irq_pin(entry, cfg->irq_2_pin) { |
| 2273 | for (;;) { | ||
| 2274 | unsigned int reg; | 2244 | unsigned int reg; |
| 2275 | 2245 | ||
| 2276 | if (!entry) | ||
| 2277 | break; | ||
| 2278 | |||
| 2279 | apic = entry->apic; | 2246 | apic = entry->apic; |
| 2280 | pin = entry->pin; | 2247 | pin = entry->pin; |
| 2281 | /* | 2248 | /* |
| @@ -2288,9 +2255,6 @@ static void __target_IO_APIC_irq(unsigned int irq, unsigned int dest, struct irq | |||
| 2288 | reg &= ~IO_APIC_REDIR_VECTOR_MASK; | 2255 | reg &= ~IO_APIC_REDIR_VECTOR_MASK; |
| 2289 | reg |= vector; | 2256 | reg |= vector; |
| 2290 | io_apic_modify(apic, 0x10 + pin*2, reg); | 2257 | io_apic_modify(apic, 0x10 + pin*2, reg); |
| 2291 | if (!entry->next) | ||
| 2292 | break; | ||
| 2293 | entry = entry->next; | ||
| 2294 | } | 2258 | } |
| 2295 | } | 2259 | } |
| 2296 | 2260 | ||
| @@ -2515,11 +2479,8 @@ atomic_t irq_mis_count; | |||
| 2515 | static void ack_apic_level(unsigned int irq) | 2479 | static void ack_apic_level(unsigned int irq) |
| 2516 | { | 2480 | { |
| 2517 | struct irq_desc *desc = irq_to_desc(irq); | 2481 | struct irq_desc *desc = irq_to_desc(irq); |
| 2518 | |||
| 2519 | #ifdef CONFIG_X86_32 | ||
| 2520 | unsigned long v; | 2482 | unsigned long v; |
| 2521 | int i; | 2483 | int i; |
| 2522 | #endif | ||
| 2523 | struct irq_cfg *cfg; | 2484 | struct irq_cfg *cfg; |
| 2524 | int do_unmask_irq = 0; | 2485 | int do_unmask_irq = 0; |
| 2525 | 2486 | ||
| @@ -2532,31 +2493,28 @@ static void ack_apic_level(unsigned int irq) | |||
| 2532 | } | 2493 | } |
| 2533 | #endif | 2494 | #endif |
| 2534 | 2495 | ||
| 2535 | #ifdef CONFIG_X86_32 | ||
| 2536 | /* | 2496 | /* |
| 2537 | * It appears there is an erratum which affects at least version 0x11 | 2497 | * It appears there is an erratum which affects at least version 0x11 |
| 2538 | * of I/O APIC (that's the 82093AA and cores integrated into various | 2498 | * of I/O APIC (that's the 82093AA and cores integrated into various |
| 2539 | * chipsets). Under certain conditions a level-triggered interrupt is | 2499 | * chipsets). Under certain conditions a level-triggered interrupt is |
| 2540 | * erroneously delivered as edge-triggered one but the respective IRR | 2500 | * erroneously delivered as edge-triggered one but the respective IRR |
| 2541 | * bit gets set nevertheless. As a result the I/O unit expects an EOI | 2501 | * bit gets set nevertheless. As a result the I/O unit expects an EOI |
| 2542 | * message but it will never arrive and further interrupts are blocked | 2502 | * message but it will never arrive and further interrupts are blocked |
| 2543 | * from the source. The exact reason is so far unknown, but the | 2503 | * from the source. The exact reason is so far unknown, but the |
| 2544 | * phenomenon was observed when two consecutive interrupt requests | 2504 | * phenomenon was observed when two consecutive interrupt requests |
| 2545 | * from a given source get delivered to the same CPU and the source is | 2505 | * from a given source get delivered to the same CPU and the source is |
| 2546 | * temporarily disabled in between. | 2506 | * temporarily disabled in between. |
| 2547 | * | 2507 | * |
| 2548 | * A workaround is to simulate an EOI message manually. We achieve it | 2508 | * A workaround is to simulate an EOI message manually. We achieve it |
| 2549 | * by setting the trigger mode to edge and then to level when the edge | 2509 | * by setting the trigger mode to edge and then to level when the edge |
| 2550 | * trigger mode gets detected in the TMR of a local APIC for a | 2510 | * trigger mode gets detected in the TMR of a local APIC for a |
| 2551 | * level-triggered interrupt. We mask the source for the time of the | 2511 | * level-triggered interrupt. We mask the source for the time of the |
| 2552 | * operation to prevent an edge-triggered interrupt escaping meanwhile. | 2512 | * operation to prevent an edge-triggered interrupt escaping meanwhile. |
| 2553 | * The idea is from Manfred Spraul. --macro | 2513 | * The idea is from Manfred Spraul. --macro |
| 2554 | */ | 2514 | */ |
| 2555 | cfg = desc->chip_data; | 2515 | cfg = desc->chip_data; |
| 2556 | i = cfg->vector; | 2516 | i = cfg->vector; |
| 2557 | |||
| 2558 | v = apic_read(APIC_TMR + ((i & ~0x1f) >> 1)); | 2517 | v = apic_read(APIC_TMR + ((i & ~0x1f) >> 1)); |
| 2559 | #endif | ||
| 2560 | 2518 | ||
| 2561 | /* | 2519 | /* |
| 2562 | * We must acknowledge the irq before we move it or the acknowledge will | 2520 | * We must acknowledge the irq before we move it or the acknowledge will |
| @@ -2598,7 +2556,7 @@ static void ack_apic_level(unsigned int irq) | |||
| 2598 | unmask_IO_APIC_irq_desc(desc); | 2556 | unmask_IO_APIC_irq_desc(desc); |
| 2599 | } | 2557 | } |
| 2600 | 2558 | ||
| 2601 | #ifdef CONFIG_X86_32 | 2559 | /* Tail end of version 0x11 I/O APIC bug workaround */ |
| 2602 | if (!(v & (1 << (i & 0x1f)))) { | 2560 | if (!(v & (1 << (i & 0x1f)))) { |
| 2603 | atomic_inc(&irq_mis_count); | 2561 | atomic_inc(&irq_mis_count); |
| 2604 | spin_lock(&ioapic_lock); | 2562 | spin_lock(&ioapic_lock); |
| @@ -2606,26 +2564,15 @@ static void ack_apic_level(unsigned int irq) | |||
| 2606 | __unmask_and_level_IO_APIC_irq(cfg); | 2564 | __unmask_and_level_IO_APIC_irq(cfg); |
| 2607 | spin_unlock(&ioapic_lock); | 2565 | spin_unlock(&ioapic_lock); |
| 2608 | } | 2566 | } |
| 2609 | #endif | ||
| 2610 | } | 2567 | } |
| 2611 | 2568 | ||
| 2612 | #ifdef CONFIG_INTR_REMAP | 2569 | #ifdef CONFIG_INTR_REMAP |
| 2613 | static void __eoi_ioapic_irq(unsigned int irq, struct irq_cfg *cfg) | 2570 | static void __eoi_ioapic_irq(unsigned int irq, struct irq_cfg *cfg) |
| 2614 | { | 2571 | { |
| 2615 | int apic, pin; | ||
| 2616 | struct irq_pin_list *entry; | 2572 | struct irq_pin_list *entry; |
| 2617 | 2573 | ||
| 2618 | entry = cfg->irq_2_pin; | 2574 | for_each_irq_pin(entry, cfg->irq_2_pin) |
| 2619 | for (;;) { | 2575 | io_apic_eoi(entry->apic, entry->pin); |
| 2620 | |||
| 2621 | if (!entry) | ||
| 2622 | break; | ||
| 2623 | |||
| 2624 | apic = entry->apic; | ||
| 2625 | pin = entry->pin; | ||
| 2626 | io_apic_eoi(apic, pin); | ||
| 2627 | entry = entry->next; | ||
| 2628 | } | ||
| 2629 | } | 2576 | } |
| 2630 | 2577 | ||
| 2631 | static void | 2578 | static void |
| @@ -3241,8 +3188,7 @@ void destroy_irq(unsigned int irq) | |||
| 3241 | cfg = desc->chip_data; | 3188 | cfg = desc->chip_data; |
| 3242 | dynamic_irq_cleanup(irq); | 3189 | dynamic_irq_cleanup(irq); |
| 3243 | /* connect back irq_cfg */ | 3190 | /* connect back irq_cfg */ |
| 3244 | if (desc) | 3191 | desc->chip_data = cfg; |
| 3245 | desc->chip_data = cfg; | ||
| 3246 | 3192 | ||
| 3247 | free_irte(irq); | 3193 | free_irte(irq); |
| 3248 | spin_lock_irqsave(&vector_lock, flags); | 3194 | spin_lock_irqsave(&vector_lock, flags); |
| @@ -3912,7 +3858,11 @@ static int __io_apic_set_pci_routing(struct device *dev, int irq, | |||
| 3912 | */ | 3858 | */ |
| 3913 | if (irq >= NR_IRQS_LEGACY) { | 3859 | if (irq >= NR_IRQS_LEGACY) { |
| 3914 | cfg = desc->chip_data; | 3860 | cfg = desc->chip_data; |
| 3915 | add_pin_to_irq_node(cfg, node, ioapic, pin); | 3861 | if (add_pin_to_irq_node_nopanic(cfg, node, ioapic, pin)) { |
| 3862 | printk(KERN_INFO "can not add pin %d for irq %d\n", | ||
| 3863 | pin, irq); | ||
| 3864 | return 0; | ||
| 3865 | } | ||
| 3916 | } | 3866 | } |
| 3917 | 3867 | ||
| 3918 | setup_IO_APIC_irq(ioapic, pin, irq, desc, trigger, polarity); | 3868 | setup_IO_APIC_irq(ioapic, pin, irq, desc, trigger, polarity); |
| @@ -3941,11 +3891,28 @@ int io_apic_set_pci_routing(struct device *dev, int irq, | |||
| 3941 | return __io_apic_set_pci_routing(dev, irq, irq_attr); | 3891 | return __io_apic_set_pci_routing(dev, irq, irq_attr); |
| 3942 | } | 3892 | } |
| 3943 | 3893 | ||
| 3944 | /* -------------------------------------------------------------------------- | 3894 | u8 __init io_apic_unique_id(u8 id) |
| 3945 | ACPI-based IOAPIC Configuration | 3895 | { |
| 3946 | -------------------------------------------------------------------------- */ | 3896 | #ifdef CONFIG_X86_32 |
| 3897 | if ((boot_cpu_data.x86_vendor == X86_VENDOR_INTEL) && | ||
| 3898 | !APIC_XAPIC(apic_version[boot_cpu_physical_apicid])) | ||
| 3899 | return io_apic_get_unique_id(nr_ioapics, id); | ||
| 3900 | else | ||
| 3901 | return id; | ||
| 3902 | #else | ||
| 3903 | int i; | ||
| 3904 | DECLARE_BITMAP(used, 256); | ||
| 3947 | 3905 | ||
| 3948 | #ifdef CONFIG_ACPI | 3906 | bitmap_zero(used, 256); |
| 3907 | for (i = 0; i < nr_ioapics; i++) { | ||
| 3908 | struct mpc_ioapic *ia = &mp_ioapics[i]; | ||
| 3909 | __set_bit(ia->apicid, used); | ||
| 3910 | } | ||
| 3911 | if (!test_bit(id, used)) | ||
| 3912 | return id; | ||
| 3913 | return find_first_zero_bit(used, 256); | ||
| 3914 | #endif | ||
| 3915 | } | ||
| 3949 | 3916 | ||
| 3950 | #ifdef CONFIG_X86_32 | 3917 | #ifdef CONFIG_X86_32 |
| 3951 | int __init io_apic_get_unique_id(int ioapic, int apic_id) | 3918 | int __init io_apic_get_unique_id(int ioapic, int apic_id) |
| @@ -4054,8 +4021,6 @@ int acpi_get_override_irq(int bus_irq, int *trigger, int *polarity) | |||
| 4054 | return 0; | 4021 | return 0; |
| 4055 | } | 4022 | } |
| 4056 | 4023 | ||
| 4057 | #endif /* CONFIG_ACPI */ | ||
| 4058 | |||
| 4059 | /* | 4024 | /* |
| 4060 | * This function currently is only a helper for the i386 smp boot process where | 4025 | * This function currently is only a helper for the i386 smp boot process where |
| 4061 | * we need to reprogram the ioredtbls to cater for the cpus which have come online | 4026 | * we need to reprogram the ioredtbls to cater for the cpus which have come online |
| @@ -4109,7 +4074,7 @@ void __init setup_ioapic_dest(void) | |||
| 4109 | 4074 | ||
| 4110 | static struct resource *ioapic_resources; | 4075 | static struct resource *ioapic_resources; |
| 4111 | 4076 | ||
| 4112 | static struct resource * __init ioapic_setup_resources(void) | 4077 | static struct resource * __init ioapic_setup_resources(int nr_ioapics) |
| 4113 | { | 4078 | { |
| 4114 | unsigned long n; | 4079 | unsigned long n; |
| 4115 | struct resource *res; | 4080 | struct resource *res; |
| @@ -4125,15 +4090,13 @@ static struct resource * __init ioapic_setup_resources(void) | |||
| 4125 | mem = alloc_bootmem(n); | 4090 | mem = alloc_bootmem(n); |
| 4126 | res = (void *)mem; | 4091 | res = (void *)mem; |
| 4127 | 4092 | ||
| 4128 | if (mem != NULL) { | 4093 | mem += sizeof(struct resource) * nr_ioapics; |
| 4129 | mem += sizeof(struct resource) * nr_ioapics; | ||
| 4130 | 4094 | ||
| 4131 | for (i = 0; i < nr_ioapics; i++) { | 4095 | for (i = 0; i < nr_ioapics; i++) { |
| 4132 | res[i].name = mem; | 4096 | res[i].name = mem; |
| 4133 | res[i].flags = IORESOURCE_MEM | IORESOURCE_BUSY; | 4097 | res[i].flags = IORESOURCE_MEM | IORESOURCE_BUSY; |
| 4134 | sprintf(mem, "IOAPIC %u", i); | 4098 | sprintf(mem, "IOAPIC %u", i); |
| 4135 | mem += IOAPIC_RESOURCE_NAME_SIZE; | 4099 | mem += IOAPIC_RESOURCE_NAME_SIZE; |
| 4136 | } | ||
| 4137 | } | 4100 | } |
| 4138 | 4101 | ||
| 4139 | ioapic_resources = res; | 4102 | ioapic_resources = res; |
| @@ -4147,7 +4110,7 @@ void __init ioapic_init_mappings(void) | |||
| 4147 | struct resource *ioapic_res; | 4110 | struct resource *ioapic_res; |
| 4148 | int i; | 4111 | int i; |
| 4149 | 4112 | ||
| 4150 | ioapic_res = ioapic_setup_resources(); | 4113 | ioapic_res = ioapic_setup_resources(nr_ioapics); |
| 4151 | for (i = 0; i < nr_ioapics; i++) { | 4114 | for (i = 0; i < nr_ioapics; i++) { |
| 4152 | if (smp_found_config) { | 4115 | if (smp_found_config) { |
| 4153 | ioapic_phys = mp_ioapics[i].apicaddr; | 4116 | ioapic_phys = mp_ioapics[i].apicaddr; |
| @@ -4176,11 +4139,9 @@ fake_ioapic_page: | |||
| 4176 | __fix_to_virt(idx), ioapic_phys); | 4139 | __fix_to_virt(idx), ioapic_phys); |
| 4177 | idx++; | 4140 | idx++; |
| 4178 | 4141 | ||
| 4179 | if (ioapic_res != NULL) { | 4142 | ioapic_res->start = ioapic_phys; |
| 4180 | ioapic_res->start = ioapic_phys; | 4143 | ioapic_res->end = ioapic_phys + (4 * 1024) - 1; |
| 4181 | ioapic_res->end = ioapic_phys + (4 * 1024) - 1; | 4144 | ioapic_res++; |
| 4182 | ioapic_res++; | ||
| 4183 | } | ||
| 4184 | } | 4145 | } |
| 4185 | } | 4146 | } |
| 4186 | 4147 | ||
| @@ -4201,3 +4162,76 @@ void __init ioapic_insert_resources(void) | |||
| 4201 | r++; | 4162 | r++; |
| 4202 | } | 4163 | } |
| 4203 | } | 4164 | } |
| 4165 | |||
| 4166 | int mp_find_ioapic(int gsi) | ||
| 4167 | { | ||
| 4168 | int i = 0; | ||
| 4169 | |||
| 4170 | /* Find the IOAPIC that manages this GSI. */ | ||
| 4171 | for (i = 0; i < nr_ioapics; i++) { | ||
| 4172 | if ((gsi >= mp_gsi_routing[i].gsi_base) | ||
| 4173 | && (gsi <= mp_gsi_routing[i].gsi_end)) | ||
| 4174 | return i; | ||
| 4175 | } | ||
| 4176 | |||
| 4177 | printk(KERN_ERR "ERROR: Unable to locate IOAPIC for GSI %d\n", gsi); | ||
| 4178 | return -1; | ||
| 4179 | } | ||
| 4180 | |||
| 4181 | int mp_find_ioapic_pin(int ioapic, int gsi) | ||
| 4182 | { | ||
| 4183 | if (WARN_ON(ioapic == -1)) | ||
| 4184 | return -1; | ||
| 4185 | if (WARN_ON(gsi > mp_gsi_routing[ioapic].gsi_end)) | ||
| 4186 | return -1; | ||
| 4187 | |||
| 4188 | return gsi - mp_gsi_routing[ioapic].gsi_base; | ||
| 4189 | } | ||
| 4190 | |||
| 4191 | static int bad_ioapic(unsigned long address) | ||
| 4192 | { | ||
| 4193 | if (nr_ioapics >= MAX_IO_APICS) { | ||
| 4194 | printk(KERN_WARNING "WARING: Max # of I/O APICs (%d) exceeded " | ||
| 4195 | "(found %d), skipping\n", MAX_IO_APICS, nr_ioapics); | ||
| 4196 | return 1; | ||
| 4197 | } | ||
| 4198 | if (!address) { | ||
| 4199 | printk(KERN_WARNING "WARNING: Bogus (zero) I/O APIC address" | ||
| 4200 | " found in table, skipping!\n"); | ||
| 4201 | return 1; | ||
| 4202 | } | ||
| 4203 | return 0; | ||
| 4204 | } | ||
| 4205 | |||
| 4206 | void __init mp_register_ioapic(int id, u32 address, u32 gsi_base) | ||
| 4207 | { | ||
| 4208 | int idx = 0; | ||
| 4209 | |||
| 4210 | if (bad_ioapic(address)) | ||
| 4211 | return; | ||
| 4212 | |||
| 4213 | idx = nr_ioapics; | ||
| 4214 | |||
| 4215 | mp_ioapics[idx].type = MP_IOAPIC; | ||
| 4216 | mp_ioapics[idx].flags = MPC_APIC_USABLE; | ||
| 4217 | mp_ioapics[idx].apicaddr = address; | ||
| 4218 | |||
| 4219 | set_fixmap_nocache(FIX_IO_APIC_BASE_0 + idx, address); | ||
| 4220 | mp_ioapics[idx].apicid = io_apic_unique_id(id); | ||
| 4221 | mp_ioapics[idx].apicver = io_apic_get_version(idx); | ||
| 4222 | |||
| 4223 | /* | ||
| 4224 | * Build basic GSI lookup table to facilitate gsi->io_apic lookups | ||
| 4225 | * and to prevent reprogramming of IOAPIC pins (PCI GSIs). | ||
| 4226 | */ | ||
| 4227 | mp_gsi_routing[idx].gsi_base = gsi_base; | ||
| 4228 | mp_gsi_routing[idx].gsi_end = gsi_base + | ||
| 4229 | io_apic_get_redir_entries(idx); | ||
| 4230 | |||
| 4231 | printk(KERN_INFO "IOAPIC[%d]: apic_id %d, version %d, address 0x%x, " | ||
| 4232 | "GSI %d-%d\n", idx, mp_ioapics[idx].apicid, | ||
| 4233 | mp_ioapics[idx].apicver, mp_ioapics[idx].apicaddr, | ||
| 4234 | mp_gsi_routing[idx].gsi_base, mp_gsi_routing[idx].gsi_end); | ||
| 4235 | |||
| 4236 | nr_ioapics++; | ||
| 4237 | } | ||
diff --git a/arch/x86/kernel/apic/probe_64.c b/arch/x86/kernel/apic/probe_64.c index fcec2f1d34a1..65edc180fc82 100644 --- a/arch/x86/kernel/apic/probe_64.c +++ b/arch/x86/kernel/apic/probe_64.c | |||
| @@ -55,11 +55,11 @@ static int apicid_phys_pkg_id(int initial_apic_id, int index_msb) | |||
| 55 | void __init default_setup_apic_routing(void) | 55 | void __init default_setup_apic_routing(void) |
| 56 | { | 56 | { |
| 57 | #ifdef CONFIG_X86_X2APIC | 57 | #ifdef CONFIG_X86_X2APIC |
| 58 | if (x2apic_mode && (apic != &apic_x2apic_phys && | 58 | if (x2apic_mode |
| 59 | #ifdef CONFIG_X86_UV | 59 | #ifdef CONFIG_X86_UV |
| 60 | apic != &apic_x2apic_uv_x && | 60 | && apic != &apic_x2apic_uv_x |
| 61 | #endif | 61 | #endif |
| 62 | apic != &apic_x2apic_cluster)) { | 62 | ) { |
| 63 | if (x2apic_phys) | 63 | if (x2apic_phys) |
| 64 | apic = &apic_x2apic_phys; | 64 | apic = &apic_x2apic_phys; |
| 65 | else | 65 | else |
diff --git a/arch/x86/kernel/mpparse.c b/arch/x86/kernel/mpparse.c index 651c93b28862..fcd513bf2846 100644 --- a/arch/x86/kernel/mpparse.c +++ b/arch/x86/kernel/mpparse.c | |||
| @@ -482,11 +482,11 @@ static void __init construct_ioapic_table(int mpc_default_type) | |||
| 482 | MP_bus_info(&bus); | 482 | MP_bus_info(&bus); |
| 483 | } | 483 | } |
| 484 | 484 | ||
| 485 | ioapic.type = MP_IOAPIC; | 485 | ioapic.type = MP_IOAPIC; |
| 486 | ioapic.apicid = 2; | 486 | ioapic.apicid = 2; |
| 487 | ioapic.apicver = mpc_default_type > 4 ? 0x10 : 0x01; | 487 | ioapic.apicver = mpc_default_type > 4 ? 0x10 : 0x01; |
| 488 | ioapic.flags = MPC_APIC_USABLE; | 488 | ioapic.flags = MPC_APIC_USABLE; |
| 489 | ioapic.apicaddr = 0xFEC00000; | 489 | ioapic.apicaddr = IO_APIC_DEFAULT_PHYS_BASE; |
| 490 | MP_ioapic_info(&ioapic); | 490 | MP_ioapic_info(&ioapic); |
| 491 | 491 | ||
| 492 | /* | 492 | /* |
