PCI MSI (was Re: What current Dell Systems are supported/work)

John Baldwin jhb at freebsd.org
Fri Jan 18 07:11:34 PST 2008


On Friday 18 January 2008 08:50:31 am John Baldwin wrote:
> On Friday 18 January 2008 05:30:06 am Parv wrote:
> > There was no page fault or trap 12 message when the panic happened.
> > After some of messages are printed (as in dmesg), kdb is entered ...
> > 
> >   ioapic0: Assigning PCI IRQ 23 to local APIC 1
> >   msi: Assigning MSI IRQ 256 to local APIC 0
> >   panic: blockabke sleep block (sleep mutex) msi @ /misc/src-6/sys/i386/i386/msi.c:381
> >   cpuid: 0
> >   kdb: stack backtrace
> >   kbd_backtrace( c0adc531,0,c0abaafd,c1020c34,c0bab700,...) at ... \
> >     [I skipped from here to the "db>" prompt]
> >   .
> >   .
> >   .
> > 
> > Tomorrow, rather later today, I will type up the "trace" output.
> > Please let me know if you would like to see any other output that I
> > could possibly provide.
> 
> This is good enough for me to see the bug, I'll work on fixing it.  There are
> some locking changes in the x86 interrupt code I need to MFC.

Try this patch:

Index: amd64/amd64/intr_machdep.c
===================================================================
RCS file: /host/cvs/usr/cvs/src/sys/amd64/amd64/intr_machdep.c,v
retrieving revision 1.15.2.5
diff -u -r1.15.2.5 intr_machdep.c
--- amd64/amd64/intr_machdep.c	26 Nov 2007 15:08:35 -0000	1.15.2.5
+++ amd64/amd64/intr_machdep.c	18 Jan 2008 15:05:08 -0000
@@ -43,13 +43,14 @@
 #include <sys/param.h>
 #include <sys/bus.h>
 #include <sys/interrupt.h>
-#include <sys/lock.h>
 #include <sys/ktr.h>
 #include <sys/kernel.h>
+#include <sys/lock.h>
 #include <sys/mutex.h>
 #include <sys/proc.h>
 #include <sys/syslog.h>
 #include <sys/systm.h>
+#include <sys/sx.h>
 #include <machine/clock.h>
 #include <machine/intr_machdep.h>
 #ifdef DDB
@@ -70,7 +71,8 @@
 
 static int intrcnt_index;
 static struct intsrc *interrupt_sources[NUM_IO_INTS];
-static struct mtx intr_table_lock;
+static struct sx intr_table_lock;
+static struct mtx intrcnt_lock;
 static STAILQ_HEAD(, pic) pics;
 
 #ifdef SMP
@@ -108,14 +110,14 @@
 {
 	int error;
 
-	mtx_lock_spin(&intr_table_lock);
+	sx_xlock(&intr_table_lock);
 	if (intr_pic_registered(pic))
 		error = EBUSY;
 	else {
 		STAILQ_INSERT_TAIL(&pics, pic, pics);
 		error = 0;
 	}
-	mtx_unlock_spin(&intr_table_lock);
+	sx_xunlock(&intr_table_lock);
 	return (error);
 }
 
@@ -137,16 +139,16 @@
 	    (mask_fn)isrc->is_pic->pic_enable_source, "irq%d:", vector);
 	if (error)
 		return (error);
-	mtx_lock_spin(&intr_table_lock);
+	sx_xlock(&intr_table_lock);
 	if (interrupt_sources[vector] != NULL) {
-		mtx_unlock_spin(&intr_table_lock);
+		sx_xunlock(&intr_table_lock);
 		intr_event_destroy(isrc->is_event);
 		return (EEXIST);
 	}
 	intrcnt_register(isrc);
 	interrupt_sources[vector] = isrc;
 	isrc->is_enabled = 0;
