Hi All,
I recently started to play around with uvideo(4) and uaudio(4) on my
amd64 iMacs. There I quickly noticed regular freezes when streaming
USB video or audio. On some of those machines it was very frequent,
like every few seconds the video or audio stream did freeze for ~1s,
then resume, while the rest of the system did continue to operate fine.
First I found that when running the machine with an SP kernel, the issue
disappears. Secondly some debugging hours, and quite some e-mail
exchanges with mpi@ later, I found that the freeze is getting triggered
by the asmc(4) driver, specifically by the sensor_task_register()
update function. My first intention was to change
sensor_task_register() to call taskq_create() with the TASKQ_MPSAFE
flag for a test, to remove the kernel lock, which also resolved the
freezing with an MP kernel. [1]
In the end I found that the asmc(4) sensor update code is calling a
busy loop in asmc_wait(), where the delay call is spending ~50ms in
average. Doing that during the KERNEL_LOCK() is resulting in
noticeable USB ISOC transfer delays. Obviously replacing the delay(9)
with tsleep_nsec(9) in asmc(4) did fix the issue as well. [2]
I'm not sure if just applying diff [2] to the driver is the right
approach finally or if we need to take a more generic path to address
this problem. Any feedback, help, comments appreciated.
[1]
Index: kern/kern_sensors.c
===================================================================
RCS file: /cvs/src/sys/kern/kern_sensors.c,v
retrieving revision 1.39
diff -u -p -u -p -r1.39 kern_sensors.c
--- kern/kern_sensors.c 19 Dec 2019 17:40:11 -0000 1.39
+++ kern/kern_sensors.c 9 Dec 2020 12:13:10 -0000
@@ -193,7 +193,8 @@ sensor_task_register(void *arg, void (*f
#endif
if (sensors_taskq == NULL &&
- (sensors_taskq = taskq_create("sensors", 1, IPL_HIGH, 0))
== NULL)
+ (sensors_taskq = taskq_create("sensors", 1, IPL_HIGH,
+ TASKQ_MPSAFE)) == NULL)
sensors_taskq = systq;
st = malloc(sizeof(*st), M_DEVBUF, M_NOWAIT);
[2]
Index: dev/acpi/asmc.c
===================================================================
RCS file: /cvs/src/sys/dev/acpi/asmc.c,v
retrieving revision 1.2
diff -u -p -u -p -r1.2 asmc.c
--- dev/acpi/asmc.c 13 Sep 2020 14:11:28 -0000 1.2
+++ dev/acpi/asmc.c 9 Dec 2020 22:06:50 -0000
@@ -442,7 +442,7 @@ asmc_wait(struct asmc_softc *sc, uint8_t
if ((bus_space_read_1(sc->sc_iot, sc->sc_ioh,
ASMC_COMMAND) & mask) == val)
return 0;
- delay(10);
+ tsleep_nsec(sc, PWAIT, "asmc_wait", USEC_TO_NSEC(10));
}
return ETIMEDOUT;
}