Merge 5.13-rc4 into usb-next
We need the usb/thunderbolt fixes in here as well. Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
@@ -194,6 +194,17 @@ int device_links_read_lock_held(void)
|
||||
{
|
||||
return srcu_read_lock_held(&device_links_srcu);
|
||||
}
|
||||
|
||||
static void device_link_synchronize_removal(void)
|
||||
{
|
||||
synchronize_srcu(&device_links_srcu);
|
||||
}
|
||||
|
||||
static void device_link_remove_from_lists(struct device_link *link)
|
||||
{
|
||||
list_del_rcu(&link->s_node);
|
||||
list_del_rcu(&link->c_node);
|
||||
}
|
||||
#else /* !CONFIG_SRCU */
|
||||
static DECLARE_RWSEM(device_links_lock);
|
||||
|
||||
@@ -224,6 +235,16 @@ int device_links_read_lock_held(void)
|
||||
return lockdep_is_held(&device_links_lock);
|
||||
}
|
||||
#endif
|
||||
|
||||
static inline void device_link_synchronize_removal(void)
|
||||
{
|
||||
}
|
||||
|
||||
static void device_link_remove_from_lists(struct device_link *link)
|
||||
{
|
||||
list_del(&link->s_node);
|
||||
list_del(&link->c_node);
|
||||
}
|
||||
#endif /* !CONFIG_SRCU */
|
||||
|
||||
static bool device_is_ancestor(struct device *dev, struct device *target)
|
||||
@@ -445,8 +466,13 @@ static struct attribute *devlink_attrs[] = {
|
||||
};
|
||||
ATTRIBUTE_GROUPS(devlink);
|
||||
|
||||
static void device_link_free(struct device_link *link)
|
||||
static void device_link_release_fn(struct work_struct *work)
|
||||
{
|
||||
struct device_link *link = container_of(work, struct device_link, rm_work);
|
||||
|
||||
/* Ensure that all references to the link object have been dropped. */
|
||||
device_link_synchronize_removal();
|
||||
|
||||
while (refcount_dec_not_one(&link->rpm_active))
|
||||
pm_runtime_put(link->supplier);
|
||||
|
||||
@@ -455,24 +481,19 @@ static void device_link_free(struct device_link *link)
|
||||
kfree(link);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SRCU
|
||||
static void __device_link_free_srcu(struct rcu_head *rhead)
|
||||
{
|
||||
device_link_free(container_of(rhead, struct device_link, rcu_head));
|
||||
}
|
||||
|
||||
static void devlink_dev_release(struct device *dev)
|
||||
{
|
||||
struct device_link *link = to_devlink(dev);
|
||||
|
||||
call_srcu(&device_links_srcu, &link->rcu_head, __device_link_free_srcu);
|
||||
INIT_WORK(&link->rm_work, device_link_release_fn);
|
||||
/*
|
||||
* It may take a while to complete this work because of the SRCU
|
||||
* synchronization in device_link_release_fn() and if the consumer or
|
||||
* supplier devices get deleted when it runs, so put it into the "long"
|
||||
* workqueue.
|
||||
*/
|
||||
queue_work(system_long_wq, &link->rm_work);
|
||||
}
|
||||
#else
|
||||
static void devlink_dev_release(struct device *dev)
|
||||
{
|
||||
device_link_free(to_devlink(dev));
|
||||
}
|
||||
#endif
|
||||
|
||||
static struct class devlink_class = {
|
||||
.name = "devlink",
|
||||
@@ -846,7 +867,6 @@ out:
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(device_link_add);
|
||||
|
||||
#ifdef CONFIG_SRCU
|
||||
static void __device_link_del(struct kref *kref)
|
||||
{
|
||||
struct device_link *link = container_of(kref, struct device_link, kref);
|
||||
@@ -856,25 +876,9 @@ static void __device_link_del(struct kref *kref)
|
||||
|
||||
pm_runtime_drop_link(link);
|
||||
|
||||
list_del_rcu(&link->s_node);
|
||||
list_del_rcu(&link->c_node);
|
||||
device_link_remove_from_lists(link);
|
||||
device_unregister(&link->link_dev);
|
||||
}
|
||||
#else /* !CONFIG_SRCU */
|
||||
static void __device_link_del(struct kref *kref)
|
||||
{
|
||||
struct device_link *link = container_of(kref, struct device_link, kref);
|
||||
|
||||
dev_info(link->consumer, "Dropping the link to %s\n",
|
||||
dev_name(link->supplier));
|
||||
|
||||
pm_runtime_drop_link(link);
|
||||
|
||||
list_del(&link->s_node);
|
||||
list_del(&link->c_node);
|
||||
device_unregister(&link->link_dev);
|
||||
}
|
||||
#endif /* !CONFIG_SRCU */
|
||||
|
||||
static void device_link_put_kref(struct device_link *link)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user