Skip to content

Commit

Permalink
linuxkpi: Add struct kset support in <linux/kobject.h>
Browse files Browse the repository at this point in the history
[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
  • Loading branch information
dumbbell committed Dec 13, 2023
1 parent d6d1e73 commit fe84281
Show file tree
Hide file tree
Showing 2 changed files with 186 additions and 4 deletions.
49 changes: 49 additions & 0 deletions sys/compat/linuxkpi/common/include/linux/kobject.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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;
Expand All @@ -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)
{
Expand Down Expand Up @@ -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_ */
141 changes: 137 additions & 4 deletions sys/compat/linuxkpi/common/src/linux_kobject.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
Expand Down Expand Up @@ -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;
Expand All @@ -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);
}

Expand All @@ -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
Expand All @@ -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
Expand All @@ -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);
Expand Down Expand Up @@ -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);
}

0 comments on commit fe84281

Please sign in to comment.