mirror of
https://github.com/tbsdtv/linux_media.git
synced 2025-07-23 12:43:29 +02:00
driver core: Fix device_pm_lock() locking for device links
This commit fixes two issues:
1. The lockdep warning reported by Dong Aisheng <dongas86@gmail.com> [1].
It is a warning about a cycle (dpm_list_mtx --> kn->active#3 --> fw_lock)
that was introduced when device-link devices were added to expose device
link information in sysfs.
The patch that "introduced" this cycle can't be reverted because it's fixes
a real SRCU issue and also ensures that the device-link device is deleted
as soon as the device-link is deleted. This is important to avoid sysfs
name collisions if the device-link is create again immediately (this can
happen a lot with deferred probing).
2. Inconsistency in grabbing device_pm_lock() during device link deletion
Some device link deletion code paths grab device_pm_lock(), while others
don't. The device_pm_lock() is grabbed during device_link_add() because it
checks if the supplier is in the dpm_list and also reorders the dpm_list.
However, when a device link is deleted, it does not do either of those and
therefore device_pm_lock() is not necessary. Dropping the device_pm_lock()
in all the device link deletion paths removes the inconsistency in locking.
Thanks to Stephen Boyd for helping me understand the lockdep splat.
Fixes: 843e600b8a
("driver core: Fix sleeping in invalid context during device link deletion")
[1] - https://lore.kernel.org/lkml/CAA+hA=S4eAreb7vo69LAXSk2t5=DEKNxHaiY1wSpk4xTp9urLg@mail.gmail.com/
Reported-by: Dong Aisheng <dongas86@gmail.com>
Signed-off-by: Saravana Kannan <saravanak@google.com>
Tested-by: Peng Fan <peng.fan@nxp.com>
Link: https://lore.kernel.org/r/20200901184445.1736658-1-saravanak@google.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
committed by
Greg Kroah-Hartman
parent
51de18bff2
commit
6b57b15abe
@@ -807,9 +807,7 @@ static void device_link_put_kref(struct device_link *link)
|
|||||||
void device_link_del(struct device_link *link)
|
void device_link_del(struct device_link *link)
|
||||||
{
|
{
|
||||||
device_links_write_lock();
|
device_links_write_lock();
|
||||||
device_pm_lock();
|
|
||||||
device_link_put_kref(link);
|
device_link_put_kref(link);
|
||||||
device_pm_unlock();
|
|
||||||
device_links_write_unlock();
|
device_links_write_unlock();
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(device_link_del);
|
EXPORT_SYMBOL_GPL(device_link_del);
|
||||||
@@ -830,7 +828,6 @@ void device_link_remove(void *consumer, struct device *supplier)
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
device_links_write_lock();
|
device_links_write_lock();
|
||||||
device_pm_lock();
|
|
||||||
|
|
||||||
list_for_each_entry(link, &supplier->links.consumers, s_node) {
|
list_for_each_entry(link, &supplier->links.consumers, s_node) {
|
||||||
if (link->consumer == consumer) {
|
if (link->consumer == consumer) {
|
||||||
@@ -839,7 +836,6 @@ void device_link_remove(void *consumer, struct device *supplier)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
device_pm_unlock();
|
|
||||||
device_links_write_unlock();
|
device_links_write_unlock();
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(device_link_remove);
|
EXPORT_SYMBOL_GPL(device_link_remove);
|
||||||
|
Reference in New Issue
Block a user