summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorhselasky <hselasky@FreeBSD.org>2015-10-30 14:50:29 +0000
committerhselasky <hselasky@FreeBSD.org>2015-10-30 14:50:29 +0000
commit232f7e59dfdfb0b4695e73ef77162336c2931fe7 (patch)
treeaa287fa07797a5e3b925190b64a9a450bf9c29cf
parent5e057d29086245855ba89118eb697cab393b48ef (diff)
downloadFreeBSD-src-232f7e59dfdfb0b4695e73ef77162336c2931fe7.zip
FreeBSD-src-232f7e59dfdfb0b4695e73ef77162336c2931fe7.tar.gz
Reduce the DWC OTG interrupt load by not reading all the host channel
status registers for every interrupt. Check a common host channel status interrupt register first, then conditionally read the individual host channel status registers. Submitted by: Sebastian Huber <sebastian.huber@embedded-brains.de> MFC after: 1 week
-rw-r--r--sys/dev/usb/controller/dwc_otg.c17
1 files changed, 11 insertions, 6 deletions
diff --git a/sys/dev/usb/controller/dwc_otg.c b/sys/dev/usb/controller/dwc_otg.c
index e018ab5..6243d8e 100644
--- a/sys/dev/usb/controller/dwc_otg.c
+++ b/sys/dev/usb/controller/dwc_otg.c
@@ -2558,6 +2558,7 @@ dwc_otg_interrupt_poll_locked(struct dwc_otg_softc *sc)
struct usb_xfer *xfer;
uint32_t count;
uint32_t temp;
+ uint32_t haint;
uint8_t got_rx_status;
uint8_t x;
@@ -2575,14 +2576,18 @@ repeat:
DPRINTF("Yield\n");
return;
}
+
/* get all host channel interrupts */
- for (x = 0; x != sc->sc_host_ch_max; x++) {
+ haint = DWC_OTG_READ_4(sc, DOTG_HAINT);
+ while (1) {
+ x = ffs(haint) - 1;
+ if (x >= sc->sc_host_ch_max)
+ break;
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) {
OpenPOWER on IntegriCloud