diff options
| author | nisimura <nisimura@NetBSD.org> | 2000-07-04 01:10:18 +0000 |
|---|---|---|
| committer | nisimura <nisimura@NetBSD.org> | 2000-07-04 01:10:18 +0000 |
| commit | 0c92b006c6db96455c00a13269cab0b8637bc316 (patch) | |
| tree | 8e9e16c07c6e7db5e7934407aea672e5d6a66d6a /sys/dev | |
| parent | 0f20cdad3f2bea88bd8744398df1d78e8eb68a5a (diff) | |
Fix negative timeout symptoms caused by integer multiply overflow,
which is revealed with larger HZ systems like NetBSD/pmax (256Hz)
and NetBSD/alpha (1024Hz) as reported by PR#8645. Polled tape
drive access is done with maximum 6 hour timeout which ended up
with negative time and then confused SCSI bus severely.
Diffstat (limited to 'sys/dev')
| -rw-r--r-- | sys/dev/ic/ncr53c9x.c | 22 |
1 files changed, 18 insertions, 4 deletions
diff --git a/sys/dev/ic/ncr53c9x.c b/sys/dev/ic/ncr53c9x.c index 3212de5f25e..5624f311ce6 100644 --- a/sys/dev/ic/ncr53c9x.c +++ b/sys/dev/ic/ncr53c9x.c @@ -1,4 +1,4 @@ -/* $NetBSD: ncr53c9x.c,v 1.51 2000/06/05 15:19:42 tsutsui Exp $ */ +/* $NetBSD: ncr53c9x.c,v 1.52 2000/07/04 01:10:18 nisimura Exp $ */ /*- * Copyright (c) 1998 The NetBSD Foundation, Inc. @@ -541,9 +541,16 @@ ncr53c9x_select(sc, ecb) * expecting to come back due to an interrupt, because it is * always possible that the interrupt may never happen. */ - if ((ecb->xs->xs_control & XS_CTL_POLL) == 0) - callout_reset(&ecb->xs->xs_callout, (ecb->timeout * hz) / 1000, + if ((ecb->xs->xs_control & XS_CTL_POLL) == 0) { + int timeout = ecb->timeout; + + if (hz > 100 && timeout > 1000) + timeout = (timeout / 1000) * hz; + else + timeout = (timeout * hz) / 1000; + callout_reset(&ecb->xs->xs_callout, timeout, ncr53c9x_timeout, ecb); + } /* * The docs say the target register is never reset, and I @@ -2179,6 +2186,8 @@ ncr53c9x_abort(sc, ecb) ecb->flags |= ECB_ABORT; if (ecb == sc->sc_nexus) { + int timeout; + /* * If we're still selecting, the message will be scheduled * after selection is complete. @@ -2189,7 +2198,12 @@ ncr53c9x_abort(sc, ecb) /* * Reschedule timeout. */ - callout_reset(&ecb->xs->xs_callout, (ecb->timeout * hz) / 1000, + timeout = ecb->timeout; + if (hz > 100 && timeout > 1000) + timeout = (timeout / 1000) * hz; + else + timeout = (timeout * hz) / 1000; + callout_reset(&ecb->xs->xs_callout, timeout, ncr53c9x_timeout, ecb); } else { /* The command should be on the nexus list */ |
