Module Name:    src
Committed By:   jdolecek
Date:           Tue Aug  1 21:43:49 UTC 2017

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

Log Message:
adjust code to be closer to HEAD to it's easier to compare and find
regressions, undoing some changes which were actually not necessary


To generate a diff of this commit:
cvs rdiff -u -r1.30.4.29 -r1.30.4.30 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.30.4.29 src/sys/dev/ic/siisata.c:1.30.4.30
--- src/sys/dev/ic/siisata.c:1.30.4.29	Sun Jul 30 20:46:31 2017
+++ src/sys/dev/ic/siisata.c	Tue Aug  1 21:43:49 2017
@@ -1,4 +1,4 @@
-/* $NetBSD: siisata.c,v 1.30.4.29 2017/07/30 20:46:31 jdolecek Exp $ */
+/* $NetBSD: siisata.c,v 1.30.4.30 2017/08/01 21:43:49 jdolecek Exp $ */
 
 /* from ahcisata_core.c */
 
@@ -79,7 +79,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: siisata.c,v 1.30.4.29 2017/07/30 20:46:31 jdolecek Exp $");
+__KERNEL_RCSID(0, "$NetBSD: siisata.c,v 1.30.4.30 2017/08/01 21:43:49 jdolecek Exp $");
 
 #include <sys/types.h>
 #include <sys/param.h>
