Skip site navigation (1)Skip section navigation (2)
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>