git: 2cda5031841f - stable/14 - device: add generic named per-device property
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Thu, 24 Oct 2024 02:46:08 UTC
The branch stable/14 has been updated by kib:
URL: https://cgit.FreeBSD.org/src/commit/?id=2cda5031841fa3745486a0f5c08981d266742569
commit 2cda5031841fa3745486a0f5c08981d266742569
Author: Konstantin Belousov <kib@FreeBSD.org>
AuthorDate: 2024-09-08 04:40:41 +0000
Commit: Konstantin Belousov <kib@FreeBSD.org>
CommitDate: 2024-10-24 02:44:40 +0000
device: add generic named per-device property
(cherry picked from commit cb83af64f161b228171d6fb4f36d22493cefaa7f)
---
sys/kern/subr_bus.c | 120 ++++++++++++++++++++++++++++++++++++++++++++++++++++
sys/sys/bus.h | 7 +++
2 files changed, 127 insertions(+)
diff --git a/sys/kern/subr_bus.c b/sys/kern/subr_bus.c
index 5965b8941b54..9e6973f6174c 100644
--- a/sys/kern/subr_bus.c
+++ b/sys/kern/subr_bus.c
@@ -105,6 +105,16 @@ struct devclass {
struct sysctl_oid *sysctl_tree;
};
+struct device_prop_elm {
+ const char *name;
+ void *val;
+ void *dtr_ctx;
+ device_prop_dtr_t dtr;
+ LIST_ENTRY(device_prop_elm) link;
+};
+
+static void device_destroy_props(device_t dev);
+
/**
* @brief Implementation of _device.
*
@@ -141,6 +151,7 @@ struct _device {
u_int order; /**< order from device_add_child_ordered() */
void *ivars; /**< instance variables */
void *softc; /**< current driver's variables */
+ LIST_HEAD(, device_prop_elm) props;
struct sysctl_ctx_list sysctl_ctx; /**< state for sysctl variables */
struct sysctl_oid *sysctl_tree; /**< state for sysctl variables */
@@ -1350,6 +1361,7 @@ make_device(device_t parent, const char *name, int unit)
dev->flags |= DF_QUIET | DF_QUIET_CHILDREN;
dev->ivars = NULL;
dev->softc = NULL;
+ LIST_INIT(&dev->props);
dev->state = DS_NOTPRESENT;
@@ -1489,6 +1501,7 @@ device_delete_child(device_t dev, device_t child)
return (error);
}
+ device_destroy_props(dev);
if (child->devclass)
devclass_delete_device(child->devclass, child);
if (child->parent)
@@ -5990,6 +6003,113 @@ dev_wired_cache_match(device_location_cache_t *dcp, device_t dev,
return (strcmp(res->dln_path, cp) == 0);
}
+static struct device_prop_elm *
+device_prop_find(device_t dev, const char *name)
+{
+ struct device_prop_elm *e;
+
+ bus_topo_assert();
+
+ LIST_FOREACH(e, &dev->props, link) {
+ if (strcmp(name, e->name) == 0)
+ return (e);
+ }
+ return (NULL);
+}
+
+int
+device_set_prop(device_t dev, const char *name, void *val,
+ device_prop_dtr_t dtr, void *dtr_ctx)
+{
+ struct device_prop_elm *e, *e1;
+
+ bus_topo_assert();
+
+ e = device_prop_find(dev, name);
+ if (e != NULL)
+ goto found;
+
+ e1 = malloc(sizeof(*e), M_BUS, M_WAITOK);
+ e = device_prop_find(dev, name);
+ if (e != NULL) {
+ free(e1, M_BUS);
+ goto found;
+ }
+
+ e1->name = name;
+ e1->val = val;
+ e1->dtr = dtr;
+ e1->dtr_ctx = dtr_ctx;
+ LIST_INSERT_HEAD(&dev->props, e1, link);
+ return (0);
+
+found:
+ LIST_REMOVE(e, link);
+ if (e->dtr != NULL)
+ e->dtr(dev, name, e->val, e->dtr_ctx);
+ e->val = val;
+ e->dtr = dtr;
+ e->dtr_ctx = dtr_ctx;
+ LIST_INSERT_HEAD(&dev->props, e, link);
+ return (EEXIST);
+}
+
+int
+device_get_prop(device_t dev, const char *name, void **valp)
+{
+ struct device_prop_elm *e;
+
+ bus_topo_assert();
+
+ e = device_prop_find(dev, name);
+ if (e == NULL)
+ return (ENOENT);
+ *valp = e->val;
+ return (0);
+}
+
+int
+device_clear_prop(device_t dev, const char *name)
+{
+ struct device_prop_elm *e;
+
+ bus_topo_assert();
+
+ e = device_prop_find(dev, name);
+ if (e == NULL)
+ return (ENOENT);
+ LIST_REMOVE(e, link);
+ if (e->dtr != NULL)
+ e->dtr(dev, e->name, e->val, e->dtr_ctx);
+ free(e, M_BUS);
+ return (0);
+}
+
+static void
+device_destroy_props(device_t dev)
+{
+ struct device_prop_elm *e;
+
+ bus_topo_assert();
+
+ while ((e = LIST_FIRST(&dev->props)) != NULL) {
+ LIST_REMOVE_HEAD(&dev->props, link);
+ if (e->dtr != NULL)
+ e->dtr(dev, e->name, e->val, e->dtr_ctx);
+ free(e, M_BUS);
+ }
+}
+
+void
+device_clear_prop_alldev(const char *name)
+{
+ device_t dev;
+
+ TAILQ_FOREACH(dev, &bus_data_devices, devlink) {
+ device_clear_prop(dev, name);
+ }
+}
+
/*
* APIs to manage deprecation and obsolescence.
*/
diff --git a/sys/sys/bus.h b/sys/sys/bus.h
index 581e81352be4..eecff0c7c03e 100644
--- a/sys/sys/bus.h
+++ b/sys/sys/bus.h
@@ -889,6 +889,13 @@ device_location_cache_t *dev_wired_cache_init(void);
void dev_wired_cache_fini(device_location_cache_t *dcp);
bool dev_wired_cache_match(device_location_cache_t *dcp, device_t dev, const char *at);
+typedef void (*device_prop_dtr_t)(device_t dev, const char *name, void *val,
+ void *dtr_ctx);
+int device_set_prop(device_t dev, const char *name, void *val,
+ device_prop_dtr_t dtr, void *dtr_ctx);
+int device_get_prop(device_t dev, const char *name, void **valp);
+int device_clear_prop(device_t dev, const char *name);
+void device_clear_prop_alldev(const char *name);
/**
* Shorthand macros, taking resource argument