The branch main has been updated by kib:

URL: 
https://cgit.FreeBSD.org/src/commit/?id=cb83af64f161b228171d6fb4f36d22493cefaa7f

commit cb83af64f161b228171d6fb4f36d22493cefaa7f
Author:     Konstantin Belousov <[email protected]>
AuthorDate: 2024-09-08 04:40:41 +0000
Commit:     Konstantin Belousov <[email protected]>
CommitDate: 2024-10-17 14:31:50 +0000

    device: add generic named per-device property
    
    The KPI allows to store arbitrary data within struct device, retrieve it
    back by name, and update the value.  The data is automatically destroyed
    on the device deletion.  Also, the user can request to clear the named
    property from all devices.
    
    My need for this interface is due to IOMMU needing to save some
    indicator on device, which must survive the re-creation of the domain
    context.
    
    Reviewed by:    imp
    Discussed with: emaste
    Sponsored by:   Advanced Micro Devices (AMD)
    Sponsored by:   The FreeBSD Foundation
    MFC after:      1 week
    Differential revision:  https://reviews.freebsd.org/D46605
---
 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 7c21325f8684..26c476e9fef6 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 */
@@ -1349,6 +1360,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;
 
@@ -1491,6 +1503,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)
@@ -6015,6 +6028,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 acadbb217711..49c5d62cebce 100644
--- a/sys/sys/bus.h
+++ b/sys/sys/bus.h
@@ -924,6 +924,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

Reply via email to