linux-pm.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/2] PM: runtime: Fix race getting/putting suppliers at probe
@ 2021-03-26 10:56 Adrian Hunter
  2021-03-26 10:56 ` [PATCH 1/2] PM: runtime: Fix ordering in pm_runtime_get_suppliers() Adrian Hunter
                   ` (2 more replies)
  0 siblings, 3 replies; 4+ messages in thread
From: Adrian Hunter @ 2021-03-26 10:56 UTC (permalink / raw)
  To: Rafael J . Wysocki
  Cc: linux-pm, Martin K . Petersen, James E . J . Bottomley,
	linux-scsi, Avri Altman, Bean Huo, Can Guo, Asutosh Das

Hi

SCSI UFS is starting to use device links for power management but
has run into issues. Here are 2 patches that seem to help.


Adrian Hunter (2):
      PM: runtime: Fix ordering in pm_runtime_get_suppliers()
      PM: runtime: Fix race getting/putting suppliers at probe

 drivers/base/power/runtime.c | 10 ++++++++--
 1 file changed, 8 insertions(+), 2 deletions(-)


Regards
Adrian

^ permalink raw reply	[flat|nested] 4+ messages in thread

* [PATCH 1/2] PM: runtime: Fix ordering in pm_runtime_get_suppliers()
  2021-03-26 10:56 [PATCH 0/2] PM: runtime: Fix race getting/putting suppliers at probe Adrian Hunter
@ 2021-03-26 10:56 ` Adrian Hunter
  2021-03-26 10:56 ` [PATCH 2/2] PM: runtime: Fix race getting/putting suppliers at probe Adrian Hunter
  2021-03-26 16:42 ` [PATCH 0/2] " Rafael J. Wysocki
  2 siblings, 0 replies; 4+ messages in thread
From: Adrian Hunter @ 2021-03-26 10:56 UTC (permalink / raw)
  To: Rafael J . Wysocki
  Cc: linux-pm, Martin K . Petersen, James E . J . Bottomley,
	linux-scsi, Avri Altman, Bean Huo, Can Guo, Asutosh Das

rpm_active indicates how many times the supplier usage_count has been
incremented. Consequently it must be updated after pm_runtime_get_sync() of
the supplier, not before.

Fixes: 4c06c4e6cf63 ("driver core: Fix possible supplier PM-usage counter imbalance")
Signed-off-by: Adrian Hunter <adrian.hunter@intel.com>
---
 drivers/base/power/runtime.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/base/power/runtime.c b/drivers/base/power/runtime.c
index d54e540067bf..4fde37713c58 100644
--- a/drivers/base/power/runtime.c
+++ b/drivers/base/power/runtime.c
@@ -1690,8 +1690,8 @@ void pm_runtime_get_suppliers(struct device *dev)
 				device_links_read_lock_held())
 		if (link->flags & DL_FLAG_PM_RUNTIME) {
 			link->supplier_preactivated = true;
-			refcount_inc(&link->rpm_active);
 			pm_runtime_get_sync(link->supplier);
+			refcount_inc(&link->rpm_active);
 		}
 
 	device_links_read_unlock(idx);
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 4+ messages in thread

* [PATCH 2/2] PM: runtime: Fix race getting/putting suppliers at probe
  2021-03-26 10:56 [PATCH 0/2] PM: runtime: Fix race getting/putting suppliers at probe Adrian Hunter
  2021-03-26 10:56 ` [PATCH 1/2] PM: runtime: Fix ordering in pm_runtime_get_suppliers() Adrian Hunter
@ 2021-03-26 10:56 ` Adrian Hunter
  2021-03-26 16:42 ` [PATCH 0/2] " Rafael J. Wysocki
  2 siblings, 0 replies; 4+ messages in thread
From: Adrian Hunter @ 2021-03-26 10:56 UTC (permalink / raw)
  To: Rafael J . Wysocki
  Cc: linux-pm, Martin K . Petersen, James E . J . Bottomley,
	linux-scsi, Avri Altman, Bean Huo, Can Guo, Asutosh Das

pm_runtime_put_suppliers() must not decrement rpm_active unless the
consumer is suspended. That is because, otherwise, it could suspend
suppliers for an active consumer.

