Skip to content

Commit

Permalink
PM: runtime: Drop runtime PM references to supplier on link removal
Browse files Browse the repository at this point in the history
commit e0e398e upstream.

While removing a device link, drop the supplier device's runtime PM
usage counter as many times as needed to drop all of the runtime PM
references to it from the consumer in addition to dropping the
consumer's link count.

Fixes: baa8809 ("PM / runtime: Optimize the use of device links")
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Cc: 5.1+ <stable@vger.kernel.org> # 5.1+
Tested-by: Xiang Chen <chenxiang66@hisilicon.com>
Reviewed-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
  • Loading branch information
rafaeljw authored and gregkh committed Nov 10, 2020
1 parent 7f20461 commit 4163d25
Show file tree
Hide file tree
Showing 3 changed files with 24 additions and 7 deletions.
6 changes: 2 additions & 4 deletions drivers/base/core.c
Expand Up @@ -763,8 +763,7 @@ static void __device_link_del(struct kref *kref)
dev_dbg(link->consumer, "Dropping the link to %s\n",
dev_name(link->supplier));

if (link->flags & DL_FLAG_PM_RUNTIME)
pm_runtime_drop_link(link->consumer);
pm_runtime_drop_link(link);

list_del_rcu(&link->s_node);
list_del_rcu(&link->c_node);
Expand All @@ -778,8 +777,7 @@ static void __device_link_del(struct kref *kref)
dev_info(link->consumer, "Dropping the link to %s\n",
dev_name(link->supplier));

if (link->flags & DL_FLAG_PM_RUNTIME)
pm_runtime_drop_link(link->consumer);
pm_runtime_drop_link(link);

list_del(&link->s_node);
list_del(&link->c_node);
Expand Down
21 changes: 20 additions & 1 deletion drivers/base/power/runtime.c
Expand Up @@ -1729,14 +1729,33 @@ void pm_runtime_new_link(struct device *dev)
spin_unlock_irq(&dev->power.lock);
}

void pm_runtime_drop_link(struct device *dev)
static void pm_runtime_drop_link_count(struct device *dev)
{
spin_lock_irq(&dev->power.lock);
WARN_ON(dev->power.links_count == 0);
dev->power.links_count--;
spin_unlock_irq(&dev->power.lock);
}

/**
* pm_runtime_drop_link - Prepare for device link removal.
* @link: Device link going away.
*
* Drop the link count of the consumer end of @link and decrement the supplier
* device's runtime PM usage counter as many times as needed to drop all of the
* PM runtime reference to it from the consumer.
*/
void pm_runtime_drop_link(struct device_link *link)
{
if (!(link->flags & DL_FLAG_PM_RUNTIME))
return;

pm_runtime_drop_link_count(link->consumer);

while (refcount_dec_not_one(&link->rpm_active))
pm_runtime_put(link->supplier);
}

static bool pm_runtime_need_not_resume(struct device *dev)
{
return atomic_read(&dev->power.usage_count) <= 1 &&
Expand Down
4 changes: 2 additions & 2 deletions include/linux/pm_runtime.h
Expand Up @@ -58,7 +58,7 @@ extern void pm_runtime_clean_up_links(struct device *dev);
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 *dev);
extern void pm_runtime_drop_link(struct device_link *link);

/**
* pm_runtime_get_if_in_use - Conditionally bump up runtime PM usage counter.
Expand Down Expand Up @@ -280,7 +280,7 @@ static inline void pm_runtime_clean_up_links(struct device *dev) {}
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 *dev) {}
static inline void pm_runtime_drop_link(struct device_link *link) {}

#endif /* !CONFIG_PM */

Expand Down

0 comments on commit 4163d25

Please sign in to comment.