summaryrefslogtreecommitdiffstats
path: root/sys/dev/siis/siis.c
diff options
context:
space:
mode:
authormav <mav@FreeBSD.org>2010-09-16 12:39:50 +0000
committermav <mav@FreeBSD.org>2010-09-16 12:39:50 +0000
commitc24aa138ad5069ce7bb3a791efb6736b43b1067e (patch)
tree2a4f6c03dbfdac46619a31231273bb11261d4a1e /sys/dev/siis/siis.c
parenta170307205b7b1030786eed8dec7d80c04f9f7d0 (diff)
downloadFreeBSD-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/siis/siis.c')
-rw-r--r--sys/dev/siis/siis.c13
1 files changed, 8 insertions, 5 deletions
diff --git a/sys/dev/siis/siis.c b/sys/dev/siis/siis.c
index 34a77fc..0aef775 100644
--- a/sys/dev/siis/siis.c
+++ b/sys/dev/siis/siis.c
@@ -1179,6 +1179,7 @@ siis_end_transaction(struct siis_slot *slot, enum siis_err_type et)
device_t dev = slot->dev;
struct siis_channel *ch = device_get_softc(dev);
union ccb *ccb = slot->ccb;
+ int lastto;
mtx_assert(&ch->mtx, MA_OWNED);
bus_dmamap_sync(ch->dma.work_tag, ch->dma.work_map,
@@ -1262,11 +1263,6 @@ siis_end_transaction(struct siis_slot *slot, enum siis_err_type et)
ch->oslots &= ~(1 << slot->slot);
ch->rslots &= ~(1 << slot->slot);
ch->aslots &= ~(1 << slot->slot);
- if (et != SIIS_ERR_TIMEOUT) {
- if (ch->toslots == (1 << slot->slot))
- xpt_release_simq(ch->sim, TRUE);
- ch->toslots &= ~(1 << slot->slot);
- }
slot->state = SIIS_SLOT_EMPTY;
slot->ccb = NULL;
/* Update channel stats. */
@@ -1275,6 +1271,13 @@ siis_end_transaction(struct siis_slot *slot, enum siis_err_type et)
(ccb->ataio.cmd.flags & CAM_ATAIO_FPDMA)) {
ch->numtslots[ccb->ccb_h.target_id]--;
}
+ /* Cancel timeout state if request completed normally. */
+ if (et != SIIS_ERR_TIMEOUT) {
+ lastto = (ch->toslots == (1 << slot->slot));
+ ch->toslots &= ~(1 << slot->slot);
+ if (lastto)
+ xpt_release_simq(ch->sim, TRUE);
+ }
/* If it was our READ LOG command - process it. */
if (ch->readlog) {
siis_process_read_log(dev, ccb);
OpenPOWER on IntegriCloud