DF-4694 / fix.diff
--- 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; |