Devicetree
 help / color / mirror / Atom feed
* [PATCH] of: base: Handle optional argument in of_parse_phandle_with_args_map()
@ 2026-07-16 10:51 Miquel Raynal (Schneider Electric)
  2026-07-16 11:05 ` sashiko-bot
  0 siblings, 1 reply; 2+ messages in thread
From: Miquel Raynal (Schneider Electric) @ 2026-07-16 10:51 UTC (permalink / raw)
  To: Rob Herring, Saravana Kannan
  Cc: Thomas Petazzoni, Pascal EBERHARD, devicetree, linux-kernel,
	Sashiko, Miquel Raynal (Schneider Electric)

The kernel doc claims out_args is optional. In practice, the function
unconditionally dereferences it. It feels like calling this function
with a NULL out_args argument may be a valid use case (in order to know
if the lookup would work, even though we might not care about the
result), even though in practice there seem to be no actual user of that
possibility. All callers give an on-stack object to fill.

There are two ways out: either we drop the "optional" wording from the
kernel doc, or we handle the NULL case properly. Since handling this
case goes in favor of more harmonization of the semantics and since
of_parse_phandle_with_args() actually do handle that situation
correctly, let's handle it in the _map() case as well.

Use a local on-stack object in case no argument is passed. This way, we
actually go through the same logic as if there was an argument. We may
however return rather early, since the second part of the function is
dedicated at filling that argument.

Reported-by: Sashiko <sashiko-bot@kernel.org>
Closes: https://lore.kernel.org/all/20260710183359.61D3A1F000E9@smtp.kernel.org/
Signed-off-by: Miquel Raynal (Schneider Electric) <miquel.raynal@bootlin.com>
---
The number of passing unit tests is identical before/after the commit:
[   10.774120] ### dt-test ### end of unittest - 426 passed, 1 failed
---
 drivers/of/base.c | 12 ++++++++----
 1 file changed, 8 insertions(+), 4 deletions(-)

diff --git a/drivers/of/base.c b/drivers/of/base.c
index 6e7a42dedad3..dd7dda0e0a57 100644
--- a/drivers/of/base.c
+++ b/drivers/of/base.c
@@ -1505,15 +1505,15 @@ EXPORT_SYMBOL(__of_parse_phandle_with_args);
  * @list_name:	property name that contains a list
  * @stem_name:	stem of property names that specify phandles' arguments count
  * @index:	index of a phandle to parse out
- * @out_args:	optional pointer to output arguments structure (will be filled)
+ * @_out_args:	optional pointer to output arguments structure (will be filled)
  *
  * This function is useful to parse lists of phandles and their arguments.
- * Returns 0 on success and fills out_args, on error returns appropriate errno
+ * Returns 0 on success and fills @_out_args, on error returns appropriate errno
  * value. The difference between this function and of_parse_phandle_with_args()
  * is that this API remaps a phandle if the node the phandle points to has
  * a <@stem_name>-map property.
  *
- * Caller is responsible to call of_node_put() on the returned out_args->np
+ * Caller is responsible to call of_node_put() on the returned @_out_args->np
  * pointer.
  *
  * Example::
@@ -1544,7 +1544,7 @@ EXPORT_SYMBOL(__of_parse_phandle_with_args);
 int of_parse_phandle_with_args_map(const struct device_node *np,
 				   const char *list_name,
 				   const char *stem_name,
-				   int index, struct of_phandle_args *out_args)
+				   int index, struct of_phandle_args *_out_args)
 {
 	char *cells_name __free(kfree) = kasprintf(GFP_KERNEL, "#%s-cells", stem_name);
 	char *map_name __free(kfree) = kasprintf(GFP_KERNEL, "%s-map", stem_name);
@@ -1554,6 +1554,8 @@ int of_parse_phandle_with_args_map(const struct device_node *np,
 	const __be32 *map, *mask, *pass;
 	static const __be32 dummy_mask[] = { [0 ... (MAX_PHANDLE_ARGS - 1)] = cpu_to_be32(~0) };
 	static const __be32 dummy_pass[] = { [0 ... (MAX_PHANDLE_ARGS - 1)] = cpu_to_be32(0) };
+	struct of_phandle_args _oa = {};
+	struct of_phandle_args *out_args = _out_args ? _out_args : &_oa;
 	__be32 initial_match_array[MAX_PHANDLE_ARGS];
 	const __be32 *match_array = initial_match_array;
 	int i, ret, map_len, match;
@@ -1585,6 +1587,8 @@ int of_parse_phandle_with_args_map(const struct device_node *np,
 		/* Get the <list>-map property */
 		map = of_get_property(cur, map_name, &map_len);
 		if (!map) {
+			if (!_out_args)
+				of_node_put(out_args->np);
 			return 0;
 		}
 		map_len /= sizeof(u32);

---
base-commit: 7f26e010764df304602f33912a0550dcf46e72c2
change-id: 20260716-schneider-v7-2-rc1-eip-of-fix-c812599db058

Best regards,
-- 
Miquel Raynal (Schneider Electric) <miquel.raynal@bootlin.com>


^ permalink raw reply related	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2026-07-16 11:05 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-07-16 10:51 [PATCH] of: base: Handle optional argument in of_parse_phandle_with_args_map() Miquel Raynal (Schneider Electric)
2026-07-16 11:05 ` sashiko-bot

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox