Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/dev reintroduce ATACH_IRQ_WAIT flag for attachments usin...
details: https://anonhg.NetBSD.org/src/rev/26766ad8931c
branches: trunk
changeset: 356864:26766ad8931c
user: jdolecek <jdolecek%NetBSD.org@localhost>
date: Tue Oct 17 18:52:50 2017 +0000
description:
reintroduce ATACH_IRQ_WAIT flag for attachments using wdcintr(), only
process the interrupt when the flag is set - this fixes spurious interrupt
during post-reset drive setup in wdc_ata_bio_start(), and wdc_atapi_start()
while those functions set WDCTL_IDS, this seems to be ignored by certain
(maybe all) PCI-IDE controllers; usually the implicit KERNEL_LOCK() would
prevent the interrupt anyway, but not when the start routine is started
from the atabus thread, which doesn't take it
fixes 'panic: wdc_ata_bio_intr: bad state' reported on current-users
by Chavdar Ivanov
diffstat:
sys/dev/ata/ata_subr.c | 6 +++---
sys/dev/ata/ata_wdc.c | 11 ++++++++---
sys/dev/ata/atavar.h | 3 ++-
sys/dev/ic/wdc.c | 16 ++++++++++++++--
sys/dev/pci/pciide_common.c | 8 ++++++--
sys/dev/scsipi/atapi_wdc.c | 26 ++++++++++++++++++++------
6 files changed, 53 insertions(+), 17 deletions(-)
diffs (262 lines):
diff -r ef289f476df3 -r 26766ad8931c sys/dev/ata/ata_subr.c
--- a/sys/dev/ata/ata_subr.c Tue Oct 17 16:24:14 2017 +0000
+++ b/sys/dev/ata/ata_subr.c Tue Oct 17 18:52:50 2017 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: ata_subr.c,v 1.1 2017/10/10 17:19:38 jdolecek Exp $ */
+/* $NetBSD: ata_subr.c,v 1.2 2017/10/17 18:52:50 jdolecek Exp $ */
/*
* Copyright (c) 1998, 2001 Manuel Bouyer. All rights reserved.
@@ -25,7 +25,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ata_subr.c,v 1.1 2017/10/10 17:19:38 jdolecek Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ata_subr.c,v 1.2 2017/10/17 18:52:50 jdolecek Exp $");
#include "opt_ata.h"
@@ -334,7 +334,7 @@
/* finish the busmastering PIO */
(*wdc->piobm_done)(wdc->dma_arg,
chp->ch_channel, xfer->c_drive);
- chp->ch_flags &= ~(ATACH_DMA_WAIT | ATACH_PIOBM_WAIT);
+ chp->ch_flags &= ~(ATACH_DMA_WAIT | ATACH_PIOBM_WAIT | ATACH_IRQ_WAIT);
}
#endif
diff -r ef289f476df3 -r 26766ad8931c sys/dev/ata/ata_wdc.c
--- a/sys/dev/ata/ata_wdc.c Tue Oct 17 16:24:14 2017 +0000
+++ b/sys/dev/ata/ata_wdc.c Tue Oct 17 18:52:50 2017 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: ata_wdc.c,v 1.108 2017/10/15 11:27:14 jdolecek Exp $ */
+/* $NetBSD: ata_wdc.c,v 1.109 2017/10/17 18:52:50 jdolecek Exp $ */
/*
* Copyright (c) 1998, 2001, 2003 Manuel Bouyer.
@@ -54,7 +54,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ata_wdc.c,v 1.108 2017/10/15 11:27:14 jdolecek Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ata_wdc.c,v 1.109 2017/10/17 18:52:50 jdolecek Exp $");
#include "opt_ata.h"
#include "opt_wdc.h"
@@ -592,7 +592,12 @@
intr:
#endif
/* Wait for IRQ (either real or polled) */
- return (ata_bio->flags & ATA_POLL) ? ATASTART_POLL : ATASTART_STARTED;
+ if ((ata_bio->flags & ATA_POLL) == 0) {
+ chp->ch_flags |= ATACH_IRQ_WAIT;
+ return ATASTART_STARTED;
+ } else {
+ return ATASTART_POLL;
+ }
timeout:
printf("%s:%d:%d: not ready, st=0x%02x, err=0x%02x\n",
diff -r ef289f476df3 -r 26766ad8931c sys/dev/ata/atavar.h
--- a/sys/dev/ata/atavar.h Tue Oct 17 16:24:14 2017 +0000
+++ b/sys/dev/ata/atavar.h Tue Oct 17 18:52:50 2017 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: atavar.h,v 1.94 2017/10/10 17:19:38 jdolecek Exp $ */
+/* $NetBSD: atavar.h,v 1.95 2017/10/17 18:52:50 jdolecek Exp $ */
/*
* Copyright (c) 1998, 2001 Manuel Bouyer.
@@ -399,6 +399,7 @@
/* Our state */
volatile int ch_flags;
#define ATACH_SHUTDOWN 0x02 /* channel is shutting down */
+#define ATACH_IRQ_WAIT 0x10 /* controller is waiting for irq */
#define ATACH_DMA_WAIT 0x20 /* controller is waiting for DMA */
#define ATACH_PIOBM_WAIT 0x40 /* controller is waiting for busmastering PIO */
#define ATACH_DISABLED 0x80 /* channel is disabled */
diff -r ef289f476df3 -r 26766ad8931c sys/dev/ic/wdc.c
--- a/sys/dev/ic/wdc.c Tue Oct 17 16:24:14 2017 +0000
+++ b/sys/dev/ic/wdc.c Tue Oct 17 18:52:50 2017 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: wdc.c,v 1.286 2017/10/16 05:52:43 jdolecek Exp $ */
+/* $NetBSD: wdc.c,v 1.287 2017/10/17 18:52:50 jdolecek Exp $ */
/*
* Copyright (c) 1998, 2001, 2003 Manuel Bouyer. All rights reserved.
@@ -58,7 +58,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: wdc.c,v 1.286 2017/10/16 05:52:43 jdolecek Exp $");
+__KERNEL_RCSID(0, "$NetBSD: wdc.c,v 1.287 2017/10/17 18:52:50 jdolecek Exp $");
#include "opt_ata.h"
#include "opt_wdc.h"
@@ -879,6 +879,11 @@
return (0);
}
+ if ((chp->ch_flags & ATACH_IRQ_WAIT) == 0) {
+ ATADEBUG_PRINT(("wdcintr: irq not expected\n"), DEBUG_INTR);
+ goto ignore;
+ }
+
xfer = ata_queue_get_active_xfer(chp);
if (xfer == NULL) {
ATADEBUG_PRINT(("wdcintr: inactive controller\n"), DEBUG_INTR);
@@ -915,8 +920,11 @@
chp->ch_flags &= ~ATACH_DMA_WAIT;
}
#endif
+ chp->ch_flags &= ~ATACH_IRQ_WAIT;
KASSERT(xfer->c_intr != NULL);
ret = xfer->c_intr(chp, xfer, 1);
+ if (ret == 0) /* irq was not for us, still waiting for irq */
+ chp->ch_flags |= ATACH_IRQ_WAIT;
return (ret);
}
@@ -943,6 +951,8 @@
struct wdc_softc *wdc = CHAN_TO_WDC(chp);
#endif
+ chp->ch_flags &= ~ATACH_IRQ_WAIT;
+
/*
* if the current command is on an ATAPI device, issue a
* ATAPI_SOFT_RESET
@@ -1465,6 +1475,7 @@
}
if ((ata_c->flags & AT_POLL) == 0) {
+ chp->ch_flags |= ATACH_IRQ_WAIT; /* wait for interrupt */
callout_reset(&xfer->c_timo_callout, ata_c->timeout / 1000 * hz,
wdctimeout, xfer);
return ATASTART_STARTED;
@@ -1587,6 +1598,7 @@
wdc->dataout_pio(chp, drive_flags, data, bcount);
ata_c->flags |= AT_XFDONE;
if ((ata_c->flags & AT_POLL) == 0) {
+ chp->ch_flags |= ATACH_IRQ_WAIT; /* wait for interrupt */
callout_reset(&xfer->c_timo_callout,
mstohz(ata_c->timeout), wdctimeout, xfer);
ata_channel_unlock(chp);
diff -r ef289f476df3 -r 26766ad8931c sys/dev/pci/pciide_common.c
--- a/sys/dev/pci/pciide_common.c Tue Oct 17 16:24:14 2017 +0000
+++ b/sys/dev/pci/pciide_common.c Tue Oct 17 18:52:50 2017 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: pciide_common.c,v 1.63 2017/10/07 16:05:33 jdolecek Exp $ */
+/* $NetBSD: pciide_common.c,v 1.64 2017/10/17 18:52:50 jdolecek Exp $ */
/*
@@ -70,7 +70,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: pciide_common.c,v 1.63 2017/10/07 16:05:33 jdolecek Exp $");
+__KERNEL_RCSID(0, "$NetBSD: pciide_common.c,v 1.64 2017/10/17 18:52:50 jdolecek Exp $");
#include <sys/param.h>
@@ -553,6 +553,10 @@
if (cp->compat)
continue;
+ /* if this channel not waiting for intr, skip */
+ if ((wdc_cp->ch_flags & ATACH_IRQ_WAIT) == 0)
+ continue;
+
crv = wdcintr(wdc_cp);
if (crv == 0)
; /* leave rv alone */
diff -r ef289f476df3 -r 26766ad8931c sys/dev/scsipi/atapi_wdc.c
--- a/sys/dev/scsipi/atapi_wdc.c Tue Oct 17 16:24:14 2017 +0000
+++ b/sys/dev/scsipi/atapi_wdc.c Tue Oct 17 18:52:50 2017 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: atapi_wdc.c,v 1.128 2017/10/10 21:37:49 jdolecek Exp $ */
+/* $NetBSD: atapi_wdc.c,v 1.129 2017/10/17 18:52:51 jdolecek Exp $ */
/*
* Copyright (c) 1998, 2001 Manuel Bouyer.
@@ -25,7 +25,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: atapi_wdc.c,v 1.128 2017/10/10 21:37:49 jdolecek Exp $");
+__KERNEL_RCSID(0, "$NetBSD: atapi_wdc.c,v 1.129 2017/10/17 18:52:51 jdolecek Exp $");
#ifndef ATADEBUG
#define ATADEBUG
@@ -672,8 +672,10 @@
if ((sc_xfer->xs_periph->periph_cap & ATAPI_CFG_DRQ_MASK) !=
ATAPI_CFG_IRQ_DRQ || (sc_xfer->xs_control & XS_CTL_POLL))
return ATASTART_POLL;
- else
+ else {
+ chp->ch_flags |= ATACH_IRQ_WAIT;
return ATASTART_STARTED;
+ }
timeout:
printf("%s:%d:%d: %s timed out\n",
@@ -884,6 +886,11 @@
chp->ch_flags |= ATACH_DMA_WAIT;
}
#endif
+
+ if ((sc_xfer->xs_control & XS_CTL_POLL) == 0) {
+ chp->ch_flags |= ATACH_IRQ_WAIT;
+ }
+
ata_channel_unlock(chp);
return 1;
@@ -917,7 +924,8 @@
(*wdc->piobm_start)(wdc->dma_arg,
chp->ch_channel, xfer->c_drive,
xfer->c_skip, len, WDC_PIOBM_XFER_IRQ);
- chp->ch_flags |= ATACH_DMA_WAIT | ATACH_PIOBM_WAIT;
+ chp->ch_flags |= ATACH_DMA_WAIT | ATACH_IRQ_WAIT |
+ ATACH_PIOBM_WAIT;
ata_channel_unlock(chp);
return 1;
}
@@ -934,6 +942,9 @@
xfer->c_skip += len;
xfer->c_bcount -= len;
+ if ((sc_xfer->xs_control & XS_CTL_POLL) == 0) {
+ chp->ch_flags |= ATACH_IRQ_WAIT;
+ }
ata_channel_unlock(chp);
return 1;
@@ -967,7 +978,8 @@
(*wdc->piobm_start)(wdc->dma_arg,
chp->ch_channel, xfer->c_drive,
xfer->c_skip, len, WDC_PIOBM_XFER_IRQ);
- chp->ch_flags |= ATACH_DMA_WAIT | ATACH_PIOBM_WAIT;
+ chp->ch_flags |= ATACH_DMA_WAIT | ATACH_IRQ_WAIT |
+ ATACH_PIOBM_WAIT;
ata_channel_unlock(chp);
return 1;
}
@@ -983,6 +995,9 @@
xfer->c_skip += len;
xfer->c_bcount -= len;
+ if ((sc_xfer->xs_control & XS_CTL_POLL) == 0) {
+ chp->ch_flags |= ATACH_IRQ_WAIT;
+ }
ata_channel_unlock(chp);
return 1;
@@ -1080,7 +1095,6 @@
}
}
-
/*
* Some drive occasionally set WDCS_ERR with
* "ATA illegal length indication" in the error
Home |
Main Index |
Thread Index |
Old Index