Module Name:    src
Committed By:   knakahara
Date:           Wed Nov 16 07:13:01 UTC 2016

Modified Files:
        src/sys/arch/x86/x86: intr.c

Log Message:
avoid a failure of interrupt affinity when the interrupt is pending.

pointed out and reviewed by ozaki-r@n.o, thanks.


To generate a diff of this commit:
cvs rdiff -u -r1.94 -r1.95 src/sys/arch/x86/x86/intr.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/arch/x86/x86/intr.c
diff -u src/sys/arch/x86/x86/intr.c:1.94 src/sys/arch/x86/x86/intr.c:1.95
--- src/sys/arch/x86/x86/intr.c:1.94	Mon Jul 11 23:09:34 2016
+++ src/sys/arch/x86/x86/intr.c	Wed Nov 16 07:13:01 2016
@@ -1,4 +1,4 @@
-/*	$NetBSD: intr.c,v 1.94 2016/07/11 23:09:34 knakahara Exp $	*/
+/*	$NetBSD: intr.c,v 1.95 2016/11/16 07:13:01 knakahara Exp $	*/
 
 /*-
  * Copyright (c) 2007, 2008, 2009 The NetBSD Foundation, Inc.
@@ -133,7 +133,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: intr.c,v 1.94 2016/07/11 23:09:34 knakahara Exp $");
+__KERNEL_RCSID(0, "$NetBSD: intr.c,v 1.95 2016/11/16 07:13:01 knakahara Exp $");
 
 #include "opt_intrdebug.h"
 #include "opt_multiprocessor.h"
@@ -210,6 +210,8 @@ static void intr_calculatemasks(struct c
 static SIMPLEQ_HEAD(, intrsource) io_interrupt_sources =
 	SIMPLEQ_HEAD_INITIALIZER(io_interrupt_sources);
 
+static kmutex_t intr_distribute_lock;
+
 #if NIOAPIC > 0 || NACPICA > 0
 static int intr_scan_bus(int, int, intr_handle_t *);
 #if NPCI > 0
@@ -273,6 +275,8 @@ intr_default_setup(void)
 	 * Eventually might want to check if it's actually there.
 	 */
 	i8259_default_setup();
+
+	mutex_init(&intr_distribute_lock, MUTEX_DEFAULT, IPL_NONE);
 }
 
 /*
@@ -1876,6 +1880,7 @@ intr_set_affinity(struct intrsource *isp
 	int err;
 	int pin;
 
+	KASSERT(mutex_owned(&intr_distribute_lock));
 	KASSERT(mutex_owned(&cpu_lock));
 
 	/* XXX
@@ -1921,12 +1926,8 @@ intr_set_affinity(struct intrsource *isp
 
 	pin = isp->is_pin;
 	(*pic->pic_hwmask)(pic, pin); /* for ci_ipending check */
-	if (oldci->ci_ipending & (1 << oldslot)) {
-		(*pic->pic_hwunmask)(pic, pin);
-		DPRINTF(("pin %d on cpuid %ld has pending interrupts.\n",
-			pin, oldci->ci_cpuid));
-		return EBUSY;
-	}
+	while(oldci->ci_ipending & (1 << oldslot))
+		(void)kpause("intrdist", false, 1, &cpu_lock);
 
 	kpreempt_disable();
 
@@ -2116,6 +2117,7 @@ intr_distribute_locked(struct intrhand *
 	struct intrsource *isp;
 	int slot;
 
+	KASSERT(mutex_owned(&intr_distribute_lock));
 	KASSERT(mutex_owned(&cpu_lock));
 
 	if (ih == NULL)
@@ -2140,9 +2142,11 @@ interrupt_distribute(void *cookie, const
 	int error;
 	struct intrhand *ih = cookie;
 
+	mutex_enter(&intr_distribute_lock);
 	mutex_enter(&cpu_lock);
 	error = intr_distribute_locked(ih, newset, oldset);
 	mutex_exit(&cpu_lock);
+	mutex_exit(&intr_distribute_lock);
 
 	return error;
 }
@@ -2157,6 +2161,7 @@ interrupt_distribute_handler(const char 
 	int error;
 	struct intrhand *ih;
 
+	mutex_enter(&intr_distribute_lock);
 	mutex_enter(&cpu_lock);
 
 	ih = intr_get_handler(intrid);
@@ -2168,6 +2173,7 @@ interrupt_distribute_handler(const char 
 
  out:
 	mutex_exit(&cpu_lock);
+	mutex_exit(&intr_distribute_lock);
 	return error;
 }
 

Reply via email to