⬢ DragonFlyBSD Kernel Audit
DF-3775 / fix.diff
← back to finding ↓ download raw
diff --git a/sys/dev/disk/ahci/ahci.c b/sys/dev/disk/ahci/ahci.c
index 0fda0a32..617b5e56 100644
--- a/sys/dev/disk/ahci/ahci.c
+++ b/sys/dev/disk/ahci/ahci.c
@@ -2842,6 +2842,18 @@ ahci_port_intr(struct ahci_port *ap, int blockable)
 		 */
 		if ((tfd & AHCI_PREG_TFD_STS_ERR) &&
 		    (cmd & AHCI_PREG_CMD_ST) == 0) {
+			/*
+			 * process_error() blocks (port stop/CLO/NCQ log
+			 * reads use tsleep-based pwaits), so it must not
+			 * run in the interrupt handler - defer to the
+			 * port thread like the blockable_mask sources.
+			 */
+			if (blockable == 0) {
+				ahci_pwrite(ap, AHCI_PREG_IE, 0);
+				ahci_os_signal_port_thread(ap,
+							   AP_SIGF_PORTINT);
+				return;
+			}
 			err_slot = AHCI_PREG_CMD_CCS(
 						ahci_pread(ap, AHCI_PREG_CMD));
 			ccb = &ap->ap_ccbs[err_slot];