Index: sys/dev/ic/sl811hs.c =================================================================== RCS file: /cvsroot/src/sys/dev/ic/sl811hs.c,v retrieving revision 1.87 diff -u -p -r1.87 sl811hs.c --- sys/dev/ic/sl811hs.c 30 Jun 2016 16:34:56 -0000 1.87 +++ sys/dev/ic/sl811hs.c 30 Jun 2016 20:17:09 -0000 @@ -1503,7 +1503,7 @@ repeat: if (!gcq_empty(&sc->sc_waitq)) { slhci_enter_xfers(sc); slhci_dotransfer(sc); - slhci_waitintr(sc, 0); +// slhci_waitintr(sc, 0); goto repeat; } @@ -1533,13 +1533,17 @@ slhci_intr(void *arg) { SLHCIHIST_FUNC(); SLHCIHIST_CALLED(); struct slhci_softc *sc = arg; - int ret; + int ret = 0; + int irq; start_cc_time(&t_hard_int, (unsigned int)arg); mutex_enter(&sc->sc_intr_lock); - ret = slhci_dointr(sc); - slhci_main(sc); + do { + irq = slhci_dointr(sc); + ret |= irq; + slhci_main(sc); + } while (irq); mutex_exit(&sc->sc_intr_lock); stop_cc_time(&t_hard_int); @@ -1557,8 +1561,8 @@ slhci_main(struct slhci_softc *sc) KASSERT(mutex_owned(&sc->sc_intr_lock)); -waitcheck: - slhci_waitintr(sc, slhci_wait_time); +//waitcheck: +// slhci_waitintr(sc, slhci_wait_time); /* * The direct call is needed in the ub_usepolling and disabled cases @@ -1569,8 +1573,12 @@ waitcheck: * cases. */ if ((t->flags & F_ROOTINTR) || !gcq_empty(&t->q[Q_CALLBACKS])) { - if (__predict_false(sc->sc_bus.ub_usepolling || + if (__predict_false(sc->sc_bus.ub_usepolling)) +#if 0 + /* Need to avoid this as can happen from interrupt context */ + || t->flags & F_DISABLED)) +#endif slhci_callback(sc); else slhci_callback_schedule(sc); @@ -1579,7 +1587,7 @@ waitcheck: if (!gcq_empty(&sc->sc_waitq)) { slhci_enter_xfers(sc); slhci_dotransfer(sc); - goto waitcheck; +// goto waitcheck; } DLOG(D_INTR, "... done", 0, 0, 0, 0); } @@ -2077,25 +2085,28 @@ slhci_abdone(struct slhci_softc *sc, int slhci_halt(sc, spipe, xfer); return; } else if (__predict_false(sc->sc_bus.ub_usepolling)) { - if (status == SL11_EPSTAT_STALL) + head = Q_CALLBACKS; + if (status & SL11_EPSTAT_STALL) xfer->ux_status = USBD_STALLED; - else if (status == SL11_EPSTAT_TIMEOUT) + else if (status & SL11_EPSTAT_TIMEOUT) xfer->ux_status = USBD_TIMEOUT; - else if (status == SL11_EPSTAT_NAK) - xfer->ux_status = USBD_TIMEOUT; /*XXX*/ - else + else if (!(status & (SL11_EPSTAT_NAK|SL11_EPSTAT_ERROR))) xfer->ux_status = USBD_IOERROR; - head = Q_CALLBACKS; - } else if (status == SL11_EPSTAT_NAK) { - if (spipe->pipe.up_interval) { - spipe->lastframe = spipe->frame = - t->frame + spipe->pipe.up_interval; - slhci_queue_timed(sc, spipe); - goto queued; - } - head = Q_NEXT_CB; + else + head = Q_NEXT_CB; + } else if (status & SL11_EPSTAT_NAK) { + int i = spipe->pipe.up_interval; + if (i == 0) + i = 1; + DDOLOG("xfer %p spipe %p NAK delay by %d", xfer, spipe, + i, 0); + spipe->lastframe = spipe->frame = t->frame + i; + slhci_queue_timed(sc, spipe); + goto queued; } else if (++spipe->nerrs > SLHCI_MAX_RETRIES || - status == SL11_EPSTAT_STALL) { + (status & SL11_EPSTAT_STALL)) { + DDOLOG("xfer %p spipe %p nerrs %d", xfer, spipe, + spipe->nerrs, 0); if (status == SL11_EPSTAT_STALL) xfer->ux_status = USBD_STALLED; else if (status == SL11_EPSTAT_TIMEOUT) @@ -2104,7 +2115,7 @@ slhci_abdone(struct slhci_softc *sc, int xfer->ux_status = USBD_IOERROR; DLOG(D_ERR, "Max retries reached! status %#x " - "xfer->ux_status %#x", status, xfer->ux_status, 0, + "xfer->ux_status %d", status, xfer->ux_status, 0, 0); DDOLOGSTATUS(status); @@ -2158,8 +2169,8 @@ status_setup: xfer->ux_actlen += actlen; spipe->control ^= SL11_EPCTRL_DATATOGGLE; - if (actlen == spipe->tregs[LEN] && (xfer->ux_length > - xfer->ux_actlen || spipe->wantshort)) { + if (actlen == spipe->tregs[LEN] && + (xfer->ux_length > xfer->ux_actlen || spipe->wantshort)) { spipe->buffer += actlen; LK_SLASSERT(xfer->ux_length >= xfer->ux_actlen, sc, spipe, xfer, return); @@ -2204,7 +2215,7 @@ status_setup: } if (head == Q_CALLBACKS) { - gcq_remove(&spipe->to); +// gcq_remove(&spipe->to); if (xfer->ux_status == USBD_IN_PROGRESS) { LK_SLASSERT(xfer->ux_actlen <= xfer->ux_length, sc,