Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 7 Aug 2011 17:18:22 +0000 (UTC)
From:      Alexander Motin <mav@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-8@freebsd.org
Subject:   svn commit: r224694 - stable/8/sys/dev/ahci
Message-ID:  <201108071718.p77HIMUh009197@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: mav
Date: Sun Aug  7 17:18:22 2011
New Revision: 224694
URL: http://svn.freebsd.org/changeset/base/224694

Log:
  MFC r224498:
  In some cases, at least on Marvell 88SE912x controllers, Current Command
  Slot field of the PxCMD register may point to an empty command slot.
  That breaks command timeout detection logic, making impossible to find
  what command actually caused timeout, and leading to infinite wait.
  Workaround that by checking whether pointed command slot is really used
  and can timeout in its time. And if not, fallback to the dumb algorithm
  used with FBS -- let all commands to time out and then fail all of them.

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)

Modified: stable/8/sys/dev/ahci/ahci.c
==============================================================================
--- stable/8/sys/dev/ahci/ahci.c	Sun Aug  7 15:52:13 2011	(r224693)
+++ stable/8/sys/dev/ahci/ahci.c	Sun Aug  7 17:18:22 2011	(r224694)
@@ -1873,12 +1873,13 @@ ahci_execute_transaction(struct ahci_slo
 			device_printf(dev, "Poll timeout on slot %d port %d\n",
 			    slot->slot, port);
 			device_printf(dev, "is %08x cs %08x ss %08x "
-			    "rs %08x tfd %02x serr %08x\n",
+			    "rs %08x tfd %02x serr %08x cmd %08x\n",
 			    ATA_INL(ch->r_mem, AHCI_P_IS),
 			    ATA_INL(ch->r_mem, AHCI_P_CI),
 			    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));
+			    ATA_INL(ch->r_mem, AHCI_P_SERR),
+			    ATA_INL(ch->r_mem, AHCI_P_CMD));
 			et = AHCI_ERR_TIMEOUT;
 		}
 
@@ -1954,8 +1955,12 @@ ahci_timeout(struct ahci_slot *slot)
 		ccs = (ATA_INL(ch->r_mem, AHCI_P_CMD) & AHCI_P_CMD_CCS_MASK)
 		    >> AHCI_P_CMD_CCS_SHIFT;
 		if ((sstatus & (1 << slot->slot)) != 0 || ccs == slot->slot ||
-		    ch->fbs_enabled)
+		    ch->fbs_enabled || ch->wrongccs)
 			slot->state = AHCI_SLOT_EXECUTING;
+		else if ((ch->rslots & (1 << ccs)) == 0) {
+			ch->wrongccs = 1;
+			slot->state = AHCI_SLOT_EXECUTING;
+		}
 
 		callout_reset(&slot->timeout,
 		    (int)slot->ccb->ccb_h.timeout * hz / 2000,
@@ -1965,10 +1970,12 @@ ahci_timeout(struct ahci_slot *slot)
 
 	device_printf(dev, "Timeout on slot %d port %d\n",
 	    slot->slot, slot->ccb->ccb_h.target_id & 0x0f);
-	device_printf(dev, "is %08x cs %08x ss %08x rs %08x tfd %02x serr %08x\n",
+	device_printf(dev, "is %08x cs %08x ss %08x rs %08x tfd %02x "
+	    "serr %08x cmd %08x\n",
 	    ATA_INL(ch->r_mem, AHCI_P_IS), ATA_INL(ch->r_mem, AHCI_P_CI),
 	    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));
+	    ATA_INL(ch->r_mem, AHCI_P_TFD), ATA_INL(ch->r_mem, AHCI_P_SERR),
+	    ATA_INL(ch->r_mem, AHCI_P_CMD));
 
 	/* Handle frozen command. */
 	if (ch->frozen) {
@@ -1981,7 +1988,7 @@ ahci_timeout(struct ahci_slot *slot)
 		}
 		xpt_done(fccb);
 	}
-	if (!ch->fbs_enabled) {
+	if (!ch->fbs_enabled && !ch->wrongccs) {
 		/* Without FBS we know real timeout source. */
 		ch->fatalerr = 1;
 		/* Handle command with timeout. */
@@ -2579,6 +2586,7 @@ ahci_reset(device_t dev)
 		xpt_release_simq(ch->sim, TRUE);
 	ch->eslots = 0;
 	ch->toslots = 0;
+	ch->wrongccs = 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	Sun Aug  7 15:52:13 2011	(r224693)
+++ stable/8/sys/dev/ahci/ahci.h	Sun Aug  7 17:18:22 2011	(r224694)
@@ -426,6 +426,7 @@ struct ahci_channel {
 	int			resetting;	/* Hard-reset in progress. */
 	int			resetpolldiv;	/* Hard-reset poll divider. */
 	int			listening;	/* SUD bit is cleared. */
+	int			wrongccs;	/* CCS field in CMD was wrong */
 	union ccb		*frozen;	/* Frozen command */
 	struct callout		pm_timer;	/* Power management events */
 	struct callout		reset_timer;	/* Hard-reset timeout */



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