PERFORCE change 162966 for review
Alexander Motin
mav at FreeBSD.org
Thu May 28 20:08:17 UTC 2009
http://perforce.freebsd.org/chv.cgi?CH=162966
Change 162966 by mav at 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
More information about the p4-projects
mailing list