diff options
| -rw-r--r-- | drivers/base/swnode.c | 24 | ||||
| -rw-r--r-- | include/linux/property.h | 13 |
2 files changed, 32 insertions, 5 deletions
diff --git a/drivers/base/swnode.c b/drivers/base/swnode.c index 6b1ee75a908f..16a8301c25d6 100644 --- a/drivers/base/swnode.c +++ b/drivers/base/swnode.c @@ -535,7 +535,24 @@ software_node_get_reference_args(const struct fwnode_handle *fwnode, ref_array = prop->pointer; ref = &ref_array[index]; - refnode = software_node_fwnode(ref->node); + /* + * A software node can reference other software nodes or firmware + * nodes (which are the abstraction layer sitting on top of them). + * This is done to ensure we can create references to static software + * nodes before they're registered with the firmware node framework. + * At the time the reference is being resolved, we expect the swnodes + * in question to already have been registered and to be backed by + * a firmware node. This is why we use the fwnode API below to read the + * relevant properties and bump the reference count. + */ + + if (ref->swnode) + refnode = software_node_fwnode(ref->swnode); + else if (ref->fwnode) + refnode = ref->fwnode; + else + return -EINVAL; + if (!refnode) return -ENOENT; @@ -633,7 +650,10 @@ software_node_graph_get_remote_endpoint(const struct fwnode_handle *fwnode) ref = prop->pointer; - return software_node_get(software_node_fwnode(ref[0].node)); + if (!ref->swnode) + return NULL; + + return software_node_get(software_node_fwnode(ref->swnode)); } static struct fwnode_handle * diff --git a/include/linux/property.h b/include/linux/property.h index 50b26589dd70..272bfbdea7bf 100644 --- a/include/linux/property.h +++ b/include/linux/property.h @@ -355,19 +355,26 @@ struct software_node; /** * struct software_node_ref_args - Reference property with additional arguments - * @node: Reference to a software node + * @swnode: Reference to a software node + * @fwnode: Alternative reference to a firmware node handle * @nargs: Number of elements in @args array * @args: Integer arguments */ struct software_node_ref_args { - const struct software_node *node; + const struct software_node *swnode; + struct fwnode_handle *fwnode; unsigned int nargs; u64 args[NR_FWNODE_REFERENCE_ARGS]; }; #define SOFTWARE_NODE_REFERENCE(_ref_, ...) \ (const struct software_node_ref_args) { \ - .node = _ref_, \ + .swnode = _Generic(_ref_, \ + const struct software_node *: _ref_, \ + default: NULL), \ + .fwnode = _Generic(_ref_, \ + struct fwnode_handle *: _ref_, \ + default: NULL), \ .nargs = COUNT_ARGS(__VA_ARGS__), \ .args = { __VA_ARGS__ }, \ } |