aboutsummaryrefslogtreecommitdiff
path: root/include/linux/device.h
diff options
context:
space:
mode:
authorRafael J. Wysocki2019-02-01 01:49:14 +0100
committerGreg Kroah-Hartman2019-02-01 10:04:08 +0100
commite2f3cd831a280fc226118d9369bf3f77aab58c56 (patch)
treefcd245c394874d3055fd0aa4e2c487cbbf88b354 /include/linux/device.h
parent5db25c9eb893df8f6b93c1d97b8006d768e1b6f5 (diff)
driver core: Fix handling of runtime PM flags in device_link_add()
After commit ead18c23c263 ("driver core: Introduce device links reference counting"), if there is a link between the given supplier and the given consumer already, device_link_add() will refcount it and return it unconditionally without updating its flags. It is possible, however, that the second (or any subsequent) caller of device_link_add() for the same consumer-supplier pair will pass DL_FLAG_PM_RUNTIME, possibly along with DL_FLAG_RPM_ACTIVE, in flags to it and the existing link may not behave as expected then. First, if DL_FLAG_PM_RUNTIME is not set in the existing link's flags at all, it needs to be set like during the original initialization of the link. Second, if DL_FLAG_RPM_ACTIVE is passed to device_link_add() in flags (in addition to DL_FLAG_PM_RUNTIME), the existing link should to be updated to reflect the "active" runtime PM configuration of the consumer-supplier pair and extra care must be taken here to avoid possible destructive races with runtime PM of the consumer. To that end, redefine the rpm_active field in struct device_link as a refcount, initialize it to 1 and make rpm_resume() (for the consumer) and device_link_add() increment it whenever they acquire a runtime PM reference on the supplier device. Accordingly, make rpm_suspend() (for the consumer) and pm_runtime_clean_up_links() decrement it and drop runtime PM references to the supplier device in a loop until rpm_active becones 1 again. Fixes: ead18c23c263 ("driver core: Introduce device links reference counting") Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'include/linux/device.h')
-rw-r--r--include/linux/device.h2
1 files changed, 1 insertions, 1 deletions
diff --git a/include/linux/device.h b/include/linux/device.h
index d0e452fd0bff..5f49d2eff6ed 100644
--- a/include/linux/device.h
+++ b/include/linux/device.h
@@ -853,7 +853,7 @@ struct device_link {
struct list_head c_node;
enum device_link_state status;
u32 flags;
- bool rpm_active;
+ refcount_t rpm_active;
struct kref kref;
#ifdef CONFIG_SRCU
struct rcu_head rcu_head;