diff options
author | Miod Vallat <miod@cvs.openbsd.org> | 2009-03-03 19:08:26 +0000 |
---|---|---|
committer | Miod Vallat <miod@cvs.openbsd.org> | 2009-03-03 19:08:26 +0000 |
commit | 0a9ca98521d5d9a8762a637b8e8f4b04a433bec8 (patch) | |
tree | 90065efc759f0ff2beabe935661620ff1309e722 | |
parent | 67b4c71c5f4eb93cde727d75cdb065ede2caa3e9 (diff) |
Make sure the scsi_xfer timeout is triggered while the command is still alive.
With the current code, a fast command could complete between splx and
the timeout being triggered, we'd then happily return COMPLETE, reuse
the scsi_xfer, schedule the timeout again, causing a nice cycle in the
timeout wheels.
(I know, I know, I have to inspect all other scsi drivers now, but I'm
really tired after spending three hours on this)
-rw-r--r-- | sys/dev/ic/osiop.c | 16 |
1 files changed, 11 insertions, 5 deletions
diff --git a/sys/dev/ic/osiop.c b/sys/dev/ic/osiop.c index 0c3abb81974..8b9c47bf188 100644 --- a/sys/dev/ic/osiop.c +++ b/sys/dev/ic/osiop.c @@ -1,4 +1,4 @@ -/* $OpenBSD: osiop.c,v 1.37 2009/02/16 21:19:07 miod Exp $ */ +/* $OpenBSD: osiop.c,v 1.38 2009/03/03 19:08:25 miod Exp $ */ /* $NetBSD: osiop.c,v 1.9 2002/04/05 18:27:54 bouyer Exp $ */ /* @@ -374,6 +374,7 @@ osiop_scsicmd(xs) struct osiop_acb *acb; struct osiop_softc *sc = periph->adapter_softc; int err, s; + int dopoll; /* XXXX ?? */ if (sc->sc_nexus && (xs->flags & SCSI_POLL)) @@ -439,15 +440,20 @@ osiop_scsicmd(xs) TAILQ_INSERT_TAIL(&sc->ready_list, acb, chain); + if ((acb->xsflags & SCSI_POLL) || (sc->sc_flags & OSIOP_NODMA)) + dopoll = 1; + else { + dopoll = 0; + /* start expire timer */ + timeout_add_msec(&xs->stimeout, xs->timeout); + } + osiop_sched(sc); splx(s); - if ((acb->xsflags & SCSI_POLL) || (sc->sc_flags & OSIOP_NODMA)) + if (dopoll) osiop_poll(sc, acb); - else - /* start expire timer */ - timeout_add_msec(&xs->stimeout, xs->timeout); if (xs->flags & (SCSI_POLL | ITSDONE)) return (COMPLETE); |