* [PATCH 1/2] soc: samsung: exynos-pmu: fix of_node refcount leak in exynos_get_pmu_regmap()
2026-06-09 9:52 [PATCH 0/2] soc: samsung: exynos-pmu: fix of_node leak and refactor regmap lookup geoffrey
@ 2026-06-09 9:52 ` geoffrey
2026-06-09 10:07 ` Krzysztof Kozlowski
2026-06-09 9:52 ` [PATCH 2/2] soc: samsung: exynos-pmu: refactor PMU regmap lookup helpers geoffrey
1 sibling, 1 reply; 4+ messages in thread
From: geoffrey @ 2026-06-09 9:52 UTC (permalink / raw)
To: Krzysztof Kozlowski
Cc: Alim Akhtar, Marek Szyprowski, Tomasz Figa, linux-arm-kernel,
linux-samsung-soc, linux-kernel, Weigang He
From: Weigang He <geoffreyhe2@gmail.com>
exynos_get_pmu_regmap() obtains a device_node via of_find_matching_node()
and passes it to exynos_get_pmu_regmap_by_phandle(np, NULL). With
propname == NULL the callee uses np directly and only drops a reference
when propname is set, so the reference taken by of_find_matching_node()
is leaked on every call -- including on each -EPROBE_DEFER retry of the
only in-tree caller, exynos_retention_init() in the Exynos pinctrl
driver.
Drop the reference in the function that acquired it.
Found by static analysis tool CodeQL.
Fixes: 76640b84bd7a ("soc: samsung: pmu: Provide global function to get PMU regmap")
Signed-off-by: Weigang He <geoffreyhe2@gmail.com>
---
drivers/soc/samsung/exynos-pmu.c | 16 +++++++++++-----
1 file changed, 11 insertions(+), 5 deletions(-)
diff --git a/drivers/soc/samsung/exynos-pmu.c b/drivers/soc/samsung/exynos-pmu.c
index d58376c38179b..a5da2741852b4 100644
--- a/drivers/soc/samsung/exynos-pmu.c
+++ b/drivers/soc/samsung/exynos-pmu.c
@@ -167,11 +167,17 @@ static const struct mfd_cell exynos_pmu_devs[] = {
*/
struct regmap *exynos_get_pmu_regmap(void)
{
- struct device_node *np = of_find_matching_node(NULL,
- exynos_pmu_of_device_ids);
- if (np)
- return exynos_get_pmu_regmap_by_phandle(np, NULL);
- return ERR_PTR(-ENODEV);
+ struct device_node *np;
+ struct regmap *regmap;
+
+ np = of_find_matching_node(NULL, exynos_pmu_of_device_ids);
+ if (!np)
+ return ERR_PTR(-ENODEV);
+
+ regmap = exynos_get_pmu_regmap_by_phandle(np, NULL);
+ of_node_put(np);
+
+ return regmap;
}
EXPORT_SYMBOL_GPL(exynos_get_pmu_regmap);
--
2.43.0
^ permalink raw reply related [flat|nested] 4+ messages in thread* [PATCH 2/2] soc: samsung: exynos-pmu: refactor PMU regmap lookup helpers
2026-06-09 9:52 [PATCH 0/2] soc: samsung: exynos-pmu: fix of_node leak and refactor regmap lookup geoffrey
2026-06-09 9:52 ` [PATCH 1/2] soc: samsung: exynos-pmu: fix of_node refcount leak in exynos_get_pmu_regmap() geoffrey
@ 2026-06-09 9:52 ` geoffrey
1 sibling, 0 replies; 4+ messages in thread
From: geoffrey @ 2026-06-09 9:52 UTC (permalink / raw)
To: Krzysztof Kozlowski
Cc: Alim Akhtar, Marek Szyprowski, Tomasz Figa, linux-arm-kernel,
linux-samsung-soc, linux-kernel, Weigang He
From: Weigang He <geoffreyhe2@gmail.com>
With the of_node leak in exynos_get_pmu_regmap() now fixed, the remaining
reference handling is still awkward: exynos_get_pmu_regmap() obtains the
PMU node by passing NULL to exynos_get_pmu_regmap_by_phandle(), which then
treats its np argument as the PMU node directly.
Factor the common PMU-node lookup into a helper,
exynos_get_pmu_regmap_by_node(), which only borrows the node. Each public
function then owns and releases the node it acquired: the node from
of_find_matching_node() in exynos_get_pmu_regmap(), and the node from
of_parse_phandle() in exynos_get_pmu_regmap_by_phandle().
exynos_get_pmu_regmap_by_phandle() now rejects propname == NULL with
-EINVAL. Passing NULL was never a documented use of this interface, which
looks up a PMU node through a phandle property; the only in-tree user of
that form is exynos_get_pmu_regmap(), which no longer needs it. Document
the requirement in the kerneldoc.
No functional change for the supported callers.
Signed-off-by: Weigang He <geoffreyhe2@gmail.com>
---
drivers/soc/samsung/exynos-pmu.c | 57 ++++++++++++++++++--------------
1 file changed, 33 insertions(+), 24 deletions(-)
diff --git a/drivers/soc/samsung/exynos-pmu.c b/drivers/soc/samsung/exynos-pmu.c
index a5da2741852b4..ab19ad265aeb1 100644
--- a/drivers/soc/samsung/exynos-pmu.c
+++ b/drivers/soc/samsung/exynos-pmu.c
@@ -157,6 +157,28 @@ static const struct mfd_cell exynos_pmu_devs[] = {
{ .name = "exynos-clkout", },
};
+/*
+ * Look up the regmap of an already-probed exynos-pmu device. The caller
+ * retains ownership of @pmu_np; this helper does not take a reference.
+ */
+static struct regmap *exynos_get_pmu_regmap_by_node(struct device_node *pmu_np)
+{
+ struct device *dev;
+
+ /*
+ * Determine if exynos-pmu device has probed and therefore regmap
+ * has been created and can be returned to the caller. Otherwise we
+ * return -EPROBE_DEFER.
+ */
+ dev = driver_find_device_by_of_node(&exynos_pmu_driver.driver, pmu_np);
+ if (!dev)
+ return ERR_PTR(-EPROBE_DEFER);
+
+ put_device(dev);
+
+ return syscon_node_to_regmap(pmu_np);
+}
+
/**
* exynos_get_pmu_regmap() - Obtain pmureg regmap
*
@@ -174,7 +196,7 @@ struct regmap *exynos_get_pmu_regmap(void)
if (!np)
return ERR_PTR(-ENODEV);
- regmap = exynos_get_pmu_regmap_by_phandle(np, NULL);
+ regmap = exynos_get_pmu_regmap_by_node(np);
of_node_put(np);
return regmap;
@@ -184,44 +206,31 @@ EXPORT_SYMBOL_GPL(exynos_get_pmu_regmap);
/**
* exynos_get_pmu_regmap_by_phandle() - Obtain pmureg regmap via phandle
* @np: Device node holding PMU phandle property
- * @propname: Name of property holding phandle value
+ * @propname: Name of property holding phandle value (must not be NULL)
*
* Find the pmureg regmap previously configured in probe() and return regmap
* pointer.
*
- * Return: A pointer to regmap if found or ERR_PTR error value.
+ * Return: A pointer to regmap on success or an ERR_PTR() error value;
+ * -EINVAL if @propname is NULL.
*/
struct regmap *exynos_get_pmu_regmap_by_phandle(struct device_node *np,
const char *propname)
{
struct device_node *pmu_np;
- struct device *dev;
+ struct regmap *regmap;
- if (propname)
- pmu_np = of_parse_phandle(np, propname, 0);
- else
- pmu_np = np;
+ if (!propname)
+ return ERR_PTR(-EINVAL);
+ pmu_np = of_parse_phandle(np, propname, 0);
if (!pmu_np)
return ERR_PTR(-ENODEV);
- /*
- * Determine if exynos-pmu device has probed and therefore regmap
- * has been created and can be returned to the caller. Otherwise we
- * return -EPROBE_DEFER.
- */
- dev = driver_find_device_by_of_node(&exynos_pmu_driver.driver,
- (void *)pmu_np);
+ regmap = exynos_get_pmu_regmap_by_node(pmu_np);
+ of_node_put(pmu_np);
- if (propname)
- of_node_put(pmu_np);
-
- if (!dev)
- return ERR_PTR(-EPROBE_DEFER);
-
- put_device(dev);
-
- return syscon_node_to_regmap(pmu_np);
+ return regmap;
}
EXPORT_SYMBOL_GPL(exynos_get_pmu_regmap_by_phandle);
--
2.43.0
^ permalink raw reply related [flat|nested] 4+ messages in thread