The branch main has been updated by dumbbell:

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

commit fe84281803d62a6846ecab5f5a7c8b4e49b0f0e0
Author:     Jean-Sébastien Pédron <dumbb...@freebsd.org>
AuthorDate: 2023-12-08 21:51:10 +0000
Commit:     Jean-Sébastien Pédron <dumbb...@freebsd.org>
CommitDate: 2023-12-13 18:57:52 +0000

    linuxkpi: Add `struct kset` support in <linux/kobject.h>
    
    [Why]
    The amdgpu DRM driver started to use it in Linux 5.18.
    
    Reviewed by:    manu
    Approved by:    manu
    Differential Revision:  https://reviews.freebsd.org/D43020
---
 sys/compat/linuxkpi/common/include/linux/kobject.h |  49 +++++++
 sys/compat/linuxkpi/common/src/linux_kobject.c     | 141 ++++++++++++++++++++-
 2 files changed, 186 insertions(+), 4 deletions(-)

diff --git a/sys/compat/linuxkpi/common/include/linux/kobject.h 
b/sys/compat/linuxkpi/common/include/linux/kobject.h
index 06d71faaa873..dadf3b3b0849 100644
--- a/sys/compat/linuxkpi/common/include/linux/kobject.h
+++ b/sys/compat/linuxkpi/common/include/linux/kobject.h
@@ -35,8 +35,10 @@
 #include <linux/kref.h>
 #include <linux/list.h>
 #include <linux/slab.h>
+#include <linux/spinlock.h>
 
 struct kobject;
+struct kset;
 struct sysctl_oid;
 
 #define        KOBJ_CHANGE             0x01
@@ -57,6 +59,7 @@ struct kobject {
        const struct kobj_type  *ktype;
        struct list_head        entry;
        struct sysctl_oid       *oidp;
+       struct kset             *kset;
 };
 
 extern struct kobject *mm_kobj;
@@ -77,6 +80,17 @@ struct kobj_attribute {
            const char *buf, size_t count);
 };
 
+struct kset_uevent_ops {
+       /* TODO */
+};
+
+struct kset {
+       struct list_head        list;
+       spinlock_t              list_lock;
+       struct kobject          kobj;
+       const struct kset_uevent_ops *uevent_ops;
+};
+
 static inline void
 kobject_init(struct kobject *kobj, const struct kobj_type *ktype)
 {
@@ -154,6 +168,41 @@ kobject_uevent_env(struct kobject *kobj, int action, char 
*envp[])
         */
 }
 
+void   kset_init(struct kset *kset);
+int    kset_register(struct kset *kset);
+void   kset_unregister(struct kset *kset);
+struct kset * kset_create_and_add(const char *name,
+    const struct kset_uevent_ops *u, struct kobject *parent_kobj);
+
+static inline struct kset *
+to_kset(struct kobject *kobj)
+{
+       if (kobj != NULL)
+               return container_of(kobj, struct kset, kobj);
+       else
+               return NULL;
+}
+
+static inline struct kset *
+kset_get(struct kset *kset)
+{
+       if (kset != NULL) {
+               struct kobject *kobj;
+
+               kobj = kobject_get(&kset->kobj);
+               return to_kset(kobj);
+       } else {
+               return NULL;
+       }
+}
+
+static inline void
+kset_put(struct kset *kset)
+{
+       if (kset != NULL)
+               kobject_put(&kset->kobj);
+}
+
 void linux_kobject_kfree_name(struct kobject *kobj);
 
 #endif /* _LINUXKPI_LINUX_KOBJECT_H_ */
diff --git a/sys/compat/linuxkpi/common/src/linux_kobject.c 
b/sys/compat/linuxkpi/common/src/linux_kobject.c
index ddd0a58660f1..02f8b8d5b709 100644
--- a/sys/compat/linuxkpi/common/src/linux_kobject.c
+++ b/sys/compat/linuxkpi/common/src/linux_kobject.c
@@ -30,6 +30,10 @@
 #include <linux/kobject.h>
 #include <linux/sysfs.h>
 
+static void kset_join(struct kobject *kobj);
+static void kset_leave(struct kobject *kobj);
+static void kset_kfree(struct kobject *kobj);
+
 struct kobject *
 kobject_create(void)
 {
@@ -101,12 +105,16 @@ kobject_set_name(struct kobject *kobj, const char *fmt, 
...)
 }
 
 static int
-kobject_add_complete(struct kobject *kobj, struct kobject *parent)
+kobject_add_complete(struct kobject *kobj)
 {
        const struct kobj_type *t;
        int error;
 
-       kobj->parent = parent;
+       if (kobj->kset != NULL) {
+               kset_join(kobj);
+               kobj->parent = &kobj->kset->kobj;
+       }
+
        error = sysfs_create_dir(kobj);
        if (error == 0 && kobj->ktype && kobj->ktype->default_attrs) {
                struct attribute **attr;
@@ -120,6 +128,10 @@ kobject_add_complete(struct kobject *kobj, struct kobject 
*parent)
                if (error)
                        sysfs_remove_dir(kobj);
        }
+
+       if (error != 0)
+               kset_leave(kobj);
+
        return (error);
 }
 
@@ -129,13 +141,15 @@ kobject_add(struct kobject *kobj, struct kobject *parent, 
const char *fmt, ...)
        va_list args;
        int error;
 
+       kobj->parent = parent;
+
        va_start(args, fmt);
        error = kobject_set_name_vargs(kobj, fmt, args);
        va_end(args);
        if (error)
                return (error);
 
-       return kobject_add_complete(kobj, parent);
+       return kobject_add_complete(kobj);
 }
 
 int
@@ -155,7 +169,7 @@ kobject_init_and_add(struct kobject *kobj, const struct 
kobj_type *ktype,
        va_end(args);
        if (error)
                return (error);
-       return kobject_add_complete(kobj, parent);
+       return kobject_add_complete(kobj);
 }
 
 void
@@ -166,6 +180,7 @@ linux_kobject_release(struct kref *kref)
 
        kobj = container_of(kref, struct kobject, kref);
        sysfs_remove_dir(kobj);
+       kset_leave(kobj);
        name = kobj->name;
        if (kobj->ktype && kobj->ktype->release)
                kobj->ktype->release(kobj);
@@ -219,3 +234,121 @@ const struct sysfs_ops kobj_sysfs_ops = {
        .show   = lkpi_kobj_attr_show,
        .store  = lkpi_kobj_attr_store,
 };
+
+const struct kobj_type linux_kset_kfree_type = {
+       .release = kset_kfree
+};
+
+static struct kset *
+kset_create(const char *name,
+    const struct kset_uevent_ops *uevent_ops,
+    struct kobject *parent_kobj)
+{
+       struct kset *kset;
+
+       kset = kzalloc(sizeof(*kset), GFP_KERNEL);
+       if (kset == NULL)
+               return (NULL);
+
+       kset->uevent_ops = uevent_ops;
+
+       kobject_set_name(&kset->kobj, "%s", name);
+       kset->kobj.parent = parent_kobj;
+       kset->kobj.kset = NULL;
+
+       return (kset);
+}
+
+void
+kset_init(struct kset *kset)
+{
+       kobject_init(&kset->kobj, &linux_kset_kfree_type);
+       INIT_LIST_HEAD(&kset->list);
+       spin_lock_init(&kset->list_lock);
+}
+
+static void
+kset_join(struct kobject *kobj)
+{
+       struct kset *kset;
+
+       kset = kobj->kset;
+       if (kset == NULL)
+               return;
+
+       kset_get(kobj->kset);
+
+       spin_lock(&kset->list_lock);
+       list_add_tail(&kobj->entry, &kset->list);
+       spin_unlock(&kset->list_lock);
+}
+
+static void
+kset_leave(struct kobject *kobj)
+{
+       struct kset *kset;
+
+       kset = kobj->kset;
+       if (kset == NULL)
+               return;
+
+       spin_lock(&kset->list_lock);
+       list_del_init(&kobj->entry);
+       spin_unlock(&kset->list_lock);
+
+       kset_put(kobj->kset);
+}
+
+struct kset *
+kset_create_and_add(const char *name, const struct kset_uevent_ops *u,
+    struct kobject *parent_kobj)
+{
+       int ret;
+       struct kset *kset;
+
+       kset = kset_create(name, u, parent_kobj);
+       if (kset == NULL)
+               return (NULL);
+
+       ret = kset_register(kset);
+       if (ret != 0) {
+               linux_kobject_kfree_name(&kset->kobj);
+               kfree(kset);
+               return (NULL);
+       }
+
+       return (kset);
+}
+
+int
+kset_register(struct kset *kset)
+{
+       int ret;
+
+       if (kset == NULL)
+               return -EINVAL;
+
+       kset_init(kset);
+       ret = kobject_add_complete(&kset->kobj);
+
+       return ret;
+}
+
+void
+kset_unregister(struct kset *kset)
+{
+       if (kset == NULL)
+               return;
+
+       kobject_del(&kset->kobj);
+       kobject_put(&kset->kobj);
+}
+
+static void
+kset_kfree(struct kobject *kobj)
+{
+       struct kset *kset;
+
+       kset = to_kset(kobj);
+       kfree(kset);
+}

Reply via email to