Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 28 May 2009 20:08:15 GMT
From:      Alexander Motin <mav@FreeBSD.org>
To:        Perforce Change Reviews <perforce@freebsd.org>
Subject:   PERFORCE change 162966 for review
Message-ID:  <200905282008.n4SK8FQm090616@repoman.freebsd.org>

next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=162966

Change 162966 by mav@mav_mavbook on 2009/05/28 20:08:04

	Improve error reporting. Add request timeout handling.

Affected files ...

.. //depot/projects/scottl-camlock/src/sys/dev/ahci/ahci.c#5 edit
.. //depot/projects/scottl-camlock/src/sys/dev/ahci/ahci.h#2 edit

Differences ...

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

@@ -66,7 +66,8 @@
 static void ahci_begin_transaction(device_t dev, union ccb *ccb);
 static void ahci_dmasetprd(void *arg, bus_dma_segment_t *segs, int nsegs, int error);
 static void ahci_execute_command(struct ahci_slot *slot);
-static void ahci_end_transaction(struct ahci_slot *slot, int err);
+static void ahci_timeout(struct ahci_slot *slot);
+static void ahci_end_transaction(struct ahci_slot *slot, enum ahci_err_type et);
 //static int ahci_pm_read(device_t dev, int port, int reg, u_int32_t *result);
 //static int ahci_pm_write(device_t dev, int port, int reg, u_int32_t result);
 static int ahci_hardreset(device_t dev, int port, uint32_t *signature);
@@ -621,7 +622,8 @@
 	device_t dev = (device_t)data;
 	struct ahci_channel *ch = device_get_softc(dev);
 	uint32_t istatus, cstatus, res, err;
-	int i;
+	enum ahci_err_type et;
+	int i, ccs;
 
 	mtx_lock(&ch->mtx);
 	/* Read interrupt and command statuses. */
@@ -641,12 +643,15 @@
 
 	if ((istatus & AHCI_STATBITS) && (cstatus & ch->rslots)) {
 device_printf(dev, "%s ERROR is %08x cs %08x rs %08x\n", __func__, istatus, cstatus, ch->rslots);
+		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_start(dev);
 		res = ch->rslots;
 		err = ch->rslots & cstatus;
 	} else {
+		ccs = 0;
 		res = ch->rslots & ~cstatus;
 		err = 0;
 	}
@@ -662,7 +667,14 @@
 			continue;
 		}
 		/* Process request completion. */
-		ahci_end_transaction(&ch->slot[i], err & (1 << i));
+		et = AHCI_ERR_NONE;
+		if ((err >> i) & 1) {
+			if (i == ccs)
+				et = AHCI_ERR_REAL;
+			else
+				et = AHCI_ERR_BTW;
+		}
+		ahci_end_transaction(&ch->slot[i], et);
 	}
 	mtx_unlock(&ch->mtx);
 }
@@ -842,14 +854,38 @@
 	}
 
 	/* start the timeout */
-//	callout_reset(&request->callout, request->timeout * hz,
-//		  (timeout_t*)ata_timeout, request);
+	callout_reset(&slot->timeout, (int)slot->ccb->ccb_h.timeout * hz / 1000,
+	    (timeout_t*)ahci_timeout, slot);
 	return;
 }
 
-/* must be called with ATA channel locked and state_mtx held */
+/* Locked by callout mechanism. */
+static void
+ahci_timeout(struct ahci_slot *slot)
+{
+	device_t dev = slot->dev;
+	struct ahci_channel *ch = device_get_softc(dev);
+	enum ahci_err_type et;
+	int i;
+
+device_printf(dev, "Timeout on slot %d\n", slot->slot);
+	ahci_stop(dev);
+	for (i = 0; i < AHCI_MAX_SLOTS; i++) {
+		/* Do we have a running request on slot? */
+	        if (ch->slot[i].state < AHCI_SLOT_RUNNING)
+			continue;
+		if (i == slot->slot)
+			et = AHCI_ERR_TIMEOUT;
+		else
+			et = AHCI_ERR_RESET;
+		ahci_end_transaction(&ch->slot[i], et);
+	}
+	ahci_reset(dev);
+}
+
+/* Must be called with channel locked. */
 static void
