Skip to content

Commit

Permalink
of: property: Simplify of_link_to_phandle()
Browse files Browse the repository at this point in the history
commit 4a03282 upstream.

The driver core now:
- Has the parent device of a supplier pick up the consumers if the
  supplier never has a device created for it.
- Ignores a supplier if the supplier has no parent device and will never
  be probed by a driver

And already prevents creating a device link with the consumer as a
supplier of a parent.

So, we no longer need to find the "compatible" node of the supplier or
do any other checks in of_link_to_phandle(). We simply need to make sure
that the supplier is available in DT.

Signed-off-by: Saravana Kannan <saravanak@google.com>
Tested-by: Colin Foster <colin.foster@in-advantage.com>
Tested-by: Sudeep Holla <sudeep.holla@arm.com>
Tested-by: Douglas Anderson <dianders@chromium.org>
Tested-by: Geert Uytterhoeven <geert+renesas@glider.be>
Tested-by: Luca Weiss <luca.weiss@fairphone.com> # qcom/sm7225-fairphone-fp4
Link: https://lore.kernel.org/r/20230207014207.1678715-10-saravanak@google.com
Fixes: eaf9b56 ("driver core: fw_devlink: Don't purge child fwnode's consumer links")
Signed-off-by:  Adam Ford <aford173@gmail.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
  • Loading branch information
Saravana Kannan authored and gregkh committed Sep 13, 2023
1 parent 8f647ac commit c50fdd5
Showing 1 changed file with 13 additions and 71 deletions.
84 changes: 13 additions & 71 deletions drivers/of/property.c
Expand Up @@ -1062,20 +1062,6 @@ of_fwnode_device_get_match_data(const struct fwnode_handle *fwnode,
return of_device_get_match_data(dev);
}

static bool of_is_ancestor_of(struct device_node *test_ancestor,
struct device_node *child)
{
of_node_get(child);
while (child) {
if (child == test_ancestor) {
of_node_put(child);
return true;
}
child = of_get_next_parent(child);
}
return false;
}

static struct device_node *of_get_compat_node(struct device_node *np)
{
of_node_get(np);
Expand Down Expand Up @@ -1106,71 +1092,27 @@ static struct device_node *of_get_compat_node_parent(struct device_node *np)
return node;
}

/**
* of_link_to_phandle - Add fwnode link to supplier from supplier phandle
* @con_np: consumer device tree node
* @sup_np: supplier device tree node
*
* Given a phandle to a supplier device tree node (@sup_np), this function
* finds the device that owns the supplier device tree node and creates a
* device link from @dev consumer device to the supplier device. This function
* doesn't create device links for invalid scenarios such as trying to create a
* link with a parent device as the consumer of its child device. In such
* cases, it returns an error.
*
* Returns:
* - 0 if fwnode link successfully created to supplier
* - -EINVAL if the supplier link is invalid and should not be created
* - -ENODEV if struct device will never be create for supplier
*/
static int of_link_to_phandle(struct device_node *con_np,
static void of_link_to_phandle(struct device_node *con_np,
struct device_node *sup_np)
{
struct device *sup_dev;
struct device_node *tmp_np = sup_np;
struct device_node *tmp_np = of_node_get(sup_np);

/*
* Find the device node that contains the supplier phandle. It may be
* @sup_np or it may be an ancestor of @sup_np.
*/
sup_np = of_get_compat_node(sup_np);
if (!sup_np) {
pr_debug("Not linking %pOFP to %pOFP - No device\n",
con_np, tmp_np);
return -ENODEV;
}
/* Check that sup_np and its ancestors are available. */
while (tmp_np) {
if (of_fwnode_handle(tmp_np)->dev) {
of_node_put(tmp_np);
break;
}

/*
* Don't allow linking a device node as a consumer of one of its
* descendant nodes. By definition, a child node can't be a functional
* dependency for the parent node.
*/
if (of_is_ancestor_of(con_np, sup_np)) {
pr_debug("Not linking %pOFP to %pOFP - is descendant\n",
con_np, sup_np);
of_node_put(sup_np);
return -EINVAL;
}
if (!of_device_is_available(tmp_np)) {
of_node_put(tmp_np);
return;
}

/*
* Don't create links to "early devices" that won't have struct devices
* created for them.
*/
sup_dev = get_dev_from_fwnode(&sup_np->fwnode);
if (!sup_dev &&
(of_node_check_flag(sup_np, OF_POPULATED) ||
sup_np->fwnode.flags & FWNODE_FLAG_NOT_DEVICE)) {
pr_debug("Not linking %pOFP to %pOFP - No struct device\n",
con_np, sup_np);
of_node_put(sup_np);
return -ENODEV;
tmp_np = of_get_next_parent(tmp_np);
}
put_device(sup_dev);

fwnode_link_add(of_fwnode_handle(con_np), of_fwnode_handle(sup_np));
of_node_put(sup_np);

return 0;
}

/**
Expand Down

0 comments on commit c50fdd5

Please sign in to comment.