summaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorAlexander Yurchenko <grange@cvs.openbsd.org>2006-11-28 18:27:54 +0000
committerAlexander Yurchenko <grange@cvs.openbsd.org>2006-11-28 18:27:54 +0000
commitc7bcd45f8a2a06c0f09a4d7b38c17fee3783bbab (patch)
tree1313c612ecf80f6f8a0cb641d44c8f4300c81bfe /sys
parent69aebf6d86b0fb1978a7fdd24bfb50ec9b3b4348 (diff)
Try to detect stalled xfers with timeouts.
Diffstat (limited to 'sys')
-rw-r--r--sys/dev/pci/ips.c31
1 files changed, 30 insertions, 1 deletions
diff --git a/sys/dev/pci/ips.c b/sys/dev/pci/ips.c
index 0001f100e9d..31f68cbbc60 100644
--- a/sys/dev/pci/ips.c
+++ b/sys/dev/pci/ips.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ips.c,v 1.7 2006/11/28 16:17:29 grange Exp $ */
+/* $OpenBSD: ips.c,v 1.8 2006/11/28 18:27:53 grange Exp $ */
/*
* Copyright (c) 2006 Alexander Yurchenko <grange@openbsd.org>
@@ -24,7 +24,9 @@
#include <sys/systm.h>
#include <sys/buf.h>
#include <sys/device.h>
+#include <sys/kernel.h>
#include <sys/malloc.h>
+#include <sys/timeout.h>
#include <sys/queue.h>
#include <machine/bus.h>
@@ -181,6 +183,7 @@ struct ccb {
bus_dmamap_t c_dmam;
struct scsi_xfer * c_xfer;
+ struct timeout c_timo;
TAILQ_ENTRY(ccb) c_link;
};
@@ -232,6 +235,8 @@ int ips_scsi_ioctl(struct scsi_link *, u_long, caddr_t, int,
struct proc *);
void ips_scsi_minphys(struct buf *);
+void ips_xfer_timeout(void *);
+
void ips_flushcache(struct ips_softc *);
int ips_getadapterinfo(struct ips_softc *, struct ips_adapterinfo *);
int ips_getdriveinfo(struct ips_softc *, struct ips_driveinfo *);
@@ -529,6 +534,8 @@ ips_scsi_io(struct scsi_xfer *xs)
cmd->buffaddr = ccb->c_dmam->dm_segs[0].ds_addr;
}
+ timeout_add(&ccb->c_timo, hz);
+
s = splbio();
(*sc->sc_exec)(sc);
ccb->c_flags |= CCB_F_RUN;
@@ -551,6 +558,26 @@ ips_scsi_minphys(struct buf *bp)
}
void
+ips_xfer_timeout(void *arg)
+{
+ struct ccb *ccb = arg;
+ struct scsi_xfer *xs = ccb->c_xfer;
+ struct ips_softc *sc = xs->sc_link->adapter_softc;
+ int s;
+
+ DPRINTF(IPS_D_ERR, ("%s: xfer timeout, ccb id %d\n",
+ sc->sc_dev.dv_xname, ccb->c_id));
+
+ bus_dmamap_unload(sc->sc_dmat, ccb->c_dmam);
+ xs->error = XS_TIMEOUT;
+ s = splbio();
+ scsi_done(xs);
+ ccb->c_flags &= ~CCB_F_RUN;
+ TAILQ_INSERT_TAIL(&sc->sc_ccbq, ccb, c_link);
+ splx(s);
+}
+
+void
ips_flushcache(struct ips_softc *sc)
{
struct ips_cmd_generic *cmd;
@@ -669,6 +696,7 @@ ips_morpheus_intr(void *arg)
}
rv = 1;
+ timeout_del(&ccb->c_timo);
bus_dmamap_unload(sc->sc_dmat, ccb->c_dmam);
xs = ccb->c_xfer;
xs->resid = 0;
@@ -699,6 +727,7 @@ ips_ccb_alloc(bus_dma_tag_t dmat, int n)
IPS_MAXFER, 0, BUS_DMA_NOWAIT | BUS_DMA_ALLOCNOW,
&ccb[i].c_dmam))
goto fail;
+ timeout_set(&ccb[i].c_timo, ips_xfer_timeout, &ccb[i]);
}
return (ccb);