Date: Thu, 29 May 2014 11:11:19 +0000 (UTC) From: Hans Petter Selasky <hselasky@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r266833 - head/sys/dev/usb/controller Message-ID: <201405291111.s4TBBJL5043738@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: hselasky Date: Thu May 29 11:11:19 2014 New Revision: 266833 URL: http://svnweb.freebsd.org/changeset/base/266833 Log: Add some more spinlocks to protect the state of the USB transfer queue. Rename some functions to indicate locking requirements. MFC after: 1 week Modified: head/sys/dev/usb/controller/dwc_otg.c Modified: head/sys/dev/usb/controller/dwc_otg.c ============================================================================== --- head/sys/dev/usb/controller/dwc_otg.c Thu May 29 10:46:09 2014 (r266832) +++ head/sys/dev/usb/controller/dwc_otg.c Thu May 29 11:11:19 2014 (r266833) @@ -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; } } @@ -2677,6 +2677,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); @@ -2701,10 +2703,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; @@ -2901,15 +2901,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); } @@ -3274,12 +3273,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); @@ -3456,6 +3456,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 { @@ -3470,6 +3472,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 @@ -3497,6 +3501,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; @@ -3525,14 +3531,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; @@ -3590,8 +3597,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 @@ -3612,15 +3619,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 @@ -3891,12 +3902,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?201405291111.s4TBBJL5043738>