diff options
author | Yinghai Lu <yinghai@kernel.org> | 2009-02-08 19:18:03 -0500 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2009-02-09 03:21:29 -0500 |
commit | f72dccace737df74d04a96461785a3ad61724b9f (patch) | |
tree | c5abe37e1746cce2e1675bc58f7a66dc175fb6bb | |
parent | abcaa2b8319a7673e76c2391cb5de3045ab1b401 (diff) |
x86: check_timer cleanup
Impact: make check-timer more robust potentially solve boot fragility
For edge trigger io-apic routing, we already unmasked the pin via
setup_IO_APIC_irq(), so don't unmask it again.
Also call local_irq_disable() between timer_irq_works(), because it
calls local_irq_enable() inside.
Also remove not needed apic version reading for 64-bit
Signed-off-by: Yinghai Lu <yinghai@kernel.org>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
-rw-r--r-- | arch/x86/kernel/io_apic.c | 30 |
1 files changed, 22 insertions, 8 deletions
diff --git a/arch/x86/kernel/io_apic.c b/arch/x86/kernel/io_apic.c index e5be9f35ea54..855209a1b172 100644 --- a/arch/x86/kernel/io_apic.c +++ b/arch/x86/kernel/io_apic.c | |||
@@ -1657,7 +1657,7 @@ static void __init setup_timer_IRQ0_pin(unsigned int apic_id, unsigned int pin, | |||
1657 | * to the first CPU. | 1657 | * to the first CPU. |
1658 | */ | 1658 | */ |
1659 | entry.dest_mode = apic->irq_dest_mode; | 1659 | entry.dest_mode = apic->irq_dest_mode; |
1660 | entry.mask = 1; /* mask IRQ now */ | 1660 | entry.mask = 0; /* don't mask IRQ for edge */ |
1661 | entry.dest = apic->cpu_mask_to_apicid(apic->target_cpus()); | 1661 | entry.dest = apic->cpu_mask_to_apicid(apic->target_cpus()); |
1662 | entry.delivery_mode = apic->irq_delivery_mode; | 1662 | entry.delivery_mode = apic->irq_delivery_mode; |
1663 | entry.polarity = 0; | 1663 | entry.polarity = 0; |
@@ -2863,14 +2863,10 @@ static inline void __init check_timer(void) | |||
2863 | int cpu = boot_cpu_id; | 2863 | int cpu = boot_cpu_id; |
2864 | int apic1, pin1, apic2, pin2; | 2864 | int apic1, pin1, apic2, pin2; |
2865 | unsigned long flags; | 2865 | unsigned long flags; |
2866 | unsigned int ver; | ||
2867 | int no_pin1 = 0; | 2866 | int no_pin1 = 0; |
2868 | 2867 | ||
2869 | local_irq_save(flags); | 2868 | local_irq_save(flags); |
2870 | 2869 | ||
2871 | ver = apic_read(APIC_LVR); | ||
2872 | ver = GET_APIC_VERSION(ver); | ||
2873 | |||
2874 | /* | 2870 | /* |
2875 | * get/set the timer IRQ vector: | 2871 | * get/set the timer IRQ vector: |
2876 | */ | 2872 | */ |
@@ -2889,7 +2885,13 @@ static inline void __init check_timer(void) | |||
2889 | apic_write(APIC_LVT0, APIC_LVT_MASKED | APIC_DM_EXTINT); | 2885 | apic_write(APIC_LVT0, APIC_LVT_MASKED | APIC_DM_EXTINT); |
2890 | init_8259A(1); | 2886 | init_8259A(1); |
2891 | #ifdef CONFIG_X86_32 | 2887 | #ifdef CONFIG_X86_32 |
2892 | timer_ack = (nmi_watchdog == NMI_IO_APIC && !APIC_INTEGRATED(ver)); | 2888 | { |
2889 | unsigned int ver; | ||
2890 | |||
2891 | ver = apic_read(APIC_LVR); | ||
2892 | ver = GET_APIC_VERSION(ver); | ||
2893 | timer_ack = (nmi_watchdog == NMI_IO_APIC && !APIC_INTEGRATED(ver)); | ||
2894 | } | ||
2893 | #endif | 2895 | #endif |
2894 | 2896 | ||
2895 | pin1 = find_isa_irq_pin(0, mp_INT); | 2897 | pin1 = find_isa_irq_pin(0, mp_INT); |
@@ -2928,8 +2930,17 @@ static inline void __init check_timer(void) | |||
2928 | if (no_pin1) { | 2930 | if (no_pin1) { |
2929 | add_pin_to_irq_cpu(cfg, cpu, apic1, pin1); | 2931 | add_pin_to_irq_cpu(cfg, cpu, apic1, pin1); |
2930 | setup_timer_IRQ0_pin(apic1, pin1, cfg->vector); | 2932 | setup_timer_IRQ0_pin(apic1, pin1, cfg->vector); |
2933 | } else { | ||
2934 | /* for edge trigger, setup_IO_APIC_irq already | ||
2935 | * leave it unmasked. | ||
2936 | * so only need to unmask if it is level-trigger | ||
2937 | * do we really have level trigger timer? | ||
2938 | */ | ||
2939 | int idx; | ||
2940 | idx = find_irq_entry(apic1, pin1, mp_INT); | ||
2941 | if (idx != -1 && irq_trigger(idx)) | ||
2942 | unmask_IO_APIC_irq_desc(desc); | ||
2931 | } | 2943 | } |
2932 | unmask_IO_APIC_irq_desc(desc); | ||
2933 | if (timer_irq_works()) { | 2944 | if (timer_irq_works()) { |
2934 | if (nmi_watchdog == NMI_IO_APIC) { | 2945 | if (nmi_watchdog == NMI_IO_APIC) { |
2935 | setup_nmi(); | 2946 | setup_nmi(); |
@@ -2943,6 +2954,7 @@ static inline void __init check_timer(void) | |||
2943 | if (intr_remapping_enabled) | 2954 | if (intr_remapping_enabled) |
2944 | panic("timer doesn't work through Interrupt-remapped IO-APIC"); | 2955 | panic("timer doesn't work through Interrupt-remapped IO-APIC"); |
2945 | #endif | 2956 | #endif |
2957 | local_irq_disable(); | ||
2946 | clear_IO_APIC_pin(apic1, pin1); | 2958 | clear_IO_APIC_pin(apic1, pin1); |
2947 | if (!no_pin1) | 2959 | if (!no_pin1) |
2948 | apic_printk(APIC_QUIET, KERN_ERR "..MP-BIOS bug: " | 2960 | apic_printk(APIC_QUIET, KERN_ERR "..MP-BIOS bug: " |
@@ -2957,7 +2969,6 @@ static inline void __init check_timer(void) | |||
2957 | */ | 2969 | */ |
2958 | replace_pin_at_irq_cpu(cfg, cpu, apic1, pin1, apic2, pin2); | 2970 | replace_pin_at_irq_cpu(cfg, cpu, apic1, pin1, apic2, pin2); |
2959 | setup_timer_IRQ0_pin(apic2, pin2, cfg->vector); | 2971 | setup_timer_IRQ0_pin(apic2, pin2, cfg->vector); |
2960 | unmask_IO_APIC_irq_desc(desc); | ||
2961 | enable_8259A_irq(0); | 2972 | enable_8259A_irq(0); |
2962 | if (timer_irq_works()) { | 2973 | if (timer_irq_works()) { |
2963 | apic_printk(APIC_QUIET, KERN_INFO "....... works.\n"); | 2974 | apic_printk(APIC_QUIET, KERN_INFO "....... works.\n"); |
@@ -2972,6 +2983,7 @@ static inline void __init check_timer(void) | |||
2972 | /* | 2983 | /* |
2973 | * Cleanup, just in case ... | 2984 | * Cleanup, just in case ... |
2974 | */ | 2985 | */ |
2986 | local_irq_disable(); | ||
2975 | disable_8259A_irq(0); | 2987 | disable_8259A_irq(0); |
2976 | clear_IO_APIC_pin(apic2, pin2); | 2988 | clear_IO_APIC_pin(apic2, pin2); |
2977 | apic_printk(APIC_QUIET, KERN_INFO "....... failed.\n"); | 2989 | apic_printk(APIC_QUIET, KERN_INFO "....... failed.\n"); |
@@ -2997,6 +3009,7 @@ static inline void __init check_timer(void) | |||
2997 | apic_printk(APIC_QUIET, KERN_INFO "..... works.\n"); | 3009 | apic_printk(APIC_QUIET, KERN_INFO "..... works.\n"); |
2998 | goto out; | 3010 | goto out; |
2999 | } | 3011 | } |
3012 | local_irq_disable(); | ||
3000 | disable_8259A_irq(0); | 3013 | disable_8259A_irq(0); |
3001 | apic_write(APIC_LVT0, APIC_LVT_MASKED | APIC_DM_FIXED | cfg->vector); | 3014 | apic_write(APIC_LVT0, APIC_LVT_MASKED | APIC_DM_FIXED | cfg->vector); |
3002 | apic_printk(APIC_QUIET, KERN_INFO "..... failed.\n"); | 3015 | apic_printk(APIC_QUIET, KERN_INFO "..... failed.\n"); |
@@ -3014,6 +3027,7 @@ static inline void __init check_timer(void) | |||
3014 | apic_printk(APIC_QUIET, KERN_INFO "..... works.\n"); | 3027 | apic_printk(APIC_QUIET, KERN_INFO "..... works.\n"); |
3015 | goto out; | 3028 | goto out; |
3016 | } | 3029 | } |
3030 | local_irq_disable(); | ||
3017 | apic_printk(APIC_QUIET, KERN_INFO "..... failed :(.\n"); | 3031 | apic_printk(APIC_QUIET, KERN_INFO "..... failed :(.\n"); |
3018 | panic("IO-APIC + timer doesn't work! Boot with apic=debug and send a " | 3032 | panic("IO-APIC + timer doesn't work! Boot with apic=debug and send a " |
3019 | "report. Then try booting with the 'noapic' option.\n"); | 3033 | "report. Then try booting with the 'noapic' option.\n"); |