⬢ DragonFlyBSD Kernel Audit
DF-5653 / fix.diff
← back to finding ↓ download raw
--- sys/platform/pc64/icu/elcr.c
+++ sys/platform/pc64/icu/elcr.c
@@ -48,6 +48,8 @@
 #include <sys/param.h>
 #include <sys/bus.h>
 #include <sys/systm.h>
 #include <sys/kernel.h>
+#include <sys/spinlock.h>
+#include <sys/spinlock2.h>
 
 #include <machine_base/icu/elcr_var.h>
 #include <machine_base/isa/isa_intr.h>
@@ -59,6 +61,8 @@
 
 int 		elcr_found;
 static int	elcr_status;
+static struct	spinlock elcr_lock =
+			SPINLOCK_INITIALIZER(elcr_lock, "elcr_lock");
 
 /*
  * Check to see if we have what looks like a valid ELCR.  We do this by
@@ -100,18 +104,21 @@
 void
 elcr_write_trigger(int irq, enum intr_trigger trigger)
 {
 	int new_status;
 
 	KASSERT(elcr_found, ("%s: no ELCR was found!", __func__));
 	KASSERT(irq < ISA_IRQ_CNT, ("%s: invalid IRQ %u", __func__, irq));
+	spin_lock(&elcr_lock);
 	if (trigger == INTR_TRIGGER_LEVEL)
 		new_status = elcr_status | ELCR_MASK(irq);
 	else
 		new_status = elcr_status & ~ELCR_MASK(irq);
-	if (new_status == elcr_status)
-		return;
-	elcr_status = new_status;
-	if (irq >= 8)
-		outb(ELCR_PORT + 1, elcr_status >> 8);
-	else
-		outb(ELCR_PORT, elcr_status & 0xff);
+	if (new_status != elcr_status) {
+		elcr_status = new_status;
+		if (irq >= 8)
+			outb(ELCR_PORT + 1, elcr_status >> 8);
+		else
+			outb(ELCR_PORT, elcr_status & 0xff);
+	}
+	spin_unlock(&elcr_lock);
 }