summaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorMiod Vallat <miod@cvs.openbsd.org>2004-08-30 17:01:44 +0000
committerMiod Vallat <miod@cvs.openbsd.org>2004-08-30 17:01:44 +0000
commit5ca0d3ab4dcdb0bec326f0f25fc437029de21575 (patch)
tree32dbc638300dbdc585595a1f57f99b18d422d7f6 /sys
parent6bfd44faeed330c963602e2b06422af2c61921cf (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.c35
-rw-r--r--sys/arch/hp300/dev/spc.c17
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) {