Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

USB: Fix the issue of task recovery failure caused by USB status when S4 wakes up

When a device is inserted into the USB port and an S4 wakeup is initiated,
after the USB-hub initialization is completed, it will automatically enter
suspend mode. Upon detecting a device on the USB port, it will proceed with
resume and set the hcd to the HCD_FLAG_WAKEUP_PENDING state. During the S4
wakeup process, peripherals are put into suspend mode, followed by task
recovery. However, upon detecting that the hcd is in the
HCD_FLAG_WAKEUP_PENDING state, it will return an EBUSY status, causing the
S4 suspend to fail and subsequent task recovery to not proceed.
-
[ 27.594598][ 1] PM: pci_pm_freeze(): hcd_pci_suspend+0x0/0x28 returns -16
[ 27.594601][ 1] PM: dpm_run_callback(): pci_pm_freeze+0x0/0x100 returns -16
[ 27.603420][ 1] ehci-pci 0000:00:04.1: pci_pm_freeze+0x0/0x100 returned 0 after 3 usecs
[ 27.612233][ 1] ehci-pci 0000:00:05.1: pci_pm_freeze+0x0/0x100 returned -16 after 17223 usecs
[ 27.810067][ 1] PM: Device 0000:00:05.1 failed to quiesce async: error -16
[ 27.816988][ 1] PM: quiesce of devices aborted after 1833.282 msecs
[ 27.823302][ 1] PM: start quiesce of devices aborted after 1839.975 msecs
......
[ 31.303172][ 1] PM: recover of devices complete after 3473.039 msecs
[ 31.309818][ 1] PM: Failed to load hibernation image, recovering.
[ 31.348188][ 1] PM: Basic memory bitmaps freed
[ 31.352686][ 1] OOM killer enabled.
[ 31.356232][ 1] Restarting tasks ... done.
[ 31.360609][ 1] PM: resume from hibernation failed (0)
[ 31.365800][ 1] PM: Hibernation image not present or could not be loaded.

The "do_wakeup" is determined based on whether the controller's
power/wakeup attribute is set. The current issue necessitates considering
the type of suspend that is occurring. If the suspend type is either
PM_EVENT_FREEZE or PM_EVENT_QUIESCE, then "do_wakeup" should be set to
false.

Reported-by: kernel test robot <lkp@intel.com>
Closes: https://lore.kernel.org/oe-kbuild-all/202410151722.rfjtknRz-lkp@intel.com/
Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
Signed-off-by: Duan Chenghao <duanchenghao@kylinos.cn>
Link: https://lore.kernel.org/r/20241024024038.26157-1-duanchenghao@kylinos.cn
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

authored by

Duan Chenghao and committed by
Greg Kroah-Hartman
d9b4067a 89da9eba

+15 -3
+13 -2
drivers/usb/core/hcd-pci.c
··· 422 422 bool do_wakeup; 423 423 int retval; 424 424 425 - do_wakeup = PMSG_IS_AUTO(msg) ? true : device_may_wakeup(dev); 425 + if (PMSG_IS_AUTO(msg)) 426 + do_wakeup = true; 427 + else if (PMSG_NO_WAKEUP(msg)) 428 + do_wakeup = false; 429 + else 430 + do_wakeup = device_may_wakeup(dev); 426 431 427 432 /* Root hub suspend should have stopped all downstream traffic, 428 433 * and all bus master traffic. And done so for both the interface ··· 526 521 return suspend_common(dev, PMSG_SUSPEND); 527 522 } 528 523 524 + static int hcd_pci_freeze(struct device *dev) 525 + { 526 + return suspend_common(dev, PMSG_FREEZE); 527 + } 528 + 529 529 static int hcd_pci_suspend_noirq(struct device *dev) 530 530 { 531 531 struct pci_dev *pci_dev = to_pci_dev(dev); ··· 600 590 #else 601 591 602 592 #define hcd_pci_suspend NULL 593 + #define hcd_pci_freeze NULL 603 594 #define hcd_pci_suspend_noirq NULL 604 595 #define hcd_pci_poweroff_late NULL 605 596 #define hcd_pci_resume_noirq NULL ··· 635 624 .suspend_noirq = hcd_pci_suspend_noirq, 636 625 .resume_noirq = hcd_pci_resume_noirq, 637 626 .resume = hcd_pci_resume, 638 - .freeze = hcd_pci_suspend, 627 + .freeze = hcd_pci_freeze, 639 628 .freeze_noirq = check_root_hub_suspended, 640 629 .thaw_noirq = NULL, 641 630 .thaw = hcd_pci_resume,
+2 -1
include/linux/pm.h
··· 570 570 { .event = PM_EVENT_AUTO_RESUME, }) 571 571 572 572 #define PMSG_IS_AUTO(msg) (((msg).event & PM_EVENT_AUTO) != 0) 573 - 573 + #define PMSG_NO_WAKEUP(msg) (((msg).event & \ 574 + (PM_EVENT_FREEZE | PM_EVENT_QUIESCE)) != 0) 574 575 /* 575 576 * Device run-time power management status. 576 577 *