FROMGIT: drivers: base: Fix device link removal

When device_link_free() drops references to the supplier and
consumer devices of the device link going away and the reference
being dropped turns out to be the last one for any of those
device objects, its ->release callback will be invoked and it
may sleep which goes against the SRCU callback execution
requirements.

To address this issue, make the device link removal code carry out
the device_link_free() actions preceded by SRCU synchronization from
a separate work item (the "long" workqueue is used for that, because
it does not matter when the device link memory is released and it may
take time to get to that point) instead of using SRCU callbacks.

While at it, make the code work analogously when SRCU is not enabled
to reduce the differences between the SRCU and non-SRCU cases.

Fixes: 843e600b8a ("driver core: Fix sleeping in invalid context during device link deletion")
Cc: stable <stable@vger.kernel.org>
Reported-by: chenxiang (M) <chenxiang66@hisilicon.com>
Tested-by: chenxiang (M) <chenxiang66@hisilicon.com>
Reviewed-by: Saravana Kannan <saravanak@google.com>
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Link: https://lore.kernel.org/r/5722787.lOV4Wx5bFT@kreacher
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
(cherry picked from commit 80dd33cf72d1ab4f0af303f1fa242c6d6c8d328f
 https://git.kernel.org/pub/scm/linux/kernel/git/gregkh/driver-core.git
 driver-core-linus)
Signed-off-by: Greg Kroah-Hartman <gregkh@google.com>
Change-Id: Ied905bee2346bab71c8ebdc554e5f3f7836db516
This commit is contained in:
Rafael J. Wysocki
2021-05-14 14:10:15 +02:00
committed by Todd Kjos
parent fb57fa3d60
commit cead4664c2
2 changed files with 25 additions and 18 deletions

View File

@@ -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.
* @rcu_head: An RCU head to use for deferred execution of SRCU callbacks.
* @rm_work: Work structure used for removing the link.
* @supplier_preactivated: Supplier has been made active before consumer probe.
*/
struct device_link {
@@ -579,9 +579,7 @@ struct device_link {
u32 flags;
refcount_t rpm_active;
struct kref kref;
#ifdef CONFIG_SRCU
struct rcu_head rcu_head;
#endif
struct work_struct rm_work;
bool supplier_preactivated; /* Owned by consumer probe. */
ANDROID_KABI_RESERVE(1);
ANDROID_KABI_RESERVE(2);