Blog

Desactivar wakeup de USB3 a través de udev

Desactivar wakeup de USB3 a través de udev

Mi PC con Arch tenía problemas para entrar en suspensión. dmesg mostraba un error en el módulo que controla USB3, xhci_hcd:

Jul 08 17:56:55 arai.home.arpa systemd[1]: Starting System Suspend...
Jul 08 17:56:55 arai.home.arpa systemd-sleep[30765]: Performing sleep operation 'suspend'...
Jul 08 17:56:55 arai.home.arpa kernel: PM: suspend entry (deep)
Jul 08 17:56:58 arai.home.arpa kernel: Filesystems sync: 0.005 seconds
Jul 08 17:56:58 arai.home.arpa kernel: Freezing user space processes
Jul 08 17:56:58 arai.home.arpa kernel: Freezing user space processes completed (elapsed 0.001 seconds)
Jul 08 17:56:58 arai.home.arpa kernel: OOM killer disabled.
Jul 08 17:56:58 arai.home.arpa kernel: Freezing remaining freezable tasks
Jul 08 17:56:58 arai.home.arpa kernel: Freezing remaining freezable tasks completed (elapsed 0.001 seconds)
Jul 08 17:56:58 arai.home.arpa kernel: printk: Suspending console(s) (use no_console_suspend to debug)
Jul 08 17:56:58 arai.home.arpa kernel: serial 00:04: disabled


Jul 08 17:56:58 arai.home.arpa kernel: xhci_hcd 0000:0f:00.4: PM: pci_pm_suspend(): hcd_pci_suspend+0x0/0x20 returns ->
Jul 08 17:56:58 arai.home.arpa kernel: xhci_hcd 0000:0f:00.4: PM: dpm_run_callback(): pci_pm_suspend+0x0/0x170 returns>
Jul 08 17:56:58 arai.home.arpa kernel: xhci_hcd 0000:0f:00.4: PM: failed to suspend async: error -16
Jul 08 17:56:58 arai.home.arpa kernel: PM: Some devices failed to suspend, or early wake event detected


Jul 08 17:56:58 arai.home.arpa kernel: xhci_hcd 0000:0c:00.0: xHC error in resume, USBSTS 0x401, Reinit
Jul 08 17:56:58 arai.home.arpa kernel: usb usb1: root hub lost power or was reset
Jul 08 17:56:58 arai.home.arpa kernel: usb usb2: root hub lost power or was reset
Jul 08 17:56:58 arai.home.arpa kernel: [drm] PCIE GART of 1024M enabled (table at 0x000000F41FC00000).
Jul 08 17:56:58 arai.home.arpa kernel: amdgpu 0000:0f:00.0: amdgpu: PSP is resuming...
Jul 08 17:56:58 arai.home.arpa kernel: serial 00:04: activated
Jul 08 17:56:58 arai.home.arpa kernel: amdgpu 0000:0f:00.0: amdgpu: reserve 0xa00000 from 0xf41e000000 for PSP TMR
Jul 08 17:56:58 arai.home.arpa kernel: amdgpu 0000:03:00.0: amdgpu: S3 suspend aborted, resetting...
Jul 08 17:56:58 arai.home.arpa kernel: amdgpu 0000:03:00.0: amdgpu: MODE1 reset
Jul 08 17:56:58 arai.home.arpa kernel: amdgpu 0000:03:00.0: amdgpu: GPU mode1 reset
Jul 08 17:56:58 arai.home.arpa kernel: amdgpu 0000:03:00.0: amdgpu: GPU smu mode1 reset

La línea «PM: Some devices failed to suspend, or early wake event detected» nos indica dos posibles motivos. Mirando aquí, el problema es el segundo: un «early» wakeup causado por, en mi caso, mi hub usb, o el teclado, o el ratón que tengo conectados al puerto 0000:0f:00.4

/proc/acpi /wakeup mostraba XHC0, XHC1 y XHC2 habilitados :

j@arai ~ % cat /proc/acpi/wakeup                                                                                                                                                           [0]
Device	S-state	 Status   Sysfs node
[...]
XHC0	 S4	*enabled   pci:0000:0f:00.3
XHC1	 S4	*enabled   pci:0000:0f:00.4
XHC2	 S4	*enabled   pci:0000:10:00.0
[...]

Una forma de desactivarlo temporalmente es:

sudo echo XHC0 > /proc/acpi/wakeup
sudo echo XHC1 > /proc/acpi/wakeup
sudo echo XHC2 > /proc/acpi/wakeup

Si deseamos que el cambio sea permanente, podemos introducir lo anterior en un script y ejecutarlo al arranque. Sin embargo, creo que es más elegante hacerlo con udev. En este artículo es la opción elegida.

