summaryrefslogtreecommitdiffstats
path: root/sys/dev/ida
diff options
context:
space:
mode:
authormdodd <mdodd@FreeBSD.org>2004-12-14 17:45:30 +0000
committermdodd <mdodd@FreeBSD.org>2004-12-14 17:45:30 +0000
commitd793b0d8c8facd8247f49d54490f08e9dbf016f6 (patch)
treee8cf4d76e3deab0c60485f82f2d35a9f6b400f48 /sys/dev/ida
parentfb985e2a0c07e7e8e74515b81f7f31237c8eb559 (diff)
downloadFreeBSD-src-d793b0d8c8facd8247f49d54490f08e9dbf016f6.zip
FreeBSD-src-d793b0d8c8facd8247f49d54490f08e9dbf016f6.tar.gz
Add a callout to dump card status on command queue timeouts.
Diffstat (limited to 'sys/dev/ida')
-rw-r--r--sys/dev/ida/ida.c45
-rw-r--r--sys/dev/ida/idavar.h4
2 files changed, 48 insertions, 1 deletions
diff --git a/sys/dev/ida/ida.c b/sys/dev/ida/ida.c
index 16c85f1..1f09cc1 100644
--- a/sys/dev/ida/ida.c
+++ b/sys/dev/ida/ida.c
@@ -63,6 +63,7 @@ static void ida_construct_qcb(struct ida_softc *ida);
static void ida_start(struct ida_softc *ida);
static void ida_done(struct ida_softc *ida, struct ida_qcb *qcb);
static int ida_wait(struct ida_softc *ida, struct ida_qcb *qcb);
+static void ida_timeout (void *arg);
static d_ioctl_t ida_ioctl;
static struct cdevsw ida_cdevsw = {
@@ -77,6 +78,8 @@ ida_free(struct ida_softc *ida)
{
int i;
+ callout_stop(&ida->ch);
+
for (i = 0; i < ida->num_qcbs; i++)
bus_dmamap_destroy(ida->buffer_dmat, ida->qcbs[i].dmamap);
@@ -260,6 +263,8 @@ ida_init(struct ida_softc *ida)
ida_alloc_qcb(ida); /* allocate an initial qcb */
+ callout_init(&ida->ch, CALLOUT_MPSAFE);
+
return (0);
}
@@ -459,8 +464,14 @@ ida_start(struct ida_softc *ida)
STAILQ_REMOVE_HEAD(&ida->qcb_queue, link.stqe);
/*
* XXX
- * place the qcb on an active list and set a timeout?
+ * place the qcb on an active list?
*/
+
+ /* Set a timeout. */
+ if (!ida->qactive)
+ callout_reset(&ida->ch, hz * 5, ida_timeout, ida);
+ ida->qactive++;
+
qcb->state = QCB_ACTIVE;
ida->cmd.submit(ida, qcb);
}
@@ -573,12 +584,44 @@ ida_done(struct ida_softc *ida, struct ida_qcb *qcb)
idad_intr(qcb->buf);
}
+ ida->qactive--;
+ /* Reschedule or cancel timeout */
+ if (ida->qactive)
+ callout_reset(&ida->ch, hz * 5, ida_timeout, ida);
+ else
+ callout_stop(&ida->ch);
+
qcb->state = QCB_FREE;
qcb->buf = NULL;
SLIST_INSERT_HEAD(&ida->free_qcbs, qcb, link.sle);
ida_construct_qcb(ida);
}
+static void
+ida_timeout (void *arg)
+{
+ struct ida_softc *ida;
+
+ ida = (struct ida_softc *)arg;
+ device_printf(ida->dev, "%s() qactive %d\n", __func__, ida->qactive);
+
+ if (ida->flags & IDA_INTERRUPTS)
+ device_printf(ida->dev, "IDA_INTERRUPTS\n");
+
+ device_printf(ida->dev, "\t R_CMD_FIFO: %08x\n"
+ "\t R_DONE_FIFO: %08x\n"
+ "\t R_INT_MASK: %08x\n"
+ "\t R_STATUS: %08x\n"
+ "\tR_INT_PENDING: %08x\n",
+ ida_inl(ida, R_CMD_FIFO),
+ ida_inl(ida, R_DONE_FIFO),
+ ida_inl(ida, R_INT_MASK),
+ ida_inl(ida, R_STATUS),
+ ida_inl(ida, R_INT_PENDING));
+
+ return;
+}
+
/*
* IOCTL stuff follows.
*/
diff --git a/sys/dev/ida/idavar.h b/sys/dev/ida/idavar.h
index 118e680..8b56540 100644
--- a/sys/dev/ida/idavar.h
+++ b/sys/dev/ida/idavar.h
@@ -126,6 +126,8 @@ struct ida_access {
struct ida_softc {
device_t dev;
int unit;
+
+ struct callout ch;
struct cdev *ida_dev_t;
int regs_res_type;
@@ -153,6 +155,8 @@ struct ida_softc {
int num_qcbs;
int flags;
+ int qactive;
+
struct ida_hardware_qcb *hwqcbs; /* HW QCB array */
struct ida_qcb *qcbs; /* kernel QCB array */
SLIST_HEAD(, ida_qcb) free_qcbs;
OpenPOWER on IntegriCloud