From 28e408cd4c0742c098c2484e7e12514347a5003c Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Thu, 3 Jun 2021 13:36:10 +0200 Subject: [PATCH] Revert "drivers: base: Fix device link removal" This reverts commit d007150b4e15bfcb8d36cfd88a5645d42e44d383 which is commit 80dd33cf72d1ab4f0af303f1fa242c6d6c8d328f upstream. It breaks the abi and will be brought back at the proper time that we can. Signed-off-by: Greg Kroah-Hartman Change-Id: I5b49602baf86e11e10eecb1c300ea8634826dbd2 --- drivers/base/core.c | 37 ++++++++++++++----------------------- include/linux/device.h | 6 ++++-- 2 files changed, 18 insertions(+), 25 deletions(-) diff --git a/drivers/base/core.c b/drivers/base/core.c index 588d6d4f6a49..313a7ef22716 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c @@ -191,11 +191,6 @@ 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); -} #else /* !CONFIG_SRCU */ static DECLARE_RWSEM(device_links_lock); @@ -226,10 +221,6 @@ int device_links_read_lock_held(void) return lockdep_is_held(&device_links_lock); } #endif - -static inline void device_link_synchronize_removal(void) -{ -} #endif /* !CONFIG_SRCU */ static bool device_is_ancestor(struct device *dev, struct device *target) @@ -451,13 +442,8 @@ static struct attribute *devlink_attrs[] = { }; ATTRIBUTE_GROUPS(devlink); -static void device_link_release_fn(struct work_struct *work) +static void device_link_free(struct device_link *link) { - 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); @@ -466,19 +452,24 @@ static void device_link_release_fn(struct work_struct *work) 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); - 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); + call_srcu(&device_links_srcu, &link->rcu_head, __device_link_free_srcu); } +#else +static void devlink_dev_release(struct device *dev) +{ + device_link_free(to_devlink(dev)); +} +#endif static struct class devlink_class = { .name = "devlink", diff --git a/include/linux/device.h b/include/linux/device.h index 5ec9be377a76..3c71b779668e 100644 --- a/include/linux/device.h +++ b/include/linux/device.h @@ -566,7 +566,7 @@ struct device { * @flags: Link flags. * @rpm_active: Whether or not the consumer device is runtime-PM-active. * @kref: Count repeated addition of the same link. - * @rm_work: Work structure used for removing the link. + * @rcu_head: An RCU head to use for deferred execution of SRCU callbacks. * @supplier_preactivated: Supplier has been made active before consumer probe. */ struct device_link { @@ -579,7 +579,9 @@ struct device_link { u32 flags; refcount_t rpm_active; struct kref kref; - struct work_struct rm_work; +#ifdef CONFIG_SRCU + struct rcu_head rcu_head; +#endif bool supplier_preactivated; /* Owned by consumer probe. */ ANDROID_KABI_RESERVE(1); ANDROID_KABI_RESERVE(2);