summaryrefslogtreecommitdiffstats
path: root/sys/dev/mfi/mfi.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/dev/mfi/mfi.c')
-rw-r--r--sys/dev/mfi/mfi.c44
1 files changed, 44 insertions, 0 deletions
diff --git a/sys/dev/mfi/mfi.c b/sys/dev/mfi/mfi.c
index 8c97ea3..b8fab65 100644
--- a/sys/dev/mfi/mfi.c
+++ b/sys/dev/mfi/mfi.c
@@ -81,6 +81,7 @@ static int mfi_send_frame(struct mfi_softc *, struct mfi_command *);
static void mfi_complete(struct mfi_softc *, struct mfi_command *);
static int mfi_abort(struct mfi_softc *, struct mfi_command *);
static int mfi_linux_ioctl_int(struct cdev *, u_long, caddr_t, int, d_thread_t *);
+static void mfi_timeout(void *);
SYSCTL_NODE(_hw, OID_AUTO, mfi, CTLFLAG_RD, 0, "MFI driver parameters");
@@ -389,6 +390,11 @@ mfi_attach(struct mfi_softc *sc)
if (sc->mfi_cdev != NULL)
sc->mfi_cdev->si_drv1 = sc;
+ /* Start the timeout watchdog */
+ callout_init(&sc->mfi_watchdog_callout, 1);
+ callout_reset(&sc->mfi_watchdog_callout, MFI_CMD_TIMEOUT * hz,
+ mfi_timeout, sc);
+
return (0);
}
@@ -416,6 +422,7 @@ mfi_alloc_commands(struct mfi_softc *sc)
cm->cm_sense = &sc->mfi_sense[i];
cm->cm_sense_busaddr= sc->mfi_sense_busaddr + MFI_SENSE_LEN * i;
cm->cm_sc = sc;
+ cm->cm_index = i;
if (bus_dmamap_create(sc->mfi_buffer_dmat, 0,
&cm->cm_dmamap) == 0)
mfi_release_command(cm);
@@ -701,6 +708,8 @@ mfi_free(struct mfi_softc *sc)
struct mfi_command *cm;
int i;
+ callout_drain(&sc->mfi_watchdog_callout);
+
if (sc->mfi_cdev != NULL)
destroy_dev(sc->mfi_cdev);
@@ -1530,6 +1539,7 @@ mfi_mapcmd(struct mfi_softc *sc, struct mfi_command *cm)
return (0);
}
} else {
+ cm->cm_timestamp = time_uptime;
mfi_enqueue_busy(cm);
error = mfi_send_frame(sc, cm);
}
@@ -1591,6 +1601,7 @@ mfi_data_cb(void *arg, bus_dma_segment_t *segs, int nsegs, int error)
/* The caller will take care of delivering polled commands */
if ((cm->cm_flags & MFI_CMD_POLLED) == 0) {
+ cm->cm_timestamp = time_uptime;
mfi_enqueue_busy(cm);
mfi_send_frame(sc, cm);
}
@@ -2023,3 +2034,36 @@ mfi_poll(struct cdev *dev, int poll_events, struct thread *td)
return revents;
}
+
+static void
+mfi_timeout(void *data)
+{
+ struct mfi_softc *sc = (struct mfi_softc *)data;
+ struct mfi_command *cm;
+ time_t deadline;
+ int timedout = 0;
+
+ deadline = time_uptime - MFI_CMD_TIMEOUT;
+ mtx_lock(&sc->mfi_io_lock);
+ TAILQ_FOREACH(cm, &sc->mfi_busy, cm_link) {
+ if (cm->cm_timestamp < deadline) {
+ device_printf(sc->mfi_dev,
+ "COMMAND %p TIMEOUT AFTER %d SECONDS\n", cm,
+ (int)(time_uptime - cm->cm_timestamp));
+ MFI_PRINT_CMD(cm);
+ timedout++;
+ }
+ }
+
+#if 0
+ if (timedout)
+ MFI_DUMP_CMDS(SC);
+#endif
+
+ mtx_unlock(&sc->mfi_io_lock);
+
+ callout_reset(&sc->mfi_watchdog_callout, MFI_CMD_TIMEOUT * hz,
+ mfi_timeout, sc);
+
+ return;
+}
OpenPOWER on IntegriCloud