Module Name: src Committed By: riastradh Date: Sun Nov 29 22:54:51 UTC 2020
Modified Files: src/sys/dev/usb: uhid.c uhidev.c uhidev.h Log Message: usb: Overhaul uhid(4) and uhidev(4) locking. - uhidev API rules: 1. Call uhidev_open when you want exclusive use of a report id. After it succeeds, you will get interrupts. 2. Call uhidev_close when done with exclusive use of a report id. After it returns, you will no longer get interrupts. => uhidev_open/close do not nest. 3. uhidev_write no longer requires the caller to have exclusive access -- if there is a write in progress, it will block interruptibly until done. This way drivers for individual report ids need not work separately to coordinate their writes. 4. You must uhidev_stop to abort any pending writes on the same report id. (uhidev_stop no longer does anything else -- to ensure no more interrupts, just use uhidev_close.) - Fix uhidev_open/close locking -- uhidev now has an interruptible config lock held only on first open and last close by any report id in the device, to serialize the transition between zero and nonzero numbers of references which requires opening/closing pipes and allocating/freeing buffers. - Make /dev/uhidN selnotify(POLLHUP) when the device is yanked. - Factor uhid device lookup and reference counting and dying detection and so on into uhid_enter/exit. - Nix struct uhid_softc::sc_access_lock. This served no purpose but to confuse me when trying to understand the logic of this beast (and to ensure uhidev_write exclusion, but it was uninterruptible, which is wrong for something that implements userland operations, and didn't actually work because uhidev_write did nothing to coordinate between different report ids). - Fix locking in select/poll. - Use atomics to manage UHID_IMMED to keep it simple. (sc_lock would be fine too but it makes the code more verbose.) - Omit needless UHID_ASLP -- cv_broadcast already has this micro-optimization. With these changes, my Pinebook survives for i in `jot 100`; do echo '###' $i for j in `jot 16`; do usbhidctl -rf /dev/uhid$j >/dev/null & done wait done while plugging and unplugging uhid(4) devices (U2F keys), and the U2F keys still work as U2F keys. ok nick, mrg XXX pullup-9 XXX pullup-8? Note on ABI and pullups: This changes the layout of struct uhidev_softc, but with the sole exception of ucycom(4) -- which at the moment is completely broken and unusable -- the only members that USB HID drivers use are sc_udev and sc_iface, which haven't changed. The layout of struct uhidev, which is allocated by each USB HID driver in its own softc structure, is unchanged. To generate a diff of this commit: cvs rdiff -u -r1.114 -r1.115 src/sys/dev/usb/uhid.c cvs rdiff -u -r1.78 -r1.79 src/sys/dev/usb/uhidev.c cvs rdiff -u -r1.20 -r1.21 src/sys/dev/usb/uhidev.h Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.