Module Name: src Committed By: christos Date: Thu Mar 12 18:53:22 UTC 2015
Modified Files: src/sys/dev/ic: ciss.c Log Message: Untangle the poll/wait/timeout code in ciss_cmd() Tested on a DL-360. To generate a diff of this commit: cvs rdiff -u -r1.33 -r1.34 src/sys/dev/ic/ciss.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/dev/ic/ciss.c diff -u src/sys/dev/ic/ciss.c:1.33 src/sys/dev/ic/ciss.c:1.34 --- src/sys/dev/ic/ciss.c:1.33 Thu Mar 12 11:33:10 2015 +++ src/sys/dev/ic/ciss.c Thu Mar 12 14:53:22 2015 @@ -1,4 +1,4 @@ -/* $NetBSD: ciss.c,v 1.33 2015/03/12 15:33:10 christos Exp $ */ +/* $NetBSD: ciss.c,v 1.34 2015/03/12 18:53:22 christos Exp $ */ /* $OpenBSD: ciss.c,v 1.68 2013/05/30 16:15:02 deraadt Exp $ */ /* @@ -19,7 +19,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: ciss.c,v 1.33 2015/03/12 15:33:10 christos Exp $"); +__KERNEL_RCSID(0, "$NetBSD: ciss.c,v 1.34 2015/03/12 18:53:22 christos Exp $"); #include "bio.h" @@ -437,6 +437,97 @@ cissminphys(struct buf *bp) minphys(bp); } +static struct ciss_ccb * +ciss_poll1(struct ciss_softc *sc) +{ + struct ciss_ccb *ccb; + uint32_t id; + + if (!(bus_space_read_4(sc->sc_iot, sc->sc_ioh, CISS_ISR) & sc->iem)) { + CISS_DPRINTF(CISS_D_CMD, ("N")); + return NULL; + } + + if (sc->cfg.methods & CISS_METH_FIFO64) { + if (bus_space_read_4(sc->sc_iot, sc->sc_ioh, CISS_OUTQ64_HI) == + 0xffffffff) { + CISS_DPRINTF(CISS_D_CMD, ("Q")); + return NULL; + } + id = bus_space_read_4(sc->sc_iot, sc->sc_ioh, CISS_OUTQ64_LO); + } else if (sc->cfg.methods & CISS_METH_FIFO64_RRO) { + id = bus_space_read_4(sc->sc_iot, sc->sc_ioh, CISS_OUTQ64_LO); + if (id == 0xffffffff) { + CISS_DPRINTF(CISS_D_CMD, ("Q")); + return NULL; + } + (void)bus_space_read_4(sc->sc_iot, sc->sc_ioh, CISS_OUTQ64_HI); + } else { + id = bus_space_read_4(sc->sc_iot, sc->sc_ioh, CISS_OUTQ); + if (id == 0xffffffff) { + CISS_DPRINTF(CISS_D_CMD, ("Q")); + return NULL; + } + } + + CISS_DPRINTF(CISS_D_CMD, ("got=0x%x ", id)); + ccb = (struct ciss_ccb *) ((char *)sc->ccbs + (id >> 2) * sc->ccblen); + ccb->ccb_cmd.id = htole32(id); + ccb->ccb_cmd.id_hi = htole32(0); + return ccb; +} + +static int +ciss_poll(struct ciss_softc *sc, struct ciss_ccb *ccb, int ms) +{ + struct ciss_ccb *ccb1; + + ms /= 10; + + while (ms-- > 0) { + DELAY(10); + ccb1 = ciss_poll1(sc); + if (ccb1 == NULL) + continue; + ciss_done(ccb1); + if (ccb1 == ccb) + return 0; + } + + return ETIMEDOUT; +} + +static int +ciss_wait(struct ciss_softc *sc, struct ciss_ccb *ccb, int ms) +{ + int tohz, etick; + + tohz = mstohz(ms); + if (tohz == 0) + tohz = 1; + etick = tick + tohz; + + for (;;) { + ccb->ccb_state = CISS_CCB_POLL; + CISS_DPRINTF(CISS_D_CMD, ("cv_timedwait(%d) ", tohz)); + mutex_enter(&sc->sc_mutex); + if (cv_timedwait(&sc->sc_condvar, &sc->sc_mutex, tohz) + == EWOULDBLOCK) { + mutex_exit(&sc->sc_mutex); + return EWOULDBLOCK; + } + mutex_exit(&sc->sc_mutex); + if (ccb->ccb_state == CISS_CCB_ONQ) { + ciss_done(ccb); + return 0; + } + tohz = etick - tick; + if (tohz <= 0) + return EWOULDBLOCK; + CISS_DPRINTF(CISS_D_CMD, ("T")); + } +} + /* * submit a command and optionally wait for completition. * wait arg abuses XS_CTL_POLL|XS_CTL_NOSLEEP flags to request @@ -448,11 +539,9 @@ ciss_cmd(struct ciss_ccb *ccb, int flags { struct ciss_softc *sc = ccb->ccb_sc; struct ciss_cmd *cmd = &ccb->ccb_cmd; - struct ciss_ccb *ccb1; bus_dmamap_t dmap = ccb->ccb_dmamap; - u_int32_t id; u_int64_t addr; - int i, tohz, error = 0; + int i, error = 0; if (ccb->ccb_state != CISS_CCB_READY) { printf("%s: ccb %d not ready state=0x%x\n", device_xname(sc->sc_dev), @@ -527,83 +616,18 @@ ciss_cmd(struct ciss_ccb *ccb, int flags ccb->ccb_cmdpa); if (wait & XS_CTL_POLL) { - int etick; + int ms; CISS_DPRINTF(CISS_D_CMD, ("waiting ")); - i = ccb->ccb_xs? ccb->ccb_xs->timeout : 60000; - tohz = (i / 1000) * hz + (i % 1000) * (hz / 1000); - if (tohz == 0) - tohz = 1; - for (i *= 100, etick = tick + tohz; i--; ) { - if (!(wait & XS_CTL_NOSLEEP)) { - ccb->ccb_state = CISS_CCB_POLL; - CISS_DPRINTF(CISS_D_CMD, ("cv_timedwait(%d) ", tohz)); - mutex_enter(&sc->sc_mutex); - if (cv_timedwait(&sc->sc_condvar, - &sc->sc_mutex, tohz) == EWOULDBLOCK) { - mutex_exit(&sc->sc_mutex); - break; - } - mutex_exit(&sc->sc_mutex); - if (ccb->ccb_state != CISS_CCB_ONQ) { - tohz = etick - tick; - if (tohz <= 0) - break; - CISS_DPRINTF(CISS_D_CMD, ("T")); - continue; - } - ccb1 = ccb; - } else { - DELAY(10); - - if (!(bus_space_read_4(sc->sc_iot, sc->sc_ioh, - CISS_ISR) & sc->iem)) { - CISS_DPRINTF(CISS_D_CMD, ("N")); - continue; - } - - if (sc->cfg.methods & CISS_METH_FIFO64) { - if (bus_space_read_4(sc->sc_iot, - sc->sc_ioh, - CISS_OUTQ64_HI) == 0xffffffff) { - CISS_DPRINTF(CISS_D_CMD, ("Q")); - continue; - } - id = bus_space_read_4(sc->sc_iot, - sc->sc_ioh, CISS_OUTQ64_LO); - } else if (sc->cfg.methods & - CISS_METH_FIFO64_RRO) { - id = bus_space_read_4(sc->sc_iot, - sc->sc_ioh, CISS_OUTQ64_LO); - if (id == 0xffffffff) { - CISS_DPRINTF(CISS_D_CMD, ("Q")); - continue; - } - (void)bus_space_read_4(sc->sc_iot, - sc->sc_ioh, CISS_OUTQ64_HI); - } else { - id = bus_space_read_4(sc->sc_iot, - sc->sc_ioh, CISS_OUTQ); - if (id == 0xffffffff) { - CISS_DPRINTF(CISS_D_CMD, ("Q")); - continue; - } - } - - CISS_DPRINTF(CISS_D_CMD, ("got=0x%x ", id)); - ccb1 = (struct ciss_ccb *) - ((char *)sc->ccbs + (id >> 2) * sc->ccblen); - ccb1->ccb_cmd.id = htole32(id); - ccb1->ccb_cmd.id_hi = htole32(0); - } - - error = ciss_done(ccb1); - if (ccb1 == ccb) - break; - } + ms = ccb->ccb_xs ? ccb->ccb_xs->timeout : 60000; + if (wait & XS_CTL_NOSLEEP) + error = ciss_poll(sc, ccb, ms); + else + error = ciss_wait(sc, ccb, ms); /* if never got a chance to be done above... */ if (ccb->ccb_state != CISS_CCB_FREE) { + KASSERT(error); ccb->ccb_err.cmd_stat = CISS_ERR_TMO; error = ciss_done(ccb); }