svn commit: r204095 - stable/8/sys/dev/ahci
Alexander Motin
mav at FreeBSD.org
Fri Feb 19 17:54:03 UTC 2010
Author: mav
Date: Fri Feb 19 17:54:03 2010
New Revision: 204095
URL: http://svn.freebsd.org/changeset/base/204095
Log:
MFC r203873:
With FBS enabled, we have no idea what command caused timeout.
Implement same logic as in siis(4) - wait for other commands
complete or timeout and then give some more time.
Modified:
stable/8/sys/dev/ahci/ahci.c
stable/8/sys/dev/ahci/ahci.h
Directory Properties:
stable/8/sys/ (props changed)
stable/8/sys/amd64/include/xen/ (props changed)
stable/8/sys/cddl/contrib/opensolaris/ (props changed)
stable/8/sys/contrib/dev/acpica/ (props changed)
stable/8/sys/contrib/pf/ (props changed)
stable/8/sys/dev/xen/xenpci/ (props changed)
stable/8/sys/netinet/ (props changed)
Modified: stable/8/sys/dev/ahci/ahci.c
==============================================================================
--- stable/8/sys/dev/ahci/ahci.c Fri Feb 19 17:45:47 2010 (r204094)
+++ stable/8/sys/dev/ahci/ahci.c Fri Feb 19 17:54:03 2010 (r204095)
@@ -1657,6 +1657,45 @@ ahci_execute_transaction(struct ahci_slo
return;
}
+/* Must be called with channel locked. */
+static void
+ahci_process_timeout(device_t dev)
+{
+ struct ahci_channel *ch = device_get_softc(dev);
+ int i;
+
+ mtx_assert(&ch->mtx, MA_OWNED);
+ /* Handle the rest of commands. */
+ 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_TIMEOUT);
+ }
+}
+
+/* Must be called with channel locked. */
+static void
+ahci_rearm_timeout(device_t dev)
+{
+ struct ahci_channel *ch = device_get_softc(dev);
+ int i;
+
+ mtx_assert(&ch->mtx, MA_OWNED);
+ for (i = 0; i < ch->numslots; i++) {
+ struct ahci_slot *slot = &ch->slot[i];
+
+ /* Do we have a running request on slot? */
+ if (slot->state < AHCI_SLOT_RUNNING)
+ continue;
+ if ((ch->toslots & (1 << i)) == 0)
+ continue;
+ callout_reset(&slot->timeout,
+ (int)slot->ccb->ccb_h.timeout * hz / 2000,
+ (timeout_t*)ahci_timeout, slot);
+ }
+}
+
/* Locked by callout mechanism. */
static void
ahci_timeout(struct ahci_slot *slot)
@@ -1693,7 +1732,6 @@ ahci_timeout(struct ahci_slot *slot)
ATA_INL(ch->r_mem, AHCI_P_SACT), ch->rslots,
ATA_INL(ch->r_mem, AHCI_P_TFD), ATA_INL(ch->r_mem, AHCI_P_SERR));
- ch->fatalerr = 1;
/* Handle frozen command. */
if (ch->frozen) {
union ccb *fccb = ch->frozen;
@@ -1705,14 +1743,28 @@ ahci_timeout(struct ahci_slot *slot)
}
xpt_done(fccb);
}
- /* Handle command with timeout. */
- ahci_end_transaction(&ch->slot[slot->slot], AHCI_ERR_TIMEOUT);
- /* Handle the rest of commands. */
- 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);
+ if (!ch->fbs_enabled) {
+ /* Without FBS we know real timeout source. */
+ ch->fatalerr = 1;
+ /* Handle command with timeout. */
+ ahci_end_transaction(&ch->slot[slot->slot], AHCI_ERR_TIMEOUT);
+ /* Handle the rest of commands. */
+ 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);
+ }
+ } else {
+ /* With FBS we wait for other commands timeout and pray. */
+ if (ch->toslots == 0)
+ xpt_freeze_simq(ch->sim, 1);
+ ch->toslots |= (1 << slot->slot);
+ if ((ch->rslots & ~ch->toslots) == 0)
+ ahci_process_timeout(dev);
+ else
+ device_printf(dev, " ... waiting for slots %08x\n",
+ ch->rslots & ~ch->toslots);
}
}
@@ -1809,10 +1861,6 @@ ahci_end_transaction(struct ahci_slot *s
ccb->ccb_h.status |= CAM_UNCOR_PARITY;
break;
case AHCI_ERR_TIMEOUT:
- /* Do no treat soft-reset timeout as fatal here. */
- if (ccb->ccb_h.func_code != XPT_ATA_IO ||
- !(ccb->ataio.cmd.flags & CAM_ATAIO_CONTROL))
- ch->fatalerr = 1;
if (!ch->readlog) {
xpt_freeze_simq(ch->sim, 1);
ccb->ccb_h.status &= ~CAM_STATUS_MASK;
@@ -1828,6 +1876,11 @@ ahci_end_transaction(struct ahci_slot *s
ch->oslots &= ~(1 << slot->slot);
ch->rslots &= ~(1 << slot->slot);
ch->aslots &= ~(1 << slot->slot);
+ if (et != AHCI_ERR_TIMEOUT) {
+ if (ch->toslots == (1 << slot->slot))
+ xpt_release_simq(ch->sim, TRUE);
+ ch->toslots &= ~(1 << slot->slot);
+ }
slot->state = AHCI_SLOT_EMPTY;
slot->ccb = NULL;
/* Update channel stats. */
@@ -1867,7 +1920,7 @@ ahci_end_transaction(struct ahci_slot *s
/* If we have no other active commands, ... */
if (ch->rslots == 0) {
/* if there was fatal error - reset port. */
- if (ch->fatalerr) {
+ if (ch->toslots != 0 || ch->fatalerr) {
ahci_reset(dev);
} else {
/* if we have slots in error, we can reinit port. */
@@ -1879,7 +1932,10 @@ ahci_end_transaction(struct ahci_slot *s
if (!ch->readlog && ch->numhslots)
ahci_issue_read_log(dev);
}
- }
+ /* If all the rest of commands are in timeout - give them chance. */
+ } else if ((ch->rslots & ~ch->toslots) == 0 &&
+ et != AHCI_ERR_TIMEOUT)
+ ahci_rearm_timeout(dev);
/* Start PM timer. */
if (ch->numrslots == 0 && ch->pm_level > 3) {
callout_schedule(&ch->pm_timer,
@@ -2143,7 +2199,10 @@ ahci_reset(device_t dev)
ch->hold[i] = NULL;
ch->numhslots--;
}
+ if (ch->toslots != 0)
+ xpt_release_simq(ch->sim, TRUE);
ch->eslots = 0;
+ ch->toslots = 0;
ch->fatalerr = 0;
/* Tell the XPT about the event */
xpt_async(AC_BUS_RESET, ch->path, NULL);
Modified: stable/8/sys/dev/ahci/ahci.h
==============================================================================
--- stable/8/sys/dev/ahci/ahci.h Fri Feb 19 17:45:47 2010 (r204094)
+++ stable/8/sys/dev/ahci/ahci.h Fri Feb 19 17:54:03 2010 (r204095)
@@ -401,6 +401,7 @@ struct ahci_channel {
uint32_t rslots; /* Running slots */
uint32_t aslots; /* Slots with atomic commands */
uint32_t eslots; /* Slots in error */
+ uint32_t toslots; /* Slots in timeout */
int numrslots; /* Number of running slots */
int numrslotspd[16];/* Number of running slots per dev */
int numtslots; /* Number of tagged slots */
More information about the svn-src-stable-8
mailing list