git: fe84281803d6 - main - linuxkpi: Add `struct kset` support in <linux/kobject.h>
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Wed, 13 Dec 2023 19:00:13 UTC
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 <dumbbell@FreeBSD.org> AuthorDate: 2023-12-08 21:51:10 +0000 Commit: Jean-Sébastien Pédron <dumbbell@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); +}