Thread (46 messages) 46 messages, 5 authors, 2026-01-06

Re: [PATCH v2 05/20] drm/tilcdc: Convert legacy panel binding via DT overlay at boot time

From: "Luca Ceresoli" <luca.ceresoli@bootlin.com>
Date: 2026-01-05 17:18:45
Also in: dri-devel, linux-devicetree, linux-omap, lkml

Hi Köry,

On Mon Jan 5, 2026 at 3:29 PM CET, Kory Maincent wrote:
quoted
quoted
+static int __init tilcdc_panel_copy_props(struct device_node *old_panel,
+					  struct device_node *new_panel)
+{
+	struct device_node *child, *old_timing, *new_timing, *panel_info;
+	u32 invert_pxl_clk = 0, sync_edge = 0;
+	struct property *prop;
+
+	/* Copy all panel properties to the new panel node */
+	for_each_property_of_node(old_panel, prop) {
+		if (!strncmp(prop->name, "compatible",
sizeof("compatible")))
+			continue;
+
+		tilcdc_panel_update_prop(new_panel, prop->name,
+					 prop->value, prop->length);
+	}
+
+	child = of_get_child_by_name(old_panel, "display-timings");
There's some housekeeping code in this function to ensure you put all the
device_node refs. It would be simpler and less error prone to use a cleanup
action. E.g.:

-	struct device_node *child, *old_timing, *new_timing, *panel_info;

-	child = of_get_child_by_name(old_panel, "display-timings");
+	struct device_node *child __free(device_node) =
of_get_child_by_name(old_panel, "display-timings");
I am not used to this __free() macro and even some subsystem (net) are avoiding
it but ok I will move to it. I don't know what are the pros and cons.
I don't see drawbacks from a technical point of view. Only potentially a
matter of taste.

The pro is that with a cleanup action the compiler will put the cleanup
code at scope exit, whichever exit point is taken. Example:

int myfunc()
{
    struct device_node *node1, *node2, *node3;

    struct device_node *node1 = of_get_child_by_name();
    ...
    if (foo) {
        of_node_put(node1);
        return -E...;
    }

    struct device_node *node2 = of_get_child_by_name();
    ...
    if (bar) {
        of_node_put(node2);
        of_node_put(node1);
        return -E...;
    }

    struct device_node *node3 = of_get_child_by_name();
    ...
    if (foo) {
        of_node_put(node3);
        of_node_put(node2);
        of_node_put(node1);
        return -E...;
    }
}

Here the of_node_put() list grows at every return point. Of course you can
use gotos to do all the of_node_put()s in a single place, but still with
some code to maintain, potential bugs, and take care of corner cases in
case of a complex code path.

Same example with a cleanup action:

int myfunc()
{
    struct device_node *node1 __free(of_node_put) = of_get_child_by_name();
    ...
    if (foo)
        return -E...;

    struct device_node *node2 __free(of_node_put) = of_get_child_by_name();
    ...
    if (bar)
        return -E...;

    struct device_node *node3 __free(of_node_put) = of_get_child_by_name();
    ...
    if (foo)
        return -E...;
}

The compiler will insert the of_node_put() calls at scope exit (the scope
is the entire function in the above example), so they are called whichever
'return' statement happens. Pros: less code to write and maintain, code is
cleaner, less potential mistakes.

Luca

--
Luca Ceresoli, Bootlin
Embedded Linux and Kernel engineering
https://bootlin.com
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help