PERFORCE change 164373 for review

Alexander Motin mav at FreeBSD.org
Sun Jun 14 19:49:35 UTC 2009


http://perforce.freebsd.org/chv.cgi?CH=164373

Change 164373 by mav at mav_mavbook on 2009/06/14 19:49:15

	Tune error reporting.
	Do not do any error recovery here except controller itself, give
	all information to XPT and wait until it will handle everything.

Affected files ...

.. //depot/projects/scottl-camlock/src/sys/dev/ahci/ahci.c#30 edit
.. //depot/projects/scottl-camlock/src/sys/dev/ahci/ahci.h#14 edit

Differences ...

==== //depot/projects/scottl-camlock/src/sys/dev/ahci/ahci.c#30 (text+ko) ====

@@ -834,7 +834,7 @@
 {
 	device_t dev = (device_t)data;
 	struct ahci_channel *ch = device_get_softc(dev);
-	uint32_t istatus, cstatus, sstatus, res, err;
+	uint32_t istatus, cstatus, sstatus, ok, err;
 	enum ahci_err_type et;
 	int i, ccs;
 
@@ -851,42 +851,58 @@
 		ahci_phy_check_events(dev);
 	/* Process command errors */
 	if (istatus & (AHCI_P_IX_IF|AHCI_P_IX_HBD|AHCI_P_IX_HBF|AHCI_P_IX_TFE)) {
-device_printf(dev, "%s ERROR is %08x cs %08x ss %08x rs %08x\n", __func__, istatus, cstatus, sstatus, ch->rslots);
+device_printf(dev, "%s ERROR is %08x cs %08x ss %08x rs %08x tfd %02x\n",
+    __func__, istatus, cstatus, sstatus, ch->rslots, ATA_INL(ch->r_mem, AHCI_P_TFD));
 		ccs = (ATA_INL(ch->r_mem, AHCI_P_CMD) & AHCI_P_CMD_CCS_MASK)
 		    >> AHCI_P_CMD_CCS_SHIFT;
 		/* Kick controller into sane state */
 		ahci_stop(dev);
 		ahci_clo(dev);
 		ahci_start(dev);
-		res = ch->rslots;
+		ok = ch->rslots & ~(cstatus | sstatus);
 		err = ch->rslots & (cstatus | sstatus);
 	} else {
 		ccs = 0;
-		res = ch->rslots & ~(cstatus | sstatus);
+		ok = ch->rslots & ~(cstatus | sstatus);
 		err = 0;
 	}
-	/* On error, requeue frozen command. */
-	if (err && ch->frozen) {
-		union ccb *fccb = ch->frozen;
-		ch->frozen = NULL;
-		xpt_release_simq(ch->sim, TRUE);
-		fccb->ccb_h.status = CAM_REQUEUE_REQ;
-		xpt_done(fccb);
+	/* Complete all successfull commands. */
+	for (i = 0; i < ch->numslots; i++) {
+		if ((ok >> i) & 1)
+			ahci_end_transaction(&ch->slot[i], AHCI_ERR_NONE);
 	}
-	/* Check all slots. */
-	for (i = 0; i < ch->numslots; i++) {
-		/* Do we have an event on slot? */
-	        if ((res & (1 << i)) == 0)
-			continue;
-		/* Process request completion. */
-		et = AHCI_ERR_NONE;
-		if ((err >> i) & 1) {
-			if (i == ccs)
-				et = AHCI_ERR_REAL;
-			else
-				et = AHCI_ERR_BTW;
+	/* On error, complete the rest of commands with error statuses. */
+	if (err) {
+		xpt_freeze_simq(ch->sim, ch->numrslots);
+		if (ch->frozen) {
+			union ccb *fccb = ch->frozen;
+			ch->frozen = NULL;
+			fccb->ccb_h.status = CAM_REQUEUE_REQ | CAM_RELEASE_SIMQ;
+			xpt_done(fccb);
+		}
+		for (i = 0; i < ch->numslots; i++) {
+			/* XXX: reqests in loading state. */
+			if (((err >> i) & 1) == 0)
+				continue;
+			if (istatus & AHCI_P_IX_IF) {
+				/* SATA error */
+				et = AHCI_ERR_SATA;
+			} else if (istatus & AHCI_P_IX_TFE) {
+				/* Task File Error */
+				if (ch->numtslots == 0) {
+					/* Untagged operation. */
+					if (i == ccs)
+						et = AHCI_ERR_TFE;
+					else
+						et = AHCI_ERR_INNOCENT;
+				} else {
+					/* Tagged operation. */
+					et = AHCI_ERR_TFE;
+				}
+			} else
+				et = AHCI_ERR_INVALID;
+			ahci_end_transaction(&ch->slot[i], et);
 		}
-		ahci_end_transaction(&ch->slot[i], et);
 	}
 	mtx_unlock(&ch->mtx);
 }
@@ -990,6 +1006,7 @@
 //device_printf(slot->dev, "%s slot %d\n", __func__, slot->slot);
 	if (error) {
 		device_printf(slot->dev, "DMA load error\n");
+		xpt_freeze_simq(ch->sim, 1);
 		ahci_end_transaction(slot, AHCI_ERR_INVALID);
 		return;
 	}
@@ -1029,6 +1046,7 @@
 	/* Setup the FIS for this request */
 	if (!(fis_size = ahci_setup_fis(ctp, ccb, slot->slot))) {
 		device_printf(ch->dev, "Setting up SATA FIS failed\n");
+		xpt_freeze_simq(ch->sim, 1);
 		ahci_end_transaction(slot, AHCI_ERR_INVALID);
 		return;
 	}
@@ -1097,20 +1115,21 @@
 				device_printf(ch->dev,
 				    "Poll error on slot %d, TFD: %04x\n",
 				    slot->slot, ATA_INL(ch->r_mem, AHCI_P_TFD));
-				et = AHCI_ERR_REAL;
+				et = AHCI_ERR_TFE;
 				break;
 			}
 		}
 		if (timeout && (count >= timeout)) {
 			device_printf(ch->dev,
 			    "Poll timeout on slot %d\n", slot->slot);
-			et = CAM_CMD_TIMEOUT;
+			et = AHCI_ERR_TIMEOUT;
 		}
 		if (et != AHCI_ERR_NONE) {
 			/* Kick controller into sane state */
 			ahci_stop(ch->dev);
 			ahci_clo(ch->dev);
 			ahci_start(ch->dev);
+			xpt_freeze_simq(ch->sim, 1);
 		}
 		ahci_end_transaction(slot, et);
 		return;
@@ -1127,11 +1146,31 @@
 {
 	device_t dev = slot->dev;
 	struct ahci_channel *ch = device_get_softc(dev);
+	int i;
 
 device_printf(dev, "Timeout on slot %d\n", slot->slot);
+
+	/* Kick controller into sane state. */
+	ahci_stop(ch->dev);
+	ahci_clo(ch->dev);
+	ahci_start(ch->dev);
+
+	xpt_freeze_simq(ch->sim, ch->numrslots);
+	/* Handle command with timeout. */
 	ahci_end_transaction(&ch->slot[slot->slot], AHCI_ERR_TIMEOUT);
-	/* XXX: This is wrong for NCQ error recovery. */
-	ahci_reset(dev);
+	/* Handle the rest of commands. */
+	if (ch->frozen) {
+		union ccb *fccb = ch->frozen;
+		ch->frozen = NULL;
+		fccb->ccb_h.status = CAM_REQUEUE_REQ | CAM_RELEASE_SIMQ;
+		xpt_done(fccb);
+	}
+	for (i = 0; i < ch->numslots; i++) {
+		/* Do we have a running request on slot? */
+		if (ch->slot[i].state < AHCI_SLOT_RUNNING)
+			continue;
+		ahci_end_transaction(&ch->slot[i], AHCI_ERR_INNOCENT);
+	}
 }
 
 /* Must be called with channel locked. */
@@ -1149,19 +1188,20 @@
 	    BUS_DMASYNC_POSTWRITE);
 	/* Read result registers to the result struct
 	 * May be incorrect if several commands finished same time,
-	 * so read only when sure.
+	 * so read only when sure or have to.
 	 */
 	if (ccb->ccb_h.func_code == XPT_ATA_IO) {
 		struct ata_res *res = &ccb->ataio.res;
 
-		if ((et == AHCI_ERR_REAL) ||
+		if ((et == AHCI_ERR_TFE) ||
 		    (ccb->ataio.cmd.flags & CAM_ATAIO_NEEDRESULT)) {
 			u_int8_t *fis = ch->dma.rfis + 0x40;
+			uint16_t tfd = ATA_INL(ch->r_mem, AHCI_P_TFD);
 
 			bus_dmamap_sync(ch->dma.rfis_tag, ch->dma.rfis_map,
 			    BUS_DMASYNC_POSTREAD);
-			res->status = fis[2];
-			res->error = fis[3];
+			res->status = tfd;
+			res->error = tfd >> 8;
 			res->lba_low = fis[4];
 			res->lba_mid = fis[5];
 			res->lba_high = fis[6];
@@ -1182,6 +1222,8 @@
 	}
 	/* Set proper result status. */
 	ccb->ccb_h.status &= ~CAM_STATUS_MASK;
+	if (et != AHCI_ERR_NONE)
+		ccb->ccb_h.status |= CAM_RELEASE_SIMQ;
 	switch (et) {
 	case AHCI_ERR_NONE:
 		ccb->ccb_h.status |= CAM_REQ_CMP;
@@ -1191,18 +1233,18 @@
 	case AHCI_ERR_INVALID:
 		ccb->ccb_h.status |= CAM_REQ_INVALID;
 		break;
-	case AHCI_ERR_REAL:
+	case AHCI_ERR_INNOCENT:
+		ccb->ccb_h.status |= CAM_REQUEUE_REQ;
+		break;
+	case AHCI_ERR_TFE:
 		if (ccb->ccb_h.func_code == XPT_SCSI_IO) {
 			ccb->ccb_h.status |= CAM_SCSI_STATUS_ERROR;
 			ccb->csio.scsi_status = SCSI_STATUS_CHECK_COND;
 		} else
 			ccb->ccb_h.status |= CAM_REQ_CMP_ERR;
 		break;
-	case AHCI_ERR_BTW:
-		ccb->ccb_h.status |= CAM_REQUEUE_REQ;
-		break;
-	case AHCI_ERR_RESET:
-		ccb->ccb_h.status |= CAM_SCSI_BUS_RESET;
+	case AHCI_ERR_SATA:
+			ccb->ccb_h.status |= CAM_UNCOR_PARITY;
 		break;
 	case AHCI_ERR_TIMEOUT:
 		ccb->ccb_h.status |= CAM_CMD_TIMEOUT;
@@ -1362,12 +1404,12 @@
 
 	if (bootverbose)
 		device_printf(dev, "AHCI reset...\n");
+	xpt_freeze_simq(ch->sim, ch->numrslots);
 	/* Requeue freezed command. */
 	if (ch->frozen) {
 		union ccb *fccb = ch->frozen;
 		ch->frozen = NULL;
-		xpt_release_simq(ch->sim, TRUE);
-		fccb->ccb_h.status = CAM_SCSI_BUS_RESET;
+		fccb->ccb_h.status = CAM_REQUEUE_REQ | CAM_RELEASE_SIMQ;
 		xpt_done(fccb);
 	}
 	/* Kill the engine and requeue all running commands. */
@@ -1376,7 +1418,8 @@
 		/* Do we have a running request on slot? */
 		if (ch->slot[i].state < AHCI_SLOT_RUNNING)
 			continue;
-		ahci_end_transaction(&ch->slot[i], AHCI_ERR_RESET);
+		/* XXX; Commands in loading state. */
+		ahci_end_transaction(&ch->slot[i], AHCI_ERR_INNOCENT);
 	}
 	/* Disable port interrupts */
 	ATA_OUTL(ch->r_mem, AHCI_P_IE, 0);

==== //depot/projects/scottl-camlock/src/sys/dev/ahci/ahci.h#14 (text+ko) ====

@@ -379,12 +379,12 @@
 };
 
 enum ahci_err_type {
-	AHCI_ERR_NONE,
-	AHCI_ERR_INVALID,
-	AHCI_ERR_REAL,
-	AHCI_ERR_BTW,
-	AHCI_ERR_RESET,
-	AHCI_ERR_TIMEOUT
+	AHCI_ERR_NONE,		/* No error */
+	AHCI_ERR_INVALID,	/* Error detected by us before submitting. */
+	AHCI_ERR_INNOCENT,	/* Innocent victim. */
+	AHCI_ERR_TFE,		/* Task File Error. */
+	AHCI_ERR_SATA,		/* SATA error. */
+	AHCI_ERR_TIMEOUT,	/* Command execution timeout. */
 };
 
 /* macros to hide busspace uglyness */


More information about the p4-projects mailing list