Date: Sat, 6 Feb 2010 00:37:04 GMT From: Alexander Motin <mav@FreeBSD.org> To: Perforce Change Reviews <perforce@freebsd.org> Subject: PERFORCE change 174382 for review Message-ID: <201002060037.o160b4dV016448@repoman.freebsd.org>
next in thread | raw e-mail | index | archive | help
http://p4web.freebsd.org/chv.cgi?CH=174382 Change 174382 by mav@mav_mavtest on 2010/02/06 00:36:09 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. Affected files ... .. //depot/projects/scottl-camlock/src/sys/dev/ahci/ahci.c#104 edit .. //depot/projects/scottl-camlock/src/sys/dev/ahci/ahci.h#37 edit Differences ... ==== //depot/projects/scottl-camlock/src/sys/dev/ahci/ahci.c#104 (text+ko) ==== @@ -1663,6 +1663,45 @@ 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) @@ -1699,7 +1738,6 @@ 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; @@ -1711,14 +1749,28 @@ } 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); } } @@ -1815,10 +1867,6 @@ 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; @@ -1834,6 +1882,11 @@ 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. */ @@ -1873,7 +1926,7 @@ /* 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. */ @@ -1885,7 +1938,10 @@ 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, @@ -2149,7 +2205,10 @@ 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); ==== //depot/projects/scottl-camlock/src/sys/dev/ahci/ahci.h#37 (text+ko) ==== @@ -401,6 +401,7 @@ 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 */
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201002060037.o160b4dV016448>
