From 4c8bc9a2426dee5093816cbf17783ee6e59ae87d Mon Sep 17 00:00:00 2001 From: Matthew Dillon Date: Sun, 3 Jun 2007 11:52:09 +0000 Subject: [PATCH] Part 1/2: Add a sanity check to the NATA interrupt code to assert that the command has actually been issued. --- sys/dev/disk/nata/ata-all.c | 19 +++++++++++++++---- sys/dev/disk/nata/ata-all.h | 4 +++- sys/dev/disk/nata/ata-queue.c | 8 +++++++- 3 files changed, 25 insertions(+), 6 deletions(-) diff --git a/sys/dev/disk/nata/ata-all.c b/sys/dev/disk/nata/ata-all.c index 76638ac094..7d88309146 100644 --- a/sys/dev/disk/nata/ata-all.c +++ b/sys/dev/disk/nata/ata-all.c @@ -24,7 +24,7 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * $FreeBSD: src/sys/dev/ata/ata-all.c,v 1.273 2006/05/12 05:04:40 jhb Exp $ - * $DragonFly: src/sys/dev/disk/nata/ata-all.c,v 1.10 2007/06/01 00:31:14 dillon Exp $ + * $DragonFly: src/sys/dev/disk/nata/ata-all.c,v 1.11 2007/06/03 11:52:09 dillon Exp $ */ #include "opt_ata.h" @@ -317,13 +317,24 @@ ata_interrupt(void *data) spin_lock_wr(&ch->state_mtx); do { - /* ignore interrupt if its not for us */ + /* + * Ignore interrupt if its not for us. This may also have the + * side effect of processing events unrelated to I/O requests. + */ if (ch->hw.status && !ch->hw.status(ch->dev)) break; - /* do we have a running request */ - if (!(request = ch->running)) + /* + * Check if we have a running request, and make sure it has been + * completely queued. Otherwise the channel status may indicate + * not-busy when, in fact, the command had not yet been issued. + */ + if ((request = ch->running) == NULL) + break; + if ((request->flags & ATA_R_HWCMDQUEUED) == 0) { + kprintf("ata_interrupt: early interrupt\n"); break; + } /* XXX TGEN Ignore weird ATAPI+DMA interrupts on SMP */ if (ch->dma && (request->flags & ATA_R_ATAPI)) { diff --git a/sys/dev/disk/nata/ata-all.h b/sys/dev/disk/nata/ata-all.h index 7fcf7a4f66..5564712d42 100644 --- a/sys/dev/disk/nata/ata-all.h +++ b/sys/dev/disk/nata/ata-all.h @@ -24,7 +24,7 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * $FreeBSD: src/sys/dev/ata/ata-all.h,v 1.118 2006/06/28 09:59:09 sos Exp $ - * $DragonFly: src/sys/dev/disk/nata/ata-all.h,v 1.5 2007/06/01 00:31:14 dillon Exp $ + * $DragonFly: src/sys/dev/disk/nata/ata-all.h,v 1.6 2007/06/03 11:52:09 dillon Exp $ */ #include @@ -374,6 +374,8 @@ struct ata_request { #define ATA_R_THREAD 0x00000800 #define ATA_R_DIRECT 0x00001000 +#define ATA_R_HWCMDQUEUED 0x00010000 + #define ATA_R_DEBUG 0x10000000 #define ATA_R_DANGER1 0x20000000 #define ATA_R_DANGER2 0x40000000 diff --git a/sys/dev/disk/nata/ata-queue.c b/sys/dev/disk/nata/ata-queue.c index 114cd84543..f10e751674 100644 --- a/sys/dev/disk/nata/ata-queue.c +++ b/sys/dev/disk/nata/ata-queue.c @@ -24,7 +24,7 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * $FreeBSD: src/sys/dev/ata/ata-queue.c,v 1.65 2006/07/21 19:13:05 imp Exp $ - * $DragonFly: src/sys/dev/disk/nata/ata-queue.c,v 1.5 2007/06/01 00:31:15 dillon Exp $ + * $DragonFly: src/sys/dev/disk/nata/ata-queue.c,v 1.6 2007/06/03 11:52:09 dillon Exp $ */ #include "opt_ata.h" @@ -77,6 +77,8 @@ ata_queue_request(struct ata_request *request) spin_unlock_wr(&ch->state_mtx); return; } + /* interlock against interrupt */ + request->flags |= ATA_R_HWCMDQUEUED; spin_unlock_wr(&ch->state_mtx); } /* otherwise put request on the locked queue at the specified location */ @@ -218,6 +220,10 @@ ata_start(device_t dev) ata_finish(request); return; } + + /* interlock against interrupt */ + request->flags |= ATA_R_HWCMDQUEUED; + if (dumping) { spin_unlock_wr(&ch->state_mtx); spin_unlock_wr(&ch->queue_mtx); -- 2.11.4.GIT