Busqué el «nodo» («Sysfs node»)

j@arai ~ % sudo find /sys -name "*0000:0f:00.3*"                                           [0]
[sudo] password for j: 
/sys/kernel/iommu_groups/29/devices/0000:0f:00.3
/sys/kernel/debug/usb/xhci/0000:0f:00.3
/sys/devices/pci0000:00/0000:00:00.2/iommu/ivhd0/devices/0000:0f:00.3
/sys/devices/pci0000:00/0000:00:08.1/0000:0f:00.3
/sys/bus/pci/devices/0000:0f:00.3
/sys/bus/pci/drivers/xhci_hcd/0000:0f:00.3

Listo los atributos configurables en udev mediante udevadm:

[root@arai j]# udevadm info -a -p /sys/devices/pci0000:00/0000:00:08.1/0000:0f:00.3

Udevadm info starts with the device specified by the devpath and then
walks up the chain of parent devices. It prints for every device
found, all possible attributes in the udev rules key format.
A rule to match, can be composed by the attributes of the device
and the attributes from one single parent device.

  looking at device '/devices/pci0000:00/0000:00:08.1/0000:0f:00.3':
    KERNEL=="0000:0f:00.3"
    SUBSYSTEM=="pci"
    DRIVER=="xhci_hcd"
    ATTR{ari_enabled}=="0"
    ATTR{broken_parity_status}=="0"
    ATTR{class}=="0x0c0330"
    ATTR{consistent_dma_mask_bits}=="64"
    ATTR{current_link_speed}=="16.0 GT/s PCIe"
    ATTR{current_link_width}=="16"
    ATTR{d3cold_allowed}=="1"
    ATTR{device}=="0x15b6"
    ATTR{dma_mask_bits}=="64"
    ATTR{driver_override}=="(null)"
    ATTR{enable}=="0"
    ATTR{irq}=="90"
    ATTR{link/l0s_aspm}=="0"
    ATTR{link/l1_aspm}=="0"
    ATTR{local_cpulist}=="0-31"
    ATTR{local_cpus}=="ffffffff"
    ATTR{max_link_speed}=="16.0 GT/s PCIe"
    ATTR{max_link_width}=="16"
    ATTR{msi_bus}=="1"
    ATTR{msi_irqs/91}=="msix"
    ATTR{msi_irqs/92}=="msix"
    ATTR{msi_irqs/93}=="msix"
    ATTR{msi_irqs/94}=="msix"
    ATTR{msi_irqs/95}=="msix"
    ATTR{msi_irqs/96}=="msix"
    ATTR{msi_irqs/97}=="msix"
    ATTR{msi_irqs/98}=="msix"
    ATTR{numa_node}=="-1"
    ATTR{power/control}=="auto"
    ATTR{power/runtime_active_time}=="9870"
    ATTR{power/runtime_status}=="suspended"
    ATTR{power/runtime_suspended_time}=="11689376"
    ATTR{power/wakeup}=="disabled"
    ATTR{power/wakeup_abort_count}==""
    ATTR{power/wakeup_active}==""
    ATTR{power/wakeup_active_count}==""
    ATTR{power/wakeup_count}==""
    ATTR{power/wakeup_expire_count}==""
    ATTR{power/wakeup_last_time_ms}==""
    ATTR{power/wakeup_max_time_ms}==""
    ATTR{power/wakeup_total_time_ms}==""
    ATTR{power_state}=="D3hot"
    ATTR{remove}=="(not readable)"
    ATTR{rescan}=="(not readable)"
    ATTR{reset}=="(not readable)"

El atributo que nos interesa es power/wakeup

Creo el fichero /etc/udev/rules.d/50-wake-on-device.rules con este contenido:

ACTION=="add", KERNEL=="0000:0f:00.3", ATTR{power/wakeup}="disabled"
ACTION=="add", KERNEL=="0000:0f:00.4", ATTR{power/wakeup}="disabled"
ACTION=="add", KERNEL=="0000:10:00.0", ATTR{power/wakeup}="disabled"

Reinicié y ya entraba en suspensión correctamente. Para confirmar, /proc/acpi/wakeup los muestra deshabilitados:

j@arai ~/Documents % sudo cat /proc/acpi/wakeup                                                                                                                                            [0]
[sudo] password for j: 
Device	S-state	 Status   Sysfs node
[...]
XHC0	 S4	*disabled  pci:0000:0f:00.3
XHC1	 S4	*disabled  pci:0000:0f:00.4
XHC2	 S4	*disabled  pci:0000:10:00.0
[...]