A race condition occurs during system suspend if interrupted between usb_suspend() and the parent device’s PM suspend (e.g., a power domain). This triggers PM resume workflows (via usb_resume()), but if parent device is already runtime-suspended, pm_runtime_set_active() fails. Subsequent operations like pm_runtime_enable() and interface unbinding may leave the USB device in an inconsistent state or trigger unintended behavior.
Found by code review.
Cc: stable@vger.kernel.org Fixes: 98d9a82e5f75 ("USB: cleanup the handling of the PM complete call") Signed-off-by: Ma Ke make24@iscas.ac.cn --- drivers/usb/core/driver.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-)
diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c index 460d4dde5994..7478fcc11fd4 100644 --- a/drivers/usb/core/driver.c +++ b/drivers/usb/core/driver.c @@ -1624,11 +1624,17 @@ int usb_resume(struct device *dev, pm_message_t msg) status = usb_resume_both(udev, msg); if (status == 0) { pm_runtime_disable(dev); - pm_runtime_set_active(dev); + status = pm_runtime_set_active(dev); + if (status) { + pm_runtime_enable(dev); + goto out; + } + pm_runtime_enable(dev); unbind_marked_interfaces(udev); }
+out: /* Avoid PM error messages for devices disconnected while suspended * as we'll display regular disconnect messages just a bit later. */
On Mon, Feb 24, 2025 at 09:33:25AM +0800, Ma Ke wrote:
A race condition occurs during system suspend if interrupted between usb_suspend() and the parent device’s PM suspend (e.g., a power domain).
I don't understand exactly what you mean. Is this supposed to be a scenario where a USB device is suspended during a system sleep transition, but before the device's parent can be suspended, the sleep transition is aborted?
This triggers PM resume workflows (via usb_resume()), but if parent device is already runtime-suspended, pm_runtime_set_active() fails.
In other words, before the device can be resumed the parent goes into runtime suspend? I don't understand how that could happen. The PM core is careful to make sure that unwanted runtime PM changes don't occur during system sleep/resume transitions.
And if somehow this can happen, doesn't that indicate the real problem lies in the PM core? After all, why shouldn't the same sort of race condition affect a device on any bus, not just USB devices?
Subsequent operations like pm_runtime_enable() and interface unbinding may leave the USB device in an inconsistent state or trigger unintended behavior.
Found by code review.
Cc: stable@vger.kernel.org Fixes: 98d9a82e5f75 ("USB: cleanup the handling of the PM complete call") Signed-off-by: Ma Ke make24@iscas.ac.cn
drivers/usb/core/driver.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-)
diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c index 460d4dde5994..7478fcc11fd4 100644 --- a/drivers/usb/core/driver.c +++ b/drivers/usb/core/driver.c @@ -1624,11 +1624,17 @@ int usb_resume(struct device *dev, pm_message_t msg) status = usb_resume_both(udev, msg); if (status == 0) { pm_runtime_disable(dev);
pm_runtime_set_active(dev);
status = pm_runtime_set_active(dev);
if (status) {
pm_runtime_enable(dev);
The patch description says that pm_runtime_enable() following an unsuccessful pm_runtime_set_active() may trigger unintended behavior. So why does the patch do it?
Alan Stern
goto out;
}
- pm_runtime_enable(dev); unbind_marked_interfaces(udev); }
+out: /* Avoid PM error messages for devices disconnected while suspended * as we'll display regular disconnect messages just a bit later. */ -- 2.25.1
linux-stable-mirror@lists.linaro.org