mirror of
https://github.com/opnsense/src.git
synced 2026-06-09 00:32:25 -04:00
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
This commit is contained in:
parent
d6d1e73e5f
commit
fe84281803
2 changed files with 186 additions and 4 deletions
|
|
@ -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_ */
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue