DF-3772 / fix.diff
diff --git a/sys/dev/disk/ahci/ahci.c b/sys/dev/disk/ahci/ahci.c index 0fda0a32..3a4e8ed6 100644 --- a/sys/dev/disk/ahci/ahci.c +++ b/sys/dev/disk/ahci/ahci.c @@ -2619,7 +2619,18 @@ ahci_port_intr(struct ahci_port *ap, int blockable) active = &ap->ap_active; } KKASSERT(!(ap->ap_sactive && ap->ap_active)); - KKASSERT((ci_saved & (ap->ap_sactive | ap->ap_active)) == ci_saved); + /* + * Some chipsets (e.g. AMD after IFS errors) leave stale CI/SACT + * bits set after a port stop. The driver is designed to survive + * this (see the ahci_pactive() recovery below), so mask-and-warn + * instead of turning a recoverable condition into a panic. + */ + if ((ci_saved & ~(ap->ap_sactive | ap->ap_active)) != 0) { + kprintf("%s: WARNING: stale chip activity %08x\n", + PORTNAME(ap), + ci_saved & ~(ap->ap_sactive | ap->ap_active)); + ci_saved &= (ap->ap_sactive | ap->ap_active); + } #if 0 kprintf("CHECK act=%08x/%08x sact=%08x/%08x\n", ap->ap_active, ahci_pread(ap, AHCI_PREG_CI), @@ -3347,8 +3358,8 @@ ahci_get_err_ccb(struct ahci_port *ap) if (ci) { kprintf("%s: ahci_get_err_ccb: ci not 0 (%08x)\n", ap->ap_name, ci); + ahci_pwrite(ap, AHCI_PREG_CI, ci); /* clear stale bits */ } - KKASSERT(ci == 0); KKASSERT((ap->ap_flags & AP_F_ERR_CCB_RESERVED) == 0); ap->ap_flags |= AP_F_ERR_CCB_RESERVED; @@ -3396,10 +3407,12 @@ ahci_put_err_ccb(struct ahci_ccb *ccb) } ci = ahci_pread(ap, AHCI_PREG_CI); if (ci) { - panic("ahci_put_err_ccb(%d) but CI %08x != 0 " + kprintf("%s: ahci_put_err_ccb(%d) but CI %08x != 0 " "(act=%08x sact=%08x)\n", + PORTNAME(ap), ccb->ccb_slot, ci, ap->ap_active, ap->ap_sactive); + ahci_pwrite(ap, AHCI_PREG_CI, ci); } KKASSERT(ccb == ap->ap_err_ccb); |