--- /home/maxx/dfbsd/dfbsd/sys/dev/raid/asr/asr.c 2026-06-29 12:51:19.000000000 +0000 +++ /tmp/opencode/fix/asr.c 2026-09-16 10:59:46.460872200 +0000 @@ -722,10 +722,26 @@ } /* - * Wait for this board to report a finished instruction. + * Wait for this board to report a finished instruction, bounded + * (a wedged adapter must fail the command, not hang the kernel). */ - while ((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_INPROG) { - (void)asr_intr (sc); + { + u_int poll = 30 * 100; /* ~30s of 10ms polls */ + while (((ccb->ccb_h.status & CAM_STATUS_MASK) + == CAM_REQ_INPROG) && (--poll != 0)) { + (void)asr_intr(sc); + if ((ccb->ccb_h.status & CAM_STATUS_MASK) + != CAM_REQ_INPROG) + break; + crit_exit(); + DELAY(10000); + crit_enter(); + } + if ((ccb->ccb_h.status & CAM_STATUS_MASK) + == CAM_REQ_INPROG) { + ccb->ccb_h.status &= ~CAM_STATUS_MASK; + ccb->ccb_h.status |= CAM_CMD_TIMEOUT; + } } /* Re-enable Interrupts */ @@ -1250,8 +1266,15 @@ * good thing. In a production system, however, one may wish * to instead take the card off-line ... */ - /* Wait Forever */ - while (ASR_resetIOP(sc) == 0); + { + /* Bounded retries: an unresponsive IOP must take + * the adapter off-line, not spin inside crit. */ + int retry; + for (retry = 0; retry < 60; ++retry) { + if (ASR_resetIOP(sc) != 0) + break; + } + } } retVal = ASR_init (sc); crit_exit(); @@ -1887,9 +1910,15 @@ u_long size, addr; /* - * Wait for a response (Poll). + * Wait for a response (Poll), bounded. */ - while (*Reply_Ptr < I2O_EXEC_OUTBOUND_INIT_REJECTED); + { + u_int delay = 300; /* up to ~3s */ + while ((*Reply_Ptr < I2O_EXEC_OUTBOUND_INIT_REJECTED) + && (--delay != 0)) { + DELAY(10000); + } + } /* * Re-enable the interrupts. */