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

_______________________________________________
[email protected] mailing list
https://lists.freebsd.org/mailman/listinfo/freebsd-usb
To unsubscribe, send any mail to "[email protected]"

Reply via email to