Skip to contentSkip to conversation

FAILED: patch "[PATCH] ata: libahci_platform: Fix device reference leak in" failed to apply to 5.10-stable tree

PATCH New [email protected] 2 participants 4 messages Sep 22

Subsystems (3)
lore
Share & tools
lore

[email protected]

author maintainer
#0 lore raw

The patch below does not apply to the 5.10-stable tree.
If someone wants it applied there, or to any other stable or longterm tree, then please email the backport, including the original git commit id to <[email protected]>.

To reproduce the conflict and resubmit, you may use the following commands:

git fetch https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/ linux-5.10.y
git checkout FETCH_HEAD
git cherry-pick -x 0d1cb83337f13af082afb68b28d3fdfe29cde7fb
# <resolve conflicts, build, test, etc.>
git commit -s
git send-email --to '<[email protected]>' --in-reply-to '2026092256-genetics-desecrate-9b80@gregkh' --subject-prefix 'PATCH 5.10.y' 'HEAD^..'

Possible dependencies:

thanks,

greg k-h

------------------ original commit in Linus's tree ------------------

From 0d1cb83337f13af082afb68b28d3fdfe29cde7fb Mon Sep 17 00:00:00 2001
From: Wentao Liang <[email protected]>
Date: Tue, 15 Sep 2026 06:59:33 +0000
Subject: [PATCH] ata: libahci_platform: Fix device reference leak in
ahci_platform_get_resources()

of_find_device_by_node() takes a reference on the port platform device, which is only used to look up its port regulator and is never released, neither on success nor on the error paths. Drop the reference with put_device() once the regulator has been obtained, which covers both the success and error paths.

