Skip to content

Commit

Permalink
PM / runtime: Optimize the use of device links
Browse files Browse the repository at this point in the history
If the device has no links to suppliers that should be used for
runtime PM (links with DEVICE_LINK_PM_RUNTIME set), there is no
reason to walk the list of suppliers for that device during
runtime suspend and resume.

Add a simple mechanism to detect that case and possibly avoid the
extra unnecessary overhead.

Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
  • Loading branch information
Rafael J. Wysocki authored and Greg Kroah-Hartman committed Oct 31, 2016
1 parent 21d5c57 commit baa8809
Show file tree
Hide file tree
Showing 4 changed files with 38 additions and 10 deletions.
20 changes: 13 additions & 7 deletions drivers/base/core.c
Original file line number Diff line number Diff line change
Expand Up @@ -205,14 +205,17 @@ struct device_link *device_link_add(struct device *consumer,
if (!link)
goto out;

if ((flags & DL_FLAG_PM_RUNTIME) && (flags & DL_FLAG_RPM_ACTIVE)) {
if (pm_runtime_get_sync(supplier) < 0) {
pm_runtime_put_noidle(supplier);
kfree(link);
link = NULL;
goto out;
if (flags & DL_FLAG_PM_RUNTIME) {
if (flags & DL_FLAG_RPM_ACTIVE) {
if (pm_runtime_get_sync(supplier) < 0) {
pm_runtime_put_noidle(supplier);
kfree(link);
link = NULL;
goto out;
}
link->rpm_active = true;
}
link->rpm_active = true;
pm_runtime_new_link(consumer);
}
get_device(supplier);
link->supplier = supplier;
Expand Down Expand Up @@ -296,6 +299,9 @@ static void __device_link_del(struct device_link *link)
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);

list_del_rcu(&link->s_node);
list_del_rcu(&link->c_node);
call_srcu(&device_links_srcu, &link->rcu_head, __device_link_free_srcu);
Expand Down
23 changes: 20 additions & 3 deletions drivers/base/power/runtime.c
Original file line number Diff line number Diff line change
Expand Up @@ -305,6 +305,7 @@ static int __rpm_callback(int (*cb)(struct device *), struct device *dev)
__releases(&dev->power.lock) __acquires(&dev->power.lock)
{
int retval, idx;
bool use_links = dev->power.links_count > 0;

if (dev->power.irq_safe) {
spin_unlock(&dev->power.lock);
Expand All @@ -318,7 +319,7 @@ static int __rpm_callback(int (*cb)(struct device *), struct device *dev)
* routine returns, so it is safe to read the status outside of
* the lock.
*/
if (dev->power.runtime_status == RPM_RESUMING) {
if (use_links && dev->power.runtime_status == RPM_RESUMING) {
idx = device_links_read_lock();

retval = rpm_get_suppliers(dev);
Expand All @@ -341,8 +342,9 @@ static int __rpm_callback(int (*cb)(struct device *), struct device *dev)
*
* Do that if resume fails too.
*/
if ((dev->power.runtime_status == RPM_SUSPENDING && !retval)
|| (dev->power.runtime_status == RPM_RESUMING && retval)) {
if (use_links
&& ((dev->power.runtime_status == RPM_SUSPENDING && !retval)
|| (dev->power.runtime_status == RPM_RESUMING && retval))) {
idx = device_links_read_lock();

fail:
Expand Down Expand Up @@ -1593,6 +1595,21 @@ void pm_runtime_put_suppliers(struct device *dev)
device_links_read_unlock(idx);
}

void pm_runtime_new_link(struct device *dev)
{
spin_lock_irq(&dev->power.lock);
dev->power.links_count++;
spin_unlock_irq(&dev->power.lock);
}

void pm_runtime_drop_link(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_force_suspend - Force a device into suspend state if needed.
* @dev: Device to suspend.
Expand Down
1 change: 1 addition & 0 deletions include/linux/pm.h
Original file line number Diff line number Diff line change
Expand Up @@ -597,6 +597,7 @@ struct dev_pm_info {
unsigned int use_autosuspend:1;
unsigned int timer_autosuspends:1;
unsigned int memalloc_noio:1;
unsigned int links_count;
enum rpm_request request;
enum rpm_status runtime_status;
int runtime_error;
Expand Down
4 changes: 4 additions & 0 deletions include/linux/pm_runtime.h
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,8 @@ extern void pm_runtime_set_memalloc_noio(struct device *dev, bool enable);
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);

static inline void pm_suspend_ignore_children(struct device *dev, bool enable)
{
Expand Down Expand Up @@ -192,6 +194,8 @@ static inline void pm_runtime_set_memalloc_noio(struct device *dev,
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) {}

#endif /* !CONFIG_PM */

Expand Down

0 comments on commit baa8809

Please sign in to comment.