Re: Panic when pressing Caps Lock in the console

Stefan Sperling <[email protected]> Fri, 19 Jun 2026 12:54:54 +0200
Newsgroups gmane.os.openbsd.bugs
Message-ID <[email protected]>
On Thu, Jun 18, 2026 at 11:06:58PM -0400, [email protected] wrote:
> >Synopsis:	Panic when pressing Caps Lock in the console
> >Category:	amd64
> >Environment:
> 	System      : OpenBSD 7.9
> 	Details     : OpenBSD 7.9-current (GENERIC.MP) #2: Fri Jun 12 12:08:26 MDT 2026
> 			 [email protected]:/usr/src/sys/arch/amd64/compile/GENERIC.MP
> 
> 	Architecture: OpenBSD.amd64
> 	Machine     : amd64
> >Description:
> 	When pressing the Caps Lock key in a virtual console, the
> 	system may lock up or panic. At that point, the keyboard is no
> 	longer responsive. Caps Lock works as expected under X11.
> 	Transcribed traceback:
> 
> 	panic: kernel diagnostic assertion "p->p_wchan == NULL" failed: file "/usr/src/sys/kern/kern_sched.c", line 370
> 	Stopped at db_enter+@x14: popq %rbp
> 	   TID   PID UID PRFLAGS PFLAGS CPU COMMAND
> 	250371 22668   0     0x2      0   1 ld
> 	297504 48402   0 0x14000  0x200   3 sdmmc0
> 	db_enter() at db_enter+0x14
> 	panic(...) at panic+0xd5
> 	__assert(...) at __assert+0x29
> 	sched_chooseproc() at sched_chooseproc+0x241
> 	mi_switch() at mi_switch+0x10a
> 	sleep_finish(...) at sleep_finish+0x165
> 	dwiic_i2c_exec(...) at dwiic_i2c_exec+0x356
> 	ihidev_send_report(...) at ihidev_send_report+0xac
> 	ikbd_set_leds(...) at ikbd_set_leds+0x57
> 	wskbd_translate(...) at wskbd_translate+0x2e7
> 	wskbd_input(...) at wskbd_input+0x84
> 	hidkbd_decode(...) at hidkbd_decode+0x398
> 	ihidev_intr(...) at ihidev_intr+0x34e
> 	bytgpio_intr(...) at bytgpio_intr+0x118
> 	end trace frame: ..., count: 0
> 
> >How-To-Repeat:
> 	From ttyC0: press the Caps Lock key 1-3 times.
> >Fix:
> 	It looks like the bug stems from sleeping inside an interrupt
> 	handler. My understanding is that pressing Caps Lock fires an
> 	interrupt that ultimately tries to toggle the Caps Lock LED on.
> 	The obvious fix is to pass I2C_F_POLL to iic_exec(). This patch
> 	fixes my panic, but maybe it's preferable to defer it to a task
> 	instead. I'm happy to come back with a more complete patch
> 	based on your guidance.

Nice find. I suspect a task should be used here, perhaps depending on
the type of child HID device. We will definitely want interrupts to
be used when ihidev is serving touchpads since jcs@ spent quite a lot
of effort on avoiding polling mode for them.

> diff --git a/sys/dev/i2c/ihidev.c b/sys/dev/i2c/ihidev.c
> index 39680c727d5..f4f87f01e17 100644
> --- a/sys/dev/i2c/ihidev.c
> +++ b/sys/dev/i2c/ihidev.c
> @@ -1001,7 +1001,7 @@ ihidev_send_report(struct device *dev, int repid, void *data, int data_len)
>         memcpy(finalcmd + cmd_len, data, data_len);
> 
>         res = iic_exec(sc->sc_tag, I2C_OP_WRITE_WITH_STOP, sc->sc_addr,
> -           finalcmd, cmd_len + data_len, NULL, 0, 0);
> +           finalcmd, cmd_len + data_len, NULL, 0, I2C_F_POLL);
> 
>         free(finalcmd, M_DEVBUF, cmd_len + data_len);