Re: Panic when pressing Caps Lock in the console

John Troy <[email protected]> Tue, 23 Jun 2026 13:42:46 -0400
Newsgroups gmane.os.openbsd.bugs
Message-ID <[email protected]>
On 6/22/26 5:33 PM, Vitaliy Makkoveev wrote:
> It's all kernel locked. You don't need atomic operations here.

Understood, thanks for the feedback. Here it is without atomics.

-John


diff --git a/sys/dev/i2c/ikbd.c b/sys/dev/i2c/ikbd.c
index 6551b918f01..5dc9430d6ff 100644
--- a/sys/dev/i2c/ikbd.c
+++ b/sys/dev/i2c/ikbd.c
@@ -23,6 +23,7 @@
 #include <sys/device.h>
 #include <sys/ioctl.h>
 #include <sys/timeout.h>
+#include <sys/task.h>
 
 #include <dev/i2c/i2cvar.h>
 #include <dev/i2c/ihidev.h>
@@ -38,6 +39,8 @@ struct ikbd_softc {
 	struct ihidev	sc_hdev;
 #define sc_ledsize	sc_hdev.sc_osize
 	struct hidkbd	sc_kbd;
+	struct task	sc_led_task;
+	uint8_t		sc_led_report;
 	int		sc_spl;
 };
 
@@ -55,6 +58,7 @@ const struct wskbd_consops ikbd_consops = {
 
 int	ikbd_enable(void *, int);
 void	ikbd_set_leds(void *, int);
+void	ikbd_set_leds_task(void *);
 int	ikbd_ioctl(void *, u_long, caddr_t, int, struct proc *);
 
 const struct wskbd_accessops ikbd_accessops = {
@@ -117,6 +121,8 @@ ikbd_attach(struct device *parent, struct device *self, void *aux)
 
 	printf("\n");
 
+	task_set(&sc->sc_led_task, ikbd_set_leds_task, sc);
+
 	if (kbd->sc_console_keyboard) {
 		extern struct wskbd_mapdata ukbd_keymapdata;
 
@@ -133,8 +139,11 @@ ikbd_detach(struct device *self, int flags)
 {
 	struct ikbd_softc *sc = (struct ikbd_softc *)self;
 	struct hidkbd *kbd = &sc->sc_kbd;
+	int rv;
 
-	return hidkbd_detach(kbd, flags);
+	rv = hidkbd_detach(kbd, flags);
+	taskq_del_barrier(systq, &sc->sc_led_task);
+	return rv;
 }
 
 void
@@ -173,11 +182,20 @@ ikbd_set_leds(void *v, int leds)
 	uint8_t res;
 
 	if (sc->sc_ledsize && hidkbd_set_leds(kbd, leds, &res) != 0) {
-		ihidev_send_report((struct device *)sc->sc_hdev.sc_parent,
-		    sc->sc_hdev.sc_report_id, &res, 1);
+		sc->sc_led_report = res;
+		task_add(systq, &sc->sc_led_task);
 	}
 }
 
+void
+ikbd_set_leds_task(void *v)
+{
+	struct ikbd_softc *sc = v;
+
+	ihidev_send_report((struct device *)sc->sc_hdev.sc_parent,
+	    sc->sc_hdev.sc_report_id, &sc->sc_led_report, 1);
+}
+
 int
 ikbd_ioctl(void *v, u_long cmd, caddr_t data, int flag, struct proc *p)
 {