aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorYinghai Lu <yinghai@kernel.org>2009-02-08 19:18:03 -0500
committerIngo Molnar <mingo@elte.hu>2009-02-09 03:21:29 -0500
commitf72dccace737df74d04a96461785a3ad61724b9f (patch)
treec5abe37e1746cce2e1675bc58f7a66dc175fb6bb
parentabcaa2b8319a7673e76c2391cb5de3045ab1b401 (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.c30
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");