Module Name:    src
Committed By:   jdolecek
Date:           Sun Dec 22 20:54:00 UTC 2019

Modified Files:
        src/sys/dev/ic: mvsata.c

Log Message:
remove check for idle status when disabling EDMA, and always toggle
the disable regardless of current state - this particularly seems
to fail during error recovery, and on my system this also fails
during regular boot

this matches both FreeBSD and Linux drivers - neither of those checks
the idle status

should help with PR kern/52419 and maybe also the lock spinout part
of PR kern/52126


To generate a diff of this commit:
cvs rdiff -u -r1.49 -r1.50 src/sys/dev/ic/mvsata.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/dev/ic/mvsata.c
diff -u src/sys/dev/ic/mvsata.c:1.49 src/sys/dev/ic/mvsata.c:1.50
--- src/sys/dev/ic/mvsata.c:1.49	Sun Nov 10 21:16:35 2019
+++ src/sys/dev/ic/mvsata.c	Sun Dec 22 20:54:00 2019
@@ -1,4 +1,4 @@
-/*	$NetBSD: mvsata.c,v 1.49 2019/11/10 21:16:35 chs Exp $	*/
+/*	$NetBSD: mvsata.c,v 1.50 2019/12/22 20:54:00 jdolecek Exp $	*/
 /*
  * Copyright (c) 2008 KIYOHARA Takashi
  * All rights reserved.
@@ -26,7 +26,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: mvsata.c,v 1.49 2019/11/10 21:16:35 chs Exp $");
+__KERNEL_RCSID(0, "$NetBSD: mvsata.c,v 1.50 2019/12/22 20:54:00 jdolecek Exp $");
 
 #include "opt_mvsata.h"
 
@@ -198,7 +198,7 @@ static uint32_t mvsata_softreset(struct 
 #ifndef MVSATA_WITHOUTDMA
 static void mvsata_edma_reset_qptr(struct mvsata_port *);
 static inline void mvsata_edma_enable(struct mvsata_port *);
-static int mvsata_edma_disable(struct mvsata_port *, int, int);
+static void mvsata_edma_disable(struct mvsata_port *, int, int);
 static void mvsata_edma_config(struct mvsata_port *, enum mvsata_edmamode);
 
 static void mvsata_edma_setup_crqb(struct mvsata_port *, int,
@@ -3425,54 +3425,32 @@ mvsata_edma_enable(struct mvsata_port *m
 	MVSATA_EDMA_WRITE_4(mvport, EDMA_CMD, EDMA_CMD_EENEDMA);
 }
 
-static int
+static void
 mvsata_edma_disable(struct mvsata_port *mvport, int timeout, int wflags)
 {
 	struct ata_channel *chp = &mvport->port_ata_channel;
-	uint32_t status, command;
-	uint32_t idlestatus = EDMA_S_EDMAIDLE | EDMA_S_ECACHEEMPTY;
+	uint32_t command;
 	int t;
 
 	ata_channel_lock_owned(chp);
 
-	if (MVSATA_EDMA_READ_4(mvport, EDMA_CMD) & EDMA_CMD_EENEDMA) {
-
-		timeout = mstohz(timeout + hztoms(1) - 1);
-
-		for (t = 0; ; ++t) {
-			status = MVSATA_EDMA_READ_4(mvport, EDMA_S);
-			if ((status & idlestatus) == idlestatus)
-				break;
-			if (t >= timeout)
-				break;
-			ata_delay(chp, hztoms(1), "mvsata_edma1", wflags);
-		}
-		if (t >= timeout) {
-			aprint_error("%s:%d:%d: unable to stop EDMA\n",
-			    device_xname(MVSATA_DEV2(mvport)),
-			    mvport->port_hc->hc, mvport->port);
-			return EBUSY;
-		}
+	/* The disable bit (eDsEDMA) is self negated. */
+	MVSATA_EDMA_WRITE_4(mvport, EDMA_CMD, EDMA_CMD_EDSEDMA);
 
-		/* The disable bit (eDsEDMA) is self negated. */
-		MVSATA_EDMA_WRITE_4(mvport, EDMA_CMD, EDMA_CMD_EDSEDMA);
+	timeout = mstohz(timeout + hztoms(1) - 1);
 
-		for (t = 0; ; ++t) {
-			command = MVSATA_EDMA_READ_4(mvport, EDMA_CMD);
-			if (!(command & EDMA_CMD_EENEDMA))
-				break;
-			if (t >= timeout)
-				break;
-			ata_delay(chp, hztoms(1), "mvsata_edma2", wflags);
-		}
-		if (t >= timeout) {
-			aprint_error("%s:%d:%d: unable to re-enable EDMA\n",
-			    device_xname(MVSATA_DEV2(mvport)),
-			    mvport->port_hc->hc, mvport->port);
-			return EBUSY;
-		}
+	for (t = 0; ; ++t) {
+		command = MVSATA_EDMA_READ_4(mvport, EDMA_CMD);
+		if (!(command & EDMA_CMD_EENEDMA))
+			return;
+		if (t >= timeout)
+			break;
+		ata_delay(chp, hztoms(1), "mvsata_edma2", wflags);
 	}
-	return 0;
+
+	aprint_error("%s:%d:%d: unable to disable EDMA\n",
+	    device_xname(MVSATA_DEV2(mvport)),
+	    mvport->port_hc->hc, mvport->port);
 }
 
 /*

Reply via email to