diff options
author | Miod Vallat <miod@cvs.openbsd.org> | 2004-08-30 17:01:44 +0000 |
---|---|---|
committer | Miod Vallat <miod@cvs.openbsd.org> | 2004-08-30 17:01:44 +0000 |
commit | 5ca0d3ab4dcdb0bec326f0f25fc437029de21575 (patch) | |
tree | 32dbc638300dbdc585595a1f57f99b18d422d7f6 /sys | |
parent | 6bfd44faeed330c963602e2b06422af2c61921cf (diff) |
In the interrupt handler, if there is a DMA transfer in progress, do
not busy wait for the transfer to complete at the very beginning, as
this interrupt could be unrelated to the transfer; busywaiting could
cause the scsi command timeout to be triggered, and the code would not
recover correctly.
Instead, make the DMA check simply return, leaving the "busy" flag set;
and perform the usual interrupt handler duties, except for the phase
change.
test&ok millert@
Diffstat (limited to 'sys')
-rw-r--r-- | sys/arch/hp300/dev/mb89352.c | 35 | ||||
-rw-r--r-- | sys/arch/hp300/dev/spc.c | 17 |
2 files changed, 28 insertions, 24 deletions
diff --git a/sys/arch/hp300/dev/mb89352.c b/sys/arch/hp300/dev/mb89352.c index 3019c3bb91b..dcda7432de3 100644 --- a/sys/arch/hp300/dev/mb89352.c +++ b/sys/arch/hp300/dev/mb89352.c @@ -1,4 +1,4 @@ -/* $OpenBSD: mb89352.c,v 1.6 2004/08/21 18:00:26 miod Exp $ */ +/* $OpenBSD: mb89352.c,v 1.7 2004/08/30 17:01:43 miod Exp $ */ /* $NetBSD: mb89352.c,v 1.5 2000/03/23 07:01:31 thorpej Exp $ */ /* NecBSD: mb89352.c,v 1.4 1998/03/14 07:31:20 kmatsuda Exp */ @@ -1485,26 +1485,29 @@ spc_process_intr(void *arg, u_char ints) SPC_TRACE(("spc_process_intr ")); - if (sc->sc_dma_done != NULL && - sc->sc_state == SPC_CONNECTED && - (sc->sc_flags & SPC_DOINGDMA) != 0 && - (sc->sc_phase == PH_DATAOUT || sc->sc_phase == PH_DATAIN)) { - (*sc->sc_dma_done)(sc); - } - goto start; loop: /* * Loop until transfer completion. */ - /* - * First check for abnormal conditions, such as reset. - */ ints = spc_read(INTS); start: SPC_MISC(("ints = 0x%x ", ints)); + /* + * Check for the end of a DMA operation before doing anything else... + */ + if (sc->sc_dma_done != NULL && + sc->sc_state == SPC_CONNECTED && + (sc->sc_flags & SPC_DOINGDMA) != 0 && + (sc->sc_phase == PH_DATAOUT || sc->sc_phase == PH_DATAIN)) { + (*sc->sc_dma_done)(sc); + } + + /* + * Then check for abnormal conditions, such as reset. + */ if ((ints & INTS_RST) != 0) { printf("%s: SCSI bus reset\n", sc->sc_dev.dv_xname); goto reset; @@ -1734,6 +1737,16 @@ start: sc->sc_state != SPC_CONNECTED) goto out; + /* + * Do not change phase (yet) if we have a pending DMA operation. + */ + if (sc->sc_dma_done != NULL && + sc->sc_state == SPC_CONNECTED && + (sc->sc_flags & SPC_DOINGDMA) != 0 && + (sc->sc_phase == PH_DATAOUT || sc->sc_phase == PH_DATAIN)) { + goto out; + } + dophase: #if 0 if ((spc_read(PSNS) & PSNS_REQ) == 0) { diff --git a/sys/arch/hp300/dev/spc.c b/sys/arch/hp300/dev/spc.c index 7fa89855b19..83bfc354845 100644 --- a/sys/arch/hp300/dev/spc.c +++ b/sys/arch/hp300/dev/spc.c @@ -1,4 +1,4 @@ -/* $OpenBSD: spc.c,v 1.7 2004/08/25 21:00:37 miod Exp $ */ +/* $OpenBSD: spc.c,v 1.8 2004/08/30 17:01:43 miod Exp $ */ /* $NetBSD: spc.c,v 1.2 2003/11/17 14:37:59 tsutsui Exp $ */ /* @@ -246,18 +246,9 @@ spc_dio_dmadone(struct spc_softc *sc) int resid, trans; u_int8_t cmd; - /* wait DMA complete */ - if ((spc_read(SSTS) & SSTS_BUSY) != 0) { - int timeout = 1000; /* XXX how long? */ - while ((spc_read(SSTS) & SSTS_BUSY) != 0) { - if (--timeout < 0) { - printf("%s: DMA complete timeout\n", - sc->sc_dev.dv_xname); - timeout = 1000; - } - DELAY(1); - } - } + /* Check if the DMA operation is finished. */ + if ((spc_read(SSTS) & SSTS_BUSY) != 0) + return; sc->sc_flags &= ~SPC_DOINGDMA; if ((dsc->sc_dflags & SCSI_HAVEDMA) != 0) { |