If you look at the for-loop in ciss_cmd() you can see that there are really two loops. One for SCSI_NOSLEEP with delay(9), the other with tsleep(9). The two paths basically don't interact, they merely happen to share the loop.
If we pull the if-else out of the loop and give each clause its own for-loop the logic is a bit easier to follow. Each loop then needs its own copy of error = ciss_done(ccb1); if (ccb1 == ccb) return (error); but that's a minor concession. With the loop split it should be more obvious that we can remove the ticks from the tsleep(9) path without breaking the other path. Ken: I think this is better than what I sent you before. ok? Index: ic/ciss.c =================================================================== RCS file: /cvs/src/sys/dev/ic/ciss.c,v retrieving revision 1.76 diff -u -p -r1.76 ciss.c --- ic/ciss.c 20 Jan 2020 07:28:03 -0000 1.76 +++ ic/ciss.c 22 Jan 2020 02:34:19 -0000 @@ -532,8 +532,9 @@ ciss_cmd(struct ciss_ccb *ccb, int flags tohz = tvtohz(&tv); if (tohz == 0) tohz = 1; - for (i *= 100, etick = tick + tohz; i--; ) { - if (!(wait & SCSI_NOSLEEP)) { + + if (!(wait & SCSI_NOSLEEP)) { + for (etick = tick + tohz;;) { ccb->ccb_state = CISS_CCB_POLL; CISS_DPRINTF(CISS_D_CMD, ("tsleep(%d) ", tohz)); if (tsleep(ccb, PRIBIO + 1, "ciss_cmd", @@ -548,7 +549,13 @@ ciss_cmd(struct ciss_ccb *ccb, int flags continue; } ccb1 = ccb; - } else { + + error = ciss_done(ccb1); + if (ccb1 == ccb) + return (error); + } + } else { + for (i *= 100; i--;) { DELAY(10); if (!(bus_space_read_4(sc->iot, sc->ioh, @@ -588,11 +595,11 @@ ciss_cmd(struct ciss_ccb *ccb, int flags ccb1 = sc->ccbs + (id >> 2) * sc->ccblen; ccb1->ccb_cmd.id = htole32(id); ccb1->ccb_cmd.id_hi = htole32(0); - } - error = ciss_done(ccb1); - if (ccb1 == ccb) - return (error); + error = ciss_done(ccb1); + if (ccb1 == ccb) + return (error); + } } /* if never got a chance to be done above... */