⬢ DragonFlyBSD Kernel Audit
DF-5527 / fix.diff
← back to finding ↓ download raw
--- a/sys/bus/gpio/gpio_intel/gpio_cherryview.c
+++ b/sys/bus/gpio/gpio_intel/gpio_cherryview.c
@@ -381,7 +381,8 @@
 gpio_cherryview_unmap_intr(struct gpio_intel_softc *sc,
     struct pin_intr_map *map)
 {
-	uint32_t reg, intcfg, gpiocfg;
+	uint32_t reg, intcfg, gpiocfg, mask;
+	int intidx = map->intidx;
 	uint16_t pin = map->pin;
 
 	intcfg = map->orig_intcfg;
@@ -396,6 +397,21 @@
 	map->orig_intcfg = 0;
 	map->orig_gpiocfg = 0;
 
+	/*
+	 * Make sure the interrupt line is masked and has no pending
+	 * status, in case the caller did not tear the interrupt down
+	 * before freeing it.  Leaving the line armed with no mapping
+	 * turns a level-asserted pad into an endless interrupt storm,
+	 * because gpio_cherryview_intr() then takes the is_level==0
+	 * edge-clear path on a source that re-asserts immediately.
+	 */
+	if (intidx >= 0) {
+		mask = chvgpio_read(sc, CHV_GPIO_REG_MASK);
+		mask &= ~(1U << intidx);
+		chvgpio_write(sc, CHV_GPIO_REG_MASK, mask);
+		chvgpio_write(sc, CHV_GPIO_REG_IS, 1U << intidx);
+	}
+
 	/* Restore interrupt configuration if needed */
 	reg = chvgpio_read(sc, PIN_CTL1(pin));
 	if ((reg & CHV_GPIO_CTL1_INTCFG_MASK) != intcfg) {