diff options
| author | Rafael J. Wysocki <rafael.j.wysocki@intel.com> | 2019-02-01 01:49:14 +0100 |
|---|---|---|
| committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2020-01-27 14:50:17 +0100 |
| commit | d6a91833c6ed8a95ad1b4a5e2364bb6d4a039f25 (patch) | |
| tree | 2355618f0e06ba747a5ee155baeca2c0a3aa0a8f /include | |
| parent | 301c669961142183a7b157cc79bbba3d963b8a29 (diff) | |
driver core: Fix handling of runtime PM flags in device_link_add()
[ Upstream commit e2f3cd831a280fc226118d9369bf3f77aab58c56 ]
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>
Signed-off-by: Sasha Levin <sashal@kernel.org>
Diffstat (limited to 'include')
| -rw-r--r-- | include/linux/device.h | 2 |
1 files changed, 1 insertions, 1 deletions
diff --git a/include/linux/device.h b/include/linux/device.h index 19dd8852602c..b8fd2a1f859d 100644 --- a/include/linux/device.h +++ b/include/linux/device.h @@ -849,7 +849,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; |
