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>
This commit is contained in:
Duan Chenghao 2024-10-24 10:40:38 +08:00 committed by Greg Kroah-Hartman
parent 89da9eba12
commit d9b4067aef
2 changed files with 15 additions and 3 deletions

View File

@ -422,7 +422,12 @@ static int suspend_common(struct device *dev, pm_message_t msg)
bool do_wakeup;
int retval;
do_wakeup = PMSG_IS_AUTO(msg) ? true : device_may_wakeup(dev);
if (PMSG_IS_AUTO(msg))
do_wakeup = true;
else if (PMSG_NO_WAKEUP(msg))
do_wakeup = false;
else
do_wakeup = device_may_wakeup(dev);
/* Root hub suspend should have stopped all downstream traffic,
* and all bus master traffic. And done so for both the interface
@ -521,6 +526,11 @@ static int hcd_pci_suspend(struct device *dev)
return suspend_common(dev, PMSG_SUSPEND);
}
static int hcd_pci_freeze(struct device *dev)
{
return suspend_common(dev, PMSG_FREEZE);
}
static int hcd_pci_suspend_noirq(struct device *dev)
{
struct pci_dev *pci_dev = to_pci_dev(dev);
@ -590,6 +600,7 @@ static int hcd_pci_restore(struct device *dev)
#else
#define hcd_pci_suspend NULL
#define hcd_pci_freeze NULL
#define hcd_pci_suspend_noirq NULL
#define hcd_pci_poweroff_late NULL
#define hcd_pci_resume_noirq NULL
@ -624,7 +635,7 @@ const struct dev_pm_ops usb_hcd_pci_pm_ops = {
.suspend_noirq = hcd_pci_suspend_noirq,
.resume_noirq = hcd_pci_resume_noirq,
.resume = hcd_pci_resume,
.freeze = hcd_pci_suspend,
.freeze = hcd_pci_freeze,
.freeze_noirq = check_root_hub_suspended,
.thaw_noirq = NULL,
.thaw = hcd_pci_resume,

View File

@ -570,7 +570,8 @@ const struct dev_pm_ops name = { \
{ .event = PM_EVENT_AUTO_RESUME, })
#define PMSG_IS_AUTO(msg) (((msg).event & PM_EVENT_AUTO) != 0)
#define PMSG_NO_WAKEUP(msg) (((msg).event & \
(PM_EVENT_FREEZE | PM_EVENT_QUIESCE)) != 0)
/*
* Device run-time power management status.
*