lkml.org 
[lkml]   [2020]   [Dec]   [17]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH v2 04/12] software_node: Enforce parent before child ordering of nodes arrays
    Date
    Registering software_nodes with the .parent member set to point to a
    currently unregistered software_node has the potential for problems,
    so enforce parent -> child ordering in arrays passed in to
    software_node_register_nodes().

    Software nodes that are children of another software node should be
    unregistered before their parent. To allow easy unregistering of an array
    of software_nodes ordered parent to child, reverse the order in which
    software_node_unregister_nodes() unregisters software_nodes.

    Suggested-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
    Signed-off-by: Daniel Scally <djrscally@gmail.com>
    ---
    Changes in v2:

    - Squashed the patches that originally touched these separately
    - Updated documentation

    drivers/base/swnode.c | 43 ++++++++++++++++++++++++++++++-------------
    1 file changed, 30 insertions(+), 13 deletions(-)

    diff --git a/drivers/base/swnode.c b/drivers/base/swnode.c
    index 615a0c93e116..cfd1faea48a7 100644
    --- a/drivers/base/swnode.c
    +++ b/drivers/base/swnode.c
    @@ -692,7 +692,10 @@ swnode_register(const struct software_node *node, struct swnode *parent,
    * software_node_register_nodes - Register an array of software nodes
    * @nodes: Zero terminated array of software nodes to be registered
    *
    - * Register multiple software nodes at once.
    + * Register multiple software nodes at once. If any node in the array
    + * has it's .parent pointer set, then it's parent **must** have been
    + * registered before it is; either outside of this function or by
    + * ordering the array such that parent comes before child.
    */
    int software_node_register_nodes(const struct software_node *nodes)
    {
    @@ -700,33 +703,47 @@ int software_node_register_nodes(const struct software_node *nodes)
    int i;

    for (i = 0; nodes[i].name; i++) {
    - ret = software_node_register(&nodes[i]);
    - if (ret) {
    - software_node_unregister_nodes(nodes);
    - return ret;
    + const struct software_node *parent = nodes[i].parent;
    +
    + if (parent && !software_node_to_swnode(parent)) {
    + ret = -EINVAL;
    + goto err_unregister_nodes;
    }
    +
    + ret = software_node_register(&nodes[i]);
    + if (ret)
    + goto err_unregister_nodes;
    }

    return 0;
    +
    +err_unregister_nodes:
    + software_node_unregister_nodes(nodes);
    + return ret;
    }
    EXPORT_SYMBOL_GPL(software_node_register_nodes);

    /**
    * software_node_unregister_nodes - Unregister an array of software nodes
    - * @nodes: Zero terminated array of software nodes to be unregistered
    + * @nodes: Zero terminated array of software nodes to be unregistered.
    *
    - * Unregister multiple software nodes at once.
    + * Unregister multiple software nodes at once. If parent pointers are set up
    + * in any of the software nodes then the array MUST be ordered such that
    + * parents come before their children.
    *
    - * NOTE: Be careful using this call if the nodes had parent pointers set up in
    - * them before registering. If so, it is wiser to remove the nodes
    - * individually, in the correct order (child before parent) instead of relying
    - * on the sequential order of the list of nodes in the array.
    + * NOTE: If you are uncertain whether the array is ordered such that
    + * parents will be unregistered before their children, it is wiser to
    + * remove the nodes individually, in the correct order (child before
    + * parent).
    */
    void software_node_unregister_nodes(const struct software_node *nodes)
    {
    - int i;
    + unsigned int i = 0;
    +
    + while (nodes[i].name)
    + i++;

    - for (i = 0; nodes[i].name; i++)
    + while (i--)
    software_node_unregister(&nodes[i]);
    }
    EXPORT_SYMBOL_GPL(software_node_unregister_nodes);
    --
    2.25.1
    \
     
     \ /
      Last update: 2020-12-18 00:45    [W:4.336 / U:0.008 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site