From owner-svn-src-stable-8@FreeBSD.ORG Fri Feb 19 17:54:03 2010 Return-Path: Delivered-To: svn-src-stable-8@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id D6828106568F; Fri, 19 Feb 2010 17:54:03 +0000 (UTC) (envelope-from mav@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id C4BC58FC08; Fri, 19 Feb 2010 17:54:03 +0000 (UTC) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.3/8.14.3) with ESMTP id o1JHs3iL056375; Fri, 19 Feb 2010 17:54:03 GMT (envelope-from mav@svn.freebsd.org) Received: (from mav@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id o1JHs3Ge056372; Fri, 19 Feb 2010 17:54:03 GMT (envelope-from mav@svn.freebsd.org) Message-Id: <201002191754.o1JHs3Ge056372@svn.freebsd.org> From: Alexander Motin Date: Fri, 19 Feb 2010 17:54:03 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-8@freebsd.org X-SVN-Group: stable-8 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r204095 - stable/8/sys/dev/ahci X-BeenThere: svn-src-stable-8@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: SVN commit messages for only the 8-stable src tree List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 19 Feb 2010 17:54:03 -0000 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 */