Skip to contentSkip to conversation

2.5.29 NUMA-Q minimal workaround updates

PATCH William Lee Irwin III 1 participant 1 message Jul 28, 2002

Subsystems (3)
lore
Share & tools
lore
#0 lore raw

This is my latest set of combined workarounds and fixes to get my machines to boot. Without them, booting is impossible. These are the "minimalistic" ones for easy porting, but unfortunately new and serious issues have been introduced (addressed by the "hotplug fixes" and the do_IRQ() fix), so they're a wee bit more heavyweight than I'd like. If there are better equivalents (as there are for the xquad_portio stuff and balance_irq() stuff) then please push them instead. I've tried to note the ones where superior methods of dealing with the issues exist in the changelog below. One issue not addressed by this patch is the overflow of zone->zone_start_paddr with fix from Pat Gaughen pending.

Zwane, I've cc:'d you as you appear to have a strong interest in APIC manipulation code. Martin, you're the NUMA-Q maintainer. =) Pat, you've got pending fixes and arch support you're working on that may hit this stuff later on in boot. Matt, one of your patches is the "superior method of dealing with the issue" mentioned in the description of the patch component.

Ingo, Rusty, & Russell, you're included so whatever objections you might have to your fixes being bundled here may be voiced.

This has successfully compiled, booted, and run 2.5.29 on elm3b17 (16 cpus, 16GB RAM NUMA-Q) in combination testing with some stealth patches I'm working on. Expect offsets and/or fuzz.

Many thanks to Ingo Molnar, Rusty Russell, and Russell King for their rapid responses to bugreports and quick fixing of the bugs in this release.

This patch is left monolithic as the "real fixes" I myself (among others) would like to have merged are still pending. Linus, please *don't* apply.

Flame on!

(1) comment out the /DISCARD/ line in arch/i386/vmlinux.lds to kill all the link errors in one stroke workaround, do not merge

(2) #ifdef out balance_irq()
superior equivalent exists, do not merge IO-APIC's are configured to use physical APIC ID's, not clustered hierachical. Physical mode interrupts are not cross-node routable on NUMA-Q, and connectivity information to restrict the interrupt affinity bindings is unavailable. Superior fix due to Matt Dobson, not included here.

(3) make smp_call_function() deal with num_cpus_online() == 0 superior equivalent exists, do not merge
Real answer is either moving xquad_portio ioremap to after cpus_online_map is initialized or to force initialization to cpu 0 being online before the call.
Real fix due to Martin Bligh, not included here.

(4) call printk() to get delays in cpu_init()
blatant workaround not fixing fundamental issue, do not merge Pat Mochel and H. Peter Anvin slated to investigate the Heisenbug but starved for time, someone please help. This one is non-deterministic.
No real fix exists.

(5) fix typo in arch/i386/mm/init.c pagetable init for PAE trivial fix, missing 'p' in a variable name.

(6) synchronize_irq() for acenic

	trivial compilefix, pass dev->irq to it

(7) synchronize_irq() for ns83820

	trivial compilefix, pass dev->irq to it

(8) synchronize_irq() for sb1250-mac

	trivial compilefix, pass dev->irq to it

(9) synchronize_irq() for e1000

	trivial compilefix, pass adapter->pdev->irq to it

(10) synchronize_irq() for NCR53C9x

	trivial compilefix, pass esp->irq to it

(11) use akpm's workaround for MPAGE_BIO_MAX_SIZE
blatant workaround not fixing fundamental issue, do not merge bio splitting is required to deal with qlogicisp's constraints on sglist length
Real fix due to Adam Richter (and/or Jens Axboe), not included here.

(12) bump up MAX_IO_APICS to 1024
MAX_IO_APICS is 8, but 28+ IO-APIC appear 8+ quad configurations. Martin, Zwane, we've seen some bad IO-APIC stuff come out of the affected code, I'll leave it up to Martin to decide when the time is right to deal with this.
Do not merge, pending Martin Bligh's (NUMA-Q maintainer) decision

(13) rusty's hotplug fixes
pending desperately-needed bugfix, please merge

(14) mingo's hotplug fixes
pending desperately-needed bugfix, please merge

(15) mingo's do_irq()/synchronize_irq() fixes pending desperately-needed bugfix, please merge

Cheers,
Bill

===== arch/i386/vmlinux.lds 1.9 vs edited =====

arch/i386/vmlinux.lds +2 -0
@@ -84,11 +84,13 @@
   _end = . ;
 
   /* Sections to be discarded */
+  /*
   /DISCARD/ : {
 	*(.text.exit)
 	*(.data.exit)
 	*(.exitcall.exit)
 	}
+  */
 
   /* Stabs debugging sections.  */
   .stab 0 : { *(.stab) }

===== arch/i386/kernel/i8259.c 1.13 vs edited =====

arch/i386/kernel/i8259.c +2 -1
@@ -38,7 +38,8 @@
 
 static void end_8259A_irq (unsigned int irq)
 {
-	if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
+	if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)) &&
+							irq_desc[irq].action)
 		enable_8259A_irq(irq);
 }
 

