Date: Mon, 16 Aug 2021 00:49:48 GMT From: Vladimir Kondratyev <wulf@FreeBSD.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-branches@FreeBSD.org Subject: git: c3bccba63d0d - stable/13 - iichid(4): Perform bus_teardown_intr/bus_setup_intr to disable interrupts Message-ID: <202108160049.17G0nmIW099621@gitrepo.freebsd.org>
next in thread | raw e-mail | index | archive | help
The branch stable/13 has been updated by wulf: URL: https://cgit.FreeBSD.org/src/commit/?id=c3bccba63d0d2beb105bfc7b7c6db5ecc977ccfa commit c3bccba63d0d2beb105bfc7b7c6db5ecc977ccfa Author: Vladimir Kondratyev <wulf@FreeBSD.org> AuthorDate: 2021-07-09 19:32:59 +0000 Commit: Vladimir Kondratyev <wulf@FreeBSD.org> CommitDate: 2021-08-16 00:46:18 +0000 iichid(4): Perform bus_teardown_intr/bus_setup_intr to disable interrupts during suspend/resume cycle. Previously used bus_generic_suspend_intr and bus_generic_resume_intr may cause interrupt storm because of missed interrupt acknowledges caused by blocking of intr handler. Reported by: J.R. Oldroyd <jr_AT_opal_DOT_com> (cherry picked from commit 82626fef6253a9172163df137097f54e93e3c209) --- sys/dev/iicbus/iichid.c | 47 +++++++++++++++++++++++++++++++++++------------ 1 file changed, 35 insertions(+), 12 deletions(-) diff --git a/sys/dev/iicbus/iichid.c b/sys/dev/iicbus/iichid.c index 68d7cfd9090f..d95ffb8add88 100644 --- a/sys/dev/iicbus/iichid.c +++ b/sys/dev/iicbus/iichid.c @@ -177,6 +177,7 @@ struct iichid_softc { struct task event_task; #endif + struct task suspend_task; bool open; /* iicbus lock */ bool suspend; /* iicbus lock */ bool power_on; /* iicbus lock */ @@ -188,6 +189,8 @@ static device_detach_t iichid_detach; static device_resume_t iichid_resume; static device_suspend_t iichid_suspend; +static void iichid_suspend_task(void *, int); + #ifdef IICHID_SAMPLING static int iichid_setup_callout(struct iichid_softc *); static int iichid_reset_callout(struct iichid_softc *); @@ -1075,6 +1078,7 @@ iichid_attach(device_t dev) sc->power_on = true; + TASK_INIT(&sc->suspend_task, 0, iichid_suspend_task, sc); #ifdef IICHID_SAMPLING TASK_INIT(&sc->event_task, 0, iichid_event_task, sc); /* taskqueue_create can't fail with M_WAITOK mflag passed. */ @@ -1146,7 +1150,6 @@ iichid_attach(device_t dev) device_printf(dev, "failed to attach child: error %d\n", error); iichid_detach(dev); } - done: (void)iichid_set_power(sc, I2C_HID_POWER_OFF); sc->power_on = false; @@ -1175,6 +1178,14 @@ iichid_detach(device_t dev) return (0); } +static void +iichid_suspend_task(void *context, int pending) +{ + struct iichid_softc *sc = context; + + iichid_teardown_interrupt(sc); +} + static int iichid_suspend(device_t dev) { @@ -1183,12 +1194,6 @@ iichid_suspend(device_t dev) sc = device_get_softc(dev); (void)bus_generic_suspend(dev); -#ifdef IICHID_SAMPLING - if (sc->sampling_rate_slow < 0) -#endif - (void)bus_generic_suspend_intr(device_get_parent(dev), dev, - sc->irq_res); - /* * 8.2 - The HOST is going into a deep power optimized state and wishes * to put all the devices into a low power state also. The HOST @@ -1202,6 +1207,24 @@ iichid_suspend(device_t dev) else DPRINTF(sc, "Successfully set power_state\n"); +#ifdef IICHID_SAMPLING + if (sc->sampling_rate_slow < 0) +#endif + { + /* + * bus_teardown_intr can not be executed right here as it wants + * to run on certain CPU to interacts with LAPIC while suspend + * thread is bound to CPU0. So run it from taskqueue context. + */ +#ifdef IICHID_SAMPLING +#define suspend_thread sc->taskqueue +#else +#define suspend_thread taskqueue_thread +#endif + taskqueue_enqueue(suspend_thread, &sc->suspend_task); + taskqueue_drain(suspend_thread, &sc->suspend_task); + } + return (0); } @@ -1212,6 +1235,11 @@ iichid_resume(device_t dev) int error; sc = device_get_softc(dev); +#ifdef IICHID_SAMPLING + if (sc->sampling_rate_slow < 0) +#endif + iichid_setup_interrupt(sc); + DPRINTF(sc, "Resume called, setting device to power_state 0\n"); error = iichid_set_power_state(sc, IICHID_PS_NULL, IICHID_PS_ON); if (error != 0) @@ -1219,11 +1247,6 @@ iichid_resume(device_t dev) else DPRINTF(sc, "Successfully set power_state\n"); (void)bus_generic_resume(dev); -#ifdef IICHID_SAMPLING - if (sc->sampling_rate_slow < 0) -#endif - (void)bus_generic_resume_intr(device_get_parent(dev), dev, - sc->irq_res); return (0); }
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?202108160049.17G0nmIW099621>