Hi, I was looking at libusb/libusb#237 and noticed that TLP is a huge offender with regard to USB device processing in udev.
The TLP udev rules need an extremely long time to process events. This is not really necessary, as there is no reason to block the rest of udev (and userspace!) in order to possibly enable USB autosuspend.
The obvious reason for it to go really horribly wrong is the sleep of 500ms in the codebase, see https://github.com/linrunner/TLP/blob/main/func.d/20-tlp-func-usb#L64. This sleep is probably just plain wrong, if subdevices are of such importance, you can also modify the parent device from a DEVTYPE=usb_interface rule.
But, equally bad is the fact that we even wait for this operation to complete. I am thinking the following solutions are possible (roughly in preferred order in my view):
- Have
udev rules that do not require executing a long script. You can test for file existence in udev, so writing out a file to e.g. /run/tlp and testing for that you can enable/disable rules. Not sure if a RUN rule though, as autosuspend needs to be set on the parent device.
- Have a tiny daemon that monitors udev and reacts to the events.
- Push the script into a systemd (template) unit. i.e. add
TAG+="systemd" and set ENV{SYSTEMD_WANTS}+="tlp-usb-udev@.service". The service should be Type=oneshot with ExecStart=/lib/udev/tlp-usb-udev usb %I or something similar (did not test it).
- To avoid the sleep, one could trigger it for each interface update. But, that is kind of ugly as it would create a lot of
.device units.
- I expect
udevadm settle is enough though, so possibly just an ExecStartPre-=/usr/sbin/udevadm settle.
- Remove the sleep and run for
usb_interface and update the parent; but that still means loading all the shell scripting.
So, 1. not sure, might be complicated. As for 2. (daemon), that seems kinda neat in a way. 3. may be a bit verbose in systemctl status, I imagine. And, 4. is simple, but I am not sure I like it that much :-)
Hi, I was looking at libusb/libusb#237 and noticed that TLP is a huge offender with regard to USB device processing in udev.
The TLP udev rules need an extremely long time to process events. This is not really necessary, as there is no reason to block the rest of udev (and userspace!) in order to possibly enable USB autosuspend.
The obvious reason for it to go really horribly wrong is the sleep of 500ms in the codebase, see https://github.com/linrunner/TLP/blob/main/func.d/20-tlp-func-usb#L64. This sleep is probably just plain wrong, if subdevices are of such importance, you can also modify the parent device from a
DEVTYPE=usb_interfacerule.But, equally bad is the fact that we even wait for this operation to complete. I am thinking the following solutions are possible (roughly in preferred order in my view):
udevrules that do not require executing a long script. You can test for file existence in udev, so writing out a file to e.g./run/tlpand testing for that you can enable/disable rules. Not sure if aRUNrule though, as autosuspend needs to be set on the parent device.TAG+="systemd"and setENV{SYSTEMD_WANTS}+="tlp-usb-udev@.service". The service should beType=oneshotwithExecStart=/lib/udev/tlp-usb-udev usb %Ior something similar (did not test it)..deviceunits.udevadm settleis enough though, so possibly just anExecStartPre-=/usr/sbin/udevadm settle.usb_interfaceand update the parent; but that still means loading all the shell scripting.So, 1. not sure, might be complicated. As for 2. (daemon), that seems kinda neat in a way. 3. may be a bit verbose in
systemctl status, I imagine. And, 4. is simple, but I am not sure I like it that much :-)