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];