-ahci_end_transaction(struct ahci_slot *slot, int err)
+ahci_end_transaction(struct ahci_slot *slot, enum ahci_err_type et)
 {
 	device_t dev = slot->dev;
 	struct ahci_channel *ch = device_get_softc(dev);
@@ -858,7 +894,7 @@
 
 //device_printf(dev, "%s slot %d\n", __func__, slot->slot);
 	/* kill the timeout */
-//	callout_stop(&request->callout);
+	callout_stop(&slot->timeout);
 
 	/* get status */
 	tf_data = ATA_INL(ch->r_mem, AHCI_P_TFD);
@@ -901,11 +937,13 @@
 		bus_dmamap_unload(ch->dma.data_tag, slot->dma.data_map);
 	}
 
-	if (err == 0) {
+	switch (et) {
+	case AHCI_ERR_NONE:
 		slot->ccb->ccb_h.status = CAM_REQ_CMP;
 		if (slot->ccb->ccb_h.func_code == XPT_SCSI_IO)
 			slot->ccb->csio.scsi_status = SCSI_STATUS_OK;
-	} else {
+		break;
+	case AHCI_ERR_REAL:
 		if (slot->ccb->ccb_h.func_code == XPT_SCSI_IO) {
 			slot->ccb->ccb_h.status = CAM_SCSI_STATUS_ERROR;
 			slot->ccb->csio.scsi_status = SCSI_STATUS_CHECK_COND;
@@ -913,6 +951,18 @@
 			slot->ccb->ccb_h.status = CAM_REQ_CMP_ERR;
 			slot->ccb->ataio.status = tf_data;
 		}
+		break;
+	case AHCI_ERR_BTW:
+		slot->ccb->ccb_h.status = CAM_REQUEUE_REQ;
+		break;
+	case AHCI_ERR_RESET:
+		slot->ccb->ccb_h.status = CAM_SCSI_BUS_RESET;
+		break;
+	case AHCI_ERR_TIMEOUT:
+		slot->ccb->ccb_h.status = CAM_CMD_TIMEOUT;
+		break;
+	default:
+		slot->ccb->ccb_h.status = CAM_REQ_CMP_ERR;
 	}
 	xpt_done(slot->ccb);
 
@@ -1387,7 +1437,7 @@
 		slot->slot = i;
 		slot->state = AHCI_SLOT_EMPTY;
 		slot->ccb = NULL;
-		callout_init(&slot->timeout, 1);
+		callout_init_mtx(&slot->timeout, &ch->mtx, 0);
 
 		if (bus_dma_tag_create(ch->dma.dmatag, PAGE_SIZE, PAGE_SIZE,
 			       ch->dma.max_address, BUS_SPACE_MAXADDR,

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

@@ -206,6 +206,7 @@
 #define         AHCI_P_CMD_CLO      0x00000008
 #define         AHCI_P_CMD_FRE      0x00000010
 #define         AHCI_P_CMD_CCS_MASK 0x00001f00
+#define         AHCI_P_CMD_CCS_SHIFT 8
 #define         AHCI_P_CMD_ISS      0x00002000
 #define         AHCI_P_CMD_FR       0x00004000
 #define         AHCI_P_CMD_CR       0x00008000
@@ -450,6 +451,14 @@
 	} interrupt[AHCI_MAX_PORTS];
 };
 
+enum ahci_err_type {
+	AHCI_ERR_NONE,
+	AHCI_ERR_REAL,
+	AHCI_ERR_BTW,
+	AHCI_ERR_RESET,
+	AHCI_ERR_TIMEOUT
+};
+
 /* disk bay/enclosure related */
 #define         ATA_LED_OFF             0x00
 #define         ATA_LED_RED             0x01



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200905282008.n4SK8FQm090616>