aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSaravana Kannan <[email protected]>2023-02-06 17:41:54 -0800
committerGreg Kroah-Hartman <[email protected]>2023-02-08 13:37:54 +0100
commit411c0d58ca6faa9bc4b9f5382118a31c7bb92a6f (patch)
treeeb399c89cec52ae46496302b2d1f4960d08cc01e
parent3a2dbc510c437ca392516b0105bad8e7970e6614 (diff)
driver core: fw_devlink: Improve check for fwnode with no device/driver
fw_devlink shouldn't defer the probe of a device to wait on a supplier that'll never have a struct device or will never be probed by a driver. We currently check if a supplier falls into this category, but don't check its ancestors. We need to check the ancestors too because if the ancestor will never probe, then the supplier will never probe either. Signed-off-by: Saravana Kannan <[email protected]> Tested-by: Colin Foster <[email protected]> Tested-by: Sudeep Holla <[email protected]> Tested-by: Douglas Anderson <[email protected]> Tested-by: Geert Uytterhoeven <[email protected]> Tested-by: Luca Weiss <[email protected]> # qcom/sm7225-fairphone-fp4 Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Greg Kroah-Hartman <[email protected]>
-rw-r--r--drivers/base/core.c40
1 files changed, 38 insertions, 2 deletions
diff --git a/drivers/base/core.c b/drivers/base/core.c
index 040c8072fd3e..3daaa7ffe751 100644
--- a/drivers/base/core.c
+++ b/drivers/base/core.c
@@ -1867,6 +1867,35 @@ static int fw_devlink_relax_cycle(struct device *con, void *sup)
return ret;
}
+static bool fwnode_init_without_drv(struct fwnode_handle *fwnode)
+{
+ struct device *dev;
+ bool ret;
+
+ if (!(fwnode->flags & FWNODE_FLAG_INITIALIZED))
+ return false;
+
+ dev = get_dev_from_fwnode(fwnode);
+ ret = !dev || dev->links.status == DL_DEV_NO_DRIVER;
+ put_device(dev);
+
+ return ret;
+}
+
+static bool fwnode_ancestor_init_without_drv(struct fwnode_handle *fwnode)
+{
+ struct fwnode_handle *parent;
+
+ fwnode_for_each_parent_node(fwnode, parent) {
+ if (fwnode_init_without_drv(parent)) {
+ fwnode_handle_put(parent);
+ return true;
+ }
+ }
+
+ return false;
+}
+
/**
* fw_devlink_create_devlink - Create a device link from a consumer to fwnode
* @con: consumer device for the device link
@@ -1948,9 +1977,16 @@ static int fw_devlink_create_devlink(struct device *con,
goto out;
}
- /* Supplier that's already initialized without a struct device. */
- if (sup_handle->flags & FWNODE_FLAG_INITIALIZED)
+ /*
+ * Supplier or supplier's ancestor already initialized without a struct
+ * device or being probed by a driver.
+ */
+ if (fwnode_init_without_drv(sup_handle) ||
+ fwnode_ancestor_init_without_drv(sup_handle)) {
+ dev_dbg(con, "Not linking %pfwP - Might never probe\n",
+ sup_handle);
return -EINVAL;
+ }
/*
* DL_FLAG_SYNC_STATE_ONLY doesn't block probing and supports