diff options
author | Ingo Molnar <mingo@elte.hu> | 2009-04-07 06:05:21 -0400 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2009-04-07 06:05:25 -0400 |
commit | 6c009ecef8cca28c7c09eb16d0802e37915a76e1 (patch) | |
tree | 11c773f780186fdb9fbc9c80a73fb7c8426b1fba /arch/x86/kernel/apic | |
parent | 98c2aaf8be5baf7193be37fb28bce8e7327158bc (diff) | |
parent | d508afb437daee7cf07da085b635c44a4ebf9b38 (diff) |
Merge branch 'linus' into perfcounters/core
Merge reason: need the upstream facility added by:
7f1e2ca: hrtimer: fix rq->lock inversion (again)
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'arch/x86/kernel/apic')
-rw-r--r-- | arch/x86/kernel/apic/apic.c | 70 | ||||
-rw-r--r-- | arch/x86/kernel/apic/io_apic.c | 140 |
2 files changed, 156 insertions, 54 deletions
diff --git a/arch/x86/kernel/apic/apic.c b/arch/x86/kernel/apic/apic.c index b0e5e712a7af..fb504f843e58 100644 --- a/arch/x86/kernel/apic/apic.c +++ b/arch/x86/kernel/apic/apic.c | |||
@@ -1308,6 +1308,7 @@ void __init enable_IR_x2apic(void) | |||
1308 | #ifdef CONFIG_INTR_REMAP | 1308 | #ifdef CONFIG_INTR_REMAP |
1309 | int ret; | 1309 | int ret; |
1310 | unsigned long flags; | 1310 | unsigned long flags; |
1311 | struct IO_APIC_route_entry **ioapic_entries = NULL; | ||
1311 | 1312 | ||
1312 | if (!cpu_has_x2apic) | 1313 | if (!cpu_has_x2apic) |
1313 | return; | 1314 | return; |
@@ -1338,17 +1339,23 @@ void __init enable_IR_x2apic(void) | |||
1338 | return; | 1339 | return; |
1339 | } | 1340 | } |
1340 | 1341 | ||
1341 | ret = save_IO_APIC_setup(); | 1342 | ioapic_entries = alloc_ioapic_entries(); |
1343 | if (!ioapic_entries) { | ||
1344 | pr_info("Allocate ioapic_entries failed: %d\n", ret); | ||
1345 | goto end; | ||
1346 | } | ||
1347 | |||
1348 | ret = save_IO_APIC_setup(ioapic_entries); | ||
1342 | if (ret) { | 1349 | if (ret) { |
1343 | pr_info("Saving IO-APIC state failed: %d\n", ret); | 1350 | pr_info("Saving IO-APIC state failed: %d\n", ret); |
1344 | goto end; | 1351 | goto end; |
1345 | } | 1352 | } |
1346 | 1353 | ||
1347 | local_irq_save(flags); | 1354 | local_irq_save(flags); |
1348 | mask_IO_APIC_setup(); | 1355 | mask_IO_APIC_setup(ioapic_entries); |
1349 | mask_8259A(); | 1356 | mask_8259A(); |
1350 | 1357 | ||
1351 | ret = enable_intr_remapping(1); | 1358 | ret = enable_intr_remapping(EIM_32BIT_APIC_ID); |
1352 | 1359 | ||
1353 | if (ret && x2apic_preenabled) { | 1360 | if (ret && x2apic_preenabled) { |
1354 | local_irq_restore(flags); | 1361 | local_irq_restore(flags); |
@@ -1368,9 +1375,9 @@ end_restore: | |||
1368 | /* | 1375 | /* |
1369 | * IR enabling failed | 1376 | * IR enabling failed |
1370 | */ | 1377 | */ |
1371 | restore_IO_APIC_setup(); | 1378 | restore_IO_APIC_setup(ioapic_entries); |
1372 | else | 1379 | else |
1373 | reinit_intr_remapped_IO_APIC(x2apic_preenabled); | 1380 | reinit_intr_remapped_IO_APIC(x2apic_preenabled, ioapic_entries); |
1374 | 1381 | ||
1375 | unmask_8259A(); | 1382 | unmask_8259A(); |
1376 | local_irq_restore(flags); | 1383 | local_irq_restore(flags); |
@@ -1383,6 +1390,8 @@ end: | |||
1383 | pr_info("Enabled Interrupt-remapping\n"); | 1390 | pr_info("Enabled Interrupt-remapping\n"); |
1384 | } else | 1391 | } else |
1385 | pr_err("Failed to enable Interrupt-remapping and x2apic\n"); | 1392 | pr_err("Failed to enable Interrupt-remapping and x2apic\n"); |
1393 | if (ioapic_entries) | ||
1394 | free_ioapic_entries(ioapic_entries); | ||
1386 | #else | 1395 | #else |
1387 | if (!cpu_has_x2apic) | 1396 | if (!cpu_has_x2apic) |
1388 | return; | 1397 | return; |
@@ -1958,6 +1967,10 @@ static int lapic_suspend(struct sys_device *dev, pm_message_t state) | |||
1958 | 1967 | ||
1959 | local_irq_save(flags); | 1968 | local_irq_save(flags); |
1960 | disable_local_APIC(); | 1969 | disable_local_APIC(); |
1970 | #ifdef CONFIG_INTR_REMAP | ||
1971 | if (intr_remapping_enabled) | ||
1972 | disable_intr_remapping(); | ||
1973 | #endif | ||
1961 | local_irq_restore(flags); | 1974 | local_irq_restore(flags); |
1962 | return 0; | 1975 | return 0; |
1963 | } | 1976 | } |
@@ -1968,15 +1981,41 @@ static int lapic_resume(struct sys_device *dev) | |||
1968 | unsigned long flags; | 1981 | unsigned long flags; |
1969 | int maxlvt; | 1982 | int maxlvt; |
1970 | 1983 | ||
1984 | #ifdef CONFIG_INTR_REMAP | ||
1985 | int ret; | ||
1986 | struct IO_APIC_route_entry **ioapic_entries = NULL; | ||
1987 | |||
1971 | if (!apic_pm_state.active) | 1988 | if (!apic_pm_state.active) |
1972 | return 0; | 1989 | return 0; |
1973 | 1990 | ||
1974 | maxlvt = lapic_get_maxlvt(); | ||
1975 | |||
1976 | local_irq_save(flags); | 1991 | local_irq_save(flags); |
1992 | if (x2apic) { | ||
1993 | ioapic_entries = alloc_ioapic_entries(); | ||
1994 | if (!ioapic_entries) { | ||
1995 | WARN(1, "Alloc ioapic_entries in lapic resume failed."); | ||
1996 | return -ENOMEM; | ||
1997 | } | ||
1998 | |||
1999 | ret = save_IO_APIC_setup(ioapic_entries); | ||
2000 | if (ret) { | ||
2001 | WARN(1, "Saving IO-APIC state failed: %d\n", ret); | ||
2002 | free_ioapic_entries(ioapic_entries); | ||
2003 | return ret; | ||
2004 | } | ||
2005 | |||
2006 | mask_IO_APIC_setup(ioapic_entries); | ||
2007 | mask_8259A(); | ||
2008 | enable_x2apic(); | ||
2009 | } | ||
2010 | #else | ||
2011 | if (!apic_pm_state.active) | ||
2012 | return 0; | ||
1977 | 2013 | ||
2014 | local_irq_save(flags); | ||
1978 | if (x2apic) | 2015 | if (x2apic) |
1979 | enable_x2apic(); | 2016 | enable_x2apic(); |
2017 | #endif | ||
2018 | |||
1980 | else { | 2019 | else { |
1981 | /* | 2020 | /* |
1982 | * Make sure the APICBASE points to the right address | 2021 | * Make sure the APICBASE points to the right address |
@@ -1990,6 +2029,7 @@ static int lapic_resume(struct sys_device *dev) | |||
1990 | wrmsr(MSR_IA32_APICBASE, l, h); | 2029 | wrmsr(MSR_IA32_APICBASE, l, h); |
1991 | } | 2030 | } |
1992 | 2031 | ||
2032 | maxlvt = lapic_get_maxlvt(); | ||
1993 | apic_write(APIC_LVTERR, ERROR_APIC_VECTOR | APIC_LVT_MASKED); | 2033 | apic_write(APIC_LVTERR, ERROR_APIC_VECTOR | APIC_LVT_MASKED); |
1994 | apic_write(APIC_ID, apic_pm_state.apic_id); | 2034 | apic_write(APIC_ID, apic_pm_state.apic_id); |
1995 | apic_write(APIC_DFR, apic_pm_state.apic_dfr); | 2035 | apic_write(APIC_DFR, apic_pm_state.apic_dfr); |
@@ -2013,8 +2053,20 @@ static int lapic_resume(struct sys_device *dev) | |||
2013 | apic_write(APIC_ESR, 0); | 2053 | apic_write(APIC_ESR, 0); |
2014 | apic_read(APIC_ESR); | 2054 | apic_read(APIC_ESR); |
2015 | 2055 | ||
2056 | #ifdef CONFIG_INTR_REMAP | ||
2057 | if (intr_remapping_enabled) | ||
2058 | reenable_intr_remapping(EIM_32BIT_APIC_ID); | ||
2059 | |||
2060 | if (x2apic) { | ||
2061 | unmask_8259A(); | ||
2062 | restore_IO_APIC_setup(ioapic_entries); | ||
2063 | free_ioapic_entries(ioapic_entries); | ||
2064 | } | ||
2065 | #endif | ||
2066 | |||
2016 | local_irq_restore(flags); | 2067 | local_irq_restore(flags); |
2017 | 2068 | ||
2069 | |||
2018 | return 0; | 2070 | return 0; |
2019 | } | 2071 | } |
2020 | 2072 | ||
@@ -2052,7 +2104,9 @@ static int __init init_lapic_sysfs(void) | |||
2052 | error = sysdev_register(&device_lapic); | 2104 | error = sysdev_register(&device_lapic); |
2053 | return error; | 2105 | return error; |
2054 | } | 2106 | } |
2055 | device_initcall(init_lapic_sysfs); | 2107 | |
2108 | /* local apic needs to resume before other devices access its registers. */ | ||
2109 | core_initcall(init_lapic_sysfs); | ||
2056 | 2110 | ||
2057 | #else /* CONFIG_PM */ | 2111 | #else /* CONFIG_PM */ |
2058 | 2112 | ||
diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c index 1bb5c6cee3eb..767fe7e46d68 100644 --- a/arch/x86/kernel/apic/io_apic.c +++ b/arch/x86/kernel/apic/io_apic.c | |||
@@ -851,63 +851,74 @@ __setup("pirq=", ioapic_pirq_setup); | |||
851 | #endif /* CONFIG_X86_32 */ | 851 | #endif /* CONFIG_X86_32 */ |
852 | 852 | ||
853 | #ifdef CONFIG_INTR_REMAP | 853 | #ifdef CONFIG_INTR_REMAP |
854 | /* I/O APIC RTE contents at the OS boot up */ | 854 | struct IO_APIC_route_entry **alloc_ioapic_entries(void) |
855 | static struct IO_APIC_route_entry *early_ioapic_entries[MAX_IO_APICS]; | 855 | { |
856 | int apic; | ||
857 | struct IO_APIC_route_entry **ioapic_entries; | ||
858 | |||
859 | ioapic_entries = kzalloc(sizeof(*ioapic_entries) * nr_ioapics, | ||
860 | GFP_ATOMIC); | ||
861 | if (!ioapic_entries) | ||
862 | return 0; | ||
863 | |||
864 | for (apic = 0; apic < nr_ioapics; apic++) { | ||
865 | ioapic_entries[apic] = | ||
866 | kzalloc(sizeof(struct IO_APIC_route_entry) * | ||
867 | nr_ioapic_registers[apic], GFP_ATOMIC); | ||
868 | if (!ioapic_entries[apic]) | ||
869 | goto nomem; | ||
870 | } | ||
871 | |||
872 | return ioapic_entries; | ||
873 | |||
874 | nomem: | ||
875 | while (--apic >= 0) | ||
876 | kfree(ioapic_entries[apic]); | ||
877 | kfree(ioapic_entries); | ||
878 | |||
879 | return 0; | ||
880 | } | ||
856 | 881 | ||
857 | /* | 882 | /* |
858 | * Saves all the IO-APIC RTE's | 883 | * Saves all the IO-APIC RTE's |
859 | */ | 884 | */ |
860 | int save_IO_APIC_setup(void) | 885 | int save_IO_APIC_setup(struct IO_APIC_route_entry **ioapic_entries) |
861 | { | 886 | { |
862 | union IO_APIC_reg_01 reg_01; | ||
863 | unsigned long flags; | ||
864 | int apic, pin; | 887 | int apic, pin; |
865 | 888 | ||
866 | /* | 889 | if (!ioapic_entries) |
867 | * The number of IO-APIC IRQ registers (== #pins): | 890 | return -ENOMEM; |
868 | */ | ||
869 | for (apic = 0; apic < nr_ioapics; apic++) { | ||
870 | spin_lock_irqsave(&ioapic_lock, flags); | ||
871 | reg_01.raw = io_apic_read(apic, 1); | ||
872 | spin_unlock_irqrestore(&ioapic_lock, flags); | ||
873 | nr_ioapic_registers[apic] = reg_01.bits.entries+1; | ||
874 | } | ||
875 | 891 | ||
876 | for (apic = 0; apic < nr_ioapics; apic++) { | 892 | for (apic = 0; apic < nr_ioapics; apic++) { |
877 | early_ioapic_entries[apic] = | 893 | if (!ioapic_entries[apic]) |
878 | kzalloc(sizeof(struct IO_APIC_route_entry) * | 894 | return -ENOMEM; |
879 | nr_ioapic_registers[apic], GFP_KERNEL); | ||
880 | if (!early_ioapic_entries[apic]) | ||
881 | goto nomem; | ||
882 | } | ||
883 | 895 | ||
884 | for (apic = 0; apic < nr_ioapics; apic++) | ||
885 | for (pin = 0; pin < nr_ioapic_registers[apic]; pin++) | 896 | for (pin = 0; pin < nr_ioapic_registers[apic]; pin++) |
886 | early_ioapic_entries[apic][pin] = | 897 | ioapic_entries[apic][pin] = |
887 | ioapic_read_entry(apic, pin); | 898 | ioapic_read_entry(apic, pin); |
899 | } | ||
888 | 900 | ||
889 | return 0; | 901 | return 0; |
890 | |||
891 | nomem: | ||
892 | while (apic >= 0) | ||
893 | kfree(early_ioapic_entries[apic--]); | ||
894 | memset(early_ioapic_entries, 0, | ||
895 | ARRAY_SIZE(early_ioapic_entries)); | ||
896 | |||
897 | return -ENOMEM; | ||
898 | } | 902 | } |
899 | 903 | ||
900 | void mask_IO_APIC_setup(void) | 904 | /* |
905 | * Mask all IO APIC entries. | ||
906 | */ | ||
907 | void mask_IO_APIC_setup(struct IO_APIC_route_entry **ioapic_entries) | ||
901 | { | 908 | { |
902 | int apic, pin; | 909 | int apic, pin; |
903 | 910 | ||
911 | if (!ioapic_entries) | ||
912 | return; | ||
913 | |||
904 | for (apic = 0; apic < nr_ioapics; apic++) { | 914 | for (apic = 0; apic < nr_ioapics; apic++) { |
905 | if (!early_ioapic_entries[apic]) | 915 | if (!ioapic_entries[apic]) |
906 | break; | 916 | break; |
917 | |||
907 | for (pin = 0; pin < nr_ioapic_registers[apic]; pin++) { | 918 | for (pin = 0; pin < nr_ioapic_registers[apic]; pin++) { |
908 | struct IO_APIC_route_entry entry; | 919 | struct IO_APIC_route_entry entry; |
909 | 920 | ||
910 | entry = early_ioapic_entries[apic][pin]; | 921 | entry = ioapic_entries[apic][pin]; |
911 | if (!entry.mask) { | 922 | if (!entry.mask) { |
912 | entry.mask = 1; | 923 | entry.mask = 1; |
913 | ioapic_write_entry(apic, pin, entry); | 924 | ioapic_write_entry(apic, pin, entry); |
@@ -916,22 +927,30 @@ void mask_IO_APIC_setup(void) | |||
916 | } | 927 | } |
917 | } | 928 | } |
918 | 929 | ||
919 | void restore_IO_APIC_setup(void) | 930 | /* |
931 | * Restore IO APIC entries which was saved in ioapic_entries. | ||
932 | */ | ||
933 | int restore_IO_APIC_setup(struct IO_APIC_route_entry **ioapic_entries) | ||
920 | { | 934 | { |
921 | int apic, pin; | 935 | int apic, pin; |
922 | 936 | ||
937 | if (!ioapic_entries) | ||
938 | return -ENOMEM; | ||
939 | |||
923 | for (apic = 0; apic < nr_ioapics; apic++) { | 940 | for (apic = 0; apic < nr_ioapics; apic++) { |
924 | if (!early_ioapic_entries[apic]) | 941 | if (!ioapic_entries[apic]) |
925 | break; | 942 | return -ENOMEM; |
943 | |||
926 | for (pin = 0; pin < nr_ioapic_registers[apic]; pin++) | 944 | for (pin = 0; pin < nr_ioapic_registers[apic]; pin++) |
927 | ioapic_write_entry(apic, pin, | 945 | ioapic_write_entry(apic, pin, |
928 | early_ioapic_entries[apic][pin]); | 946 | ioapic_entries[apic][pin]); |
929 | kfree(early_ioapic_entries[apic]); | ||
930 | early_ioapic_entries[apic] = NULL; | ||
931 | } | 947 | } |
948 | return 0; | ||
932 | } | 949 | } |
933 | 950 | ||
934 | void reinit_intr_remapped_IO_APIC(int intr_remapping) | 951 | void reinit_intr_remapped_IO_APIC(int intr_remapping, |
952 | struct IO_APIC_route_entry **ioapic_entries) | ||
953 | |||
935 | { | 954 | { |
936 | /* | 955 | /* |
937 | * for now plain restore of previous settings. | 956 | * for now plain restore of previous settings. |
@@ -940,7 +959,17 @@ void reinit_intr_remapped_IO_APIC(int intr_remapping) | |||
940 | * table entries. for now, do a plain restore, and wait for | 959 | * table entries. for now, do a plain restore, and wait for |
941 | * the setup_IO_APIC_irqs() to do proper initialization. | 960 | * the setup_IO_APIC_irqs() to do proper initialization. |
942 | */ | 961 | */ |
943 | restore_IO_APIC_setup(); | 962 | restore_IO_APIC_setup(ioapic_entries); |
963 | } | ||
964 | |||
965 | void free_ioapic_entries(struct IO_APIC_route_entry **ioapic_entries) | ||
966 | { | ||
967 | int apic; | ||
968 | |||
969 | for (apic = 0; apic < nr_ioapics; apic++) | ||
970 | kfree(ioapic_entries[apic]); | ||
971 | |||
972 | kfree(ioapic_entries); | ||
944 | } | 973 | } |
945 | #endif | 974 | #endif |
946 | 975 | ||
@@ -2495,7 +2524,7 @@ static void irq_complete_move(struct irq_desc **descp) | |||
2495 | static inline void irq_complete_move(struct irq_desc **descp) {} | 2524 | static inline void irq_complete_move(struct irq_desc **descp) {} |
2496 | #endif | 2525 | #endif |
2497 | 2526 | ||
2498 | #ifdef CONFIG_INTR_REMAP | 2527 | #ifdef CONFIG_X86_X2APIC |
2499 | static void __eoi_ioapic_irq(unsigned int irq, struct irq_cfg *cfg) | 2528 | static void __eoi_ioapic_irq(unsigned int irq, struct irq_cfg *cfg) |
2500 | { | 2529 | { |
2501 | int apic, pin; | 2530 | int apic, pin; |
@@ -2540,7 +2569,6 @@ static void ack_x2apic_edge(unsigned int irq) | |||
2540 | { | 2569 | { |
2541 | ack_x2APIC_irq(); | 2570 | ack_x2APIC_irq(); |
2542 | } | 2571 | } |
2543 | |||
2544 | #endif | 2572 | #endif |
2545 | 2573 | ||
2546 | static void ack_apic_edge(unsigned int irq) | 2574 | static void ack_apic_edge(unsigned int irq) |
@@ -2651,6 +2679,26 @@ static void ack_apic_level(unsigned int irq) | |||
2651 | #endif | 2679 | #endif |
2652 | } | 2680 | } |
2653 | 2681 | ||
2682 | #ifdef CONFIG_INTR_REMAP | ||
2683 | static void ir_ack_apic_edge(unsigned int irq) | ||
2684 | { | ||
2685 | #ifdef CONFIG_X86_X2APIC | ||
2686 | if (x2apic_enabled()) | ||
2687 | return ack_x2apic_edge(irq); | ||
2688 | #endif | ||
2689 | return ack_apic_edge(irq); | ||
2690 | } | ||
2691 | |||
2692 | static void ir_ack_apic_level(unsigned int irq) | ||
2693 | { | ||
2694 | #ifdef CONFIG_X86_X2APIC | ||
2695 | if (x2apic_enabled()) | ||
2696 | return ack_x2apic_level(irq); | ||
2697 | #endif | ||
2698 | return ack_apic_level(irq); | ||
2699 | } | ||
2700 | #endif /* CONFIG_INTR_REMAP */ | ||
2701 | |||
2654 | static struct irq_chip ioapic_chip __read_mostly = { | 2702 | static struct irq_chip ioapic_chip __read_mostly = { |
2655 | .name = "IO-APIC", | 2703 | .name = "IO-APIC", |
2656 | .startup = startup_ioapic_irq, | 2704 | .startup = startup_ioapic_irq, |
@@ -2670,8 +2718,8 @@ static struct irq_chip ir_ioapic_chip __read_mostly = { | |||
2670 | .mask = mask_IO_APIC_irq, | 2718 | .mask = mask_IO_APIC_irq, |
2671 | .unmask = unmask_IO_APIC_irq, | 2719 | .unmask = unmask_IO_APIC_irq, |
2672 | #ifdef CONFIG_INTR_REMAP | 2720 | #ifdef CONFIG_INTR_REMAP |
2673 | .ack = ack_x2apic_edge, | 2721 | .ack = ir_ack_apic_edge, |
2674 | .eoi = ack_x2apic_level, | 2722 | .eoi = ir_ack_apic_level, |
2675 | #ifdef CONFIG_SMP | 2723 | #ifdef CONFIG_SMP |
2676 | .set_affinity = set_ir_ioapic_affinity_irq, | 2724 | .set_affinity = set_ir_ioapic_affinity_irq, |
2677 | #endif | 2725 | #endif |
@@ -3397,7 +3445,7 @@ static struct irq_chip msi_ir_chip = { | |||
3397 | .unmask = unmask_msi_irq, | 3445 | .unmask = unmask_msi_irq, |
3398 | .mask = mask_msi_irq, | 3446 | .mask = mask_msi_irq, |
3399 | #ifdef CONFIG_INTR_REMAP | 3447 | #ifdef CONFIG_INTR_REMAP |
3400 | .ack = ack_x2apic_edge, | 3448 | .ack = ir_ack_apic_edge, |
3401 | #ifdef CONFIG_SMP | 3449 | #ifdef CONFIG_SMP |
3402 | .set_affinity = ir_set_msi_irq_affinity, | 3450 | .set_affinity = ir_set_msi_irq_affinity, |
3403 | #endif | 3451 | #endif |