Commit 07e09c32 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull power management fix from Rafael Wysocki:
 "Fix a regression introduced during the 6.16 development cycle that may
  cause runtime PM to be enabled by mistake for devices that do not
  support it (which may lead to some serious trouble) if there is a
  system wakeup event during the "late suspend" phase of system suspend"

* tag 'pm-6.18-rc7' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm:
  PM: sleep: core: Fix runtime PM enabling in device_resume_early()
parents 1753d40d f384497a
Loading
Loading
Loading
Loading
+16 −9
Original line number Diff line number Diff line
@@ -888,12 +888,15 @@ static void device_resume_early(struct device *dev, pm_message_t state, bool asy
	TRACE_DEVICE(dev);
	TRACE_RESUME(0);

	if (dev->power.syscore || dev->power.direct_complete)
	if (dev->power.direct_complete)
		goto Out;

	if (!dev->power.is_late_suspended)
		goto Out;

	if (dev->power.syscore)
		goto Skip;

	if (!dpm_wait_for_superior(dev, async))
		goto Out;

@@ -926,11 +929,11 @@ static void device_resume_early(struct device *dev, pm_message_t state, bool asy

Skip:
	dev->power.is_late_suspended = false;
	pm_runtime_enable(dev);

Out:
	TRACE_RESUME(error);

	pm_runtime_enable(dev);
	complete_all(&dev->power.completion);

	if (error) {
@@ -1615,12 +1618,6 @@ static void device_suspend_late(struct device *dev, pm_message_t state, bool asy
	TRACE_DEVICE(dev);
	TRACE_SUSPEND(0);

	/*
	 * Disable runtime PM for the device without checking if there is a
	 * pending resume request for it.
	 */
	__pm_runtime_disable(dev, false);

	dpm_wait_for_subordinate(dev, async);

	if (READ_ONCE(async_error))
@@ -1631,9 +1628,18 @@ static void device_suspend_late(struct device *dev, pm_message_t state, bool asy
		goto Complete;
	}

	if (dev->power.syscore || dev->power.direct_complete)
	if (dev->power.direct_complete)
		goto Complete;

	/*
	 * Disable runtime PM for the device without checking if there is a
	 * pending resume request for it.
	 */
	__pm_runtime_disable(dev, false);

	if (dev->power.syscore)
		goto Skip;

	if (dev->pm_domain) {
		info = "late power domain ";
		callback = pm_late_early_op(&dev->pm_domain->ops, state);
@@ -1664,6 +1670,7 @@ static void device_suspend_late(struct device *dev, pm_message_t state, bool asy
		WRITE_ONCE(async_error, error);
		dpm_save_failed_dev(dev_name(dev));
		pm_dev_err(dev, state, async ? " async late" : " late", error);
		pm_runtime_enable(dev);
		goto Complete;
	}
	dpm_propagate_wakeup_to_parent(dev);