Browse Source

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 <torvalds@osdl.org>
Linus Torvalds 19 years ago
parent
commit
1e4c85f97f

+ 16 - 61
arch/i386/kernel/apic.c

@@ -803,7 +803,6 @@ no_apic:
 
 
 void __init init_apic_mappings(void)
 void __init init_apic_mappings(void)
 {
 {
-	unsigned int orig_apicid;
 	unsigned long apic_phys;
 	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
 	 * Fetch the APIC ID of the BSP in case we have a
 	 * default configuration (or the MP table is broken).
 	 * 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
 #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;
 		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])) {
 	if (!cpu_has_apic && APIC_INTEGRATED(apic_version[boot_cpu_physical_apicid])) {
 		printk(KERN_ERR "BIOS bug, local APIC #%d not detected!...\n",
 		printk(KERN_ERR "BIOS bug, local APIC #%d not detected!...\n",
 			boot_cpu_physical_apicid);
 			boot_cpu_physical_apicid);
-		printk(KERN_ERR "... forcing use of dummy APIC emulation. (tell your hw vendor)\n");
-		enable_local_apic = -1;
 		return -1;
 		return -1;
 	}
 	}
 
 
 	verify_local_APIC();
 	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();
 	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
 #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
 #endif
 	setup_boot_APIC_clock();
 	setup_boot_APIC_clock();
+
+	return 0;
 }
 }

+ 0 - 4
arch/i386/kernel/i8259.c

@@ -435,8 +435,4 @@ void __init init_IRQ(void)
 		setup_irq(FPU_IRQ, &fpu_irq);
 		setup_irq(FPU_IRQ, &fpu_irq);
 
 
 	irq_ctx_init(smp_processor_id());
 	irq_ctx_init(smp_processor_id());
-
-#ifdef CONFIG_X86_LOCAL_APIC
-	APIC_init();
-#endif
 }
 }

+ 1 - 5
arch/i386/kernel/io_apic.c

@@ -2387,15 +2387,11 @@ void __init setup_IO_APIC(void)
 	sync_Arb_IDs();
 	sync_Arb_IDs();
 	setup_IO_APIC_irqs();
 	setup_IO_APIC_irqs();
 	init_IO_APIC_traps();
 	init_IO_APIC_traps();
+	check_timer();
 	if (!acpi_ioapic)
 	if (!acpi_ioapic)
 		print_IO_APIC();
 		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
  *	Called after all the initialization is done. If we didnt find any
  *	APIC bugs then we can allow the modify fast path
  *	APIC bugs then we can allow the modify fast path

+ 52 - 16
arch/i386/kernel/smpboot.c

@@ -1078,16 +1078,6 @@ void *xquad_portio;
 EXPORT_SYMBOL(xquad_portio);
 EXPORT_SYMBOL(xquad_portio);
 #endif
 #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)
 static void __init smp_boot_cpus(unsigned int max_cpus)
 {
 {
 	int apicid, cpu, bit, kicked;
 	int apicid, cpu, bit, kicked;
@@ -1100,6 +1090,7 @@ static void __init smp_boot_cpus(unsigned int max_cpus)
 	printk("CPU%d: ", 0);
 	printk("CPU%d: ", 0);
 	print_cpu_info(&cpu_data[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();
 	boot_cpu_logical_apicid = logical_smp_processor_id();
 	x86_cpu_to_apicid[0] = boot_cpu_physical_apicid;
 	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]);
 	cpus_clear(cpu_core_map[0]);
 	cpu_set(0, 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,
 	 * If we couldn't find an SMP configuration at boot time,
 	 * get out of here now!
 	 * get out of here now!
 	 */
 	 */
 	if (!smp_found_config && !acpi_lapic) {
 	if (!smp_found_config && !acpi_lapic) {
 		printk(KERN_NOTICE "SMP motherboard not detected.\n");
 		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;
 		return;
 	}
 	}
 
 
+	verify_local_APIC();
+
 	/*
 	/*
 	 * If SMP should be disabled, then really disable it!
 	 * 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;
 		return;
 	}
 	}
 
 
+	connect_bsp_APIC();
+	setup_local_APIC();
+	map_cpu_to_logical_apicid();
+
+
 	setup_portio_remap();
 	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_sibling_map[0]);
 	cpu_set(0, cpu_core_map[0]);
 	cpu_set(0, cpu_core_map[0]);
 
 
+	smpboot_setup_io_apic();
+
+	setup_boot_APIC_clock();
+
 	/*
 	/*
 	 * Synchronize the TSC with the AP
 	 * Synchronize the TSC with the AP
 	 */
 	 */

+ 1 - 11
arch/i386/kernel/time.c

@@ -440,8 +440,8 @@ static int time_init_device(void)
 
 
 device_initcall(time_init_device);
 device_initcall(time_init_device);
 
 
-extern void (*late_time_init)(void);
 #ifdef CONFIG_HPET_TIMER
 #ifdef CONFIG_HPET_TIMER
+extern void (*late_time_init)(void);
 /* Duplicate of time_init() below, with hpet_enable part added */
 /* Duplicate of time_init() below, with hpet_enable part added */
 static void __init hpet_time_init(void)
 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);
 	printk(KERN_INFO "Using %s for high-res timesource\n",cur_timer->name);
 
 
 	time_init_hook();
 	time_init_hook();
-
-#ifdef CONFIG_X86_LOCAL_APIC
-	if (enable_local_apic >= 0)
-		APIC_late_time_init();
-#endif
 }
 }
 #endif
 #endif
 
 
