diff options
author | mav <mav@FreeBSD.org> | 2010-09-16 12:39:50 +0000 |
---|---|---|
committer | mav <mav@FreeBSD.org> | 2010-09-16 12:39:50 +0000 |
commit | c24aa138ad5069ce7bb3a791efb6736b43b1067e (patch) | |
tree | 2a4f6c03dbfdac46619a31231273bb11261d4a1e /sys/dev/ahci | |
parent | a170307205b7b1030786eed8dec7d80c04f9f7d0 (diff) | |
download | FreeBSD-src-c24aa138ad5069ce7bb3a791efb6736b43b1067e.zip FreeBSD-src-c24aa138ad5069ce7bb3a791efb6736b43b1067e.tar.gz |
Fix panic, when due to some kind of congestion on FIS-based switching
port multiplier some command triggers false positive timeout, but then
completes normally.
MFC after: 2 weeks
Diffstat (limited to 'sys/dev/ahci')
-rw-r--r-- | sys/dev/ahci/ahci.c | 13 |
1 files changed, 8 insertions, 5 deletions
diff --git a/sys/dev/ahci/ahci.c b/sys/dev/ahci/ahci.c index 54e787a..d6357b2 100644 --- a/sys/dev/ahci/ahci.c +++ b/sys/dev/ahci/ahci.c @@ -1854,6 +1854,7 @@ 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); union ccb *ccb = slot->ccb; + int lastto; bus_dmamap_sync(ch->dma.work_tag, ch->dma.work_map, BUS_DMASYNC_POSTWRITE); @@ -1955,11 +1956,6 @@ ahci_end_transaction(struct ahci_slot *slot, enum ahci_err_type et) 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. */ @@ -1970,6 +1966,13 @@ ahci_end_transaction(struct ahci_slot *slot, enum ahci_err_type et) ch->numtslots--; ch->numtslotspd[ccb->ccb_h.target_id]--; } + /* Cancel timeout state if request completed normally. */ + if (et != AHCI_ERR_TIMEOUT) { + lastto = (ch->toslots == (1 << slot->slot)); + ch->toslots &= ~(1 << slot->slot); + if (lastto) + xpt_release_simq(ch->sim, TRUE); + } /* If it was first request of reset sequence and there is no error, * proceed to second request. */ if ((ccb->ccb_h.func_code == XPT_ATA_IO) && |