Module Name: src Committed By: riastradh Date: Fri Dec 31 14:24:06 UTC 2021
Modified Files: src/sys/dev/usb: ukbd.c Log Message: ukbd(4): Avoid races in LED setting on attach. - Don't reuse sc_delay for LED task -- a keyboard interrupt shortly after attach might reset sc_delay so that the LEDs never get turned back off. - Don't turn the LEDs back off after attach if something else has already changed them by the time the callout fires. (And make sure to callout_halt before done this time!) To generate a diff of this commit: cvs rdiff -u -r1.155 -r1.156 src/sys/dev/usb/ukbd.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/dev/usb/ukbd.c diff -u src/sys/dev/usb/ukbd.c:1.155 src/sys/dev/usb/ukbd.c:1.156 --- src/sys/dev/usb/ukbd.c:1.155 Sun Dec 26 16:08:21 2021 +++ src/sys/dev/usb/ukbd.c Fri Dec 31 14:24:06 2021 @@ -1,4 +1,4 @@ -/* $NetBSD: ukbd.c,v 1.155 2021/12/26 16:08:21 andvar Exp $ */ +/* $NetBSD: ukbd.c,v 1.156 2021/12/31 14:24:06 riastradh Exp $ */ /* * Copyright (c) 1998 The NetBSD Foundation, Inc. @@ -35,7 +35,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: ukbd.c,v 1.155 2021/12/26 16:08:21 andvar Exp $"); +__KERNEL_RCSID(0, "$NetBSD: ukbd.c,v 1.156 2021/12/31 14:24:06 riastradh Exp $"); #ifdef _KERNEL_OPT #include "opt_ddb.h" @@ -270,6 +270,8 @@ struct ukbd_softc { struct hid_location sc_compose; int sc_leds; struct usb_task sc_ledtask; + struct callout sc_ledreset; + int sc_leds_set; device_t sc_wskbddev; #if defined(WSDISPLAY_COMPAT_RAWKBD) @@ -483,11 +485,13 @@ ukbd_attach(device_t parent, device_t se sc->sc_data_r = 0; usb_init_task(&sc->sc_ledtask, ukbd_set_leds_task, sc, 0); + callout_init(&sc->sc_ledreset, 0); /* Flash the leds; no real purpose, just shows we're alive. */ ukbd_set_leds(sc, WSKBD_LED_SCROLL | WSKBD_LED_NUM | WSKBD_LED_CAPS | WSKBD_LED_COMPOSE); - callout_reset(&sc->sc_delay, mstohz(400), ukbd_delayed_leds_off, sc); + callout_reset(&sc->sc_ledreset, mstohz(400), ukbd_delayed_leds_off, + sc); sc->sc_wskbddev = config_found(self, &a, wskbddevprint, CFARGS_NONE); @@ -573,6 +577,7 @@ ukbd_detach(device_t self, int flags) rv = config_detach(sc->sc_wskbddev, flags); callout_halt(&sc->sc_delay, NULL); + callout_halt(&sc->sc_ledreset, NULL); usb_rem_task_wait(sc->sc_hdev.sc_parent->sc_udev, &sc->sc_ledtask, USB_TASKQ_DRIVER, NULL); @@ -715,6 +720,13 @@ ukbd_delayed_leds_off(void *addr) { struct ukbd_softc *sc = addr; + /* + * If the LEDs have already been set after attach, other than + * by our initial flashing of them, leave them be. + */ + if (sc->sc_leds_set) + return; + ukbd_set_leds(sc, 0); } @@ -880,6 +892,8 @@ ukbd_set_leds(void *v, int leds) if (sc->sc_dying) return; + sc->sc_leds_set = 1; + if (sc->sc_leds == leds) return;