summaryrefslogtreecommitdiff
path: root/sys/dev
diff options
context:
space:
mode:
authornisimura <nisimura@NetBSD.org>2000-07-04 01:10:18 +0000
committernisimura <nisimura@NetBSD.org>2000-07-04 01:10:18 +0000
commit0c92b006c6db96455c00a13269cab0b8637bc316 (patch)
tree8e9e16c07c6e7db5e7934407aea672e5d6a66d6a /sys/dev
parent0f20cdad3f2bea88bd8744398df1d78e8eb68a5a (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.c22
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 */