[PATCH 4/9] device property: provide fwnode_property_get_names()
From: Bartosz Golaszewski
Date: Wed Nov 04 2026 - 09:10:48 EST
Provide fwnode_property_get_names() - a new fwnode function that allows
callers to retrieve the list of all properties of given firmware node.
Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@xxxxxxxxxxxxxxxx>
---
drivers/base/property.c | 77 ++++++++++++++++++++++++++++++++++++++++++++++++
include/linux/property.h | 1 +
2 files changed, 78 insertions(+)
diff --git a/drivers/base/property.c b/drivers/base/property.c
index a97575ff9199004b4f401f432aed6c95e40d0c25..7b0df3dfae53b6377dba91330aac746684e8adec 100644
--- a/drivers/base/property.c
+++ b/drivers/base/property.c
@@ -11,11 +11,13 @@
#include <linux/device.h>
#include <linux/err.h>
#include <linux/export.h>
+#include <linux/minmax.h>
#include <linux/of.h>
#include <linux/property.h>
#include <linux/phy.h>
#include <linux/slab.h>
#include <linux/string.h>
+#include <linux/string_helpers.h>
#include <linux/types.h>
struct fwnode_handle *__dev_fwnode(struct device *dev)
@@ -542,6 +544,81 @@ int fwnode_property_match_string(const struct fwnode_handle *fwnode,
}
EXPORT_SYMBOL_GPL(fwnode_property_match_string);
+/**
+ * fwnode_property_get_names - get the list of all properties of this fwnode
+ * @fwnode: Firmware node to get the list of properties for
+ * @props: Pointer to an array of strings. It will contain the address of the
+ * string list containing the property names.
+ *
+ * Return: Number of property names written into *props. If > 0, the caller must
+ * free the array with kfree_strarray(). *props is only valid for
+ * a positive return value.
+ * %-EINVAL if arguments are not valid
+ * %-ENXIO if no suitable firmware interface is present
+ * %-ENOMEM if memory allocation failed
+ *
+ * The list also includes the properties of the secondary firmware node, if
+ * any. Properties present in both nodes are listed once.
+ */
+int fwnode_property_get_names(const struct fwnode_handle *fwnode, char ***props)
+{
+ int ret1, ret2 = -ENXIO, n1, n2, i, j, count;
+ char **prim = NULL, **sec = NULL, **merged;
+
+ if (IS_ERR_OR_NULL(fwnode))
+ return -EINVAL;
+
+ ret1 = fwnode_call_int_op(fwnode, property_get_names, &prim);
+ if (!IS_ERR_OR_NULL(fwnode->secondary))
+ ret2 = fwnode_call_int_op(fwnode->secondary, property_get_names, &sec);
+
+ if (ret1 == -ENXIO && ret2 == -ENXIO)
+ return -ENXIO;
+
+ n1 = max(ret1, 0);
+ n2 = max(ret2, 0);
+
+ CLASS(strarray, prim_props)(prim, n1);
+ CLASS(strarray, sec_props)(sec, n2);
+
+ if (ret1 < 0 && ret1 != -ENXIO)
+ return ret1;
+
+ if (ret2 < 0 && ret2 != -ENXIO)
+ return ret2;
+
+ if (n1 == 0 && n2 == 0)
+ return 0;
+
+ merged = kcalloc(n1 + n2, sizeof(*merged), GFP_KERNEL);
+ if (!merged)
+ return -ENOMEM;
+
+ /* The strings are now owned by merged, only free the container. */
+ for (i = 0; i < n1; i++) {
+ merged[i] = prim_props.array[i];
+ prim_props.array[i] = NULL;
+ }
+ count = n1;
+
+ /* Properties from the primary node take precedence. */
+ for (i = 0; i < n2; i++) {
+ for (j = 0; j < n1; j++) {
+ if (!strcmp(merged[j], sec_props.array[i]))
+ break;
+ }
+
+ if (j >= n1) {
+ merged[count++] = sec_props.array[i];
+ sec_props.array[i] = NULL;
+ }
+ }
+
+ *props = merged;
+ return count;
+}
+EXPORT_SYMBOL_GPL(fwnode_property_get_names);
+
/**
* fwnode_property_match_property_string - find a property string value in an array and return index
* @fwnode: Firmware node to get the property of
diff --git a/include/linux/property.h b/include/linux/property.h
index 9143fe4f5c05179e595ba875aafbcb006a740824..a70f3c4c087dd85390951da950c3632f89c6cfd1 100644
--- a/include/linux/property.h
+++ b/include/linux/property.h
@@ -77,6 +77,7 @@ int fwnode_property_read_string(const struct fwnode_handle *fwnode,
const char *propname, const char **val);
int fwnode_property_match_string(const struct fwnode_handle *fwnode,
const char *propname, const char *string);
+int fwnode_property_get_names(const struct fwnode_handle *fwnode, char ***props);
bool fwnode_device_is_available(const struct fwnode_handle *fwnode);
--
2.47.3