@@ -487,9 +482,4 @@ void __init time_init(void)
 	printk(KERN_INFO "Using %s for high-res timesource\n",cur_timer->name);
 	printk(KERN_INFO "Using %s for high-res timesource\n",cur_timer->name);
 
 
 	time_init_hook();
 	time_init_hook();
-
-#ifdef CONFIG_X86_LOCAL_APIC
-	if (enable_local_apic >= 0)
-		late_time_init = APIC_late_time_init;
-#endif
 }
 }

+ 1 - 2
include/asm-i386/apic.h

@@ -118,8 +118,7 @@ extern void release_lapic_nmi(void);
 extern void disable_timer_nmi_watchdog(void);
 extern void disable_timer_nmi_watchdog(void);
 extern void enable_timer_nmi_watchdog(void);
 extern void enable_timer_nmi_watchdog(void);
 extern void nmi_watchdog_tick (struct pt_regs * regs);
 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 disable_APIC_timer(void);
 extern void enable_APIC_timer(void);
 extern void enable_APIC_timer(void);
 
 

+ 0 - 1
include/asm-i386/hw_irq.h

@@ -55,7 +55,6 @@ void init_8259A(int aeoi);
 void FASTCALL(send_IPI_self(int vector));
 void FASTCALL(send_IPI_self(int vector));
 void init_VISWS_APIC_irqs(void);
 void init_VISWS_APIC_irqs(void);
 void setup_IO_APIC(void);
 void setup_IO_APIC(void);
-void IO_APIC_late_time_init(void);
 void disable_IO_APIC(void);
 void disable_IO_APIC(void);
 void print_IO_APIC(void);
 void print_IO_APIC(void);
 int IO_APIC_get_PCI_irq_vector(int bus, int slot, int fn);
 int IO_APIC_get_PCI_irq_vector(int bus, int slot, int fn);

+ 15 - 0
include/asm-i386/mach-default/smpboot_hooks.h

@@ -1,6 +1,11 @@
 /* two abstractions specific to kernel/smpboot.c, mainly to cater to visws
 /* two abstractions specific to kernel/smpboot.c, mainly to cater to visws
  * which needs to alter them. */
  * 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)
 static inline void smpboot_setup_warm_reset_vector(unsigned long start_eip)
 {
 {
 	CMOS_WRITE(0xa, 0xf);
 	CMOS_WRITE(0xa, 0xf);
@@ -27,3 +32,13 @@ static inline void smpboot_restore_warm_reset_vector(void)
 
 
 	*((volatile long *) phys_to_virt(0x467)) = 0;
 	*((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();
+}

+ 7 - 0
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 */
 /* 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_restore_warm_reset_vector(void)
 {
 {
 }
 }
 
 
+static inline void smpboot_setup_io_apic(void)
+{
+}

+ 11 - 0
init/main.c

@@ -64,6 +64,10 @@
 #endif
 #endif
 #endif
 #endif
 
 
+#ifdef CONFIG_X86_LOCAL_APIC
+#include <asm/smp.h>
+#endif
+
 /*
 /*
  * Versions of gcc older than that listed below may actually compile
  * Versions of gcc older than that listed below may actually compile
  * and link okay, but the end product can have subtle run time bugs.
  * 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
 #ifndef CONFIG_SMP
 
 
+#ifdef CONFIG_X86_LOCAL_APIC
+static void __init smp_init(void)
+{
+	APIC_init_uniprocessor();
+}
+#else
 #define smp_init()	do { } while (0)
 #define smp_init()	do { } while (0)
+#endif
 
 
 static inline void setup_per_cpu_areas(void) { }
 static inline void setup_per_cpu_areas(void) { }
 static inline void smp_prepare_cpus(unsigned int maxcpus) { }
 static inline void smp_prepare_cpus(unsigned int maxcpus) { }