Index: sys/dev/usb/dwc_otg.c =================================================================== RCS file: /cvsroot/src/sys/dev/usb/dwc_otg.c,v retrieving revision 1.45 diff -u -p -u -r1.45 dwc_otg.c --- sys/dev/usb/dwc_otg.c 4 Feb 2013 21:37:05 -0000 1.45 +++ sys/dev/usb/dwc_otg.c 14 Feb 2013 23:11:13 -0000 @@ -197,8 +197,8 @@ Static void dwc_otg_device_clear_toggle Static void dwc_otg_noop(usbd_pipe_handle pipe); #ifdef DWC_OTG_DEBUG -Static void dwc_otg_dump_global_regs(struct dwc_otg_softc *); -Static void dwc_otg_dump_host_regs(struct dwc_otg_softc *); +void dwc_otg_dump_global_regs(struct dwc_otg_softc *); +void dwc_otg_dump_host_regs(struct dwc_otg_softc *); #endif Static void dwc_otg_setup_data_chain(usbd_xfer_handle); @@ -423,6 +423,7 @@ dwc_otg_softintr(void *v) mutex_spin_enter(&sc->sc_intr_lock); while ((dxfer = TAILQ_FIRST(&sc->sc_complete)) != NULL) { + KASSERT(dxfer->state == DXFER_COMPLETING); TAILQ_REMOVE(&sc->sc_complete, dxfer, xnext); if (dxfer->xfer.hcflags & UXFER_ABORTING) { @@ -641,9 +642,22 @@ dwc_otg_abort_xfer(usbd_xfer_handle xfer xfer->status = status; /* make software ignore it */ callout_stop(&xfer->timeout_handle); - if (dxfer->active) { + switch (dxfer->state) { + case DXFER_INIT: + dxfer->state = DXFER_ABORTING; + break; + case DXFER_WORKQ: + /* Give the workqueue a chance */ + break; + case DXFER_ACTIVE: TAILQ_REMOVE(&sc->sc_active, dxfer, xnext); - dxfer->active = false; + dxfer->state = DXFER_ABORTING; + break; + case DXFER_COMPLETING: + TAILQ_REMOVE(&sc->sc_complete, dxfer, xnext); + dxfer->state = DXFER_ABORTING; + default: + KASSERT(false); } mutex_spin_exit(&sc->sc_intr_lock); @@ -651,7 +665,7 @@ dwc_otg_abort_xfer(usbd_xfer_handle xfer dwc_otg_host_channel_free(dxfer->td_transfer_cache); } - while (dxfer->queued) { + while (dxfer->state != DXFER_ABORTING) { cv_wait(&xfer->hccv, &sc->sc_lock); } @@ -1671,13 +1685,14 @@ dwc_otg_worker(struct work *wk, void *pr dwc_otg_timer(sc); } else { KASSERT(dwork->xfer != NULL); - KASSERT(dxfer->queued == true); + KASSERT(dxfer->state == DXFER_WORKQ); if (!(xfer->hcflags & UXFER_ABORTING)) { dwc_otg_start_standard_chain(xfer); + } else { + dxfer->state = DXFER_ABORTING; + cv_broadcast(&xfer->hccv); } - dxfer->queued = false; - cv_broadcast(&xfer->hccv); } mutex_exit(&sc->sc_lock); } @@ -3853,7 +3868,7 @@ dwc_otg_setup_standard_chain(usbd_xfer_h // DPRINTF(("%s: xfer->length %d\n", __func__, xfer->length)); - dxfer->queued = false; + dxfer->state = DXFER_INIT; /* get first again */ td = dxfer->td_transfer_first; @@ -3962,12 +3977,14 @@ dwc_otg_start_standard_chain(usbd_xfer_h /* poll one time - will turn on interrupts */ mutex_spin_enter(&sc->sc_intr_lock); + dxfer->state = DXFER_STARTED; + if (dwc_otg_xfer_do_fifo(xfer)) { KASSERT(mutex_owned(&sc->sc_lock)); /* put transfer on interrupt queue */ - dxfer->active = true; + dxfer->state = DXFER_ACTIVE; TAILQ_INSERT_TAIL(&sc->sc_active, dxfer, xnext); /* start timeout, if any */ @@ -4059,12 +4076,12 @@ dwc_otg_standard_done(usbd_xfer_handle x dwc_otg_host_channel_free(td); xfer->status = err; - if (dxfer->active) { + if (dxfer->state == DXFER_ACTIVE) { TAILQ_REMOVE(&sc->sc_active, dxfer, xnext); - dxfer->active = false; } callout_stop(&xfer->timeout_handle); + dxfer->state = DXFER_COMPLETING; TAILQ_INSERT_TAIL(&sc->sc_complete, dxfer, xnext); usb_schedsoftintr(&sc->sc_bus); @@ -4406,8 +4423,8 @@ dwc_otg_xfer_start(usbd_xfer_handle xfer if (sc->sc_bus.use_polling) { dwc_otg_start_standard_chain(xfer); } else { - KASSERT(dxfer->queued == false); - dxfer->queued = true; + KASSERT(dxfer->state == DXFER_INIT); + dxfer->state = DXFER_WORKQ; workqueue_enqueue(sc->sc_wq, (struct work *)&dxfer->work, NULL); } } Index: sys/dev/usb/dwc_otgvar.h =================================================================== RCS file: /cvsroot/src/sys/dev/usb/dwc_otgvar.h,v retrieving revision 1.11 diff -u -p -u -r1.11 dwc_otgvar.h --- sys/dev/usb/dwc_otgvar.h 4 Feb 2013 21:29:14 -0000 1.11 +++ sys/dev/usb/dwc_otgvar.h 14 Feb 2013 23:11:13 -0000 @@ -158,8 +158,14 @@ struct dwc_otg_xfer { struct usbd_xfer xfer; /* Needs to be first */ struct usb_task abort_task; TAILQ_ENTRY(dwc_otg_xfer) xnext; /* list of active/complete xfers */ - bool queued; /* pending workqueue */ - bool active; /* still active */ + int state; +#define DXFER_INIT 0 +#define DXFER_WORKQ 1 +#define DXFER_STARTED 2 +#define DXFER_ACTIVE 3 +#define DXFER_COMPLETING 4 +#define DXFER_ABORTING 5 +#define DXFER_DONE 6 void *td_start[1]; dwc_otg_td_t *td_transfer_first;