diff options
author | Lukas Wunner <lukas@wunner.de> | 2018-02-10 19:27:12 +0100 |
---|---|---|
committer | Rafael J. Wysocki <rafael.j.wysocki@intel.com> | 2018-02-27 18:10:42 +0100 |
commit | ead18c23c263374ed098a7d955b29b4a466d4573 (patch) | |
tree | 17e0951e486bd5ba4b757028c0ffef88c4d34715 /kernel | |
parent | da997b22c40473b7db60bde6ea188d35565d10c8 (diff) | |
download | linux-ead18c23c263374ed098a7d955b29b4a466d4573.tar.bz2 |
driver core: Introduce device links reference counting
If device_link_add() is invoked multiple times with the same supplier
and consumer combo, it will create the link on first addition and
return a pointer to the already existing link on all subsequent
additions.
The semantics for device_link_del() are quite different, it deletes
the link unconditionally, so multiple invocations are not allowed.
In other words, this snippet ...
struct device *dev1, *dev2;
struct device_link *link1, *link2;
link1 = device_link_add(dev1, dev2, 0);
link2 = device_link_add(dev1, dev2, 0);
device_link_del(link1);
device_link_del(link2);
... causes the following crash:
WARNING: CPU: 4 PID: 2686 at drivers/base/power/runtime.c:1611 pm_runtime_drop_link+0x40/0x50
[...]
list_del corruption, 0000000039b800a4->prev is LIST_POISON2 (00000000ecf79852)
kernel BUG at lib/list_debug.c:50!
The issue isn't as arbitrary as it may seem: Imagine a device link
which is added in both the supplier's and the consumer's ->probe hook.
The two drivers can't just call device_link_del() in their ->remove hook
without coordination.
Fix by counting multiple additions and dropping the device link only
when the last addition is unwound.
Signed-off-by: Lukas Wunner <lukas@wunner.de>
[ rjw: Subject ]
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Diffstat (limited to 'kernel')
0 files changed, 0 insertions, 0 deletions