-	mtx_unlock_spin(&intr_table_lock);
+	sx_xunlock(&intr_table_lock);
 	return (0);
 }
 
@@ -170,19 +172,18 @@
 	error = intr_event_add_handler(isrc->is_event, name, handler, arg,
 	    intr_priority(flags), flags, cookiep);
 	if (error == 0) {
+		sx_xlock(&intr_table_lock);
 		intrcnt_updatename(isrc);
-		mtx_lock_spin(&intr_table_lock);
 		if (!isrc->is_enabled) {
 			isrc->is_enabled = 1;
 #ifdef SMP
 			if (assign_cpu)
 				intr_assign_next_cpu(isrc);
 #endif
-			mtx_unlock_spin(&intr_table_lock);
 			isrc->is_pic->pic_enable_intr(isrc);
-		} else
-			mtx_unlock_spin(&intr_table_lock);
+		}
 		isrc->is_pic->pic_enable_source(isrc);
+		sx_xunlock(&intr_table_lock);
 	}
 	return (error);
 }
@@ -306,12 +307,12 @@
 #ifndef DEV_ATPIC
 	atpic_reset();
 #endif
-	mtx_lock_spin(&intr_table_lock);
+	sx_xlock(&intr_table_lock);
 	STAILQ_FOREACH(pic, &pics, pics) {
 		if (pic->pic_resume != NULL)
 			pic->pic_resume(pic);
 	}
-	mtx_unlock_spin(&intr_table_lock);
+	sx_xunlock(&intr_table_lock);
 }
 
 void
@@ -319,12 +320,12 @@
 {
 	struct pic *pic;
 
-	mtx_lock_spin(&intr_table_lock);
+	sx_xlock(&intr_table_lock);
 	STAILQ_FOREACH(pic, &pics, pics) {
 		if (pic->pic_suspend != NULL)
 			pic->pic_suspend(pic);
 	}
-	mtx_unlock_spin(&intr_table_lock);
+	sx_xunlock(&intr_table_lock);
 }
 
 static void
@@ -347,8 +348,8 @@
 {
 	char straystr[MAXCOMLEN + 1];
 
-	/* mtx_assert(&intr_table_lock, MA_OWNED); */
 	KASSERT(is->is_event != NULL, ("%s: isrc with no event", __func__));
+	mtx_lock_spin(&intrcnt_lock);
 	is->is_index = intrcnt_index;
 	intrcnt_index += 2;
 	snprintf(straystr, MAXCOMLEN + 1, "stray irq%d",
@@ -357,17 +358,18 @@
 	is->is_count = &intrcnt[is->is_index];
 	intrcnt_setname(straystr, is->is_index + 1);
 	is->is_straycount = &intrcnt[is->is_index + 1];
+	mtx_unlock_spin(&intrcnt_lock);
 }
 
 void
 intrcnt_add(const char *name, u_long **countp)
 {
 
-	mtx_lock_spin(&intr_table_lock);
+	mtx_lock_spin(&intrcnt_lock);
 	*countp = &intrcnt[intrcnt_index];
 	intrcnt_setname(name, intrcnt_index);
 	intrcnt_index++;
-	mtx_unlock_spin(&intr_table_lock);
+	mtx_unlock_spin(&intrcnt_lock);
 }
 
 static void
@@ -377,7 +379,8 @@
 	intrcnt_setname("???", 0);
 	intrcnt_index = 1;
 	STAILQ_INIT(&pics);
-	mtx_init(&intr_table_lock, "intr table", NULL, MTX_SPIN);
+	sx_init(&intr_table_lock, "intr sources");
+	mtx_init(&intrcnt_lock, "intrcnt", NULL, MTX_SPIN);
 }
 SYSINIT(intr_init, SI_SUB_INTR, SI_ORDER_FIRST, intr_init, NULL)
 
@@ -482,14 +485,14 @@
 		return;
 
 	/* Round-robin assign a CPU to each enabled source. */
