From 1e4c85f97fe26fbd70da12148b3992c0e00361fd Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Mon, 31 Oct 2005 19:16:17 -0800 Subject: Revert "i386: move apic init in init_IRQs" Commit f2b36db692b7ff6972320ad9839ae656a3b0ee3e causes a bootup hang on at least one machine. Revert for now until we understand why. The old code may be ugly, but it works. Signed-off-by: Linus Torvalds diff --git a/arch/i386/kernel/apic.c b/arch/i386/kernel/apic.c index 9204be6..7c724ff 100644 --- a/arch/i386/kernel/apic.c +++ b/arch/i386/kernel/apic.c @@ -803,7 +803,6 @@ no_apic: void __init init_apic_mappings(void) { - unsigned int orig_apicid; unsigned long apic_phys; /* @@ -825,11 +824,8 @@ void __init init_apic_mappings(void) * Fetch the APIC ID of the BSP in case we have a * default configuration (or the MP table is broken). */ - orig_apicid = boot_cpu_physical_apicid; - boot_cpu_physical_apicid = GET_APIC_ID(apic_read(APIC_ID)); - if ((orig_apicid != -1U) && (orig_apicid != boot_cpu_physical_apicid)) - printk(KERN_WARNING "Boot APIC ID in local APIC unexpected (%d vs %d)", - orig_apicid, boot_cpu_physical_apicid); + if (boot_cpu_physical_apicid == -1U) + boot_cpu_physical_apicid = GET_APIC_ID(apic_read(APIC_ID)); #ifdef CONFIG_X86_IO_APIC { @@ -1259,81 +1255,40 @@ fastcall void smp_error_interrupt(struct pt_regs *regs) } /* - * This initializes the IO-APIC and APIC hardware. + * This initializes the IO-APIC and APIC hardware if this is + * a UP kernel. */ -int __init APIC_init(void) +int __init APIC_init_uniprocessor (void) { - if (enable_local_apic < 0) { - printk(KERN_INFO "APIC disabled\n"); - return -1; - } + if (enable_local_apic < 0) + clear_bit(X86_FEATURE_APIC, boot_cpu_data.x86_capability); - /* See if we have a SMP configuration or have forced enabled - * the local apic. - */ - if (!smp_found_config && !acpi_lapic && !cpu_has_apic) { - enable_local_apic = -1; + if (!smp_found_config && !cpu_has_apic) return -1; - } /* - * Complain if the BIOS pretends there is an apic. - * Then get out because we don't have an a local apic. + * Complain if the BIOS pretends there is one. */ if (!cpu_has_apic && APIC_INTEGRATED(apic_version[boot_cpu_physical_apicid])) { printk(KERN_ERR "BIOS bug, local APIC #%d not detected!...\n", boot_cpu_physical_apicid); - printk(KERN_ERR "... forcing use of dummy APIC emulation. (tell your hw vendor)\n"); - enable_local_apic = -1; return -1; } verify_local_APIC(); - /* - * Should not be necessary because the MP table should list the boot - * CPU too, but we do it for the sake of robustness anyway. - * Makes no sense to do this check in clustered apic mode, so skip it - */ - if (!check_phys_apicid_present(boot_cpu_physical_apicid)) { - printk("weird, boot CPU (#%d) not listed by the BIOS.\n", - boot_cpu_physical_apicid); - physid_set(boot_cpu_physical_apicid, phys_cpu_present_map); - } - - /* - * Switch from PIC to APIC mode. - */ connect_bsp_APIC(); - setup_local_APIC(); -#ifdef CONFIG_X86_IO_APIC - /* - * Now start the IO-APICs - */ - if (smp_found_config && !skip_ioapic_setup && nr_ioapics) - setup_IO_APIC(); -#endif - return 0; -} + phys_cpu_present_map = physid_mask_of_physid(boot_cpu_physical_apicid); -void __init APIC_late_time_init(void) -{ - /* Improve our loops per jiffy estimate */ - loops_per_jiffy = ((1000 + HZ - 1)/HZ)*cpu_khz; - boot_cpu_data.loops_per_jiffy = loops_per_jiffy; - cpu_data[0].loops_per_jiffy = loops_per_jiffy; - - /* setup_apic_nmi_watchdog doesn't work properly before cpu_khz is - * initialized. So redo it here to ensure the boot cpu is setup - * properly. - */ - if (nmi_watchdog == NMI_LOCAL_APIC) - setup_apic_nmi_watchdog(); + setup_local_APIC(); #ifdef CONFIG_X86_IO_APIC - if (smp_found_config && !skip_ioapic_setup && nr_ioapics) - IO_APIC_late_time_init(); + if (smp_found_config) + if (!skip_ioapic_setup && nr_ioapics) + setup_IO_APIC(); #endif setup_boot_APIC_clock(); + + return 0; } diff --git a/arch/i386/kernel/i8259.c b/arch/i386/kernel/i8259.c index d86f249..323ef8a 100644 --- a/arch/i386/kernel/i8259.c +++ b/arch/i386/kernel/i8259.c @@ -435,8 +435,4 @@ void __init init_IRQ(void) setup_irq(FPU_IRQ, &fpu_irq); irq_ctx_init(smp_processor_id()); - -#ifdef CONFIG_X86_LOCAL_APIC - APIC_init(); -#endif } diff --git a/arch/i386/kernel/io_apic.c b/arch/i386/kernel/io_apic.c index 5a77c52..cc5d7ac 100644 --- a/arch/i386/kernel/io_apic.c +++ b/arch/i386/kernel/io_apic.c @@ -2387,15 +2387,11 @@ void __init setup_IO_APIC(void) sync_Arb_IDs(); setup_IO_APIC_irqs(); init_IO_APIC_traps(); + check_timer(); if (!acpi_ioapic) print_IO_APIC(); } -void __init IO_APIC_late_time_init(void) -{ - check_timer(); -} - /* * Called after all the initialization is done. If we didnt find any * APIC bugs then we can allow the modify fast path diff --git a/arch/i386/kernel/smpboot.c b/arch/i386/kernel/smpboot.c index 5a2bbe0..01b618e 100644 --- a/arch/i386/kernel/smpboot.c +++ b/arch/i386/kernel/smpboot.c @@ -1078,16 +1078,6 @@ void *xquad_portio; EXPORT_SYMBOL(xquad_portio); #endif -/* - * Fall back to non SMP mode after errors. - * - */ -static __init void disable_smp(void) -{ - cpu_set(0, cpu_sibling_map[0]); - cpu_set(0, cpu_core_map[0]); -} - static void __init smp_boot_cpus(unsigned int max_cpus) { int apicid, cpu, bit, kicked; @@ -1100,6 +1090,7 @@ static void __init smp_boot_cpus(unsigned int max_cpus) printk("CPU%d: ", 0); print_cpu_info(&cpu_data[0]); + boot_cpu_physical_apicid = GET_APIC_ID(apic_read(APIC_ID)); boot_cpu_logical_apicid = logical_smp_processor_id(); x86_cpu_to_apicid[0] = boot_cpu_physical_apicid; @@ -1111,27 +1102,68 @@ static void __init smp_boot_cpus(unsigned int max_cpus) cpus_clear(cpu_core_map[0]); cpu_set(0, cpu_core_map[0]); - map_cpu_to_logical_apicid(); - /* * If we couldn't find an SMP configuration at boot time, * get out of here now! */ if (!smp_found_config && !acpi_lapic) { printk(KERN_NOTICE "SMP motherboard not detected.\n"); - disable_smp(); + smpboot_clear_io_apic_irqs(); + phys_cpu_present_map = physid_mask_of_physid(0); + if (APIC_init_uniprocessor()) + printk(KERN_NOTICE "Local APIC not detected." + " Using dummy APIC emulation.\n"); + map_cpu_to_logical_apicid(); + cpu_set(0, cpu_sibling_map[0]); + cpu_set(0, cpu_core_map[0]); + return; + } + + /* + * Should not be necessary because the MP table should list the boot + * CPU too, but we do it for the sake of robustness anyway. + * Makes no sense to do this check in clustered apic mode, so skip it + */ + if (!check_phys_apicid_present(boot_cpu_physical_apicid)) { + printk("weird, boot CPU (#%d) not listed by the BIOS.\n", + boot_cpu_physical_apicid); + physid_set(hard_smp_processor_id(), phys_cpu_present_map); + } + + /* + * If we couldn't find a local APIC, then get out of here now! + */ + if (APIC_INTEGRATED(apic_version[boot_cpu_physical_apicid]) && !cpu_has_apic) { + printk(KERN_ERR "BIOS bug, local APIC #%d not detected!...\n", + boot_cpu_physical_apicid); + printk(KERN_ERR "... forcing use of dummy APIC emulation. (tell your hw vendor)\n"); + smpboot_clear_io_apic_irqs(); + phys_cpu_present_map = physid_mask_of_physid(0); + cpu_set(0, cpu_sibling_map[0]); + cpu_set(0, cpu_core_map[0]); return; } + verify_local_APIC(); + /* * If SMP should be disabled, then really disable it! */ - if (!max_cpus || (enable_local_apic < 0)) { - printk(KERN_INFO "SMP mode deactivated.\n"); - disable_smp(); + if (!max_cpus) { + smp_found_config = 0; + printk(KERN_INFO "SMP mode deactivated, forcing use of dummy APIC emulation.\n"); + smpboot_clear_io_apic_irqs(); + phys_cpu_present_map = physid_mask_of_physid(0); + cpu_set(0, cpu_sibling_map[0]); + cpu_set(0, cpu_core_map[0]); return; } + connect_bsp_APIC(); + setup_local_APIC(); + map_cpu_to_logical_apicid(); + + setup_portio_remap(); /* @@ -1212,6 +1244,10 @@ static void __init smp_boot_cpus(unsigned int max_cpus) cpu_set(0, cpu_sibling_map[0]); cpu_set(0, cpu_core_map[0]); + smpboot_setup_io_apic(); + + setup_boot_APIC_clock(); + /* * Synchronize the TSC with the AP */ diff --git a/arch/i386/kernel/time.c b/arch/i386/kernel/time.c index 07471bb..41c5b2d 100644 --- a/arch/i386/kernel/time.c +++ b/arch/i386/kernel/time.c @@ -440,8 +440,8 @@ static int time_init_device(void) device_initcall(time_init_device); -extern void (*late_time_init)(void); #ifdef CONFIG_HPET_TIMER +extern void (*late_time_init)(void); /* Duplicate of time_init() below, with hpet_enable part added */ static void __init hpet_time_init(void) { @@ -458,11 +458,6 @@ static void __init hpet_time_init(void) printk(KERN_INFO "Using %s for high-res timesource\n",cur_timer->name); time_init_hook(); - -#ifdef CONFIG_X86_LOCAL_APIC - if (enable_local_apic >= 0) - APIC_late_time_init(); -#endif } #endif @@ -487,9 +482,4 @@ void __init time_init(void) printk(KERN_INFO "Using %s for high-res timesource\n",cur_timer->name); time_init_hook(); - -#ifdef CONFIG_X86_LOCAL_APIC - if (enable_local_apic >= 0) - late_time_init = APIC_late_time_init; -#endif } diff --git a/include/asm-i386/apic.h b/include/asm-i386/apic.h index a515e2a..8c454aa 100644 --- a/include/asm-i386/apic.h +++ b/include/asm-i386/apic.h @@ -118,8 +118,7 @@ extern void release_lapic_nmi(void); extern void disable_timer_nmi_watchdog(void); extern void enable_timer_nmi_watchdog(void); extern void nmi_watchdog_tick (struct pt_regs * regs); -extern int APIC_init(void); -extern void APIC_late_time_init(void); +extern int APIC_init_uniprocessor (void); extern void disable_APIC_timer(void); extern void enable_APIC_timer(void); diff --git a/include/asm-i386/hw_irq.h b/include/asm-i386/hw_irq.h index 9139b89..622815b 100644 --- a/include/asm-i386/hw_irq.h +++ b/include/asm-i386/hw_irq.h @@ -55,7 +55,6 @@ void init_8259A(int aeoi); void FASTCALL(send_IPI_self(int vector)); void init_VISWS_APIC_irqs(void); void setup_IO_APIC(void); -void IO_APIC_late_time_init(void); void disable_IO_APIC(void); void print_IO_APIC(void); int IO_APIC_get_PCI_irq_vector(int bus, int slot, int fn); diff --git a/include/asm-i386/mach-default/smpboot_hooks.h b/include/asm-i386/mach-default/smpboot_hooks.h index d7c70c1..7f45f63 100644 --- a/include/asm-i386/mach-default/smpboot_hooks.h +++ b/include/asm-i386/mach-default/smpboot_hooks.h @@ -1,6 +1,11 @@ /* two abstractions specific to kernel/smpboot.c, mainly to cater to visws * which needs to alter them. */ +static inline void smpboot_clear_io_apic_irqs(void) +{ + io_apic_irqs = 0; +} + static inline void smpboot_setup_warm_reset_vector(unsigned long start_eip) { CMOS_WRITE(0xa, 0xf); @@ -27,3 +32,13 @@ static inline void smpboot_restore_warm_reset_vector(void) *((volatile long *) phys_to_virt(0x467)) = 0; } + +static inline void smpboot_setup_io_apic(void) +{ + /* + * Here we can be sure that there is an IO-APIC in the system. Let's + * go and set it up: + */ + if (!skip_ioapic_setup && nr_ioapics) + setup_IO_APIC(); +} diff --git a/include/asm-i386/mach-visws/smpboot_hooks.h b/include/asm-i386/mach-visws/smpboot_hooks.h index 14d8e03..d926471 100644 --- a/include/asm-i386/mach-visws/smpboot_hooks.h +++ b/include/asm-i386/mach-visws/smpboot_hooks.h @@ -11,7 +11,14 @@ static inline void smpboot_setup_warm_reset_vector(unsigned long start_eip) /* for visws do nothing for any of these */ +static inline void smpboot_clear_io_apic_irqs(void) +{ +} + static inline void smpboot_restore_warm_reset_vector(void) { } +static inline void smpboot_setup_io_apic(void) +{ +} diff --git a/init/main.c b/init/main.c index 4075d97..f142d40 100644 --- a/init/main.c +++ b/init/main.c @@ -64,6 +64,10 @@ #endif #endif +#ifdef CONFIG_X86_LOCAL_APIC +#include +#endif + /* * Versions of gcc older than that listed below may actually compile * and link okay, but the end product can have subtle run time bugs. @@ -310,7 +314,14 @@ extern void setup_arch(char **); #ifndef CONFIG_SMP +#ifdef CONFIG_X86_LOCAL_APIC +static void __init smp_init(void) +{ + APIC_init_uniprocessor(); +} +#else #define smp_init() do { } while (0) +#endif static inline void setup_per_cpu_areas(void) { } static inline void smp_prepare_cpus(unsigned int maxcpus) { } -- cgit v0.10.2