Date: Wed, 4 Jun 2014 06:15:46 +0000 (UTC) From: Hans Petter Selasky <hselasky@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-10@freebsd.org Subject: svn commit: r267039 - stable/10/sys/dev/usb/controller Message-ID: <201406040615.s546FknI004397@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: hselasky Date: Wed Jun 4 06:15:45 2014 New Revision: 267039 URL: http://svnweb.freebsd.org/changeset/base/267039 Log: MFC r266833: Add some more spinlocks to protect the state of the USB transfer queue. Rename some functions to indicate locking requirements. Modified: stable/10/sys/dev/usb/controller/dwc_otg.c Directory Properties: stable/10/ (props changed) Modified: stable/10/sys/dev/usb/controller/dwc_otg.c ============================================================================== --- stable/10/sys/dev/usb/controller/dwc_otg.c Wed Jun 4 05:04:15 2014 (r267038) +++ stable/10/sys/dev/usb/controller/dwc_otg.c Wed Jun 4 06:15:45 2014 (r267039) @@ -142,7 +142,7 @@ static void dwc_otg_device_done(struct u static void dwc_otg_do_poll(struct usb_bus *); static void dwc_otg_standard_done(struct usb_xfer *); static void dwc_otg_root_intr(struct dwc_otg_softc *); -static void dwc_otg_interrupt_poll(struct dwc_otg_softc *); +static void dwc_otg_interrupt_poll_locked(struct dwc_otg_softc *); static void dwc_otg_host_channel_disable(struct dwc_otg_softc *, uint8_t); /* @@ -2245,7 +2245,7 @@ done: } static uint8_t -dwc_otg_xfer_do_complete(struct dwc_otg_softc *sc, struct usb_xfer *xfer) +dwc_otg_xfer_do_complete_locked(struct dwc_otg_softc *sc, struct usb_xfer *xfer) { struct dwc_otg_td *td; @@ -2349,7 +2349,7 @@ dwc_otg_host_channel_disable(struct dwc_ } static uint8_t -dwc_otg_update_host_transfer_schedule(struct dwc_otg_softc *sc) +dwc_otg_update_host_transfer_schedule_locked(struct dwc_otg_softc *sc) { TAILQ_HEAD(, usb_xfer) head; struct usb_xfer *xfer; @@ -2519,7 +2519,7 @@ dwc_otg_update_host_transfer_schedule(st } static void -dwc_otg_interrupt_poll(struct dwc_otg_softc *sc) +dwc_otg_interrupt_poll_locked(struct dwc_otg_softc *sc) { struct usb_xfer *xfer; uint32_t temp; @@ -2620,19 +2620,19 @@ repeat: if (sc->sc_flags.status_device_mode == 0 && sc->sc_xfer_complete == 0) { /* update host transfer schedule, so that new transfers can be issued */ - if (dwc_otg_update_host_transfer_schedule(sc)) + if (dwc_otg_update_host_transfer_schedule_locked(sc)) goto repeat; } } static void -dwc_otg_interrupt_complete(struct dwc_otg_softc *sc) +dwc_otg_interrupt_complete_locked(struct dwc_otg_softc *sc) { struct usb_xfer *xfer; repeat: /* scan for completion events */ TAILQ_FOREACH(xfer, &sc->sc_bus.intr_q.head, wait_entry) { - if (dwc_otg_xfer_do_complete(sc, xfer)) + if (dwc_otg_xfer_do_complete_locked(sc, xfer)) goto repeat; } } @@ -2672,6 +2672,8 @@ dwc_otg_filter_interrupt(void *arg) int retval = FILTER_HANDLED; uint32_t status; + USB_BUS_SPIN_LOCK(&sc->sc_bus); + /* read and clear interrupt status */ status = DWC_OTG_READ_4(sc, DOTG_GINTSTS); @@ -2696,10 +2698,8 @@ dwc_otg_filter_interrupt(void *arg) } } - USB_BUS_SPIN_LOCK(&sc->sc_bus); - /* poll FIFOs, if any */ - dwc_otg_interrupt_poll(sc); + dwc_otg_interrupt_poll_locked(sc); if (sc->sc_xfer_complete != 0) retval = FILTER_SCHEDULE_THREAD; @@ -2896,15 +2896,14 @@ dwc_otg_interrupt(void *arg) sc->sc_xfer_complete = 0; /* complete FIFOs, if any */ - dwc_otg_interrupt_complete(sc); + dwc_otg_interrupt_complete_locked(sc); if (sc->sc_flags.status_device_mode == 0) { /* update host transfer schedule, so that new transfers can be issued */ - if (dwc_otg_update_host_transfer_schedule(sc)) - dwc_otg_interrupt_poll(sc); + if (dwc_otg_update_host_transfer_schedule_locked(sc)) + dwc_otg_interrupt_poll_locked(sc); } } - USB_BUS_SPIN_UNLOCK(&sc->sc_bus); USB_BUS_UNLOCK(&sc->sc_bus); } @@ -3269,12 +3268,13 @@ dwc_otg_start_standard_chain(struct usb_ * endpoint interrupts. Else wait for SOF interrupt in host * mode. */ + USB_BUS_SPIN_LOCK(&sc->sc_bus); + if (sc->sc_flags.status_device_mode != 0) { dwc_otg_xfer_do_fifo(sc, xfer); - if (dwc_otg_xfer_do_complete(sc, xfer)) - return; + if (dwc_otg_xfer_do_complete_locked(sc, xfer)) + goto done; } - USB_BUS_SPIN_LOCK(&sc->sc_bus); /* put transfer on interrupt queue */ usbd_transfer_enqueue(&xfer->xroot->bus->intr_q, xfer); @@ -3451,6 +3451,8 @@ dwc_otg_device_done(struct usb_xfer *xfe DPRINTFN(9, "xfer=%p, endpoint=%p, error=%d\n", xfer, xfer->endpoint, error); + USB_BUS_SPIN_LOCK(&sc->sc_bus); + if (xfer->flags_int.usb_mode == USB_MODE_DEVICE) { /* Interrupts are cleared by the interrupt handler */ } else { @@ -3465,6 +3467,8 @@ dwc_otg_device_done(struct usb_xfer *xfe } /* dequeue transfer and start next transfer */ usbd_transfer_done(xfer, error); + + USB_BUS_SPIN_UNLOCK(&sc->sc_bus); } static void @@ -3492,6 +3496,8 @@ dwc_otg_set_stall(struct usb_device *ude sc = DWC_OTG_BUS2SC(udev->bus); + USB_BUS_SPIN_LOCK(&sc->sc_bus); + /* get endpoint address */ ep_no = ep->edesc->bEndpointAddress; @@ -3520,14 +3526,15 @@ dwc_otg_set_stall(struct usb_device *ude /* dump data */ dwc_otg_common_rx_ack(sc); /* poll interrupt */ - dwc_otg_interrupt_poll(sc); - dwc_otg_interrupt_complete(sc); + dwc_otg_interrupt_poll_locked(sc); + dwc_otg_interrupt_complete_locked(sc); } } + USB_BUS_SPIN_UNLOCK(&sc->sc_bus); } static void -dwc_otg_clear_stall_sub(struct dwc_otg_softc *sc, uint32_t mps, +dwc_otg_clear_stall_sub_locked(struct dwc_otg_softc *sc, uint32_t mps, uint8_t ep_no, uint8_t ep_type, uint8_t ep_dir) { uint32_t reg; @@ -3585,8 +3592,8 @@ dwc_otg_clear_stall_sub(struct dwc_otg_s } /* poll interrupt */ - dwc_otg_interrupt_poll(sc); - dwc_otg_interrupt_complete(sc); + dwc_otg_interrupt_poll_locked(sc); + dwc_otg_interrupt_complete_locked(sc); } static void @@ -3607,15 +3614,19 @@ dwc_otg_clear_stall(struct usb_device *u /* get softc */ sc = DWC_OTG_BUS2SC(udev->bus); + USB_BUS_SPIN_LOCK(&sc->sc_bus); + /* get endpoint descriptor */ ed = ep->edesc; /* reset endpoint */ - dwc_otg_clear_stall_sub(sc, + dwc_otg_clear_stall_sub_locked(sc, UGETW(ed->wMaxPacketSize), (ed->bEndpointAddress & UE_ADDR), (ed->bmAttributes & UE_XFERTYPE), (ed->bEndpointAddress & (UE_DIR_IN | UE_DIR_OUT))); + + USB_BUS_SPIN_UNLOCK(&sc->sc_bus); } static void @@ -3886,12 +3897,12 @@ dwc_otg_do_poll(struct usb_bus *bus) USB_BUS_LOCK(&sc->sc_bus); USB_BUS_SPIN_LOCK(&sc->sc_bus); - dwc_otg_interrupt_poll(sc); - dwc_otg_interrupt_complete(sc); + dwc_otg_interrupt_poll_locked(sc); + dwc_otg_interrupt_complete_locked(sc); if (sc->sc_flags.status_device_mode == 0) { /* update host transfer schedule, so that new transfers can be issued */ - if (dwc_otg_update_host_transfer_schedule(sc)) - dwc_otg_interrupt_poll(sc); + if (dwc_otg_update_host_transfer_schedule_locked(sc)) + dwc_otg_interrupt_poll_locked(sc); } USB_BUS_SPIN_UNLOCK(&sc->sc_bus); USB_BUS_UNLOCK(&sc->sc_bus);
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201406040615.s546FknI004397>