That can happen as follows:

 static int driver_probe_device(struct device_driver *drv, struct device *dev)
 {
	int ret = 0;

	if (!device_is_registered(dev))
		return -ENODEV;

	dev->can_match = true;
	pr_debug("bus: '%s': %s: matched device %s with driver %s\n",
		 drv->bus->name, __func__, dev_name(dev), drv->name);

	pm_runtime_get_suppliers(dev);
	if (dev->parent)
		pm_runtime_get_sync(dev->parent);

 At this point, dev can runtime suspend so rpm_put_suppliers() can run,
 rpm_active becomes 1 (the lowest value).

	pm_runtime_barrier(dev);
	if (initcall_debug)
		ret = really_probe_debug(dev, drv);
	else
		ret = really_probe(dev, drv);

 Probe callback can have runtime resumed dev, and then runtime put
 so dev is awaiting autosuspend, but rpm_active is 2.

	pm_request_idle(dev);

	if (dev->parent)
		pm_runtime_put(dev->parent);

	pm_runtime_put_suppliers(dev);

 Now pm_runtime_put_suppliers() will put the supplier
 i.e. rpm_active 2 -> 1, but consumer can still be active.

	return ret;
 }

Fix by checking the runtime status. For any status other than
RPM_SUSPENDED, rpm_active can be considered to be "owned" by
rpm_[get/put]_suppliers() and pm_runtime_put_suppliers() need do nothing.

Reported-by: Asutosh Das <asutoshd@codeaurora.org>
Fixes: 4c06c4e6cf63 ("driver core: Fix possible supplier PM-usage counter imbalance")
Signed-off-by: Adrian Hunter <adrian.hunter@intel.com>
---
 drivers/base/power/runtime.c | 8 +++++++-
 1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/drivers/base/power/runtime.c b/drivers/base/power/runtime.c
index 4fde37713c58..fe1dad68aee4 100644
--- a/drivers/base/power/runtime.c
+++ b/drivers/base/power/runtime.c
@@ -1704,6 +1704,8 @@ void pm_runtime_get_suppliers(struct device *dev)
 void pm_runtime_put_suppliers(struct device *dev)
 {
 	struct device_link *link;
+	unsigned long flags;
+	bool put;
 	int idx;
 
 	idx = device_links_read_lock();
@@ -1712,7 +1714,11 @@ void pm_runtime_put_suppliers(struct device *dev)
 				device_links_read_lock_held())
 		if (link->supplier_preactivated) {
 			link->supplier_preactivated = false;
-			if (refcount_dec_not_one(&link->rpm_active))
+			spin_lock_irqsave(&dev->power.lock, flags);
+			put = pm_runtime_status_suspended(dev) &&
+			      refcount_dec_not_one(&link->rpm_active);
+			spin_unlock_irqrestore(&dev->power.lock, flags);
+			if (put)
 				pm_runtime_put(link->supplier);
 		}
 
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 4+ messages in thread

* Re: [PATCH 0/2] PM: runtime: Fix race getting/putting suppliers at probe
  2021-03-26 10:56 [PATCH 0/2] PM: runtime: Fix race getting/putting suppliers at probe Adrian Hunter
  2021-03-26 10:56 ` [PATCH 1/2] PM: runtime: Fix ordering in pm_runtime_get_suppliers() Adrian Hunter
  2021-03-26 10:56 ` [PATCH 2/2] PM: runtime: Fix race getting/putting suppliers at probe Adrian Hunter
@ 2021-03-26 16:42 ` Rafael J. Wysocki
  2 siblings, 0 replies; 4+ messages in thread
From: Rafael J. Wysocki @ 2021-03-26 16:42 UTC (permalink / raw)
  To: Adrian Hunter
  Cc: Rafael J . Wysocki, Linux PM, Martin K . Petersen,
	James E . J . Bottomley, open list:TARGET SUBSYSTEM, Avri Altman,
	Bean Huo, Can Guo, Asutosh Das

On Fri, Mar 26, 2021 at 11:56 AM Adrian Hunter <adrian.hunter@intel.com> wrote:
>
> Hi
>
> SCSI UFS is starting to use device links for power management but
> has run into issues. Here are 2 patches that seem to help.
>
>
> Adrian Hunter (2):
>       PM: runtime: Fix ordering in pm_runtime_get_suppliers()
>       PM: runtime: Fix race getting/putting suppliers at probe

Both look good to me, so queuing them up for the next 5.12-rc, thanks!

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2021-03-26 16:43 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2021-03-26 10:56 [PATCH 0/2] PM: runtime: Fix race getting/putting suppliers at probe Adrian Hunter
2021-03-26 10:56 ` [PATCH 1/2] PM: runtime: Fix ordering in pm_runtime_get_suppliers() Adrian Hunter
2021-03-26 10:56 ` [PATCH 2/2] PM: runtime: Fix race getting/putting suppliers at probe Adrian Hunter
2021-03-26 16:42 ` [PATCH 0/2] " Rafael J. Wysocki

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).