1*d9d16e16SGreg Kroah-Hartman // SPDX-License-Identifier: GPL-2.0 244bfe16eSGreg Kroah-Hartman /* 344bfe16eSGreg Kroah-Hartman * Sample kset and ktype implementation 444bfe16eSGreg Kroah-Hartman * 544bfe16eSGreg Kroah-Hartman * Copyright (C) 2004-2007 Greg Kroah-Hartman <greg@kroah.com> 644bfe16eSGreg Kroah-Hartman * Copyright (C) 2007 Novell Inc. 744bfe16eSGreg Kroah-Hartman * 844bfe16eSGreg Kroah-Hartman * Released under the GPL version 2 only. 944bfe16eSGreg Kroah-Hartman * 1044bfe16eSGreg Kroah-Hartman */ 1144bfe16eSGreg Kroah-Hartman #include <linux/kobject.h> 1244bfe16eSGreg Kroah-Hartman #include <linux/string.h> 1344bfe16eSGreg Kroah-Hartman #include <linux/sysfs.h> 145a0e3ad6STejun Heo #include <linux/slab.h> 1544bfe16eSGreg Kroah-Hartman #include <linux/module.h> 1644bfe16eSGreg Kroah-Hartman #include <linux/init.h> 1744bfe16eSGreg Kroah-Hartman 1844bfe16eSGreg Kroah-Hartman /* 1944bfe16eSGreg Kroah-Hartman * This module shows how to create a kset in sysfs called 2044bfe16eSGreg Kroah-Hartman * /sys/kernel/kset-example 2144bfe16eSGreg Kroah-Hartman * Then tree kobjects are created and assigned to this kset, "foo", "baz", 2244bfe16eSGreg Kroah-Hartman * and "bar". In those kobjects, attributes of the same name are also 2344bfe16eSGreg Kroah-Hartman * created and if an integer is written to these files, it can be later 2444bfe16eSGreg Kroah-Hartman * read out of it. 2544bfe16eSGreg Kroah-Hartman */ 2644bfe16eSGreg Kroah-Hartman 2744bfe16eSGreg Kroah-Hartman 2844bfe16eSGreg Kroah-Hartman /* 2944bfe16eSGreg Kroah-Hartman * This is our "object" that we will create a few of and register them with 3044bfe16eSGreg Kroah-Hartman * sysfs. 3144bfe16eSGreg Kroah-Hartman */ 3244bfe16eSGreg Kroah-Hartman struct foo_obj { 3344bfe16eSGreg Kroah-Hartman struct kobject kobj; 3444bfe16eSGreg Kroah-Hartman int foo; 3544bfe16eSGreg Kroah-Hartman int baz; 3644bfe16eSGreg Kroah-Hartman int bar; 3744bfe16eSGreg Kroah-Hartman }; 3844bfe16eSGreg Kroah-Hartman #define to_foo_obj(x) container_of(x, struct foo_obj, kobj) 3944bfe16eSGreg Kroah-Hartman 4044bfe16eSGreg Kroah-Hartman /* a custom attribute that works just for a struct foo_obj. */ 4144bfe16eSGreg Kroah-Hartman struct foo_attribute { 4244bfe16eSGreg Kroah-Hartman struct attribute attr; 4344bfe16eSGreg Kroah-Hartman ssize_t (*show)(struct foo_obj *foo, struct foo_attribute *attr, char *buf); 4444bfe16eSGreg Kroah-Hartman ssize_t (*store)(struct foo_obj *foo, struct foo_attribute *attr, const char *buf, size_t count); 4544bfe16eSGreg Kroah-Hartman }; 4644bfe16eSGreg Kroah-Hartman #define to_foo_attr(x) container_of(x, struct foo_attribute, attr) 4744bfe16eSGreg Kroah-Hartman 4844bfe16eSGreg Kroah-Hartman /* 4944bfe16eSGreg Kroah-Hartman * The default show function that must be passed to sysfs. This will be 5044bfe16eSGreg Kroah-Hartman * called by sysfs for whenever a show function is called by the user on a 5144bfe16eSGreg Kroah-Hartman * sysfs file associated with the kobjects we have registered. We need to 5244bfe16eSGreg Kroah-Hartman * transpose back from a "default" kobject to our custom struct foo_obj and 5344bfe16eSGreg Kroah-Hartman * then call the show function for that specific object. 5444bfe16eSGreg Kroah-Hartman */ 5544bfe16eSGreg Kroah-Hartman static ssize_t foo_attr_show(struct kobject *kobj, 5644bfe16eSGreg Kroah-Hartman struct attribute *attr, 5744bfe16eSGreg Kroah-Hartman char *buf) 5844bfe16eSGreg Kroah-Hartman { 5944bfe16eSGreg Kroah-Hartman struct foo_attribute *attribute; 6044bfe16eSGreg Kroah-Hartman struct foo_obj *foo; 6144bfe16eSGreg Kroah-Hartman 6244bfe16eSGreg Kroah-Hartman attribute = to_foo_attr(attr); 6344bfe16eSGreg Kroah-Hartman foo = to_foo_obj(kobj); 6444bfe16eSGreg Kroah-Hartman 6544bfe16eSGreg Kroah-Hartman if (!attribute->show) 6644bfe16eSGreg Kroah-Hartman return -EIO; 6744bfe16eSGreg Kroah-Hartman 6844bfe16eSGreg Kroah-Hartman return attribute->show(foo, attribute, buf); 6944bfe16eSGreg Kroah-Hartman } 7044bfe16eSGreg Kroah-Hartman 7144bfe16eSGreg Kroah-Hartman /* 7244bfe16eSGreg Kroah-Hartman * Just like the default show function above, but this one is for when the 7344bfe16eSGreg Kroah-Hartman * sysfs "store" is requested (when a value is written to a file.) 7444bfe16eSGreg Kroah-Hartman */ 7544bfe16eSGreg Kroah-Hartman static ssize_t foo_attr_store(struct kobject *kobj, 7644bfe16eSGreg Kroah-Hartman struct attribute *attr, 7744bfe16eSGreg Kroah-Hartman const char *buf, size_t len) 7844bfe16eSGreg Kroah-Hartman { 7944bfe16eSGreg Kroah-Hartman struct foo_attribute *attribute; 8044bfe16eSGreg Kroah-Hartman struct foo_obj *foo; 8144bfe16eSGreg Kroah-Hartman 8244bfe16eSGreg Kroah-Hartman attribute = to_foo_attr(attr); 8344bfe16eSGreg Kroah-Hartman foo = to_foo_obj(kobj); 8444bfe16eSGreg Kroah-Hartman 8544bfe16eSGreg Kroah-Hartman if (!attribute->store) 8644bfe16eSGreg Kroah-Hartman return -EIO; 8744bfe16eSGreg Kroah-Hartman 8844bfe16eSGreg Kroah-Hartman return attribute->store(foo, attribute, buf, len); 8944bfe16eSGreg Kroah-Hartman } 9044bfe16eSGreg Kroah-Hartman 9144bfe16eSGreg Kroah-Hartman /* Our custom sysfs_ops that we will associate with our ktype later on */ 9252cf25d0SEmese Revfy static const struct sysfs_ops foo_sysfs_ops = { 9344bfe16eSGreg Kroah-Hartman .show = foo_attr_show, 9444bfe16eSGreg Kroah-Hartman .store = foo_attr_store, 9544bfe16eSGreg Kroah-Hartman }; 9644bfe16eSGreg Kroah-Hartman 9744bfe16eSGreg Kroah-Hartman /* 9844bfe16eSGreg Kroah-Hartman * The release function for our object. This is REQUIRED by the kernel to 9944bfe16eSGreg Kroah-Hartman * have. We free the memory held in our object here. 10044bfe16eSGreg Kroah-Hartman * 10144bfe16eSGreg Kroah-Hartman * NEVER try to get away with just a "blank" release function to try to be 10244bfe16eSGreg Kroah-Hartman * smarter than the kernel. Turns out, no one ever is... 10344bfe16eSGreg Kroah-Hartman */ 10444bfe16eSGreg Kroah-Hartman static void foo_release(struct kobject *kobj) 10544bfe16eSGreg Kroah-Hartman { 10644bfe16eSGreg Kroah-Hartman struct foo_obj *foo; 10744bfe16eSGreg Kroah-Hartman 10844bfe16eSGreg Kroah-Hartman foo = to_foo_obj(kobj); 10944bfe16eSGreg Kroah-Hartman kfree(foo); 11044bfe16eSGreg Kroah-Hartman } 11144bfe16eSGreg Kroah-Hartman 11244bfe16eSGreg Kroah-Hartman /* 11344bfe16eSGreg Kroah-Hartman * The "foo" file where the .foo variable is read from and written to. 11444bfe16eSGreg Kroah-Hartman */ 11544bfe16eSGreg Kroah-Hartman static ssize_t foo_show(struct foo_obj *foo_obj, struct foo_attribute *attr, 11644bfe16eSGreg Kroah-Hartman char *buf) 11744bfe16eSGreg Kroah-Hartman { 11844bfe16eSGreg Kroah-Hartman return sprintf(buf, "%d\n", foo_obj->foo); 11944bfe16eSGreg Kroah-Hartman } 12044bfe16eSGreg Kroah-Hartman 12144bfe16eSGreg Kroah-Hartman static ssize_t foo_store(struct foo_obj *foo_obj, struct foo_attribute *attr, 12244bfe16eSGreg Kroah-Hartman const char *buf, size_t count) 12344bfe16eSGreg Kroah-Hartman { 1245fd637e7SRastislav Barlik int ret; 1255fd637e7SRastislav Barlik 1265fd637e7SRastislav Barlik ret = kstrtoint(buf, 10, &foo_obj->foo); 1275fd637e7SRastislav Barlik if (ret < 0) 1285fd637e7SRastislav Barlik return ret; 1295fd637e7SRastislav Barlik 13044bfe16eSGreg Kroah-Hartman return count; 13144bfe16eSGreg Kroah-Hartman } 13244bfe16eSGreg Kroah-Hartman 133de510989SRusty Russell /* Sysfs attributes cannot be world-writable. */ 13444bfe16eSGreg Kroah-Hartman static struct foo_attribute foo_attribute = 135de510989SRusty Russell __ATTR(foo, 0664, foo_show, foo_store); 13644bfe16eSGreg Kroah-Hartman 13744bfe16eSGreg Kroah-Hartman /* 13820ef9f46SRadu Voicilas * More complex function where we determine which variable is being accessed by 13944bfe16eSGreg Kroah-Hartman * looking at the attribute for the "baz" and "bar" files. 14044bfe16eSGreg Kroah-Hartman */ 14144bfe16eSGreg Kroah-Hartman static ssize_t b_show(struct foo_obj *foo_obj, struct foo_attribute *attr, 14244bfe16eSGreg Kroah-Hartman char *buf) 14344bfe16eSGreg Kroah-Hartman { 14444bfe16eSGreg Kroah-Hartman int var; 14544bfe16eSGreg Kroah-Hartman 14644bfe16eSGreg Kroah-Hartman if (strcmp(attr->attr.name, "baz") == 0) 14744bfe16eSGreg Kroah-Hartman var = foo_obj->baz; 14844bfe16eSGreg Kroah-Hartman else 14944bfe16eSGreg Kroah-Hartman var = foo_obj->bar; 15044bfe16eSGreg Kroah-Hartman return sprintf(buf, "%d\n", var); 15144bfe16eSGreg Kroah-Hartman } 15244bfe16eSGreg Kroah-Hartman 15344bfe16eSGreg Kroah-Hartman static ssize_t b_store(struct foo_obj *foo_obj, struct foo_attribute *attr, 15444bfe16eSGreg Kroah-Hartman const char *buf, size_t count) 15544bfe16eSGreg Kroah-Hartman { 1565fd637e7SRastislav Barlik int var, ret; 15744bfe16eSGreg Kroah-Hartman 1585fd637e7SRastislav Barlik ret = kstrtoint(buf, 10, &var); 1595fd637e7SRastislav Barlik if (ret < 0) 1605fd637e7SRastislav Barlik return ret; 1615fd637e7SRastislav Barlik 16244bfe16eSGreg Kroah-Hartman if (strcmp(attr->attr.name, "baz") == 0) 16344bfe16eSGreg Kroah-Hartman foo_obj->baz = var; 16444bfe16eSGreg Kroah-Hartman else 16544bfe16eSGreg Kroah-Hartman foo_obj->bar = var; 16644bfe16eSGreg Kroah-Hartman return count; 16744bfe16eSGreg Kroah-Hartman } 16844bfe16eSGreg Kroah-Hartman 16944bfe16eSGreg Kroah-Hartman static struct foo_attribute baz_attribute = 170de510989SRusty Russell __ATTR(baz, 0664, b_show, b_store); 17144bfe16eSGreg Kroah-Hartman static struct foo_attribute bar_attribute = 172de510989SRusty Russell __ATTR(bar, 0664, b_show, b_store); 17344bfe16eSGreg Kroah-Hartman 17444bfe16eSGreg Kroah-Hartman /* 17520ef9f46SRadu Voicilas * Create a group of attributes so that we can create and destroy them all 17644bfe16eSGreg Kroah-Hartman * at once. 17744bfe16eSGreg Kroah-Hartman */ 17844bfe16eSGreg Kroah-Hartman static struct attribute *foo_default_attrs[] = { 17944bfe16eSGreg Kroah-Hartman &foo_attribute.attr, 18044bfe16eSGreg Kroah-Hartman &baz_attribute.attr, 18144bfe16eSGreg Kroah-Hartman &bar_attribute.attr, 18244bfe16eSGreg Kroah-Hartman NULL, /* need to NULL terminate the list of attributes */ 18344bfe16eSGreg Kroah-Hartman }; 18444bfe16eSGreg Kroah-Hartman 18544bfe16eSGreg Kroah-Hartman /* 18644bfe16eSGreg Kroah-Hartman * Our own ktype for our kobjects. Here we specify our sysfs ops, the 18744bfe16eSGreg Kroah-Hartman * release function, and the set of default attributes we want created 18844bfe16eSGreg Kroah-Hartman * whenever a kobject of this type is registered with the kernel. 18944bfe16eSGreg Kroah-Hartman */ 19044bfe16eSGreg Kroah-Hartman static struct kobj_type foo_ktype = { 19144bfe16eSGreg Kroah-Hartman .sysfs_ops = &foo_sysfs_ops, 19244bfe16eSGreg Kroah-Hartman .release = foo_release, 19344bfe16eSGreg Kroah-Hartman .default_attrs = foo_default_attrs, 19444bfe16eSGreg Kroah-Hartman }; 19544bfe16eSGreg Kroah-Hartman 19644bfe16eSGreg Kroah-Hartman static struct kset *example_kset; 19744bfe16eSGreg Kroah-Hartman static struct foo_obj *foo_obj; 19844bfe16eSGreg Kroah-Hartman static struct foo_obj *bar_obj; 19944bfe16eSGreg Kroah-Hartman static struct foo_obj *baz_obj; 20044bfe16eSGreg Kroah-Hartman 20144bfe16eSGreg Kroah-Hartman static struct foo_obj *create_foo_obj(const char *name) 20244bfe16eSGreg Kroah-Hartman { 20344bfe16eSGreg Kroah-Hartman struct foo_obj *foo; 20444bfe16eSGreg Kroah-Hartman int retval; 20544bfe16eSGreg Kroah-Hartman 20644bfe16eSGreg Kroah-Hartman /* allocate the memory for the whole object */ 20744bfe16eSGreg Kroah-Hartman foo = kzalloc(sizeof(*foo), GFP_KERNEL); 20844bfe16eSGreg Kroah-Hartman if (!foo) 20944bfe16eSGreg Kroah-Hartman return NULL; 21044bfe16eSGreg Kroah-Hartman 21144bfe16eSGreg Kroah-Hartman /* 21244bfe16eSGreg Kroah-Hartman * As we have a kset for this kobject, we need to set it before calling 21344bfe16eSGreg Kroah-Hartman * the kobject core. 21444bfe16eSGreg Kroah-Hartman */ 21544bfe16eSGreg Kroah-Hartman foo->kobj.kset = example_kset; 21644bfe16eSGreg Kroah-Hartman 21744bfe16eSGreg Kroah-Hartman /* 21844bfe16eSGreg Kroah-Hartman * Initialize and add the kobject to the kernel. All the default files 21944bfe16eSGreg Kroah-Hartman * will be created here. As we have already specified a kset for this 22044bfe16eSGreg Kroah-Hartman * kobject, we don't have to set a parent for the kobject, the kobject 22144bfe16eSGreg Kroah-Hartman * will be placed beneath that kset automatically. 22244bfe16eSGreg Kroah-Hartman */ 22344bfe16eSGreg Kroah-Hartman retval = kobject_init_and_add(&foo->kobj, &foo_ktype, NULL, "%s", name); 22444bfe16eSGreg Kroah-Hartman if (retval) { 225185000fcSLi Zefan kobject_put(&foo->kobj); 22644bfe16eSGreg Kroah-Hartman return NULL; 22744bfe16eSGreg Kroah-Hartman } 22844bfe16eSGreg Kroah-Hartman 22944bfe16eSGreg Kroah-Hartman /* 23044bfe16eSGreg Kroah-Hartman * We are always responsible for sending the uevent that the kobject 23144bfe16eSGreg Kroah-Hartman * was added to the system. 23244bfe16eSGreg Kroah-Hartman */ 23344bfe16eSGreg Kroah-Hartman kobject_uevent(&foo->kobj, KOBJ_ADD); 23444bfe16eSGreg Kroah-Hartman 23544bfe16eSGreg Kroah-Hartman return foo; 23644bfe16eSGreg Kroah-Hartman } 23744bfe16eSGreg Kroah-Hartman 23844bfe16eSGreg Kroah-Hartman static void destroy_foo_obj(struct foo_obj *foo) 23944bfe16eSGreg Kroah-Hartman { 24044bfe16eSGreg Kroah-Hartman kobject_put(&foo->kobj); 24144bfe16eSGreg Kroah-Hartman } 24244bfe16eSGreg Kroah-Hartman 2437ec7fb39SQinghuang Feng static int __init example_init(void) 24444bfe16eSGreg Kroah-Hartman { 24544bfe16eSGreg Kroah-Hartman /* 24644bfe16eSGreg Kroah-Hartman * Create a kset with the name of "kset_example", 24744bfe16eSGreg Kroah-Hartman * located under /sys/kernel/ 24844bfe16eSGreg Kroah-Hartman */ 24944bfe16eSGreg Kroah-Hartman example_kset = kset_create_and_add("kset_example", NULL, kernel_kobj); 25044bfe16eSGreg Kroah-Hartman if (!example_kset) 25144bfe16eSGreg Kroah-Hartman return -ENOMEM; 25244bfe16eSGreg Kroah-Hartman 25344bfe16eSGreg Kroah-Hartman /* 25444bfe16eSGreg Kroah-Hartman * Create three objects and register them with our kset 25544bfe16eSGreg Kroah-Hartman */ 25644bfe16eSGreg Kroah-Hartman foo_obj = create_foo_obj("foo"); 25744bfe16eSGreg Kroah-Hartman if (!foo_obj) 25844bfe16eSGreg Kroah-Hartman goto foo_error; 25944bfe16eSGreg Kroah-Hartman 26044bfe16eSGreg Kroah-Hartman bar_obj = create_foo_obj("bar"); 26144bfe16eSGreg Kroah-Hartman if (!bar_obj) 26244bfe16eSGreg Kroah-Hartman goto bar_error; 26344bfe16eSGreg Kroah-Hartman 26444bfe16eSGreg Kroah-Hartman baz_obj = create_foo_obj("baz"); 26544bfe16eSGreg Kroah-Hartman if (!baz_obj) 26644bfe16eSGreg Kroah-Hartman goto baz_error; 26744bfe16eSGreg Kroah-Hartman 26844bfe16eSGreg Kroah-Hartman return 0; 26944bfe16eSGreg Kroah-Hartman 27044bfe16eSGreg Kroah-Hartman baz_error: 27144bfe16eSGreg Kroah-Hartman destroy_foo_obj(bar_obj); 27244bfe16eSGreg Kroah-Hartman bar_error: 27344bfe16eSGreg Kroah-Hartman destroy_foo_obj(foo_obj); 27444bfe16eSGreg Kroah-Hartman foo_error: 275e756bc56SBjorn Helgaas kset_unregister(example_kset); 27644bfe16eSGreg Kroah-Hartman return -EINVAL; 27744bfe16eSGreg Kroah-Hartman } 27844bfe16eSGreg Kroah-Hartman 2797ec7fb39SQinghuang Feng static void __exit example_exit(void) 28044bfe16eSGreg Kroah-Hartman { 28144bfe16eSGreg Kroah-Hartman destroy_foo_obj(baz_obj); 28244bfe16eSGreg Kroah-Hartman destroy_foo_obj(bar_obj); 28344bfe16eSGreg Kroah-Hartman destroy_foo_obj(foo_obj); 28444bfe16eSGreg Kroah-Hartman kset_unregister(example_kset); 28544bfe16eSGreg Kroah-Hartman } 28644bfe16eSGreg Kroah-Hartman 28744bfe16eSGreg Kroah-Hartman module_init(example_init); 28844bfe16eSGreg Kroah-Hartman module_exit(example_exit); 28907afb6acSGreg Kroah-Hartman MODULE_LICENSE("GPL v2"); 29044bfe16eSGreg Kroah-Hartman MODULE_AUTHOR("Greg Kroah-Hartman <greg@kroah.com>"); 291