diff options
author | mdodd <mdodd@FreeBSD.org> | 2004-12-14 17:45:30 +0000 |
---|---|---|
committer | mdodd <mdodd@FreeBSD.org> | 2004-12-14 17:45:30 +0000 |
commit | d793b0d8c8facd8247f49d54490f08e9dbf016f6 (patch) | |
tree | e8cf4d76e3deab0c60485f82f2d35a9f6b400f48 /sys/dev | |
parent | fb985e2a0c07e7e8e74515b81f7f31237c8eb559 (diff) | |
download | FreeBSD-src-d793b0d8c8facd8247f49d54490f08e9dbf016f6.zip FreeBSD-src-d793b0d8c8facd8247f49d54490f08e9dbf016f6.tar.gz |
Add a callout to dump card status on command queue timeouts.
Diffstat (limited to 'sys/dev')
-rw-r--r-- | sys/dev/ida/ida.c | 45 | ||||
-rw-r--r-- | sys/dev/ida/idavar.h | 4 |
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; |