⬢ DragonFlyBSD Kernel Audit
DF-4694 / fix.diff
← back to finding ↓ download raw
--- a/sys/dev/disk/sili/sili_pm.c
+++ b/sys/dev/disk/sili/sili_pm.c
@@ -442,6 +442,19 @@ sili_pm_softreset(struct sili_port *ap, int target)
 
 	ccb->ccb_xa.state = ATA_S_PENDING;
 
+	/*
+	 * sili_quick_timeout() asserts that our softreset FIS is the only
+	 * command on the chip when it times out (sili.c sili_quick_timeout,
+	 * KKASSERT((ap->ap_active & ~ap->ap_expired) == (1 << slot))).
+	 * XPT_RESET_DEV and the port-thread state machine can enter this
+	 * path while other PM targets still have commands on-chip, so drain
+	 * them first exactly like sili_pm_hardreset() does.
+	 */
+	sili_exclusive_access(ap);
+
 	timeout = (target == 15) ? 1000 : 8000;
 
 	/*
--- a/sys/dev/disk/sili/sili.c
+++ b/sys/dev/disk/sili/sili.c
@@ -2534,7 +2534,8 @@ sili_quick_timeout(struct sili_ccb *ccb)
 		break;
 	case ATA_S_ONCHIP:
-		KKASSERT((ap->ap_active & ~ap->ap_expired) ==
-			 (1 << ccb->ccb_slot));
+		if ((ap->ap_active & ~ap->ap_expired) != (1 << ccb->ccb_slot))
+			kprintf("%s: quick_timeout with co-active commands\n",
+				PORTNAME(ap));
 		ccb->ccb_xa.state = ATA_S_TIMEOUT;