Commit 4a032827 authored by Saravana Kannan's avatar Saravana Kannan Committed by Greg Kroah-Hartman
Browse files

of: property: Simplify of_link_to_phandle()



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: default avatarSaravana Kannan <saravanak@google.com>
Tested-by: default avatarColin Foster <colin.foster@in-advantage.com>
Tested-by: default avatarSudeep Holla <sudeep.holla@arm.com>
Tested-by: default avatarDouglas Anderson <dianders@chromium.org>
Tested-by: default avatarGeert 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


Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 3fb16866
Loading
Loading
Loading
Loading
+13 −71
Original line number Diff line number Diff line
@@ -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);
@@ -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;
}

/**