-	mtx_lock_spin(&intr_table_lock);
+	sx_xlock(&intr_table_lock);
 	assign_cpu = 1;
 	for (i = 0; i < NUM_IO_INTS; i++) {
 		isrc = interrupt_sources[i];
 		if (isrc != NULL && isrc->is_enabled)
 			intr_assign_next_cpu(isrc);
 	}
-	mtx_unlock_spin(&intr_table_lock);
+	sx_xunlock(&intr_table_lock);
 }
 SYSINIT(intr_shuffle_irqs, SI_SUB_SMP, SI_ORDER_SECOND, intr_shuffle_irqs, NULL)
 #endif
Index: i386/i386/intr_machdep.c
===================================================================
RCS file: /host/cvs/usr/cvs/src/sys/i386/i386/intr_machdep.c,v
retrieving revision 1.14.2.5
diff -u -r1.14.2.5 intr_machdep.c
--- i386/i386/intr_machdep.c	26 Nov 2007 15:08:35 -0000	1.14.2.5
+++ i386/i386/intr_machdep.c	18 Jan 2008 15:05:08 -0000
@@ -42,13 +42,14 @@
 #include <sys/param.h>
 #include <sys/bus.h>
 #include <sys/interrupt.h>
-#include <sys/lock.h>
 #include <sys/ktr.h>
 #include <sys/kernel.h>
+#include <sys/lock.h>
 #include <sys/mutex.h>
 #include <sys/proc.h>
 #include <sys/syslog.h>
 #include <sys/systm.h>
+#include <sys/sx.h>
 #include <machine/clock.h>
 #include <machine/intr_machdep.h>
 #ifdef DDB
@@ -61,7 +62,8 @@
 
 static int intrcnt_index;
 static struct intsrc *interrupt_sources[NUM_IO_INTS];
-static struct mtx intr_table_lock;
+static struct sx intr_table_lock;
+static struct mtx intrcnt_lock;
 static STAILQ_HEAD(, pic) pics;
 
 #ifdef SMP
@@ -99,14 +101,14 @@
 {
 	int error;
 
-	mtx_lock_spin(&intr_table_lock);
+	sx_xlock(&intr_table_lock);
 	if (intr_pic_registered(pic))
 		error = EBUSY;
 	else {
 		STAILQ_INSERT_TAIL(&pics, pic, pics);
 		error = 0;
 	}
-	mtx_unlock_spin(&intr_table_lock);
+	sx_xunlock(&intr_table_lock);
 	return (error);
 }
 
@@ -128,16 +130,16 @@
 	    (mask_fn)isrc->is_pic->pic_enable_source, "irq%d:", vector);
 	if (error)
 		return (error);
-	mtx_lock_spin(&intr_table_lock);
+	sx_xlock(&intr_table_lock);
 	if (interrupt_sources[vector] != NULL) {
-		mtx_unlock_spin(&intr_table_lock);
+		sx_xunlock(&intr_table_lock);
 		intr_event_destroy(isrc->is_event);
 		return (EEXIST);
 	}
 	intrcnt_register(isrc);
 	interrupt_sources[vector] = isrc;
 	isrc->is_enabled = 0;
-	mtx_unlock_spin(&intr_table_lock);
+	sx_xunlock(&intr_table_lock);
 	return (0);
 }
 
@@ -161,19 +163,18 @@
 	error = intr_event_add_handler(isrc->is_event, name, handler, arg,
 	    intr_priority(flags), flags, cookiep);
 	if (error == 0) {
+		sx_xlock(&intr_table_lock);
 		intrcnt_updatename(isrc);
-		mtx_lock_spin(&intr_table_lock);
 		if (!isrc->is_enabled) {
 			isrc->is_enabled = 1;
 #ifdef SMP
 			if (assign_cpu)
 				intr_assign_next_cpu(isrc);
 #endif
-			mtx_unlock_spin(&intr_table_lock);
 			isrc->is_pic->pic_enable_intr(isrc);
-		} else
-			mtx_unlock_spin(&intr_table_lock);
+		}
 		isrc->is_pic->pic_enable_source(isrc);
