of: property: Simplify of_link_to_phandle()
authorSaravana Kannan <saravanak@google.com>
Tue, 7 Feb 2023 01:42:01 +0000 (17:42 -0800)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 13 Sep 2023 07:42:25 +0000 (09:42 +0200)
commit 4a032827daa89350365166b19d14d82fe8219128 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: eaf9b5612a47 ("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>
drivers/of/property.c

index 134cfc9..c651aad 100644 (file)
@@ -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;
 }
 
 /**