diff options
| author | Rafael J. Wysocki <rafael.j.wysocki@intel.com> | 2022-07-08 20:38:51 +0200 | 
|---|---|---|
| committer | Rafael J. Wysocki <rafael.j.wysocki@intel.com> | 2022-07-08 20:38:51 +0200 | 
| commit | fe7c758c07c4729a16f940eb1d77027ad032ab29 (patch) | |
| tree | b95dcdfda6934aedf433f563f87eed56386be5c0 | |
| parent | ba7c3507087aaf98bbeab04a62251bf63c6348c1 (diff) | |
| parent | 887371066039011144b4a94af97d9328df6869a2 (diff) | |
Merge branch 'pm-core'
Merge a runtime PM framework cleanup and fix related to device links.
* pm-core:
  PM: runtime: Fix supplier device management during consumer probe
  PM: runtime: Redefine pm_runtime_release_supplier()
| -rw-r--r-- | drivers/base/core.c | 13 | ||||
| -rw-r--r-- | drivers/base/power/runtime.c | 34 | ||||
| -rw-r--r-- | include/linux/pm_runtime.h | 5 | 
3 files changed, 24 insertions, 28 deletions
diff --git a/drivers/base/core.c b/drivers/base/core.c index 7cd789c4985d..460d6f163e41 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c @@ -486,7 +486,18 @@ static void device_link_release_fn(struct work_struct *work)  	/* Ensure that all references to the link object have been dropped. */  	device_link_synchronize_removal(); -	pm_runtime_release_supplier(link, true); +	pm_runtime_release_supplier(link); +	/* +	 * If supplier_preactivated is set, the link has been dropped between +	 * the pm_runtime_get_suppliers() and pm_runtime_put_suppliers() calls +	 * in __driver_probe_device().  In that case, drop the supplier's +	 * PM-runtime usage counter to remove the reference taken by +	 * pm_runtime_get_suppliers(). +	 */ +	if (link->supplier_preactivated) +		pm_runtime_put_noidle(link->supplier); + +	pm_request_idle(link->supplier);  	put_device(link->consumer);  	put_device(link->supplier); diff --git a/drivers/base/power/runtime.c b/drivers/base/power/runtime.c index 676dc72d912d..949907e2e242 100644 --- a/drivers/base/power/runtime.c +++ b/drivers/base/power/runtime.c @@ -308,13 +308,10 @@ static int rpm_get_suppliers(struct device *dev)  /**   * pm_runtime_release_supplier - Drop references to device link's supplier.   * @link: Target device link. - * @check_idle: Whether or not to check if the supplier device is idle.   * - * Drop all runtime PM references associated with @link to its supplier device - * and if @check_idle is set, check if that device is idle (and so it can be - * suspended). + * Drop all runtime PM references associated with @link to its supplier device.   */ -void pm_runtime_release_supplier(struct device_link *link, bool check_idle) +void pm_runtime_release_supplier(struct device_link *link)  {  	struct device *supplier = link->supplier; @@ -327,9 +324,6 @@ void pm_runtime_release_supplier(struct device_link *link, bool check_idle)  	while (refcount_dec_not_one(&link->rpm_active) &&  	       atomic_read(&supplier->power.usage_count) > 0)  		pm_runtime_put_noidle(supplier); - -	if (check_idle) -		pm_request_idle(supplier);  }  static void __rpm_put_suppliers(struct device *dev, bool try_to_suspend) @@ -337,8 +331,11 @@ static void __rpm_put_suppliers(struct device *dev, bool try_to_suspend)  	struct device_link *link;  	list_for_each_entry_rcu(link, &dev->links.suppliers, c_node, -				device_links_read_lock_held()) -		pm_runtime_release_supplier(link, try_to_suspend); +				device_links_read_lock_held()) { +		pm_runtime_release_supplier(link); +		if (try_to_suspend) +			pm_request_idle(link->supplier); +	}  }  static void rpm_put_suppliers(struct device *dev) @@ -1771,7 +1768,6 @@ void pm_runtime_get_suppliers(struct device *dev)  		if (link->flags & DL_FLAG_PM_RUNTIME) {  			link->supplier_preactivated = true;  			pm_runtime_get_sync(link->supplier); -			refcount_inc(&link->rpm_active);  		}  	device_links_read_unlock(idx); @@ -1791,19 +1787,8 @@ void pm_runtime_put_suppliers(struct device *dev)  	list_for_each_entry_rcu(link, &dev->links.suppliers, c_node,  				device_links_read_lock_held())  		if (link->supplier_preactivated) { -			bool put; -  			link->supplier_preactivated = false; - -			spin_lock_irq(&dev->power.lock); - -			put = pm_runtime_status_suspended(dev) && -			      refcount_dec_not_one(&link->rpm_active); - -			spin_unlock_irq(&dev->power.lock); - -			if (put) -				pm_runtime_put(link->supplier); +			pm_runtime_put(link->supplier);  		}  	device_links_read_unlock(idx); @@ -1838,7 +1823,8 @@ void pm_runtime_drop_link(struct device_link *link)  		return;  	pm_runtime_drop_link_count(link->consumer); -	pm_runtime_release_supplier(link, true); +	pm_runtime_release_supplier(link); +	pm_request_idle(link->supplier);  }  static bool pm_runtime_need_not_resume(struct device *dev) diff --git a/include/linux/pm_runtime.h b/include/linux/pm_runtime.h index 9e4d056967c6..0a41b2dcccad 100644 --- a/include/linux/pm_runtime.h +++ b/include/linux/pm_runtime.h @@ -88,7 +88,7 @@ extern void pm_runtime_get_suppliers(struct device *dev);  extern void pm_runtime_put_suppliers(struct device *dev);  extern void pm_runtime_new_link(struct device *dev);  extern void pm_runtime_drop_link(struct device_link *link); -extern void pm_runtime_release_supplier(struct device_link *link, bool check_idle); +extern void pm_runtime_release_supplier(struct device_link *link);  extern int devm_pm_runtime_enable(struct device *dev); @@ -314,8 +314,7 @@ static inline void pm_runtime_get_suppliers(struct device *dev) {}  static inline void pm_runtime_put_suppliers(struct device *dev) {}  static inline void pm_runtime_new_link(struct device *dev) {}  static inline void pm_runtime_drop_link(struct device_link *link) {} -static inline void pm_runtime_release_supplier(struct device_link *link, -					       bool check_idle) {} +static inline void pm_runtime_release_supplier(struct device_link *link) {}  #endif /* !CONFIG_PM */  | 
