Current-Users archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
Re: New panic in wdc_ata_bio_intr
Okay, can you try following patch? It puts puts back a flag for IRQ handling. If it works, I might have an idea what's happening. I think there is some rogue interrupt disturbing the state.
If it doesn't work, can you please try to compile kernel with ATADEBUG, and set atadebug_mask (possibly via ddb during boot) to 0x40?
Jaromir
? dev/ata.c.locked_reset.diff
? dev/lst
? dev/n.zip
? dev/qq
Index: dev/ata/ata_subr.c
===================================================================
RCS file: /cvsroot/src/sys/dev/ata/ata_subr.c,v
retrieving revision 1.1
diff -u -p -r1.1 ata_subr.c
--- dev/ata/ata_subr.c 10 Oct 2017 17:19:38 -0000 1.1
+++ dev/ata/ata_subr.c 16 Oct 2017 18:01:50 -0000
@@ -334,7 +334,7 @@ ata_free_xfer(struct ata_channel *chp, s
/* 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
Index: dev/ata/ata_wdc.c
===================================================================
RCS file: /cvsroot/src/sys/dev/ata/ata_wdc.c,v
retrieving revision 1.108
diff -u -p -r1.108 ata_wdc.c
--- dev/ata/ata_wdc.c 15 Oct 2017 11:27:14 -0000 1.108
+++ dev/ata/ata_wdc.c 16 Oct 2017 18:01:50 -0000
@@ -592,7 +592,12 @@ _wdc_ata_bio_start(struct ata_channel *c
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",
Index: dev/ata/atavar.h
===================================================================
RCS file: /cvsroot/src/sys/dev/ata/atavar.h,v
retrieving revision 1.94
diff -u -p -r1.94 atavar.h
--- dev/ata/atavar.h 10 Oct 2017 17:19:38 -0000 1.94
+++ dev/ata/atavar.h 16 Oct 2017 18:01:50 -0000
@@ -399,6 +399,7 @@ struct ata_channel {
/* 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 */
Index: dev/ic/wdc.c
===================================================================
RCS file: /cvsroot/src/sys/dev/ic/wdc.c,v
retrieving revision 1.286
diff -u -p -r1.286 wdc.c
--- dev/ic/wdc.c 16 Oct 2017 05:52:43 -0000 1.286
+++ dev/ic/wdc.c 16 Oct 2017 18:01:50 -0000
@@ -879,6 +879,11 @@ wdcintr(void *arg)
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 @@ ignore:
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 @@ wdc_reset_channel(struct ata_channel *ch
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 @@ __wdccommand_start(struct ata_channel *c
}
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 @@ again:
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);
Index: dev/pci/pciide_common.c
===================================================================
RCS file: /cvsroot/src/sys/dev/pci/pciide_common.c,v
retrieving revision 1.63
diff -u -p -r1.63 pciide_common.c
--- dev/pci/pciide_common.c 7 Oct 2017 16:05:33 -0000 1.63
+++ dev/pci/pciide_common.c 16 Oct 2017 18:01:50 -0000
@@ -553,6 +553,10 @@ pciide_pci_intr(void *arg)
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 */
Index: dev/scsipi/atapi_wdc.c
===================================================================
RCS file: /cvsroot/src/sys/dev/scsipi/atapi_wdc.c,v
retrieving revision 1.128
diff -u -p -r1.128 atapi_wdc.c
--- dev/scsipi/atapi_wdc.c 10 Oct 2017 21:37:49 -0000 1.128
+++ dev/scsipi/atapi_wdc.c 16 Oct 2017 18:01:50 -0000
@@ -672,8 +672,10 @@ ready:
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 @@ again:
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 @@ again:
(*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 @@ again:
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 @@ again:
(*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 @@ again:
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 @@ wdc_atapi_phase_complete(struct ata_xfer
}
}
-
/*
* Some drive occasionally set WDCS_ERR with
* "ATA illegal length indication" in the error
Home |
Main Index |
Thread Index |
Old Index