tech-kern archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
Re: Interrupt storm mitigation needed
On Thu, Feb 12, 2015 at 05:02:28AM +0100, Tom Ivar Helbekkmo wrote:
> Joerg Sonnenberger <joerg%britannica.bec.de@localhost> writes:
>
> > Can you add a counter to uhci.c line 1317? The question for me is
> > whether the device is creating interrupts without actually setting the
> > status to anything different or if it does provide some notification but
> > at a too high rate.
>
> Well, that was an interesting experiment! It is, indeed, hitting the
> "return" at that point. In fact, many more times than the counters
> showed by "vmstat -i" indicate. Even when I'm not noticing any
> problems, the return counter I installed climbs faster than the number
> of interrupts shown for the ioapic pin, but over the course of a couple
> of back-to-back, longish hangs, the vmstat counter increased by about a
> half million, but my return counter jumped by about 23 million!
Well, let's try the first hack of keep uhci interrupts off and just poll
via timeout.
Joerg
Index: uhci.c
===================================================================
RCS file: /home/joerg/repo/netbsd/src/sys/dev/usb/uhci.c,v
retrieving revision 1.264
diff -u -p -r1.264 uhci.c
--- uhci.c 5 Aug 2014 06:35:24 -0000 1.264
+++ uhci.c 12 Feb 2015 08:35:26 -0000
@@ -72,6 +72,11 @@ __KERNEL_RCSID(0, "$NetBSD: uhci.c,v 1.2
/*#define UHCI_CTL_LOOP */
+Static int uhci_intr1(uhci_softc_t *);
+static void uhci_intr1_wrap(void *sc)
+{
+ uhci_intr1(sc);
+}
#ifdef UHCI_DEBUG
uhci_softc_t *thesc;
@@ -542,8 +547,11 @@ uhci_init(uhci_softc_t *sc)
DPRINTFN(1,("uhci_init: enabling\n"));
err = uhci_run(sc, 1, 0); /* and here we go... */
- UWRITE2(sc, UHCI_INTR, UHCI_INTR_TOCRCIE | UHCI_INTR_RIE |
- UHCI_INTR_IOCE | UHCI_INTR_SPIE); /* enable interrupts */
+
+ callout_init(&sc->sc_simulated_interrupt, CALLOUT_MPSAFE);
+ callout_setfunc(&sc->sc_simulated_interrupt, uhci_intr1_wrap, sc);
+ callout_schedule(&sc->sc_simulated_interrupt, 1);
+
return err;
}
@@ -720,8 +728,6 @@ uhci_resume(device_t dv, const pmf_qual_
UHCICMD(sc, cmd | UHCI_CMD_FGR); /* force resume */
usb_delay_ms_locked(&sc->sc_bus, USB_RESUME_DELAY, &sc->sc_intr_lock);
UHCICMD(sc, cmd & ~UHCI_CMD_EGSM); /* back to normal */
- UWRITE2(sc, UHCI_INTR, UHCI_INTR_TOCRCIE |
- UHCI_INTR_RIE | UHCI_INTR_IOCE | UHCI_INTR_SPIE);
UHCICMD(sc, UHCI_CMD_MAXP);
uhci_run(sc, 1, 1); /* and start traffic again */
usb_delay_ms_locked(&sc->sc_bus, USB_RESUME_RECOVERY, &sc->sc_intr_lock);
@@ -735,6 +741,7 @@ uhci_resume(device_t dv, const pmf_qual_
#endif
sc->sc_suspend = PWR_RESUME;
+ callout_schedule(&sc->sc_simulated_interrupt, 1);
mutex_spin_exit(&sc->sc_intr_lock);
return true;
@@ -1270,8 +1277,6 @@ uhci_remove_bulk(uhci_softc_t *sc, uhci_
sc->sc_bulk_end = pqh;
}
-Static int uhci_intr1(uhci_softc_t *);
-
int
uhci_intr(void *arg)
{
@@ -1290,8 +1295,6 @@ uhci_intr(void *arg)
goto done;
}
- ret = uhci_intr1(sc);
-
done:
mutex_spin_exit(&sc->sc_intr_lock);
return ret;
@@ -1313,8 +1316,10 @@ uhci_intr1(uhci_softc_t *sc)
KASSERT(mutex_owned(&sc->sc_intr_lock));
status = UREAD2(sc, UHCI_STS) & UHCI_STS_ALLINTRS;
- if (status == 0) /* The interrupt was not for us. */
+ if (status == 0) { /* The interrupt was not for us. */
+ callout_schedule(&sc->sc_simulated_interrupt, 1);
return (0);
+ }
if (sc->sc_suspend != PWR_RESUME) {
#ifdef DIAGNOSTIC
@@ -1322,6 +1327,7 @@ uhci_intr1(uhci_softc_t *sc)
device_xname(sc->sc_dev));
#endif
UWRITE2(sc, UHCI_STS, status); /* acknowledge the ints */
+ callout_schedule(&sc->sc_simulated_interrupt, 1);
return (0);
}
@@ -1368,6 +1374,7 @@ uhci_intr1(uhci_softc_t *sc)
DPRINTFN(15, ("%s: uhci_intr: exit\n", device_xname(sc->sc_dev)));
+ callout_schedule(&sc->sc_simulated_interrupt, 1);
return (1);
}
Home |
Main Index |
Thread Index |
Old Index