@@ -245,7 +245,10 @@ siisata_enable_port_interrupt(struct ata
 {
 	struct siisata_softc *sc = (struct siisata_softc *)chp->ch_atac;
 
-	/* enable CmdErrr+CmdCmpl interrupting */
+	/* clear any interrupts */
+	(void)PRREAD(sc, PRX(chp->ch_channel, PRO_PSS));
+	PRWRITE(sc, PRX(chp->ch_channel, PRO_PIS), 0xffffffff);
+	/* and enable CmdErrr+CmdCmpl interrupting */
 	PRWRITE(sc, PRX(chp->ch_channel, PRO_PIES),
 	    PR_PIS_CMDERRR | PR_PIS_CMDCMPL);
 }
@@ -259,12 +262,9 @@ siisata_init_port(struct siisata_softc *
 	schp = &sc->sc_channels[port];
 	chp = (struct ata_channel *)schp;
 
-	/*
-	 * Come out of reset. Disable no clearing of PR_PIS_CMDCMPL on read
-	 * of PR_PSS. Disable 32-bit PRB activation, we use 64-bit activation.
-	 */
+	/* come out of reset, 64-bit activation */
 	PRWRITE(sc, PRX(chp->ch_channel, PRO_PCC),
-	    PR_PC_32BA | PR_PC_INCOR | PR_PC_PORT_RESET);
+	    PR_PC_32BA | PR_PC_PORT_RESET);
 	/* initialize port */
 	siisata_reinit_port(chp, -1);
 	/* enable CmdErrr+CmdCmpl interrupting */
@@ -474,29 +474,25 @@ siisata_intr_port(struct siisata_channel
 	struct siisata_softc *sc =
 	    (struct siisata_softc *)schp->ata_channel.ch_atac;
 	struct ata_channel *chp = &schp->ata_channel;
-	struct ata_xfer *xfer;
-	int slot = -1;
+	struct ata_xfer *xfer = NULL;
 	uint32_t pss, pis, tfd = 0;
 	bool recover = false;
 
-	/* get slot status, clearing completion interrupt (PR_PIS_CMDCMPL) */
-	pss = PRREAD(sc, PRX(chp->ch_channel, PRO_PSS));
-
-	SIISATA_DEBUG_PRINT(("%s: %s port %d, pss 0x%x\n",
-	    SIISATANAME(sc), __func__, chp->ch_channel, pss), DEBUG_INTR);
-
-	/* if no errors, just process finished commands and we're done */
-	if (__predict_true((pss & PR_PSS_ATTENTION) == 0))
-		goto process;
-
 	pis = PRREAD(sc, PRX(chp->ch_channel, PRO_PIS));
 
 	SIISATA_DEBUG_PRINT(("%s: %s port %d, pis 0x%x ",
 	    SIISATANAME(sc), __func__, chp->ch_channel, pis),
 	    DEBUG_INTR);
 
-	/* clear */
-	PRWRITE(sc, PRX(chp->ch_channel, PRO_PIS), pis);
+	if (pis & PR_PIS_CMDCMPL) {
+		/* get slot status, clearing completion interrupt */
+		pss = PRREAD(sc, PRX(chp->ch_channel, PRO_PSS));
+
+		SIISATA_DEBUG_PRINT(("pss 0x%x\n", pss), DEBUG_INTR);
+	} else {
+		/* commands will be killed after recovery */
+		pss = 0xffffffff;
+	}
 
 	if (pis & PR_PIS_CMDERRR) {
 		uint32_t ec;
@@ -510,15 +506,12 @@ siisata_intr_port(struct siisata_channel
 		if (ec <= PR_PCE_DATAFISERROR) {
 			if (ec == PR_PCE_DEVICEERROR
 			    && (chp->ch_flags & ATACH_NCQ) == 0) {
-				uint32_t ps = PRREAD(sc,
-				    PRX(chp->ch_channel, PRO_PS));
-				/* This is only relevant for non-NCQ commands */
-				slot = PR_PS_ACTIVE_SLOT(ps);
+				xfer = ata_queue_get_active_xfer(chp);
 
 				/* read in specific information about error */
 				uint32_t prbfis = bus_space_read_stream_4(
 				    sc->sc_prt, sc->sc_prh,
-    				    PRSX(chp->ch_channel, slot,
+    				    PRSX(chp->ch_channel, xfer->c_slot,
 				    PRSO_FIS));
 
 				/* get status and error */
@@ -528,30 +521,39 @@ siisata_intr_port(struct siisata_channel
 				if (ATACH_ST(ntfd) & WDCS_ERR)
 					tfd = ntfd;
 			}
+
+			/*
+			 * We don't expect the recovery to trigger error,
+			 * but handle this just in case.
+			 */
+			if (!schp->sch_recovering) 
+				recover = true;
+			else {
+				aprint_error_dev(sc->sc_atac.atac_dev,
+				    "error ec %x while recovering\n", ec);
+
+				/* Command will be marked as errored out */
+				pss = 0;
+			}
 		} else {
 			aprint_error_dev(sc->sc_atac.atac_dev, "fatal error %d"
 			    " on channel %d (ctx 0x%x), resetting\n",
 			    ec, chp->ch_channel,
 			    PRREAD(sc, PRX(chp->ch_channel, PRO_PCR)));
 
-			tfd |= ATACH_ERR_ST(0, WDCS_BSY);
+			/* okay, we have a "Fatal Error" */
+			siisata_device_reset(chp);
 		}
-
-		if (!schp->sch_recovering)
-			recover = true;
-	} else {
-		/* Some other event, which we currently ignore */
 	}
 
+	/* clear some (ok, all) ints */
+	PRWRITE(sc, PRX(chp->ch_channel, PRO_PIS), 0xffffffff);
+
 	if (__predict_false(recover))
 		ata_channel_freeze(chp);
 
-	if (slot >= 0) {
-		if ((schp->sch_active_slots & (1 << slot)) != 0 &&
-		    (pss & (1 << slot)) == 0) {
-			xfer = ata_queue_hwslot_to_xfer(chp, slot);
-			xfer->c_intr(chp, xfer, tfd);
-		}
+	if (xfer != NULL) {
+		xfer->c_intr(chp, xfer, tfd);
 	} else {
 		/*
 		 * For NCQ, HBA halts processing when error is notified,
@@ -559,9 +561,8 @@ siisata_intr_port(struct siisata_channel
 		 * condition is cleared. Hence if a command is inactive,
 		 * it means it actually already finished successfully.
 		 */
-process:
-		for (slot=0; slot < SIISATA_MAX_SLOTS; slot++) {
-			if ((schp->sch_active_slots & (1 << slot)) != 0 &&
+		for (int slot=0; slot < SIISATA_MAX_SLOTS; slot++) {
+			if ((schp->sch_active_slots & __BIT(slot)) != 0 &&
 			    (pss & PR_PXSS(slot)) == 0) {
 				xfer = ata_queue_hwslot_to_xfer(chp, slot);
 				xfer->c_intr(chp, xfer, 0);
@@ -569,8 +570,10 @@ process:
 		}
 	}
 
-	if (__predict_false(recover))
+	if (__predict_false(recover)) {
+		ata_channel_thaw(chp);
 		siisata_channel_recover(chp, tfd);
+	}
 }
 
 static void
@@ -667,7 +670,7 @@ siisata_channel_recover(struct ata_chann
 		 * transfers.
 		 */
 reset:
-		siisata_reset_channel(chp, AT_POLL);
+		siisata_device_reset(chp);
 		goto out;
 		/* NOTREACHED */
 
@@ -696,7 +699,6 @@ reset:
 out:
 	/* Drive unblocked, back to normal operation */
 	schp->sch_recovering = false;
-	ata_channel_thaw(chp);
 	atastart(chp);
 }
 
@@ -727,18 +729,11 @@ siisata_reset_drive(struct ata_drive_dat
 	siisata_activate_prb(schp, xfer->c_slot);
 
 	for(i = 0; i < 3100; i++) {
-#if 1		/* XXX-jak-jd-ncq this block needs re-work... XXX */
-		PRWRITE(sc, PRX(chp->ch_channel, PRO_PCS), PR_PC_INCOR);
 		pss = PRREAD(sc, PRX(chp->ch_channel, PRO_PSS));
-		PRWRITE(sc, PRX(chp->ch_channel, PRO_PCC), PR_PC_INCOR);
 		if ((pss & PR_PXSS(xfer->c_slot)) == 0)
 			break;
 		if (pss & PR_PSS_ATTENTION)
 			break;
-#else
-		pss = PR_PXSS(xfer->c_slot);
-		/* XXX DO NOT MERGE UNTIL THIS IS FIXED XXX */
-#endif
 		ata_delay(10, "siiprb", flags);
 	}
 
@@ -854,6 +849,10 @@ siisata_probe_drive(struct ata_channel *
 	switch(sata_reset_interface(chp, sc->sc_prt, schp->sch_scontrol,
 		schp->sch_sstatus, AT_WAIT)) {
 	case SStatus_DET_DEV:
+		/* clear any interrupts */
+		(void)PRREAD(sc, PRX(chp->ch_channel, PRO_PSS));
+		PRWRITE(sc, PRX(chp->ch_channel, PRO_PIS), 0xffffffff);
+
 		/* wait for ready */
 		timed_out = 1;
 		for (i = 0; i < ATA_DELAY / 10; i++) {

Reply via email to