+		sx_xunlock(&intr_table_lock);
 	}
 	return (error);
 }
@@ -294,12 +295,12 @@
 {
 	struct pic *pic;
 
-	mtx_lock_spin(&intr_table_lock);
+	sx_xlock(&intr_table_lock);
 	STAILQ_FOREACH(pic, &pics, pics) {
 		if (pic->pic_resume != NULL)
 			pic->pic_resume(pic);
 	}
-	mtx_unlock_spin(&intr_table_lock);
+	sx_xunlock(&intr_table_lock);
 }
 
 void
@@ -307,12 +308,12 @@
 {
 	struct pic *pic;
 
-	mtx_lock_spin(&intr_table_lock);
+	sx_xlock(&intr_table_lock);
 	STAILQ_FOREACH(pic, &pics, pics) {
 		if (pic->pic_suspend != NULL)
 			pic->pic_suspend(pic);
 	}
-	mtx_unlock_spin(&intr_table_lock);
+	sx_xunlock(&intr_table_lock);
 }
 
 static void
@@ -335,8 +336,8 @@
 {
 	char straystr[MAXCOMLEN + 1];
 
-	/* mtx_assert(&intr_table_lock, MA_OWNED); */
 	KASSERT(is->is_event != NULL, ("%s: isrc with no event", __func__));
+	mtx_lock_spin(&intrcnt_lock);
 	is->is_index = intrcnt_index;
 	intrcnt_index += 2;
 	snprintf(straystr, MAXCOMLEN + 1, "stray irq%d",
@@ -345,17 +346,18 @@
 	is->is_count = &intrcnt[is->is_index];
 	intrcnt_setname(straystr, is->is_index + 1);
 	is->is_straycount = &intrcnt[is->is_index + 1];
+	mtx_unlock_spin(&intrcnt_lock);
 }
 
 void
 intrcnt_add(const char *name, u_long **countp)
 {
 
-	mtx_lock_spin(&intr_table_lock);
+	mtx_lock_spin(&intrcnt_lock);
 	*countp = &intrcnt[intrcnt_index];
 	intrcnt_setname(name, intrcnt_index);
 	intrcnt_index++;
-	mtx_unlock_spin(&intr_table_lock);
+	mtx_unlock_spin(&intrcnt_lock);
 }
 
 static void
@@ -365,7 +367,8 @@
 	intrcnt_setname("???", 0);
 	intrcnt_index = 1;
 	STAILQ_INIT(&pics);
-	mtx_init(&intr_table_lock, "intr table", NULL, MTX_SPIN);
+	sx_init(&intr_table_lock, "intr sources");
+	mtx_init(&intrcnt_lock, "intrcnt", NULL, MTX_SPIN);
 }
 SYSINIT(intr_init, SI_SUB_INTR, SI_ORDER_FIRST, intr_init, NULL)
 
@@ -448,14 +451,14 @@
 		return;
 
 	/* Round-robin assign a CPU to each enabled source. */
-	mtx_lock_spin(&intr_table_lock);
+	sx_xlock(&intr_table_lock);
 	assign_cpu = 1;
 	for (i = 0; i < NUM_IO_INTS; i++) {
 		isrc = interrupt_sources[i];
 		if (isrc != NULL && isrc->is_enabled)
 			intr_assign_next_cpu(isrc);
 	}
-	mtx_unlock_spin(&intr_table_lock);
+	sx_xunlock(&intr_table_lock);
 }
 SYSINIT(intr_shuffle_irqs, SI_SUB_SMP, SI_ORDER_SECOND, intr_shuffle_irqs, NULL)
 #endif

-- 
John Baldwin


More information about the freebsd-stable mailing list