Module Name:    src
Committed By:   jdolecek
Date:           Sun Oct 21 18:13:14 UTC 2018

Modified Files:
        src/sys/dev/ic [jdolecek-ncqfixes]: siisata.c

Log Message:
decouple siisata_reset_channel() from siisata_reinit_port(); the former
now needs channel lock, but we don't have it in siisata_init_port()
during attach

instead call siisata_reset_channel() when siisata_reinit_port() fails,
and ignore the error during attach


To generate a diff of this commit:
cvs rdiff -u -r1.35.6.10 -r1.35.6.11 src/sys/dev/ic/siisata.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/siisata.c
diff -u src/sys/dev/ic/siisata.c:1.35.6.10 src/sys/dev/ic/siisata.c:1.35.6.11
--- src/sys/dev/ic/siisata.c:1.35.6.10	Mon Oct 15 21:18:53 2018
+++ src/sys/dev/ic/siisata.c	Sun Oct 21 18:13:14 2018
@@ -1,4 +1,4 @@
-/* $NetBSD: siisata.c,v 1.35.6.10 2018/10/15 21:18:53 jdolecek Exp $ */
+/* $NetBSD: siisata.c,v 1.35.6.11 2018/10/21 18:13:14 jdolecek Exp $ */
 
 /* from ahcisata_core.c */
 
@@ -79,7 +79,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: siisata.c,v 1.35.6.10 2018/10/15 21:18:53 jdolecek Exp $");
+__KERNEL_RCSID(0, "$NetBSD: siisata.c,v 1.35.6.11 2018/10/21 18:13:14 jdolecek Exp $");
 
 #include <sys/types.h>
 #include <sys/param.h>
@@ -162,7 +162,7 @@ void siisata_bio_abort(struct ata_channe
 void siisata_bio_kill_xfer(struct ata_channel *, struct ata_xfer *, int);
 int siisata_exec_command(struct ata_drive_datas *, struct ata_xfer *);
 
-static void siisata_reinit_port(struct ata_channel *, int);
+static int siisata_reinit_port(struct ata_channel *, int);
 static void siisata_device_reset(struct ata_channel *);
 static void siisata_activate_prb(struct siisata_channel *, int);
 static void siisata_deactivate_prb(struct siisata_channel *, int);
@@ -261,11 +261,12 @@ siisata_enable_port_interrupt(struct ata
 	    PR_PIS_CMDERRR | PR_PIS_CMDCMPL);
 }
 
-static void
+static int
 siisata_init_port(struct siisata_softc *sc, int port)
 {
 	struct siisata_channel *schp;
 	struct ata_channel *chp;
+	int error;
 
 	schp = &sc->sc_channels[port];
 	chp = (struct ata_channel *)schp;
@@ -277,11 +278,13 @@ siisata_init_port(struct siisata_softc *
 	PRWRITE(sc, PRX(chp->ch_channel, PRO_PCC),
 	    PR_PC_32BA | PR_PC_INCOR | PR_PC_PORT_RESET);
 	/* initialize port */
-	siisata_reinit_port(chp, -1);
+	error = siisata_reinit_port(chp, -1);
 	/* enable CmdErrr+CmdCmpl interrupting */
 	siisata_enable_port_interrupt(chp);
 	/* enable port interrupt */
 	GRWRITE(sc, GR_GC, GRREAD(sc, GR_GC) | GR_GC_PXIE(chp->ch_channel));
+
+	return error;
 }
 
 static void
@@ -398,7 +401,7 @@ siisata_attach_port(struct siisata_softc
 		return;
 	}
 
-	siisata_init_port(sc, port);
+	(void)siisata_init_port(sc, port);
 
 	ata_channel_attach(chp);
 
@@ -450,15 +453,22 @@ siisata_detach(struct siisata_softc *sc,
 void
 siisata_resume(struct siisata_softc *sc)
 {
-	int i;
-
 	/* come out of reset state */
 	GRWRITE(sc, GR_GC, 0);
 
-	for (i = 0; i < sc->sc_atac.atac_nchannels; i++) {
-		siisata_init_port(sc, i);
-	}
+	for (int port = 0; port < sc->sc_atac.atac_nchannels; port++) {
+		int error;
+
+		error = siisata_init_port(sc, port);
+		if (error) {
+			struct siisata_channel *schp = &sc->sc_channels[port];
+			struct ata_channel *chp = (struct ata_channel *)schp;
 
+			ata_channel_lock(chp);
+			siisata_reset_channel(chp, AT_POLL);
+			ata_channel_unlock(chp);
+		}
+	}
 }
 
 int
@@ -625,7 +635,7 @@ siisata_channel_recover(struct ata_chann
 	}
 
 	KASSERT(drive >= 0);
-	siisata_reinit_port(chp, drive);
+	(void)siisata_reinit_port(chp, drive);
 
 	ata_recovery_resume(chp, drive, tfd, flags);
 
@@ -648,7 +658,8 @@ siisata_reset_drive(struct ata_drive_dat
 
 	ata_channel_lock_owned(chp);
 
-	siisata_reinit_port(chp, drvp->drive);
+	if (siisata_reinit_port(chp, drvp->drive))
+		siisata_reset_channel(chp, flags);
 
 	/* get a slot for running the command on */
 	if (!ata_queue_alloc_slot(chp, &c_slot, ATA_MAX_OPENINGS)) {
@@ -815,7 +826,8 @@ siisata_probe_drive(struct ata_channel *
 			aprint_error_dev(sc->sc_atac.atac_dev,
 			    "timed out waiting for PORT_READY on port %d, " 
 			    "reinitializing\n", chp->ch_channel);
-			siisata_reinit_port(chp, -1);
+			if (siisata_reinit_port(chp, -1))
+				siisata_reset_channel(chp, AT_WAIT);
 		}
 
 		prb = schp->sch_prb[c_slot];
@@ -851,7 +863,8 @@ siisata_probe_drive(struct ata_channel *
 			    PRREAD(sc, PRX(chp->ch_channel, PRO_PCE)),
 			    PRREAD(sc, PRX(chp->ch_channel, PRO_PSS)),
 			    PRREAD(sc, PRX(chp->ch_channel, PRO_PIS)));
-			siisata_reinit_port(chp, -1);
+			if (siisata_reinit_port(chp, -1))
+				siisata_reset_channel(chp, AT_WAIT);
 			break;
 		}
 
@@ -1427,12 +1440,12 @@ siisata_deactivate_prb(struct siisata_ch
 	SIISATA_PRB_SYNC(sc, schp, slot, BUS_DMASYNC_POSTWRITE);
 }
 
-static void
+static int
 siisata_reinit_port(struct ata_channel *chp, int drive)
 {
 	struct siisata_softc *sc = (struct siisata_softc *)chp->ch_atac;
 	int ps;
-
+	int error = 0;
 
 	if (chp->ch_ndrives > 1) {
 		/*
@@ -1465,13 +1478,13 @@ siisata_reinit_port(struct ata_channel *
 	}
 	if ((ps & PR_PS_PORT_READY) == 0) {
 		printf("%s: timeout waiting for port to be ready\n", __func__);
-		ata_channel_lock(chp);
-		siisata_reset_channel(chp, AT_POLL);
-		ata_channel_unlock(chp);
+		error = EBUSY;
 	}
 
 	if (chp->ch_ndrives > 1)
 		PRWRITE(sc, PRX(chp->ch_channel, PRO_PCS), PR_PC_PMP_ENABLE);
+
+	return error;
 }
 
 static void

Reply via email to