Date: Fri, 30 Oct 2015 14:38:27 +0100 From: Sebastian Huber <sebastian.huber@embedded-brains.de> To: freebsd-usb@freebsd.org Subject: [PATCH] dwc_otg: Reduce interrupt load Message-ID: <1446212307-4660-1-git-send-email-sebastian.huber@embedded-brains.de>
next in thread | raw e-mail | index | archive | help
Tested on an Altera Cyclone V development kit. Here the controller has 16 host channels. This change significantly reduced the time spent in the dwc_otg_interrupt_poll_locked() function. --- sys/dev/usb/controller/dwc_otg.c | 21 ++++++++++++--------- sys/dev/usb/controller/dwc_otg.h | 1 + 2 files changed, 13 insertions(+), 9 deletions(-) diff --git a/sys/dev/usb/controller/dwc_otg.c b/sys/dev/usb/controller/dwc_otg.c index e018ab5..a57e064 100644 --- a/sys/dev/usb/controller/dwc_otg.c +++ b/sys/dev/usb/controller/dwc_otg.c @@ -270,8 +270,7 @@ dwc_otg_init_fifo(struct dwc_otg_softc *sc, uint8_t mode) memset(sc->sc_chan_state, 0, sizeof(sc->sc_chan_state)); /* enable all host channel interrupts */ - DWC_OTG_WRITE_4(sc, DOTG_HAINTMSK, - (1U << sc->sc_host_ch_max) - 1U); + DWC_OTG_WRITE_4(sc, DOTG_HAINTMSK, sc->sc_host_ch_mask); } if (mode == DWC_MODE_DEVICE) { @@ -2559,7 +2558,8 @@ dwc_otg_interrupt_poll_locked(struct dwc_otg_softc *sc) uint32_t count; uint32_t temp; uint8_t got_rx_status; - uint8_t x; + uint32_t haint; + int x; if (sc->sc_flags.status_device_mode == 0) { /* @@ -2576,13 +2576,14 @@ repeat: return; } /* get all host channel interrupts */ - for (x = 0; x != sc->sc_host_ch_max; x++) { + haint = DWC_OTG_READ_4(sc, DOTG_HAINT) & sc->sc_host_ch_mask; + while (haint != 0) { + x = ffs((int)haint) - 1; temp = DWC_OTG_READ_4(sc, DOTG_HCINT(x)); - if (temp != 0) { - DWC_OTG_WRITE_4(sc, DOTG_HCINT(x), temp); - temp &= ~HCINT_SOFTWARE_ONLY; - sc->sc_chan_state[x].hcint |= temp; - } + DWC_OTG_WRITE_4(sc, DOTG_HCINT(x), temp); + temp &= ~HCINT_SOFTWARE_ONLY; + sc->sc_chan_state[x].hcint |= temp; + haint &= ~(1U << x); } if (sc->sc_last_rx_status == 0) { @@ -3845,6 +3846,8 @@ dwc_otg_init(struct dwc_otg_softc *sc) if (sc->sc_host_ch_max > DWC_OTG_MAX_CHANNELS) sc->sc_host_ch_max = DWC_OTG_MAX_CHANNELS; + sc->sc_host_ch_mask = (1U << sc->sc_host_ch_max) - 1U; + temp = DWC_OTG_READ_4(sc, DOTG_GHWCFG4); sc->sc_dev_in_ep_max = GHWCFG4_NUM_IN_EP_GET(temp); diff --git a/sys/dev/usb/controller/dwc_otg.h b/sys/dev/usb/controller/dwc_otg.h index f5e9887..6882e40 100644 --- a/sys/dev/usb/controller/dwc_otg.h +++ b/sys/dev/usb/controller/dwc_otg.h @@ -185,6 +185,7 @@ struct dwc_otg_softc { uint32_t sc_tmr_val; uint32_t sc_hprt_val; uint32_t sc_xfer_complete; + uint32_t sc_host_ch_mask; uint16_t sc_active_rx_ep; uint16_t sc_last_frame_num; -- 1.8.4.5
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?1446212307-4660-1-git-send-email-sebastian.huber>