===== arch/i386/kernel/io_apic.c 1.24 vs edited =====

arch/i386/kernel/io_apic.c +1 -1
@@ -219,7 +219,7 @@
 #define IRQ_ALLOWED(cpu,allowed_mask) \
 		((1 << cpu) & (allowed_mask))
 
-#if CONFIG_SMP
+#if CONFIG_SMP && !CONFIG_MULTIQUAD
 static unsigned long move(int curr_cpu, unsigned long allowed_mask, unsigned long now, int direction)
 {
 	int search_idle = 1;

===== arch/i386/kernel/irq.c 1.15 vs edited =====

arch/i386/kernel/irq.c +4 -8
@@ -187,10 +187,6 @@
 #if CONFIG_SMP
 inline void synchronize_irq(unsigned int irq)
 {
-	/* is there anything to synchronize with? */
-	if (!irq_desc[irq].action)
-		return;
-
 	while (irq_desc[irq].status & IRQ_INPROGRESS)
 		cpu_relax();
 }
@@ -350,7 +346,7 @@
 	 * use the action we have.
 	 */
 	action = NULL;
-	if (!(status & (IRQ_DISABLED | IRQ_INPROGRESS))) {
+	if (likely(!(status & (IRQ_DISABLED | IRQ_INPROGRESS)))) {
 		action = desc->action;
 		status &= ~IRQ_PENDING; /* we commit to handling */
 		status |= IRQ_INPROGRESS; /* we are handling it */
@@ -363,7 +359,7 @@
 	   a different instance of this same irq, the other processor
 	   will take care of it.
 	 */
-	if (!action)
+	if (unlikely(!action))
 		goto out;
 
 	/*
@@ -381,12 +377,12 @@
 		handle_IRQ_event(irq, &regs, action);
 		spin_lock(&desc->lock);
 		
-		if (!(desc->status & IRQ_PENDING))
+		if (likely(!(desc->status & IRQ_PENDING)))
 			break;
 		desc->status &= ~IRQ_PENDING;
 	}
-	desc->status &= ~IRQ_INPROGRESS;
 out:
+	desc->status &= ~IRQ_INPROGRESS;
 	/*
 	 * The ->end() handler has to deal with interrupts which got
 	 * disabled while the handler was running.

===== arch/i386/kernel/smp.c 1.22 vs edited =====

arch/i386/kernel/smp.c +1 -1
@@ -566,7 +566,7 @@
 	struct call_data_struct data;
 	int cpus = num_online_cpus()-1;
 
-	if (!cpus)
+	if (cpus <= 0)
 		return 0;
 
 	data.func = func;

===== arch/i386/kernel/cpu/common.c 1.4 vs edited =====

arch/i386/kernel/cpu/common.c +6 -0
@@ -454,6 +454,8 @@
 	__asm__ __volatile__("lgdt %0": "=m" (cpu_gdt_descr[cpu]));
 	__asm__ __volatile__("lidt %0": "=m" (idt_descr));
 
+	printk(KERN_INFO "Loading GDT/IDT for CPU#%d\n", cpu);
+
 	/*
 	 * Delete NT
 	 */
@@ -474,6 +476,8 @@
 	load_TR_desc();
 	load_LDT(&init_mm.context);
 
+	printk(KERN_INFO "Loaded per-cpu LDT/TSS for CPU#%d\n", cpu);
+
 	/* Clear %fs and %gs. */
 	asm volatile ("xorl %eax, %eax; movl %eax, %fs; movl %eax, %gs");
 
@@ -491,4 +495,6 @@
 	clear_thread_flag(TIF_USEDFPU);
 	current->used_math = 0;
 	stts();
+
+	printk(KERN_INFO "Cleaned up FPU and debug regs for CPU#%d\n", cpu);
 }

===== arch/i386/mm/init.c 1.22 vs edited =====

arch/i386/mm/init.c +1 -1
@@ -54,7 +54,7 @@
 		
 #if CONFIG_X86_PAE
 	pmd_table = (pmd_t *) alloc_bootmem_low_pages(PAGE_SIZE);
-	set_pgd(pgd, __pgd(__pa(md_table) | _PAGE_PRESENT));
+	set_pgd(pgd, __pgd(__pa(pmd_table) | _PAGE_PRESENT));
 	if (pmd_table != pmd_offset(pgd, 0)) 
 		BUG();
 #else

===== drivers/net/acenic.c 1.24 vs edited =====

drivers/net/acenic.c +2 -2
@@ -856,7 +856,7 @@
 		 * Then release the RX buffers - jumbo buffers were
 		 * already released in ace_close().
 		 */
-		synchronize_irq();
+		synchronize_irq(dev->irq);
 
 		for (i = 0; i < RX_STD_RING_ENTRIES; i++) {
 			struct sk_buff *skb = ap->skb->rx_std_skbuff[i].skb;
@@ -2877,7 +2877,7 @@
 		}
 	} else {
 		while (test_and_set_bit(0, &ap->jumbo_refill_busy));
-		synchronize_irq();
+		synchronize_irq(dev->irq);
 		ace_set_rxtx_parms(dev, 0);
 		if (ap->jumbo) {
 			struct cmd cmd;

===== drivers/net/ns83820.c 1.12 vs edited =====

drivers/net/ns83820.c +3 -3
@@ -755,7 +755,7 @@
 
 	/* synchronize with the interrupt handler and kill it */
 	dev->rx_info.up = 0;
-	synchronize_irq();
+	synchronize_irq(dev->irq);
 
 	/* touch the pci bus... */
 	readl(dev->base + IMR);
@@ -1296,11 +1296,11 @@
 	readl(dev->base + IER);
 
 	dev->rx_info.up = 0;
-	synchronize_irq();
+	synchronize_irq(dev->irq);
 
 	ns83820_do_reset(dev, CR_RST);
 
-	synchronize_irq();
+	synchronize_irq(dev->irq);
 
 	dev->IMR_cache &= ~(ISR_TXURN | ISR_TXIDLE | ISR_TXERR | ISR_TXDESC | ISR_TXOK);
 	ns83820_cleanup_rx(dev);

===== drivers/net/sb1250-mac.c 1.1 vs edited =====

drivers/net/sb1250-mac.c +1 -1
@@ -2544,7 +2544,7 @@
 	spin_unlock_irqrestore(&sc->sbm_lock, flags);
 	
 	/* Make sure there is no irq-handler running on a different CPU. */
-	synchronize_irq();
+	synchronize_irq(dev->irq);
 	
 	free_irq(dev->irq, dev);
 	

===== drivers/net/e1000/e1000_main.c 1.21 vs edited =====

drivers/net/e1000/e1000_main.c +1 -1
@@ -1699,7 +1699,7 @@
 {
 	atomic_inc(&adapter->irq_sem);
 	E1000_WRITE_REG(&adapter->hw, IMC, ~0);
-	synchronize_irq();
+	synchronize_irq(adapter->pdev->irq);
 }
 
 /**

===== drivers/scsi/NCR53C9x.c 1.8 vs edited =====

drivers/scsi/NCR53C9x.c +1 -1
@@ -1381,7 +1381,7 @@
 	don = esp->dma_ports_p(esp);
 	if(don) {
 		esp->dma_ints_off(esp);
-		synchronize_irq();
+		synchronize_irq(esp->irq);
 	}
 	if(esp->issue_SC) {
 		Scsi_Cmnd **prev, *this;

===== fs/mpage.c 1.11 vs edited =====

fs/mpage.c +1 -1
@@ -24,7 +24,7 @@
  * The largest-sized BIO which this code will assemble, in bytes.  Set this
  * to PAGE_CACHE_SIZE if your drivers are broken.
  */
-#define MPAGE_BIO_MAX_SIZE BIO_MAX_SIZE
+#define MPAGE_BIO_MAX_SIZE PAGE_CACHE_SIZE
 
 /*
  * I/O completion handler for multipage BIOs.

===== include/asm-i386/apicdef.h 1.3 vs edited =====

include/asm-i386/apicdef.h +4 -0
@@ -108,7 +108,11 @@
 
 #define APIC_BASE (fix_to_virt(FIX_APIC_BASE))
 
+#ifndef CONFIG_MULTIQUAD
 #define MAX_IO_APICS 8
+#else
+#define MAX_IO_APICS 1024
+#endif /* CONFIG_MULTIQUAD */
 
 /*
  * the local APIC register structure, memory mapped. Not terribly well

===== init/main.c 1.52 vs edited =====

init/main.c +16 -0
@@ -527,6 +527,19 @@
 	do_initcalls();
 }
 
+static void do_pre_smp_initcalls(void)
+{
+#if CONFIG_SMP
+	extern int migration_init(void);
+#endif
+	extern int spawn_ksoftirqd(void);
+
+#if CONFIG_SMP
+	migration_init();
+#endif
+	spawn_ksoftirqd();
+}
+
 extern void prepare_namespace(void);
 
 static int init(void * unused)
@@ -536,6 +549,9 @@
 	lock_kernel();
 	/* Sets up cpus_possible() */
 	smp_prepare_cpus(max_cpus);
+
+	do_pre_smp_initcalls();
+
 	smp_init();
 	do_basic_setup();
 

===== kernel/sched.c 1.113 vs edited =====

kernel/sched.c +57 -12

120 lines not on this page · raw message

===== kernel/softirq.c 1.21 vs edited =====

kernel/softirq.c +1 -3
@@ -410,11 +410,9 @@
 
 static struct notifier_block cpu_nfb = { &cpu_callback, NULL, 0 };
 
-static __init int spawn_ksoftirqd(void)
+__init int spawn_ksoftirqd(void)
 {
 	cpu_callback(&cpu_nfb, CPU_ONLINE, (void *)smp_processor_id());
 	register_cpu_notifier(&cpu_nfb);
 	return 0;
 }
-
-__initcall(spawn_ksoftirqd);