Author: mav
Date: Thu Sep 16 12:39:50 2010
New Revision: 212732
URL: http://svn.freebsd.org/changeset/base/212732

Log:
  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

Modified:
  head/sys/dev/ahci/ahci.c
  head/sys/dev/mvs/mvs.c
  head/sys/dev/siis/siis.c

Modified: head/sys/dev/ahci/ahci.c
==============================================================================
--- head/sys/dev/ahci/ahci.c    Thu Sep 16 12:13:06 2010        (r212731)
+++ head/sys/dev/ahci/ahci.c    Thu Sep 16 12:39:50 2010        (r212732)
@@ -1854,6 +1854,7 @@ ahci_end_transaction(struct ahci_slot *s
        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 *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. */
@@ -1970,6 +1966,13 @@ ahci_end_transaction(struct ahci_slot *s
                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) &&

Modified: head/sys/dev/mvs/mvs.c
==============================================================================
--- head/sys/dev/mvs/mvs.c      Thu Sep 16 12:13:06 2010        (r212731)
+++ head/sys/dev/mvs/mvs.c      Thu Sep 16 12:39:50 2010        (r212732)
@@ -1552,6 +1552,7 @@ mvs_end_transaction(struct mvs_slot *slo
        device_t dev = slot->dev;
        struct mvs_channel *ch = device_get_softc(dev);
        union ccb *ccb = slot->ccb;
+       int lastto;
 
 //device_printf(dev, "cmd done status %d\n", et);
        bus_dmamap_sync(ch->dma.workrq_tag, ch->dma.workrq_map,
@@ -1634,11 +1635,6 @@ mvs_end_transaction(struct mvs_slot *slo
        ch->oslots &= ~(1 << slot->slot);
        ch->rslots &= ~(1 << slot->slot);
        ch->aslots &= ~(1 << slot->slot);
-       if (et != MVS_ERR_TIMEOUT) {
-               if (ch->toslots == (1 << slot->slot))
-                       xpt_release_simq(ch->sim, TRUE);
-               ch->toslots &= ~(1 << slot->slot);
-       }
        slot->state = MVS_SLOT_EMPTY;
        slot->ccb = NULL;
        /* Update channel stats. */
@@ -1658,6 +1654,13 @@ mvs_end_transaction(struct mvs_slot *slo
                ch->numpslots--;
                ch->basic_dma = 0;
        }
+       /* Cancel timeout state if request completed normally. */
+       if (et != MVS_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) {
                mvs_process_read_log(dev, ccb);

Modified: head/sys/dev/siis/siis.c
==============================================================================
--- head/sys/dev/siis/siis.c    Thu Sep 16 12:13:06 2010        (r212731)
+++ head/sys/dev/siis/siis.c    Thu Sep 16 12:39:50 2010        (r212732)
@@ -1179,6 +1179,7 @@ siis_end_transaction(struct siis_slot *s
        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 *s
        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 *s
            (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);
_______________________________________________
svn-src-head@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to