summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMiod Vallat <miod@cvs.openbsd.org>2009-03-03 19:08:26 +0000
committerMiod Vallat <miod@cvs.openbsd.org>2009-03-03 19:08:26 +0000
commit0a9ca98521d5d9a8762a637b8e8f4b04a433bec8 (patch)
tree90065efc759f0ff2beabe935661620ff1309e722
parent67b4c71c5f4eb93cde727d75cdb065ede2caa3e9 (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.c16
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);