Fixes c7d7ddee7e24 ("ata: libahci: Allow using multiple regulators")
drivers/ata/libahci_platform.c +1 -1
index 6e072d681341..f6524135ea11 100644
@@ -620,10 +620,10 @@ struct ahci_host_priv *ahci_platform_get_resources(struct platform_device *pdev,
 			of_platform_device_create(child, NULL, NULL);
 
 			port_dev = of_find_device_by_node(child);
-
 			if (port_dev) {
 				rc = ahci_platform_get_regulator(hpriv, port,
 								&port_dev->dev);
+				put_device(&port_dev->dev);
 				if (rc == -EPROBE_DEFER)
 					goto err_out;
 			}
maintainer
#1 lore raw

PATCH 1/3 of: Introduce for_each_*_child_of_node_scoped() to automate of_node_put() handling

From: Jonathan Cameron <[email protected]>

[ Upstream commit 34af4554fb0ce164e2c4876683619eb1e23848d4 ]

To avoid issues with out of order cleanup, or ambiguity about when the auto freed data is first instantiated, do it within the for loop definition.

The disadvantage is that the struct device_node *child variable creation is not immediately obvious where this is used.
However, in many cases, if there is another definition of struct device_node *child; the compiler / static analysers will notify us that it is unused, or uninitialized.

Note that, in the vast majority of cases, the _available_ form should be used and as code is converted to these scoped handers, we should confirm that any cases that do not check for available have a good reason not to.

Stable-dep-of: 0d1cb83337f1 ("ata: libahci_platform: Fix device reference leak in ahci_platform_get_resources()")

---
 include/linux/of.h | 13 +++++++++++++
 1 file changed, 13 insertions(+)
include/linux/of.h +13 -0
index d8cd02433f910..36ef19f8bd08a 100644
@@ -1279,10 +1279,23 @@ static inline int of_property_read_s32(const struct device_node *np,
 #define for_each_child_of_node(parent, child) \
 	for (child = of_get_next_child(parent, NULL); child != NULL; \
 	     child = of_get_next_child(parent, child))
+
+#define for_each_child_of_node_scoped(parent, child) \
+	for (struct device_node *child __free(device_node) =		\
+	     of_get_next_child(parent, NULL);				\
+	     child != NULL;						\
+	     child = of_get_next_child(parent, child))
+
 #define for_each_available_child_of_node(parent, child) \
 	for (child = of_get_next_available_child(parent, NULL); child != NULL; \
 	     child = of_get_next_available_child(parent, child))
 
+#define for_each_available_child_of_node_scoped(parent, child) \
+	for (struct device_node *child __free(device_node) =		\
+	     of_get_next_available_child(parent, NULL);			\
+	     child != NULL;						\
+	     child = of_get_next_available_child(parent, child))
+
 #define for_each_of_cpu_node(cpu) \
 	for (cpu = of_get_next_cpu_node(NULL); cpu != NULL; \
 	     cpu = of_get_next_cpu_node(cpu))
Signature · 1 line
2.53.0
maintainer
#2 lore raw

PATCH 2/3 ata: libahci_platform: Simplify code with for_each_child_of_node_scoped()

From: Zhang Zekun <[email protected]>

[ Upstream commit aa3ca1faf3222af7aaa194a910995820135fc54e ]

for_each_child_of_node_scoped() can put the device_node automatically. So let's use it to make the code simpler by avoiding the need to explicitly call of_node_put().

Backport notes for Linux 5.10:
Drop the changes to ahci_platform_get_firmware(), which does not exist in this tree, and retain the existing clock and loop-index declarations.

The scoped iterator declares its variable in the for initializer, which is incompatible with this tree's -std=gnu89 build. Instead, declare child with __free(device_node) inside the child_nodes block and use the existing for_each_child_of_node() iterator. This keeps automatic node release on all exits from that block, before devres cleanup on error, without adding functions or changing the kernel's C dialect.

Removing the explicit node puts and their now-unnecessary braces also allows target commit 0d1cb83337f13af082afb68b28d3fdfe29cde7fb to apply unchanged. The platform-device reference fix remains in that target.

Stable-dep-of: 0d1cb83337f1 ("ata: libahci_platform: Fix device reference leak in ahci_platform_get_resources()")

---
 drivers/ata/libahci_platform.c | 12 ++++--------
 1 file changed, 4 insertions(+), 8 deletions(-)
drivers/ata/libahci_platform.c +4 -8
index 64d6da0a53035..d79e8d46d30e0 100644
@@ -388,7 +388,6 @@ struct ahci_host_priv *ahci_platform_get_resources(struct platform_device *pdev,
 	struct device *dev = &pdev->dev;
 	struct ahci_host_priv *hpriv;
 	struct clk *clk;
-	struct device_node *child;
 	int i, enabled_ports = 0, rc = -ENOMEM, child_nodes;
 	u32 mask_port_map = 0;
 
@@ -487,6 +486,8 @@ struct ahci_host_priv *ahci_platform_get_resources(struct platform_device *pdev,
 	}
 
 	if (child_nodes) {
+		struct device_node *child __free(device_node) = NULL;
+
 		for_each_child_of_node(dev->of_node, child) {
 			u32 port;
 			struct platform_device *port_dev __maybe_unused;
@@ -496,7 +497,6 @@ struct ahci_host_priv *ahci_platform_get_resources(struct platform_device *pdev,
 
 			if (of_property_read_u32(child, "reg", &port)) {
 				rc = -EINVAL;
-				of_node_put(child);
 				goto err_out;
 			}
 
@@ -514,18 +514,14 @@ struct ahci_host_priv *ahci_platform_get_resources(struct platform_device *pdev,
 			if (port_dev) {
 				rc = ahci_platform_get_regulator(hpriv, port,
 								&port_dev->dev);
-				if (rc == -EPROBE_DEFER) {
-					of_node_put(child);
+				if (rc == -EPROBE_DEFER)
 					goto err_out;
-				}
 			}
 #endif
 
 			rc = ahci_platform_get_phy(hpriv, port, dev, child);
-			if (rc) {
-				of_node_put(child);
+			if (rc)
 				goto err_out;
-			}
 
 			enabled_ports++;
 		}
Signature · 1 line
2.53.0
maintainer
#3 lore raw

PATCH 3/3 ata: libahci_platform: Fix device reference leak in ahci_platform_get_resources()

In reply to Sasha Levin

From: Wentao Liang <[email protected]>

[ Upstream commit 0d1cb83337f13af082afb68b28d3fdfe29cde7fb ]

of_find_device_by_node() takes a reference on the port platform device, which is only used to look up its port regulator and is never released, neither on success nor on the error paths. Drop the reference with put_device() once the regulator has been obtained, which covers both the success and error paths.

---
 drivers/ata/libahci_platform.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/ata/libahci_platform.c +1 -1
index d79e8d46d30e0..ae78665247c08 100644
@@ -510,10 +510,10 @@ struct ahci_host_priv *ahci_platform_get_resources(struct platform_device *pdev,
 			of_platform_device_create(child, NULL, NULL);
 
 			port_dev = of_find_device_by_node(child);
-
 			if (port_dev) {
 				rc = ahci_platform_get_regulator(hpriv, port,
 								&port_dev->dev);
+				put_device(&port_dev->dev);
 				if (rc == -EPROBE_DEFER)
 					goto err_out;
 			}
Signature · 1 line
2.53.0