]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/blob - releases/6.6.26/of-dynamic-synchronize-of_changeset_destroy-with-the-devlink-removals.patch
Linux 6.1.85
[thirdparty/kernel/stable-queue.git] / releases / 6.6.26 / of-dynamic-synchronize-of_changeset_destroy-with-the-devlink-removals.patch
1 From 8917e7385346bd6584890ed362985c219fe6ae84 Mon Sep 17 00:00:00 2001
2 From: Herve Codina <herve.codina@bootlin.com>
3 Date: Mon, 25 Mar 2024 16:21:26 +0100
4 Subject: of: dynamic: Synchronize of_changeset_destroy() with the devlink removals
5
6 From: Herve Codina <herve.codina@bootlin.com>
7
8 commit 8917e7385346bd6584890ed362985c219fe6ae84 upstream.
9
10 In the following sequence:
11 1) of_platform_depopulate()
12 2) of_overlay_remove()
13
14 During the step 1, devices are destroyed and devlinks are removed.
15 During the step 2, OF nodes are destroyed but
16 __of_changeset_entry_destroy() can raise warnings related to missing
17 of_node_put():
18 ERROR: memory leak, expected refcount 1 instead of 2 ...
19
20 Indeed, during the devlink removals performed at step 1, the removal
21 itself releasing the device (and the attached of_node) is done by a job
22 queued in a workqueue and so, it is done asynchronously with respect to
23 function calls.
24 When the warning is present, of_node_put() will be called but wrongly
25 too late from the workqueue job.
26
27 In order to be sure that any ongoing devlink removals are done before
28 the of_node destruction, synchronize the of_changeset_destroy() with the
29 devlink removals.
30
31 Fixes: 80dd33cf72d1 ("drivers: base: Fix device link removal")
32 Cc: stable@vger.kernel.org
33 Signed-off-by: Herve Codina <herve.codina@bootlin.com>
34 Reviewed-by: Saravana Kannan <saravanak@google.com>
35 Tested-by: Luca Ceresoli <luca.ceresoli@bootlin.com>
36 Reviewed-by: Nuno Sa <nuno.sa@analog.com>
37 Link: https://lore.kernel.org/r/20240325152140.198219-3-herve.codina@bootlin.com
38 Signed-off-by: Rob Herring <robh@kernel.org>
39 Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
40 ---
41 drivers/of/dynamic.c | 12 ++++++++++++
42 1 file changed, 12 insertions(+)
43
44 --- a/drivers/of/dynamic.c
45 +++ b/drivers/of/dynamic.c
46 @@ -9,6 +9,7 @@
47
48 #define pr_fmt(fmt) "OF: " fmt
49
50 +#include <linux/device.h>
51 #include <linux/of.h>
52 #include <linux/spinlock.h>
53 #include <linux/slab.h>
54 @@ -667,6 +668,17 @@ void of_changeset_destroy(struct of_chan
55 {
56 struct of_changeset_entry *ce, *cen;
57
58 + /*
59 + * When a device is deleted, the device links to/from it are also queued
60 + * for deletion. Until these device links are freed, the devices
61 + * themselves aren't freed. If the device being deleted is due to an
62 + * overlay change, this device might be holding a reference to a device
63 + * node that will be freed. So, wait until all already pending device
64 + * links are deleted before freeing a device node. This ensures we don't
65 + * free any device node that has a non-zero reference count.
66 + */
67 + device_link_wait_removal();
68 +
69 list_for_each_entry_safe_reverse(ce, cen, &ocs->entries, node)
70 __of_changeset_entry_destroy(ce);
71 }